blob: e477cf10e9ac0f52f894e866b20867d9f6a7aadc [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $Id$
34 */
35
36#include "defs.h"
37
Roland McGrathd81f1d92003-01-09 06:53:34 +000038#include <signal.h>
39#include <sys/syscall.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000040#include <sys/user.h>
41#include <sys/param.h>
42#include <fcntl.h>
John Hughes1d08dcf2001-07-10 13:48:44 +000043#if HAVE_SYS_UIO_H
44#include <sys/uio.h>
45#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000046#ifdef SUNOS4
47#include <machine/reg.h>
48#include <a.out.h>
49#include <link.h>
50#endif /* SUNOS4 */
Wichert Akkerman36915a11999-07-13 15:45:02 +000051
Wichert Akkerman43a74822000-06-27 17:33:32 +000052#if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
Wichert Akkerman36915a11999-07-13 15:45:02 +000053#include <linux/ptrace.h>
Roland McGrath1e85cf92002-12-16 20:40:54 +000054#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000055
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000056#if defined(LINUX) && defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000057# include <asm/ptrace_offsets.h>
58# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000059#endif
60
Wichert Akkerman36915a11999-07-13 15:45:02 +000061#ifdef HAVE_SYS_REG_H
62#include <sys/reg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000063# define PTRACE_PEEKUSR PTRACE_PEEKUSER
Wichert Akkermanfaf72222000-02-19 23:59:03 +000064#elif defined(HAVE_LINUX_PTRACE_H)
65#undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000066# ifdef HAVE_STRUCT_IA64_FPREG
67# define ia64_fpreg XXX_ia64_fpreg
68# endif
69# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
70# define pt_all_user_regs XXX_pt_all_user_regs
71# endif
Wichert Akkermanfaf72222000-02-19 23:59:03 +000072#include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000073# undef ia64_fpreg
74# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000075#endif
76
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000077#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
78#include <sys/utsname.h>
79#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
80
Roland McGrath6d1a65c2004-07-12 07:44:08 +000081#if defined(LINUXSPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000082
Roland McGrath4db26242003-01-30 20:15:19 +000083# define fpq kernel_fpq
84# define fq kernel_fq
85# define fpu kernel_fpu
86# include <asm/reg.h>
87# undef fpq
88# undef fq
89# undef fpu
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000090
Roland McGrath6d1a65c2004-07-12 07:44:08 +000091#if defined (SPARC64)
92# define r_pc r_tpc
93# undef PTRACE_GETREGS
94# define PTRACE_GETREGS PTRACE_GETREGS64
95# undef PTRACE_SETREGS
96# define PTRACE_SETREGS PTRACE_SETREGS64
97#endif /* SPARC64 */
98
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000099#if !defined(__GLIBC__)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000100
101#include <linux/unistd.h>
102
103#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
104 type5,arg5,syscall) \
105type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
106{ \
107 long __res; \
108\
109__asm__ volatile ("or %%g0, %1, %%o0\n\t" \
110 "or %%g0, %2, %%o1\n\t" \
111 "or %%g0, %3, %%o2\n\t" \
112 "or %%g0, %4, %%o3\n\t" \
113 "or %%g0, %5, %%o4\n\t" \
114 "or %%g0, %6, %%g1\n\t" \
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000115#if defined (SPARC64)
116 "t 0x6d\n\t" \
117#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118 "t 0x10\n\t" \
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000119#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120 "bcc 1f\n\t" \
121 "or %%g0, %%o0, %0\n\t" \
122 "sub %%g0, %%o0, %0\n\t" \
123 "1:\n\t" \
124 : "=r" (__res) \
125 : "0" ((long)(arg1)),"1" ((long)(arg2)), \
126 "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
127 "i" (__NR_##syscall) \
128 : "g1", "o0", "o1", "o2", "o3", "o4"); \
129if (__res>=0) \
130 return (type) __res; \
131errno = -__res; \
132return -1; \
133}
134
135static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
136
137#define _ptrace
138
139#endif
140
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000141#endif
142
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143/* macros */
144#ifndef MAX
145#define MAX(a,b) (((a) > (b)) ? (a) : (b))
146#endif
147#ifndef MIN
148#define MIN(a,b) (((a) < (b)) ? (a) : (b))
149#endif
150
151void
152tv_tv(tv, a, b)
153struct timeval *tv;
154int a;
155int b;
156{
157 tv->tv_sec = a;
158 tv->tv_usec = b;
159}
160
161int
162tv_nz(a)
163struct timeval *a;
164{
165 return a->tv_sec || a->tv_usec;
166}
167
168int
169tv_cmp(a, b)
170struct timeval *a, *b;
171{
172 if (a->tv_sec < b->tv_sec
173 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
174 return -1;
175 if (a->tv_sec > b->tv_sec
176 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
177 return 1;
178 return 0;
179}
180
181double
182tv_float(tv)
183struct timeval *tv;
184{
185 return tv->tv_sec + tv->tv_usec/1000000.0;
186}
187
188void
189tv_add(tv, a, b)
190struct timeval *tv, *a, *b;
191{
192 tv->tv_sec = a->tv_sec + b->tv_sec;
193 tv->tv_usec = a->tv_usec + b->tv_usec;
194 if (tv->tv_usec > 1000000) {
195 tv->tv_sec++;
196 tv->tv_usec -= 1000000;
197 }
198}
199
200void
201tv_sub(tv, a, b)
202struct timeval *tv, *a, *b;
203{
204 tv->tv_sec = a->tv_sec - b->tv_sec;
205 tv->tv_usec = a->tv_usec - b->tv_usec;
206 if (((long) tv->tv_usec) < 0) {
207 tv->tv_sec--;
208 tv->tv_usec += 1000000;
209 }
210}
211
212void
213tv_div(tv, a, n)
214struct timeval *tv, *a;
215int n;
216{
217 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
218 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
219 tv->tv_usec %= 1000000;
220}
221
222void
223tv_mul(tv, a, n)
224struct timeval *tv, *a;
225int n;
226{
227 tv->tv_usec = a->tv_usec * n;
228 tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
229 tv->tv_usec %= 1000000;
230}
231
232char *
233xlookup(xlat, val)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000234const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000235int val;
236{
237 for (; xlat->str != NULL; xlat++)
238 if (xlat->val == val)
239 return xlat->str;
240 return NULL;
241}
242
243/*
244 * Print entry in struct xlat table, if there.
245 */
246void
247printxval(xlat, val, dflt)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000248const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000249int val;
Roland McGrathb2dee132005-06-01 19:02:36 +0000250const char *dflt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000251{
252 char *str = xlookup(xlat, val);
253
254 if (str)
255 tprintf("%s", str);
256 else
257 tprintf("%#x /* %s */", val, dflt);
258}
259
260/*
261 * Interpret `xlat' as an array of flags
262 * print the entries whose bits are on in `flags'
263 * return # of flags printed.
264 */
265int
266addflags(xlat, flags)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000267const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000268int flags;
269{
270 int n;
271
272 for (n = 0; xlat->str; xlat++) {
273 if (xlat->val && (flags & xlat->val) == xlat->val) {
274 tprintf("|%s", xlat->str);
275 flags &= ~xlat->val;
276 n++;
277 }
278 }
279 if (flags) {
280 tprintf("|%#x", flags);
281 n++;
282 }
283 return n;
284}
285
286int
Roland McGrathb2dee132005-06-01 19:02:36 +0000287printflags(xlat, flags, dflt)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000288const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000289int flags;
Roland McGrathb2dee132005-06-01 19:02:36 +0000290const char *dflt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000291{
292 int n;
293 char *sep;
294
295 if (flags == 0 && xlat->val == 0) {
296 tprintf("%s", xlat->str);
297 return 1;
298 }
299
300 sep = "";
301 for (n = 0; xlat->str; xlat++) {
302 if (xlat->val && (flags & xlat->val) == xlat->val) {
303 tprintf("%s%s", sep, xlat->str);
304 flags &= ~xlat->val;
305 sep = "|";
306 n++;
307 }
308 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000309
310 if (n) {
311 if (flags) {
312 tprintf("%s%#x", sep, flags);
313 n++;
314 }
315 } else {
316 if (flags) {
317 tprintf("%#x", flags);
318 if (dflt)
319 tprintf(" /* %s */", dflt);
320 } else {
321 if (dflt)
322 tprintf("0");
323 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000324 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000325
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000326 return n;
327}
328
329void
330printnum(tcp, addr, fmt)
331struct tcb *tcp;
332long addr;
333char *fmt;
334{
Roland McGratheb285352003-01-14 09:59:00 +0000335 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000336
337 if (!addr) {
338 tprintf("NULL");
339 return;
340 }
341 if (umove(tcp, addr, &num) < 0) {
342 tprintf("%#lx", addr);
343 return;
344 }
345 tprintf("[");
346 tprintf(fmt, num);
347 tprintf("]");
348}
349
Roland McGrath6bc12202003-11-13 22:32:27 +0000350void
351printuid(text, uid)
352const char *text;
353unsigned long uid;
354{
355 tprintf("%s", text);
356 tprintf((uid == -1) ? "%ld" : "%lu", uid);
357}
358
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000359static char path[MAXPATHLEN + 1];
360
361void
362string_quote(str)
363char *str;
364{
365 char buf[2 * MAXPATHLEN + 1];
366 char *s;
367
368 if (!strpbrk(str, "\"\'\\")) {
369 tprintf("\"%s\"", str);
370 return;
371 }
372 for (s = buf; *str; str++) {
373 switch (*str) {
374 case '\"': case '\'': case '\\':
375 *s++ = '\\'; *s++ = *str; break;
376 default:
377 *s++ = *str; break;
378 }
379 }
380 *s = '\0';
381 tprintf("\"%s\"", buf);
382}
383
384void
385printpath(tcp, addr)
386struct tcb *tcp;
387long addr;
388{
Roland McGrath371ed8f2005-02-06 01:55:07 +0000389 if (addr == 0)
390 tprintf("NULL");
391 else if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000392 tprintf("%#lx", addr);
393 else
394 string_quote(path);
395 return;
396}
397
398void
399printpathn(tcp, addr, n)
400struct tcb *tcp;
401long addr;
402int n;
403{
Roland McGrath371ed8f2005-02-06 01:55:07 +0000404 if (addr == 0)
405 tprintf("NULL");
406 else if (umovestr(tcp, addr, n, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000407 tprintf("%#lx", addr);
408 else {
409 path[n] = '\0';
410 string_quote(path);
411 }
412}
413
414void
415printstr(tcp, addr, len)
416struct tcb *tcp;
417long addr;
418int len;
419{
420 static unsigned char *str = NULL;
421 static char *outstr;
422 int i, n, c, usehex;
423 char *s, *outend;
424
425 if (!addr) {
426 tprintf("NULL");
427 return;
428 }
429 if (!str) {
430 if ((str = malloc(max_strlen)) == NULL
431 || (outstr = malloc(2*max_strlen)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000432 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000433 tprintf("%#lx", addr);
434 return;
435 }
436 }
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000437 outend = outstr + max_strlen * 2 - 10;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000438 if (len < 0) {
439 n = max_strlen;
440 if (umovestr(tcp, addr, n, (char *) str) < 0) {
441 tprintf("%#lx", addr);
442 return;
443 }
444 }
445 else {
446 n = MIN(len, max_strlen);
447 if (umoven(tcp, addr, n, (char *) str) < 0) {
448 tprintf("%#lx", addr);
449 return;
450 }
451 }
452
453 usehex = 0;
454 if (xflag > 1)
455 usehex = 1;
456 else if (xflag) {
457 for (i = 0; i < n; i++) {
458 c = str[i];
459 if (len < 0 && c == '\0')
460 break;
461 if (!isprint(c) && !isspace(c)) {
462 usehex = 1;
463 break;
464 }
465 }
466 }
467
468 s = outstr;
469 *s++ = '\"';
470
471 if (usehex) {
472 for (i = 0; i < n; i++) {
473 c = str[i];
474 if (len < 0 && c == '\0')
475 break;
476 sprintf(s, "\\x%02x", c);
477 s += 4;
478 if (s > outend)
479 break;
480 }
481 }
482 else {
483 for (i = 0; i < n; i++) {
484 c = str[i];
485 if (len < 0 && c == '\0')
486 break;
487 switch (c) {
488 case '\"': case '\'': case '\\':
489 *s++ = '\\'; *s++ = c; break;
490 case '\f':
491 *s++ = '\\'; *s++ = 'f'; break;
492 case '\n':
493 *s++ = '\\'; *s++ = 'n'; break;
494 case '\r':
495 *s++ = '\\'; *s++ = 'r'; break;
496 case '\t':
497 *s++ = '\\'; *s++ = 't'; break;
498 case '\v':
499 *s++ = '\\'; *s++ = 'v'; break;
500 default:
501 if (isprint(c))
502 *s++ = c;
503 else if (i < n - 1 && isdigit(str[i + 1])) {
504 sprintf(s, "\\%03o", c);
505 s += 4;
506 }
507 else {
508 sprintf(s, "\\%o", c);
509 s += strlen(s);
510 }
511 break;
512 }
513 if (s > outend)
514 break;
515 }
516 }
517
518 *s++ = '\"';
519 if (i < len || (len < 0 && (i == n || s > outend))) {
520 *s++ = '.'; *s++ = '.'; *s++ = '.';
521 }
522 *s = '\0';
523 tprintf("%s", outstr);
524}
525
John Hughes1d08dcf2001-07-10 13:48:44 +0000526#if HAVE_SYS_UIO_H
527void
528dumpiov(tcp, len, addr)
529struct tcb * tcp;
530int len;
531long addr;
532{
533 struct iovec *iov;
534 int i;
Roland McGrathaa524c82005-06-01 19:22:06 +0000535 unsigned long size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000536
Roland McGrathaa524c82005-06-01 19:22:06 +0000537 size = sizeof(*iov) * (unsigned long) len;
538 if (size / sizeof(*iov) != len
539 || (iov = (struct iovec *) malloc(size)) == NULL) {
540 fprintf(stderr, "out of memory\n");
John Hughes1d08dcf2001-07-10 13:48:44 +0000541 return;
542 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000543 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000544 for (i = 0; i < len; i++) {
545 /* include the buffer number to make it easy to
546 * match up the trace with the source */
547 tprintf(" * %lu bytes in buffer %d\n",
548 (unsigned long)iov[i].iov_len, i);
549 dumpstr(tcp, (long) iov[i].iov_base,
550 iov[i].iov_len);
551 }
552 }
553 free((char *) iov);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000554
John Hughes1d08dcf2001-07-10 13:48:44 +0000555}
556#endif
557
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000558void
559dumpstr(tcp, addr, len)
560struct tcb *tcp;
561long addr;
562int len;
563{
564 static int strsize = -1;
565 static unsigned char *str;
566 static char outstr[80];
567 char *s;
568 int i, j;
569
570 if (strsize < len) {
571 if (str)
572 free(str);
573 if ((str = malloc(len)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000574 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000575 return;
576 }
577 strsize = len;
578 }
579
580 if (umoven(tcp, addr, len, (char *) str) < 0)
581 return;
582
583 for (i = 0; i < len; i += 16) {
584 s = outstr;
585 sprintf(s, " | %05x ", i);
586 s += 9;
587 for (j = 0; j < 16; j++) {
588 if (j == 8)
589 *s++ = ' ';
590 if (i + j < len) {
591 sprintf(s, " %02x", str[i + j]);
592 s += 3;
593 }
594 else {
595 *s++ = ' '; *s++ = ' '; *s++ = ' ';
596 }
597 }
598 *s++ = ' '; *s++ = ' ';
599 for (j = 0; j < 16; j++) {
600 if (j == 8)
601 *s++ = ' ';
602 if (i + j < len) {
603 if (isprint(str[i + j]))
604 *s++ = str[i + j];
605 else
606 *s++ = '.';
607 }
608 else
609 *s++ = ' ';
610 }
611 tprintf("%s |\n", outstr);
612 }
613}
614
615#define PAGMASK (~(PAGSIZ - 1))
616/*
617 * move `len' bytes of data from process `pid'
618 * at address `addr' to our space at `laddr'
619 */
620int
621umoven(tcp, addr, len, laddr)
622struct tcb *tcp;
623long addr;
624int len;
625char *laddr;
626{
627
628#ifdef LINUX
629 int pid = tcp->pid;
630 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000631 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000632 union {
633 long val;
634 char x[sizeof(long)];
635 } u;
636
637 if (addr & (sizeof(long) - 1)) {
638 /* addr not a multiple of sizeof(long) */
639 n = addr - (addr & -sizeof(long)); /* residue */
640 addr &= -sizeof(long); /* residue */
641 errno = 0;
642 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
643 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000644 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000645 /* Ran into 'end of memory' - stupid "printpath" */
646 return 0;
647 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000648 /* But if not started, we had a bogus address. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000649 perror("ptrace: umoven");
650 return -1;
651 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000652 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000653 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
654 addr += sizeof(long), laddr += m, len -= m;
655 }
656 while (len) {
657 errno = 0;
658 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
659 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000660 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000661 /* Ran into 'end of memory' - stupid "printpath" */
662 return 0;
663 }
Roland McGrath4db26242003-01-30 20:15:19 +0000664 if (addr != 0)
665 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000666 return -1;
667 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000668 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000669 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
670 addr += sizeof(long), laddr += m, len -= m;
671 }
672#endif /* LINUX */
673
674#ifdef SUNOS4
675 int pid = tcp->pid;
676#if 0
677 int n, m;
678 union {
679 long val;
680 char x[sizeof(long)];
681 } u;
682
683 if (addr & (sizeof(long) - 1)) {
684 /* addr not a multiple of sizeof(long) */
685 n = addr - (addr & -sizeof(long)); /* residue */
686 addr &= -sizeof(long); /* residue */
687 errno = 0;
688 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
689 if (errno) {
690 perror("umoven");
691 return -1;
692 }
693 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
694 addr += sizeof(long), laddr += m, len -= m;
695 }
696 while (len) {
697 errno = 0;
698 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
699 if (errno) {
700 perror("umoven");
701 return -1;
702 }
703 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
704 addr += sizeof(long), laddr += m, len -= m;
705 }
706#else /* !oldway */
707 int n;
708
709 while (len) {
710 n = MIN(len, PAGSIZ);
711 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
712 if (ptrace(PTRACE_READDATA, pid,
713 (char *) addr, len, laddr) < 0) {
714 perror("umoven: ptrace(PTRACE_READDATA, ...)");
715 abort();
716 return -1;
717 }
718 len -= n;
719 addr += n;
720 laddr += n;
721 }
722#endif /* !oldway */
723#endif /* SUNOS4 */
724
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000725#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000726#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000727 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000728#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000729 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000730#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000731 lseek(fd, addr, SEEK_SET);
732 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000733 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000734#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000735
736 return 0;
737}
738
739/*
740 * like `umove' but make the additional effort of looking
741 * for a terminating zero byte.
742 */
743int
744umovestr(tcp, addr, len, laddr)
745struct tcb *tcp;
746long addr;
747int len;
748char *laddr;
749{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000750#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000751#ifdef HAVE_MP_PROCFS
752 int fd = tcp->pfd_as;
753#else
754 int fd = tcp->pfd;
755#endif
756 /* Some systems (e.g. FreeBSD) can be upset if we read off the
757 end of valid memory, avoid this by trying to read up
758 to page boundaries. But we don't know what a page is (and
759 getpagesize(2) (if it exists) doesn't necessarily return
760 hardware page size). Assume all pages >= 1024 (a-historical
761 I know) */
762
763 int page = 1024; /* How to find this? */
764 int move = page - (addr & (page - 1));
765 int left = len;
766
767 lseek(fd, addr, SEEK_SET);
768
769 while (left) {
770 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000771 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000772 return left != len ? 0 : -1;
773 if (memchr (laddr, 0, move)) break;
774 left -= move;
775 laddr += move;
776 addr += move;
777 move = page;
778 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000779#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000780 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000781 int pid = tcp->pid;
782 int i, n, m;
783 union {
784 long val;
785 char x[sizeof(long)];
786 } u;
787
788 if (addr & (sizeof(long) - 1)) {
789 /* addr not a multiple of sizeof(long) */
790 n = addr - (addr & -sizeof(long)); /* residue */
791 addr &= -sizeof(long); /* residue */
792 errno = 0;
793 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
794 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000795 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000796 /* Ran into 'end of memory' - stupid "printpath" */
797 return 0;
798 }
799 perror("umovestr");
800 return -1;
801 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000802 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000803 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
804 while (n & (sizeof(long) - 1))
805 if (u.x[n++] == '\0')
806 return 0;
807 addr += sizeof(long), laddr += m, len -= m;
808 }
809 while (len) {
810 errno = 0;
811 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
812 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000813 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000814 /* Ran into 'end of memory' - stupid "printpath" */
815 return 0;
816 }
817 perror("umovestr");
818 return -1;
819 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000820 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000821 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
822 for (i = 0; i < sizeof(long); i++)
823 if (u.x[i] == '\0')
824 return 0;
825
826 addr += sizeof(long), laddr += m, len -= m;
827 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000828#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000829 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000830}
831
832#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000833#if !defined (SPARC) && !defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000834#define PTRACE_WRITETEXT 101
835#define PTRACE_WRITEDATA 102
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000836#endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000837#endif /* LINUX */
838
839#ifdef SUNOS4
840
841static int
842uload(cmd, pid, addr, len, laddr)
843int cmd;
844int pid;
845long addr;
846int len;
847char *laddr;
848{
849#if 0
850 int n;
851
852 while (len) {
853 n = MIN(len, PAGSIZ);
854 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
855 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
856 perror("uload: ptrace(PTRACE_WRITE, ...)");
857 return -1;
858 }
859 len -= n;
860 addr += n;
861 laddr += n;
862 }
863#else
864 int peek, poke;
865 int n, m;
866 union {
867 long val;
868 char x[sizeof(long)];
869 } u;
870
871 if (cmd == PTRACE_WRITETEXT) {
872 peek = PTRACE_PEEKTEXT;
873 poke = PTRACE_POKETEXT;
874 }
875 else {
876 peek = PTRACE_PEEKDATA;
877 poke = PTRACE_POKEDATA;
878 }
879 if (addr & (sizeof(long) - 1)) {
880 /* addr not a multiple of sizeof(long) */
881 n = addr - (addr & -sizeof(long)); /* residue */
882 addr &= -sizeof(long);
883 errno = 0;
884 u.val = ptrace(peek, pid, (char *) addr, 0);
885 if (errno) {
886 perror("uload: POKE");
887 return -1;
888 }
889 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
890 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
891 perror("uload: POKE");
892 return -1;
893 }
894 addr += sizeof(long), laddr += m, len -= m;
895 }
896 while (len) {
897 if (len < sizeof(long))
898 u.val = ptrace(peek, pid, (char *) addr, 0);
899 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
900 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
901 perror("uload: POKE");
902 return -1;
903 }
904 addr += sizeof(long), laddr += m, len -= m;
905 }
906#endif
907 return 0;
908}
909
910int
911tload(pid, addr, len, laddr)
912int pid;
913int addr, len;
914char *laddr;
915{
916 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
917}
918
919int
920dload(pid, addr, len, laddr)
921int pid;
922int addr;
923int len;
924char *laddr;
925{
926 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
927}
928
929#endif /* SUNOS4 */
930
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000931#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000932
933int
934upeek(pid, off, res)
935int pid;
936long off;
937long *res;
938{
939 long val;
940
941#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
942 {
943 static int is_sun4m = -1;
944 struct utsname name;
945
946 /* Round up the usual suspects. */
947 if (is_sun4m == -1) {
948 if (uname(&name) < 0) {
949 perror("upeek: uname?");
950 exit(1);
951 }
952 is_sun4m = strcmp(name.machine, "sun4m") == 0;
953 if (is_sun4m) {
Roland McGrathd9f816f2004-09-04 03:39:20 +0000954 extern const struct xlat struct_user_offsets[];
955 const struct xlat *x;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000956
957 for (x = struct_user_offsets; x->str; x++)
958 x->val += 1024;
959 }
960 }
961 if (is_sun4m)
962 off += 1024;
963 }
964#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
965 errno = 0;
966 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
967 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000968 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +0000969 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000970 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971 return -1;
972 }
973 *res = val;
974 return 0;
975}
976
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000977#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000978
979long
980getpc(tcp)
981struct tcb *tcp;
982{
983
984#ifdef LINUX
985 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000986#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000987 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
988 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +0000989#elif defined(X86_64)
990 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
991 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000992#elif defined(IA64)
993 if (upeek(tcp->pid, PT_B0, &pc) < 0)
994 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000995#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000996 if (upeek(tcp->pid, 4*15, &pc) < 0)
997 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000998#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +0000999 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001000 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001001#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001002 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1003 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001004#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001005 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1006 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001007#elif defined(MIPS)
1008 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1009 return -1;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001010#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001011 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001012 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
1013 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001014 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001015#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001016 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +00001017 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001018#elif defined(HPPA)
1019 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1020 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001021#elif defined(SH)
1022 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1023 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001024#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001025 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1026 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +00001027#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001028 return pc;
1029#endif /* LINUX */
1030
1031#ifdef SUNOS4
1032 /*
1033 * Return current program counter for `pid'
1034 * Assumes PC is never 0xffffffff
1035 */
1036 struct regs regs;
1037
1038 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1039 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1040 return -1;
1041 }
1042 return regs.r_pc;
1043#endif /* SUNOS4 */
1044
1045#ifdef SVR4
1046 /* XXX */
1047 return 0;
1048#endif /* SVR4 */
1049
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001050#ifdef FREEBSD
1051 struct reg regs;
1052 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1053 return regs.r_eip;
1054#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001055}
1056
1057void
1058printcall(tcp)
1059struct tcb *tcp;
1060{
Roland McGrath7a918832005-02-02 20:55:23 +00001061#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1062 sizeof(long) == 8 ? "[????????????????] " : \
1063 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001064
1065#ifdef LINUX
1066#ifdef I386
1067 long eip;
1068
1069 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001070 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001071 return;
1072 }
1073 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001074
1075#elif defined(S390) || defined(S390X)
1076 long psw;
1077 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001078 PRINTBADPC;
Roland McGratheac26fc2005-02-02 02:48:53 +00001079 return;
1080 }
1081#ifdef S390
1082 tprintf("[%08lx] ", psw);
1083#elif S390X
1084 tprintf("[%16lx] ", psw);
1085#endif
1086
Michal Ludvig0e035502002-09-23 15:41:01 +00001087#elif defined(X86_64)
1088 long rip;
1089
1090 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001091 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001092 return;
1093 }
1094 tprintf("[%16lx] ", rip);
Roland McGrathef388682003-06-03 23:28:59 +00001095#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001096 long ip;
1097
1098 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001099 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001100 return;
1101 }
1102 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001103#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001104 long pc;
1105
Roland McGratheb285352003-01-14 09:59:00 +00001106 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001107 tprintf ("[????????] ");
1108 return;
1109 }
1110 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001111#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001112 long pc;
1113
1114 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1115 tprintf ("[????????] ");
1116 return;
1117 }
1118 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001119#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001120 long pc;
1121
1122 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001123 tprintf ("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001124 return;
1125 }
1126 tprintf("[%08lx] ", pc);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001127#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001128 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001129 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001130 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001131 return;
1132 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001133 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001134#elif defined(HPPA)
1135 long pc;
1136
1137 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1138 tprintf ("[????????] ");
1139 return;
1140 }
1141 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001142#elif defined(MIPS)
1143 long pc;
1144
1145 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1146 tprintf ("[????????] ");
1147 return;
1148 }
1149 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001150#elif defined(SH)
1151 long pc;
1152
1153 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1154 tprintf ("[????????] ");
1155 return;
1156 }
1157 tprintf("[%08lx] ", pc);
Roland McGrathf5a47772003-06-26 22:40:42 +00001158#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001159 long pc;
1160
1161 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001162 tprintf ("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001163 return;
1164 }
1165 tprintf("[%08lx] ", pc);
Roland McGrathef388682003-06-03 23:28:59 +00001166#elif defined(ARM)
1167 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001168
Roland McGrathef388682003-06-03 23:28:59 +00001169 if (upeek(tcp->pid, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001170 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001171 return;
1172 }
1173 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001174#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175#endif /* LINUX */
1176
1177#ifdef SUNOS4
1178 struct regs regs;
1179
1180 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1181 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
Roland McGrath7a918832005-02-02 20:55:23 +00001182 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001183 return;
1184 }
1185 tprintf("[%08x] ", regs.r_o7);
1186#endif /* SUNOS4 */
1187
1188#ifdef SVR4
1189 /* XXX */
Roland McGrath7a918832005-02-02 20:55:23 +00001190 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001191#endif
1192
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001193#ifdef FREEBSD
1194 struct reg regs;
1195 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1196 tprintf("[%08x] ", regs.r_eip);
1197#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001198}
1199
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001200#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001201
Roland McGrathd81f1d92003-01-09 06:53:34 +00001202#if defined LINUX
1203
1204#include <sys/syscall.h>
1205#ifndef CLONE_PTRACE
1206# define CLONE_PTRACE 0x00002000
1207#endif
1208
1209#ifdef IA64
1210
Roland McGrath08267b82004-02-20 22:56:43 +00001211/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1212 subsystem has them for x86... */
1213#define SYS_fork 2
1214#define SYS_vfork 190
1215
Roland McGrathd81f1d92003-01-09 06:53:34 +00001216typedef unsigned long *arg_setup_state;
1217
1218static int
1219arg_setup(struct tcb *tcp, arg_setup_state *state)
1220{
1221 unsigned long *bsp, cfm, sof, sol;
1222
Roland McGrath08267b82004-02-20 22:56:43 +00001223 if (ia32)
1224 return 0;
1225
Roland McGrathd81f1d92003-01-09 06:53:34 +00001226 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1227 return -1;
1228 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1229 return -1;
1230
1231 sof = (cfm >> 0) & 0x7f;
1232 sol = (cfm >> 7) & 0x7f;
1233 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1234
1235 *state = bsp;
1236 return 0;
1237}
1238
1239# define arg_finish_change(tcp, state) 0
1240
1241#ifdef SYS_fork
1242static int
1243get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1244{
Roland McGrath08267b82004-02-20 22:56:43 +00001245 int ret;
1246
1247 if (ia32)
1248 ret = upeek (tcp->pid, PT_R11, valp);
1249 else
1250 ret = umoven (tcp,
1251 (unsigned long) ia64_rse_skip_regs(*state, 0),
1252 sizeof(long), (void *) valp);
1253 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001254}
1255
1256static int
1257get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1258{
Roland McGrath08267b82004-02-20 22:56:43 +00001259 int ret;
1260
1261 if (ia32)
1262 ret = upeek (tcp->pid, PT_R9, valp);
1263 else
1264 ret = umoven (tcp,
1265 (unsigned long) ia64_rse_skip_regs(*state, 1),
1266 sizeof(long), (void *) valp);
1267 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001268}
1269#endif
1270
1271static int
1272set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1273{
Roland McGrath08267b82004-02-20 22:56:43 +00001274 int req = PTRACE_POKEDATA;
1275 void *ap;
1276
1277 if (ia32) {
1278 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1279 req = PTRACE_POKEUSER;
1280 } else
1281 ap = ia64_rse_skip_regs(*state, 0);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001282 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001283 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001284 return errno ? -1 : 0;
1285}
1286
1287static int
1288set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1289{
Roland McGrath08267b82004-02-20 22:56:43 +00001290 int req = PTRACE_POKEDATA;
1291 void *ap;
1292
1293 if (ia32) {
1294 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1295 req = PTRACE_POKEUSER;
1296 } else
1297 ap = ia64_rse_skip_regs(*state, 1);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001298 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001299 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001300 return errno ? -1 : 0;
1301}
1302
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001303#elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001304
1305typedef struct regs arg_setup_state;
1306
1307# define arg_setup(tcp, state) \
1308 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1309# define arg_finish_change(tcp, state) \
1310 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1311
1312# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1313# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1314# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1315# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001316# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001317
1318#else
1319
1320# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001321/* Note: this is only true for the `clone' system call, which handles
1322 arguments specially. We could as well say that its first two arguments
1323 are swapped relative to other architectures, but that would just be
1324 another #ifdef in the calls. */
1325# define arg0_offset PT_GPR3
1326# define arg1_offset PT_ORIGGPR2
1327# define restore_arg0(tcp, state, val) ((void) (state), 0)
1328# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001329# define arg0_index 1
1330# define arg1_index 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001331# elif defined (ALPHA) || defined (MIPS)
1332# define arg0_offset REG_A0
1333# define arg1_offset (REG_A0+1)
1334# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001335# define arg0_offset (sizeof(unsigned long)*PT_R3)
1336# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001337# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001338# elif defined (HPPA)
1339# define arg0_offset PT_GR26
1340# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001341# elif defined (X86_64)
1342# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1343# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001344# elif defined (SH)
1345# define arg0_offset (4*(REG_REG0+4))
1346# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001347# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001348 /* ABI defines arg0 & 1 in r2 & r3 */
1349# define arg0_offset (REG_OFFSET+16)
1350# define arg1_offset (REG_OFFSET+24)
1351# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001352# else
1353# define arg0_offset 0
1354# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001355# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001356# define restore_arg0(tcp, state, val) 0
1357# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001358# endif
1359
1360typedef int arg_setup_state;
1361
1362# define arg_setup(tcp, state) (0)
1363# define arg_finish_change(tcp, state) 0
1364# define get_arg0(tcp, cookie, valp) \
1365 (upeek ((tcp)->pid, arg0_offset, (valp)))
1366# define get_arg1(tcp, cookie, valp) \
1367 (upeek ((tcp)->pid, arg1_offset, (valp)))
1368
1369static int
1370set_arg0 (struct tcb *tcp, void *cookie, long val)
1371{
1372 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1373}
1374
1375static int
1376set_arg1 (struct tcb *tcp, void *cookie, long val)
1377{
1378 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1379}
1380
1381#endif
1382
Roland McGrathe1df47f2003-01-14 09:46:15 +00001383#ifndef restore_arg0
1384# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1385#endif
1386#ifndef restore_arg1
1387# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1388#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001389
Roland McGrath90d0afd2004-03-01 21:05:16 +00001390#ifndef arg0_index
1391# define arg0_index 0
1392# define arg1_index 1
1393#endif
1394
Roland McGrathd81f1d92003-01-09 06:53:34 +00001395int
1396setbpt(tcp)
1397struct tcb *tcp;
1398{
1399 extern int change_syscall(struct tcb *, int);
1400 arg_setup_state state;
1401
1402 if (tcp->flags & TCB_BPTSET) {
1403 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1404 return -1;
1405 }
1406
1407 switch (tcp->scno) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001408#ifdef SYS_vfork
1409 case SYS_vfork:
1410#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001411#ifdef SYS_fork
1412 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001413#endif
1414#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001415 if (arg_setup (tcp, &state) < 0
1416 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1417 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1418 || change_syscall(tcp, SYS_clone) < 0
1419 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1420 || set_arg1 (tcp, &state, 0) < 0
1421 || arg_finish_change (tcp, &state) < 0)
1422 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001423 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1424 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001425 tcp->flags |= TCB_BPTSET;
1426 return 0;
1427#endif
1428
1429 case SYS_clone:
1430#ifdef SYS_clone2
1431 case SYS_clone2:
1432#endif
Roland McGrath02cee8d2004-03-02 08:50:42 +00001433 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001434 && (arg_setup (tcp, &state) < 0
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001435 || set_arg0 (tcp, &state,
1436 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001437 || arg_finish_change (tcp, &state) < 0))
1438 return -1;
1439 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001440 tcp->inst[0] = tcp->u_arg[arg0_index];
1441 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001442 return 0;
1443
1444 default:
1445 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1446 tcp->scno, tcp->pid);
1447 break;
1448 }
1449
1450 return -1;
1451}
1452
1453int
1454clearbpt(tcp)
1455struct tcb *tcp;
1456{
1457 arg_setup_state state;
1458 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001459 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1460 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001461 || arg_finish_change (tcp, &state))
1462 return -1;
1463 tcp->flags &= ~TCB_BPTSET;
1464 return 0;
1465}
1466
1467#else
1468
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001469int
1470setbpt(tcp)
1471struct tcb *tcp;
1472{
1473
1474#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001475#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001476 /* We simply use the SunOS breakpoint code. */
1477
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001478 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001479 unsigned long inst;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001480#define LOOPA 0x30800000 /* ba,a 0 */
1481
1482 if (tcp->flags & TCB_BPTSET) {
1483 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1484 return -1;
1485 }
1486 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1487 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1488 return -1;
1489 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001490 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001491 errno = 0;
1492 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1493 if(errno) {
1494 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1495 return -1;
1496 }
1497
1498 /*
1499 * XXX - BRUTAL MODE ON
1500 * We cannot set a real BPT in the child, since it will not be
1501 * traced at the moment it will reach the trap and would probably
1502 * die with a core dump.
1503 * Thus, we are force our way in by taking out two instructions
1504 * and insert an eternal loop instead, in expectance of the SIGSTOP
1505 * generated by out PTRACE_ATTACH.
1506 * Of cause, if we evaporate ourselves in the middle of all this...
1507 */
1508 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001509 inst = LOOPA;
1510#if defined (SPARC64)
1511 inst <<= 32;
1512 inst |= (tcp->inst[0] & 0xffffffffUL);
1513#endif
1514 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001515 if(errno) {
1516 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1517 return -1;
1518 }
1519 tcp->flags |= TCB_BPTSET;
1520
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001521#else /* !SPARC && !SPARC64 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001522#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001523 if (ia32) {
1524# define LOOP 0x0000feeb
1525 if (tcp->flags & TCB_BPTSET) {
1526 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1527 tcp->pid);
1528 return -1;
1529 }
1530 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1531 return -1;
1532 if (debug)
1533 fprintf(stderr, "[%d] setting bpt at %lx\n",
1534 tcp->pid, tcp->baddr);
1535 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1536 (char *) tcp->baddr, 0);
1537 if (errno) {
1538 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1539 return -1;
1540 }
1541 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1542 if (errno) {
1543 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1544 return -1;
1545 }
1546 tcp->flags |= TCB_BPTSET;
1547 } else {
1548 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001549 * Our strategy here is to replace the bundle that
1550 * contained the clone() syscall with a bundle of the
1551 * form:
1552 *
1553 * { 1: br 1b; br 1b; br 1b }
1554 *
1555 * This ensures that the newly forked child will loop
1556 * endlessly until we've got a chance to attach to it.
1557 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001558# define LOOP0 0x0000100000000017
1559# define LOOP1 0x4000000000200000
1560 unsigned long addr, ipsr;
1561 pid_t pid;
1562
1563 pid = tcp->pid;
1564 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1565 return -1;
1566 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1567 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001568 /* store "ri" in low two bits */
1569 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001570
1571 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001572 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1573 0);
1574 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1575 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001576 if (errno) {
1577 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1578 return -1;
1579 }
1580
1581 errno = 0;
1582 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1583 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1584 if (errno) {
1585 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1586 return -1;
1587 }
1588 tcp->flags |= TCB_BPTSET;
1589 }
1590#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001591
Michal Ludvig0e035502002-09-23 15:41:01 +00001592#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001593#define LOOP 0x0000feeb
1594#elif defined (M68K)
1595#define LOOP 0x60fe0000
1596#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001597#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001598#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001599#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001600#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001601#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001602#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001603#define LOOP 0x1000ffff
1604#elif defined(S390)
1605#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001606#elif defined(S390X)
1607#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001608#elif defined(HPPA)
1609#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001610#elif defined(SH)
1611#ifdef __LITTLE_ENDIAN__
1612#define LOOP 0x0000affe
1613#else
1614#define LOOP 0xfeaf0000
1615#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001616#else
1617#error unknown architecture
1618#endif
1619
1620 if (tcp->flags & TCB_BPTSET) {
1621 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1622 return -1;
1623 }
1624#if defined (I386)
1625 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1626 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001627#elif defined (X86_64)
1628 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1629 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001630#elif defined (M68K)
1631 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1632 return -1;
1633#elif defined (ALPHA)
1634 return -1;
1635#elif defined (ARM)
1636 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001637#elif defined (MIPS)
1638 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001639#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001640 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001641 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001642#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001643 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1644 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001645#elif defined(HPPA)
1646 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1647 return -1;
1648 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001649#elif defined(SH)
1650 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1651 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001652#else
1653#error unknown architecture
1654#endif
1655 if (debug)
1656 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1657 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1658 if (errno) {
1659 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1660 return -1;
1661 }
1662 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1663 if (errno) {
1664 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1665 return -1;
1666 }
1667 tcp->flags |= TCB_BPTSET;
1668
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001669#endif /* !IA64 */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001670#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001671#endif /* LINUX */
1672
1673#ifdef SUNOS4
1674#ifdef SPARC /* This code is slightly sparc specific */
1675
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001676 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677#define BPT 0x91d02001 /* ta 1 */
1678#define LOOP 0x10800000 /* ba 0 */
1679#define LOOPA 0x30800000 /* ba,a 0 */
1680#define NOP 0x01000000
1681#if LOOPA
1682 static int loopdeloop[1] = {LOOPA};
1683#else
1684 static int loopdeloop[2] = {LOOP, NOP};
1685#endif
1686
1687 if (tcp->flags & TCB_BPTSET) {
1688 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1689 return -1;
1690 }
1691 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1692 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1693 return -1;
1694 }
1695 tcp->baddr = regs.r_o7 + 8;
1696 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1697 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1698 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1699 return -1;
1700 }
1701
1702 /*
1703 * XXX - BRUTAL MODE ON
1704 * We cannot set a real BPT in the child, since it will not be
1705 * traced at the moment it will reach the trap and would probably
1706 * die with a core dump.
1707 * Thus, we are force our way in by taking out two instructions
1708 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1709 * generated by out PTRACE_ATTACH.
1710 * Of cause, if we evaporate ourselves in the middle of all this...
1711 */
1712 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1713 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1714 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1715 return -1;
1716 }
1717 tcp->flags |= TCB_BPTSET;
1718
1719#endif /* SPARC */
1720#endif /* SUNOS4 */
1721
1722 return 0;
1723}
1724
1725int
1726clearbpt(tcp)
1727struct tcb *tcp;
1728{
1729
1730#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001731#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001732 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001733#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001734 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001735#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001736 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001737#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001738 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001739#elif defined(HPPA)
1740 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001741#elif defined(SH)
1742 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001743#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001744
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001745#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746 /* Again, we borrow the SunOS breakpoint code. */
1747 if (!(tcp->flags & TCB_BPTSET)) {
1748 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1749 return -1;
1750 }
1751 errno = 0;
1752 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1753 if(errno) {
1754 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1755 return -1;
1756 }
1757 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001758#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001759 if (ia32) {
1760 unsigned long addr;
1761
1762 if (debug)
1763 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1764 if (!(tcp->flags & TCB_BPTSET)) {
1765 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1766 return -1;
1767 }
1768 errno = 0;
1769 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1770 if (errno) {
1771 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1772 return -1;
1773 }
1774 tcp->flags &= ~TCB_BPTSET;
1775
1776 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1777 return -1;
1778 if (addr != tcp->baddr) {
1779 /* The breakpoint has not been reached yet. */
1780 if (debug)
1781 fprintf(stderr,
1782 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1783 addr, tcp->baddr);
1784 return 0;
1785 }
1786 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001787 unsigned long addr, ipsr;
1788 pid_t pid;
1789
1790 pid = tcp->pid;
1791
1792 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1793 return -1;
1794 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1795 return -1;
1796
1797 /* restore original bundle: */
1798 errno = 0;
1799 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1800 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1801 if (errno) {
1802 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1803 return -1;
1804 }
1805
1806 /* restore original "ri" in ipsr: */
1807 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1808 errno = 0;
1809 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1810 if (errno) {
1811 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1812 return -1;
1813 }
1814
1815 tcp->flags &= ~TCB_BPTSET;
1816
1817 if (addr != (tcp->baddr & ~0x3)) {
1818 /* the breakpoint has not been reached yet. */
1819 if (debug)
1820 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1821 addr, tcp->baddr);
1822 return 0;
1823 }
1824 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001825#else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001826
1827 if (debug)
1828 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1829 if (!(tcp->flags & TCB_BPTSET)) {
1830 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1831 return -1;
1832 }
1833 errno = 0;
1834 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1835 if (errno) {
1836 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1837 return -1;
1838 }
1839 tcp->flags &= ~TCB_BPTSET;
1840
1841#ifdef I386
1842 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1843 return -1;
1844 if (eip != tcp->baddr) {
1845 /* The breakpoint has not been reached yet. */
1846 if (debug)
1847 fprintf(stderr,
1848 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1849 eip, tcp->baddr);
1850 return 0;
1851 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001852#elif defined(X86_64)
1853 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1854 return -1;
1855 if (eip != tcp->baddr) {
1856 /* The breakpoint has not been reached yet. */
1857 if (debug)
1858 fprintf(stderr,
1859 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1860 eip, tcp->baddr);
1861 return 0;
1862 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001863#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001864 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001865 return -1;
1866 if (pc != tcp->baddr) {
1867 /* The breakpoint has not been reached yet. */
1868 if (debug)
1869 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1870 pc, tcp->baddr);
1871 return 0;
1872 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001873#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001874 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1875 return -1;
1876 if (pc != tcp->baddr) {
1877 /* The breakpoint has not been reached yet. */
1878 if (debug)
1879 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1880 pc, tcp->baddr);
1881 return 0;
1882 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001883#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001884 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1885 return -1;
1886 if (pc != tcp->baddr) {
1887 /* The breakpoint has not been reached yet. */
1888 if (debug)
1889 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1890 pc, tcp->baddr);
1891 return 0;
1892 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001893#elif defined(HPPA)
1894 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1895 return -1;
1896 iaoq &= ~0x03;
1897 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1898 /* The breakpoint has not been reached yet. */
1899 if (debug)
1900 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1901 iaoq, tcp->baddr);
1902 return 0;
1903 }
1904 iaoq = tcp->baddr | 3;
1905 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1906 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1907 * has no significant effect.
1908 */
1909 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1910 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001911#elif defined(SH)
1912 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1913 return -1;
1914 if (pc != tcp->baddr) {
1915 /* The breakpoint has not been reached yet. */
1916 if (debug)
1917 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1918 pc, tcp->baddr);
1919 return 0;
1920 }
1921
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001922#endif /* arch */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001923#endif /* !SPARC && !SPARC64 && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001924#endif /* LINUX */
1925
1926#ifdef SUNOS4
1927#ifdef SPARC
1928
1929#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001930 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001931#endif
1932
1933 if (!(tcp->flags & TCB_BPTSET)) {
1934 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1935 return -1;
1936 }
1937 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1938 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1939 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1940 return -1;
1941 }
1942 tcp->flags &= ~TCB_BPTSET;
1943
1944#if !LOOPA
1945 /*
1946 * Since we don't have a single instruction breakpoint, we may have
1947 * to adjust the program counter after removing the our `breakpoint'.
1948 */
1949 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1950 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1951 return -1;
1952 }
1953 if ((regs.r_pc < tcp->baddr) ||
1954 (regs.r_pc > tcp->baddr + 4)) {
1955 /* The breakpoint has not been reached yet */
1956 if (debug)
1957 fprintf(stderr,
1958 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1959 regs.r_pc, tcp->parent->baddr);
1960 return 0;
1961 }
1962 if (regs.r_pc != tcp->baddr)
1963 if (debug)
1964 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1965 regs.r_pc, tcp->baddr);
1966
1967 regs.r_pc = tcp->baddr;
1968 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1969 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1970 return -1;
1971 }
1972#endif /* LOOPA */
1973#endif /* SPARC */
1974#endif /* SUNOS4 */
1975
1976 return 0;
1977}
1978
Roland McGrathd81f1d92003-01-09 06:53:34 +00001979#endif
1980
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001981#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001982
1983#ifdef SUNOS4
1984
1985static int
1986getex(pid, hdr)
1987int pid;
1988struct exec *hdr;
1989{
1990 int n;
1991
1992 for (n = 0; n < sizeof *hdr; n += 4) {
1993 long res;
1994 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1995 return -1;
1996 memcpy(((char *) hdr) + n, &res, 4);
1997 }
1998 if (debug) {
1999 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2000 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2001 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2002 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2003 }
2004 return 0;
2005}
2006
2007int
2008fixvfork(tcp)
2009struct tcb *tcp;
2010{
2011 int pid = tcp->pid;
2012 /*
2013 * Change `vfork' in a freshly exec'ed dynamically linked
2014 * executable's (internal) symbol table to plain old `fork'
2015 */
2016
2017 struct exec hdr;
2018 struct link_dynamic dyn;
2019 struct link_dynamic_2 ld;
2020 char *strtab, *cp;
2021
2022 if (getex(pid, &hdr) < 0)
2023 return -1;
2024 if (!hdr.a_dynamic)
2025 return -1;
2026
2027 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2028 fprintf(stderr, "Cannot read DYNAMIC\n");
2029 return -1;
2030 }
2031 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2032 fprintf(stderr, "Cannot read link_dynamic_2\n");
2033 return -1;
2034 }
2035 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00002036 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002037 return -1;
2038 }
2039 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2040 (int)ld.ld_symb_size, strtab) < 0)
2041 goto err;
2042
2043#if 0
2044 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2045 fprintf(stderr, "[symbol: %s]\n", cp);
2046 cp += strlen(cp)+1;
2047 }
2048 return 0;
2049#endif
2050 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2051 if (strcmp(cp, "_vfork") == 0) {
2052 if (debug)
2053 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2054 strcpy(cp, "_fork");
2055 break;
2056 }
2057 cp += strlen(cp)+1;
2058 }
2059 if (cp < strtab + ld.ld_symb_size)
2060 /*
2061 * Write entire symbol table back to avoid
2062 * memory alignment bugs in ptrace
2063 */
2064 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2065 (int)ld.ld_symb_size, strtab) < 0)
2066 goto err;
2067
2068 free(strtab);
2069 return 0;
2070
2071err:
2072 free(strtab);
2073 return -1;
2074}
2075
2076#endif /* SUNOS4 */