]> granicus.if.org Git - strace/blob - util.c
2003-06-03 Roland McGrath <roland@redhat.com>
[strace] / util.c
1 /*
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>
5  * 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>
9  * 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
38 #include <signal.h>
39 #include <sys/syscall.h>
40 #include <sys/user.h>
41 #include <sys/param.h>
42 #include <fcntl.h>
43 #if HAVE_SYS_UIO_H
44 #include <sys/uio.h>
45 #endif
46 #ifdef SUNOS4
47 #include <machine/reg.h>
48 #include <a.out.h>
49 #include <link.h>
50 #endif /* SUNOS4 */
51
52 #if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
53 #include <linux/ptrace.h>
54 #endif
55
56 #if defined(LINUX) && defined(IA64)
57 # include <asm/ptrace_offsets.h>
58 # include <asm/rse.h>
59 #endif
60
61 #ifdef HAVE_SYS_REG_H
62 #include <sys/reg.h>
63 # define PTRACE_PEEKUSR PTRACE_PEEKUSER
64 #elif defined(HAVE_LINUX_PTRACE_H)
65 #undef PTRACE_SYSCALL
66 #include <linux/ptrace.h>
67 #endif
68
69 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
70 #include <sys/utsname.h>
71 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
72
73 #if defined(LINUX) && defined(SPARC)
74
75 # define fpq kernel_fpq
76 # define fq kernel_fq
77 # define fpu kernel_fpu
78 # include <asm/reg.h>
79 # undef fpq
80 # undef fq
81 # undef fpu
82
83 #if !defined(__GLIBC__)
84
85 #include <linux/unistd.h>
86
87 #define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
88           type5,arg5,syscall) \
89 type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
90 { \
91       long __res; \
92 \
93 __asm__ volatile ("or %%g0, %1, %%o0\n\t" \
94                   "or %%g0, %2, %%o1\n\t" \
95                   "or %%g0, %3, %%o2\n\t" \
96                   "or %%g0, %4, %%o3\n\t" \
97                   "or %%g0, %5, %%o4\n\t" \
98                   "or %%g0, %6, %%g1\n\t" \
99                   "t 0x10\n\t" \
100                   "bcc 1f\n\t" \
101                   "or %%g0, %%o0, %0\n\t" \
102                   "sub %%g0, %%o0, %0\n\t" \
103                   "1:\n\t" \
104                   : "=r" (__res) \
105                   : "0" ((long)(arg1)),"1" ((long)(arg2)), \
106                     "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
107                     "i" (__NR_##syscall)  \
108                   : "g1", "o0", "o1", "o2", "o3", "o4"); \
109 if (__res>=0) \
110         return (type) __res; \
111 errno = -__res; \
112 return -1; \
113 }
114
115 static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
116
117 #define _ptrace
118
119 #endif
120
121 #endif
122
123 /* macros */
124 #ifndef MAX
125 #define MAX(a,b)                (((a) > (b)) ? (a) : (b))
126 #endif
127 #ifndef MIN
128 #define MIN(a,b)                (((a) < (b)) ? (a) : (b))
129 #endif
130
131 void
132 tv_tv(tv, a, b)
133 struct timeval *tv;
134 int a;
135 int b;
136 {
137         tv->tv_sec = a;
138         tv->tv_usec = b;
139 }
140
141 int
142 tv_nz(a)
143 struct timeval *a;
144 {
145         return a->tv_sec || a->tv_usec;
146 }
147
148 int
149 tv_cmp(a, b)
150 struct timeval *a, *b;
151 {
152         if (a->tv_sec < b->tv_sec
153             || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
154                 return -1;
155         if (a->tv_sec > b->tv_sec
156             || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
157                 return 1;
158         return 0;
159 }
160
161 double
162 tv_float(tv)
163 struct timeval *tv;
164 {
165         return tv->tv_sec + tv->tv_usec/1000000.0;
166 }
167
168 void
169 tv_add(tv, a, b)
170 struct timeval *tv, *a, *b;
171 {
172         tv->tv_sec = a->tv_sec + b->tv_sec;
173         tv->tv_usec = a->tv_usec + b->tv_usec;
174         if (tv->tv_usec > 1000000) {
175                 tv->tv_sec++;
176                 tv->tv_usec -= 1000000;
177         }
178 }
179
180 void
181 tv_sub(tv, a, b)
182 struct timeval *tv, *a, *b;
183 {
184         tv->tv_sec = a->tv_sec - b->tv_sec;
185         tv->tv_usec = a->tv_usec - b->tv_usec;
186         if (((long) tv->tv_usec) < 0) {
187                 tv->tv_sec--;
188                 tv->tv_usec += 1000000;
189         }
190 }
191
192 void
193 tv_div(tv, a, n)
194 struct timeval *tv, *a;
195 int n;
196 {
197         tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
198         tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
199         tv->tv_usec %= 1000000;
200 }
201
202 void
203 tv_mul(tv, a, n)
204 struct timeval *tv, *a;
205 int n;
206 {
207         tv->tv_usec = a->tv_usec * n;
208         tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
209         tv->tv_usec %= 1000000;
210 }
211
212 char *
213 xlookup(xlat, val)
214 struct xlat *xlat;
215 int val;
216 {
217         for (; xlat->str != NULL; xlat++)
218                 if (xlat->val == val)
219                         return xlat->str;
220         return NULL;
221 }
222
223 /*
224  * Print entry in struct xlat table, if there.
225  */
226 void
227 printxval(xlat, val, dflt)
228 struct xlat *xlat;
229 int val;
230 char *dflt;
231 {
232         char *str = xlookup(xlat, val);
233
234         if (str)
235                 tprintf("%s", str);
236         else
237                 tprintf("%#x /* %s */", val, dflt);
238 }
239
240 /*
241  * Interpret `xlat' as an array of flags
242  * print the entries whose bits are on in `flags'
243  * return # of flags printed.
244  */
245 int
246 addflags(xlat, flags)
247 struct xlat *xlat;
248 int flags;
249 {
250         int n;
251
252         for (n = 0; xlat->str; xlat++) {
253                 if (xlat->val && (flags & xlat->val) == xlat->val) {
254                         tprintf("|%s", xlat->str);
255                         flags &= ~xlat->val;
256                         n++;
257                 }
258         }
259         if (flags) {
260                 tprintf("|%#x", flags);
261                 n++;
262         }
263         return n;
264 }
265
266 int
267 printflags(xlat, flags)
268 struct xlat *xlat;
269 int flags;
270 {
271         int n;
272         char *sep;
273
274         if (flags == 0 && xlat->val == 0) {
275                 tprintf("%s", xlat->str);
276                 return 1;
277         }
278
279         sep = "";
280         for (n = 0; xlat->str; xlat++) {
281                 if (xlat->val && (flags & xlat->val) == xlat->val) {
282                         tprintf("%s%s", sep, xlat->str);
283                         flags &= ~xlat->val;
284                         sep = "|";
285                         n++;
286                 }
287         }
288         if (flags) {
289                 tprintf("%s%#x", sep, flags);
290                 n++;
291         }
292         return n;
293 }
294
295 void
296 printnum(tcp, addr, fmt)
297 struct tcb *tcp;
298 long addr;
299 char *fmt;
300 {
301         long num;
302
303         if (!addr) {
304                 tprintf("NULL");
305                 return;
306         }
307         if (umove(tcp, addr, &num) < 0) {
308                 tprintf("%#lx", addr);
309                 return;
310         }
311         tprintf("[");
312         tprintf(fmt, num);
313         tprintf("]");
314 }
315
316 static char path[MAXPATHLEN + 1];
317
318 void
319 string_quote(str)
320 char *str;
321 {
322         char buf[2 * MAXPATHLEN + 1];
323         char *s;
324
325         if (!strpbrk(str, "\"\'\\")) {
326                 tprintf("\"%s\"", str);
327                 return;
328         }
329         for (s = buf; *str; str++) {
330                 switch (*str) {
331                 case '\"': case '\'': case '\\':
332                         *s++ = '\\'; *s++ = *str; break;
333                 default:
334                         *s++ = *str; break;
335                 }
336         }
337         *s = '\0';
338         tprintf("\"%s\"", buf);
339 }
340
341 void
342 printpath(tcp, addr)
343 struct tcb *tcp;
344 long addr;
345 {
346         if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
347                 tprintf("%#lx", addr);
348         else
349                 string_quote(path);
350         return;
351 }
352
353 void
354 printpathn(tcp, addr, n)
355 struct tcb *tcp;
356 long addr;
357 int n;
358 {
359         if (umovestr(tcp, addr, n, path) < 0)
360                 tprintf("%#lx", addr);
361         else {
362                 path[n] = '\0';
363                 string_quote(path);
364         }
365 }
366
367 void
368 printstr(tcp, addr, len)
369 struct tcb *tcp;
370 long addr;
371 int len;
372 {
373         static unsigned char *str = NULL;
374         static char *outstr;
375         int i, n, c, usehex;
376         char *s, *outend;
377
378         if (!addr) {
379                 tprintf("NULL");
380                 return;
381         }
382         if (!str) {
383                 if ((str = malloc(max_strlen)) == NULL
384                     || (outstr = malloc(2*max_strlen)) == NULL) {
385                         fprintf(stderr, "printstr: no memory\n");
386                         tprintf("%#lx", addr);
387                         return;
388                 }
389         }
390         outend = outstr + max_strlen * 2 - 10;
391         if (len < 0) {
392                 n = max_strlen;
393                 if (umovestr(tcp, addr, n, (char *) str) < 0) {
394                         tprintf("%#lx", addr);
395                         return;
396                 }
397         }
398         else {
399                 n = MIN(len, max_strlen);
400                 if (umoven(tcp, addr, n, (char *) str) < 0) {
401                         tprintf("%#lx", addr);
402                         return;
403                 }
404         }
405
406         usehex = 0;
407         if (xflag > 1)
408                 usehex = 1;
409         else if (xflag) {
410                 for (i = 0; i < n; i++) {
411                         c = str[i];
412                         if (len < 0 && c == '\0')
413                                 break;
414                         if (!isprint(c) && !isspace(c)) {
415                                 usehex = 1;
416                                 break;
417                         }
418                 }
419         }
420
421         s = outstr;
422         *s++ = '\"';
423
424         if (usehex) {
425                 for (i = 0; i < n; i++) {
426                         c = str[i];
427                         if (len < 0 && c == '\0')
428                                 break;
429                         sprintf(s, "\\x%02x", c);
430                         s += 4;
431                         if (s > outend)
432                                 break;
433                 }
434         }
435         else {
436                 for (i = 0; i < n; i++) {
437                         c = str[i];
438                         if (len < 0 && c == '\0')
439                                 break;
440                         switch (c) {
441                         case '\"': case '\'': case '\\':
442                                 *s++ = '\\'; *s++ = c; break;
443                         case '\f':
444                                 *s++ = '\\'; *s++ = 'f'; break;
445                         case '\n':
446                                 *s++ = '\\'; *s++ = 'n'; break;
447                         case '\r':
448                                 *s++ = '\\'; *s++ = 'r'; break;
449                         case '\t':
450                                 *s++ = '\\'; *s++ = 't'; break;
451                         case '\v':
452                                 *s++ = '\\'; *s++ = 'v'; break;
453                         default:
454                                 if (isprint(c))
455                                         *s++ = c;
456                                 else if (i < n - 1 && isdigit(str[i + 1])) {
457                                         sprintf(s, "\\%03o", c);
458                                         s += 4;
459                                 }
460                                 else {
461                                         sprintf(s, "\\%o", c);
462                                         s += strlen(s);
463                                 }
464                                 break;
465                         }
466                         if (s > outend)
467                                 break;
468                 }
469         }
470
471         *s++ = '\"';
472         if (i < len || (len < 0 && (i == n || s > outend))) {
473                 *s++ = '.'; *s++ = '.'; *s++ = '.';
474         }
475         *s = '\0';
476         tprintf("%s", outstr);
477 }
478
479 #if HAVE_SYS_UIO_H
480 void
481 dumpiov(tcp, len, addr)
482 struct tcb * tcp;
483 int len;
484 long addr;
485 {
486         struct iovec *iov;
487         int i;
488
489
490         if ((iov = (struct iovec *) malloc(len * sizeof *iov)) == NULL) {
491                 fprintf(stderr, "dump: No memory");
492                 return;
493         }
494         if (umoven(tcp, addr,
495                    len * sizeof *iov, (char *) iov) >= 0) {
496
497                 for (i = 0; i < len; i++) {
498                         /* include the buffer number to make it easy to
499                          * match up the trace with the source */
500                         tprintf(" * %lu bytes in buffer %d\n",
501                                 (unsigned long)iov[i].iov_len, i);
502                         dumpstr(tcp, (long) iov[i].iov_base,
503                                 iov[i].iov_len);
504                 }
505         }
506         free((char *) iov);
507
508 }
509 #endif
510
511 void
512 dumpstr(tcp, addr, len)
513 struct tcb *tcp;
514 long addr;
515 int len;
516 {
517         static int strsize = -1;
518         static unsigned char *str;
519         static char outstr[80];
520         char *s;
521         int i, j;
522
523         if (strsize < len) {
524                 if (str)
525                         free(str);
526                 if ((str = malloc(len)) == NULL) {
527                         fprintf(stderr, "dump: no memory\n");
528                         return;
529                 }
530                 strsize = len;
531         }
532
533         if (umoven(tcp, addr, len, (char *) str) < 0)
534                 return;
535
536         for (i = 0; i < len; i += 16) {
537                 s = outstr;
538                 sprintf(s, " | %05x ", i);
539                 s += 9;
540                 for (j = 0; j < 16; j++) {
541                         if (j == 8)
542                                 *s++ = ' ';
543                         if (i + j < len) {
544                                 sprintf(s, " %02x", str[i + j]);
545                                 s += 3;
546                         }
547                         else {
548                                 *s++ = ' '; *s++ = ' '; *s++ = ' ';
549                         }
550                 }
551                 *s++ = ' '; *s++ = ' ';
552                 for (j = 0; j < 16; j++) {
553                         if (j == 8)
554                                 *s++ = ' ';
555                         if (i + j < len) {
556                                 if (isprint(str[i + j]))
557                                         *s++ = str[i + j];
558                                 else
559                                         *s++ = '.';
560                         }
561                         else
562                                 *s++ = ' ';
563                 }
564                 tprintf("%s |\n", outstr);
565         }
566 }
567
568 #define PAGMASK (~(PAGSIZ - 1))
569 /*
570  * move `len' bytes of data from process `pid'
571  * at address `addr' to our space at `laddr'
572  */
573 int
574 umoven(tcp, addr, len, laddr)
575 struct tcb *tcp;
576 long addr;
577 int len;
578 char *laddr;
579 {
580
581 #ifdef LINUX
582         int pid = tcp->pid;
583         int n, m;
584         int started = 0;
585         union {
586                 long val;
587                 char x[sizeof(long)];
588         } u;
589
590         if (addr & (sizeof(long) - 1)) {
591                 /* addr not a multiple of sizeof(long) */
592                 n = addr - (addr & -sizeof(long)); /* residue */
593                 addr &= -sizeof(long); /* residue */
594                 errno = 0;
595                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
596                 if (errno) {
597                         if (started && (errno==EPERM || errno==EIO)) {
598                                 /* Ran into 'end of memory' - stupid "printpath" */
599                                 return 0;
600                         }
601                         /* But if not started, we had a bogus address. */
602                         perror("ptrace: umoven");
603                         return -1;
604                 }
605                 started = 1;
606                 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
607                 addr += sizeof(long), laddr += m, len -= m;
608         }
609         while (len) {
610                 errno = 0;
611                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
612                 if (errno) {
613                         if (started && (errno==EPERM || errno==EIO)) {
614                                 /* Ran into 'end of memory' - stupid "printpath" */
615                                 return 0;
616                         }
617                         if (addr != 0)
618                                 perror("ptrace: umoven");
619                         return -1;
620                 }
621                 started = 1;
622                 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
623                 addr += sizeof(long), laddr += m, len -= m;
624         }
625 #endif /* LINUX */
626
627 #ifdef SUNOS4
628         int pid = tcp->pid;
629 #if 0
630         int n, m;
631         union {
632                 long val;
633                 char x[sizeof(long)];
634         } u;
635
636         if (addr & (sizeof(long) - 1)) {
637                 /* addr not a multiple of sizeof(long) */
638                 n = addr - (addr & -sizeof(long)); /* residue */
639                 addr &= -sizeof(long); /* residue */
640                 errno = 0;
641                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
642                 if (errno) {
643                         perror("umoven");
644                         return -1;
645                 }
646                 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
647                 addr += sizeof(long), laddr += m, len -= m;
648         }
649         while (len) {
650                 errno = 0;
651                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
652                 if (errno) {
653                         perror("umoven");
654                         return -1;
655                 }
656                 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
657                 addr += sizeof(long), laddr += m, len -= m;
658         }
659 #else /* !oldway */
660         int n;
661
662         while (len) {
663                 n = MIN(len, PAGSIZ);
664                 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
665                 if (ptrace(PTRACE_READDATA, pid,
666                            (char *) addr, len, laddr) < 0) {
667                         perror("umoven: ptrace(PTRACE_READDATA, ...)");
668                         abort();
669                         return -1;
670                 }
671                 len -= n;
672                 addr += n;
673                 laddr += n;
674         }
675 #endif /* !oldway */
676 #endif /* SUNOS4 */
677
678 #ifdef USE_PROCFS
679 #ifdef HAVE_MP_PROCFS
680         int fd = tcp->pfd_as;
681 #else
682         int fd = tcp->pfd;
683 #endif
684         lseek(fd, addr, SEEK_SET);
685         if (read(fd, laddr, len) == -1)
686                 return -1;
687 #endif /* USE_PROCFS */
688
689         return 0;
690 }
691
692 /*
693  * like `umove' but make the additional effort of looking
694  * for a terminating zero byte.
695  */
696 int
697 umovestr(tcp, addr, len, laddr)
698 struct tcb *tcp;
699 long addr;
700 int len;
701 char *laddr;
702 {
703 #ifdef USE_PROCFS
704 #ifdef HAVE_MP_PROCFS
705         int fd = tcp->pfd_as;
706 #else
707         int fd = tcp->pfd;
708 #endif
709         /* Some systems (e.g. FreeBSD) can be upset if we read off the
710            end of valid memory,  avoid this by trying to read up
711            to page boundaries.  But we don't know what a page is (and
712            getpagesize(2) (if it exists) doesn't necessarily return
713            hardware page size).  Assume all pages >= 1024 (a-historical
714            I know) */
715
716         int page = 1024;        /* How to find this? */
717         int move = page - (addr & (page - 1));
718         int left = len;
719
720         lseek(fd, addr, SEEK_SET);
721
722         while (left) {
723                 if (move > left) move = left;
724                 if ((move = read(fd, laddr, move)) <= 0)
725                         return left != len ? 0 : -1;
726                 if (memchr (laddr, 0, move)) break;
727                 left -= move;
728                 laddr += move;
729                 addr += move;
730                 move = page;
731         }
732 #else /* !USE_PROCFS */
733         int started = 0;
734         int pid = tcp->pid;
735         int i, n, m;
736         union {
737                 long val;
738                 char x[sizeof(long)];
739         } u;
740
741         if (addr & (sizeof(long) - 1)) {
742                 /* addr not a multiple of sizeof(long) */
743                 n = addr - (addr & -sizeof(long)); /* residue */
744                 addr &= -sizeof(long); /* residue */
745                 errno = 0;
746                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
747                 if (errno) {
748                         if (started && (errno==EPERM || errno==EIO)) {
749                                 /* Ran into 'end of memory' - stupid "printpath" */
750                                 return 0;
751                         }
752                         perror("umovestr");
753                         return -1;
754                 }
755                 started = 1;
756                 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
757                 while (n & (sizeof(long) - 1))
758                         if (u.x[n++] == '\0')
759                                 return 0;
760                 addr += sizeof(long), laddr += m, len -= m;
761         }
762         while (len) {
763                 errno = 0;
764                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
765                 if (errno) {
766                         if (started && (errno==EPERM || errno==EIO)) {
767                                 /* Ran into 'end of memory' - stupid "printpath" */
768                                 return 0;
769                         }
770                         perror("umovestr");
771                         return -1;
772                 }
773                 started = 1;
774                 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
775                 for (i = 0; i < sizeof(long); i++)
776                         if (u.x[i] == '\0')
777                                 return 0;
778
779                 addr += sizeof(long), laddr += m, len -= m;
780         }
781 #endif /* !USE_PROCFS */
782         return 0;
783 }
784
785 #ifdef LINUX
786 #ifndef SPARC
787 #define PTRACE_WRITETEXT        101
788 #define PTRACE_WRITEDATA        102
789 #endif /* !SPARC */
790 #endif /* LINUX */
791
792 #ifdef SUNOS4
793
794 static int
795 uload(cmd, pid, addr, len, laddr)
796 int cmd;
797 int pid;
798 long addr;
799 int len;
800 char *laddr;
801 {
802 #if 0
803         int n;
804
805         while (len) {
806                 n = MIN(len, PAGSIZ);
807                 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
808                 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
809                         perror("uload: ptrace(PTRACE_WRITE, ...)");
810                         return -1;
811                 }
812                 len -= n;
813                 addr += n;
814                 laddr += n;
815         }
816 #else
817         int peek, poke;
818         int n, m;
819         union {
820                 long val;
821                 char x[sizeof(long)];
822         } u;
823
824         if (cmd == PTRACE_WRITETEXT) {
825                 peek = PTRACE_PEEKTEXT;
826                 poke = PTRACE_POKETEXT;
827         }
828         else {
829                 peek = PTRACE_PEEKDATA;
830                 poke = PTRACE_POKEDATA;
831         }
832         if (addr & (sizeof(long) - 1)) {
833                 /* addr not a multiple of sizeof(long) */
834                 n = addr - (addr & -sizeof(long)); /* residue */
835                 addr &= -sizeof(long);
836                 errno = 0;
837                 u.val = ptrace(peek, pid, (char *) addr, 0);
838                 if (errno) {
839                         perror("uload: POKE");
840                         return -1;
841                 }
842                 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
843                 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
844                         perror("uload: POKE");
845                         return -1;
846                 }
847                 addr += sizeof(long), laddr += m, len -= m;
848         }
849         while (len) {
850                 if (len < sizeof(long))
851                         u.val = ptrace(peek, pid, (char *) addr, 0);
852                 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
853                 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
854                         perror("uload: POKE");
855                         return -1;
856                 }
857                 addr += sizeof(long), laddr += m, len -= m;
858         }
859 #endif
860         return 0;
861 }
862
863 int
864 tload(pid, addr, len, laddr)
865 int pid;
866 int addr, len;
867 char *laddr;
868 {
869         return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
870 }
871
872 int
873 dload(pid, addr, len, laddr)
874 int pid;
875 int addr;
876 int len;
877 char *laddr;
878 {
879         return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
880 }
881
882 #endif /* SUNOS4 */
883
884 #ifndef USE_PROCFS
885
886 int
887 upeek(pid, off, res)
888 int pid;
889 long off;
890 long *res;
891 {
892         long val;
893
894 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
895         {
896                 static int is_sun4m = -1;
897                 struct utsname name;
898
899                 /* Round up the usual suspects. */
900                 if (is_sun4m == -1) {
901                         if (uname(&name) < 0) {
902                                 perror("upeek: uname?");
903                                 exit(1);
904                         }
905                         is_sun4m = strcmp(name.machine, "sun4m") == 0;
906                         if (is_sun4m) {
907                                 extern struct xlat struct_user_offsets[];
908                                 struct xlat *x;
909
910                                 for (x = struct_user_offsets; x->str; x++)
911                                         x->val += 1024;
912                         }
913                 }
914                 if (is_sun4m)
915                         off += 1024;
916         }
917 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
918         errno = 0;
919         val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
920         if (val == -1 && errno) {
921                 char buf[60];
922                 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
923                 perror(buf);
924                 return -1;
925         }
926         *res = val;
927         return 0;
928 }
929
930 #endif /* !USE_PROCFS */
931
932 long
933 getpc(tcp)
934 struct tcb *tcp;
935 {
936
937 #ifdef LINUX
938         long pc;
939 #if defined(I386)
940         if (upeek(tcp->pid, 4*EIP, &pc) < 0)
941                 return -1;
942 #elif defined(X86_64)
943         if (upeek(tcp->pid, 8*RIP, &pc) < 0)
944                 return -1;
945 #elif defined(IA64)
946         if (upeek(tcp->pid, PT_B0, &pc) < 0)
947                 return -1;
948 #elif defined(ARM)
949         if (upeek(tcp->pid, 4*15, &pc) < 0)
950                 return -1;
951 #elif defined(POWERPC)
952         if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
953                 return -1;
954 #elif defined(M68k)
955         if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
956                 return -1;
957 #elif defined(ALPHA)
958         if (upeek(tcp->pid, REG_PC, &pc) < 0)
959                 return -1;
960 #elif defined(MIPS)
961         if (upeek(tcp->pid, REG_EPC, &pc) < 0)
962                 return -1;
963 #elif defined(SPARC)
964         struct regs regs;
965         if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
966                 return -1;
967         pc = regs.r_pc;
968 #elif defined(S390) || defined(S390X)
969         if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
970                 return -1;
971 #elif defined(HPPA)
972         if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
973                 return -1;
974 #elif defined(SH)
975        if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
976                return -1;
977 #elif defined(SHMEDIA)
978        if (upeek(tcp->pid, REG_PC ,&pc) < 0)
979                return -1;
980 #endif
981         return pc;
982 #endif /* LINUX */
983
984 #ifdef SUNOS4
985         /*
986          * Return current program counter for `pid'
987          * Assumes PC is never 0xffffffff
988          */
989         struct regs regs;
990
991         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
992                 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
993                 return -1;
994         }
995         return regs.r_pc;
996 #endif /* SUNOS4 */
997
998 #ifdef SVR4
999         /* XXX */
1000         return 0;
1001 #endif /* SVR4 */
1002
1003 #ifdef FREEBSD
1004         struct reg regs;
1005         pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1006         return regs.r_eip;
1007 #endif /* FREEBSD */
1008 }
1009
1010 void
1011 printcall(tcp)
1012 struct tcb *tcp;
1013 {
1014
1015 #ifdef LINUX
1016 #ifdef I386
1017         long eip;
1018
1019         if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1020                 tprintf("[????????] ");
1021                 return;
1022         }
1023         tprintf("[%08lx] ", eip);
1024 #elif defined(X86_64)
1025         long rip;
1026
1027         if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1028                 tprintf("[????????] ");
1029                 return;
1030         }
1031         tprintf("[%16lx] ", rip);
1032 #elif defined(IA64)
1033         long ip;
1034
1035         if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1036                 tprintf("[????????] ");
1037                 return;
1038         }
1039         tprintf("[%08lx] ", ip);
1040 #elif defined(POWERPC)
1041         long pc;
1042
1043         if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1044                 tprintf ("[????????] ");
1045                 return;
1046         }
1047         tprintf("[%08lx] ", pc);
1048 #elif defined(M68k)
1049         long pc;
1050
1051         if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1052                 tprintf ("[????????] ");
1053                 return;
1054         }
1055         tprintf("[%08lx] ", pc);
1056 #elif defined(ALPHA)
1057         long pc;
1058
1059         if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1060                 tprintf ("[????????] ");
1061                 return;
1062         }
1063         tprintf("[%08lx] ", pc);
1064 #elif defined(SPARC)
1065         struct regs regs;
1066         if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
1067                 tprintf("[????????] ");
1068                 return;
1069         }
1070         tprintf("[%08lx] ", regs.r_pc);
1071 #elif defined(HPPA)
1072         long pc;
1073
1074         if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1075                 tprintf ("[????????] ");
1076                 return;
1077         }
1078         tprintf("[%08lx] ", pc);
1079 #elif defined(MIPS)
1080         long pc;
1081
1082         if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1083                 tprintf ("[????????] ");
1084                 return;
1085         }
1086         tprintf("[%08lx] ", pc);
1087 #elif defined(SH)
1088        long pc;
1089
1090        if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1091                tprintf ("[????????] ");
1092                return;
1093        }
1094        tprintf("[%08lx] ", pc);
1095 #elif defined(SHMEDIA)
1096         long pc;
1097
1098         if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1099                 tprintf ("[????????] ");
1100                 return;
1101         }
1102         tprintf("[%08lx] ", pc);
1103 #elif defined(ARM)
1104         long pc;
1105
1106         if (upeek(tcp->pid, 4*15, &pc) < 0) {
1107                 tprintf("[????????] ");
1108                 return;
1109         }
1110         tprintf("[%08lx] ", pc);
1111 #endif /* !architecture */
1112 #endif /* LINUX */
1113
1114 #ifdef SUNOS4
1115         struct regs regs;
1116
1117         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1118                 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1119                 tprintf("[????????] ");
1120                 return;
1121         }
1122         tprintf("[%08x] ", regs.r_o7);
1123 #endif /* SUNOS4 */
1124
1125 #ifdef SVR4
1126         /* XXX */
1127         tprintf("[????????] ");
1128 #endif
1129
1130 #ifdef FREEBSD
1131         struct reg regs;
1132         pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1133         tprintf("[%08x] ", regs.r_eip);
1134 #endif /* FREEBSD */
1135 }
1136
1137 #ifndef USE_PROCFS
1138
1139 #if defined LINUX
1140
1141 #include <sys/syscall.h>
1142 #ifndef CLONE_PTRACE
1143 # define CLONE_PTRACE    0x00002000
1144 #endif
1145
1146 #ifdef IA64
1147
1148 typedef unsigned long *arg_setup_state;
1149
1150 static int
1151 arg_setup(struct tcb *tcp, arg_setup_state *state)
1152 {
1153         unsigned long *bsp, cfm, sof, sol;
1154
1155         if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1156                 return -1;
1157         if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1158                 return -1;
1159
1160         sof = (cfm >> 0) & 0x7f;
1161         sol = (cfm >> 7) & 0x7f;
1162         bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1163
1164         *state = bsp;
1165         return 0;
1166 }
1167
1168 # define arg_finish_change(tcp, state)  0
1169
1170 #ifdef SYS_fork
1171 static int
1172 get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1173 {
1174         return umoven (tcp, (unsigned long) ia64_rse_skip_regs(*state, 0),
1175                        sizeof(long), (void *) valp);
1176 }
1177
1178 static int
1179 get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1180 {
1181         return umoven (tcp, (unsigned long) ia64_rse_skip_regs(*state, 1),
1182                        sizeof(long), (void *) valp);
1183 }
1184 #endif
1185
1186 static int
1187 set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1188 {
1189         unsigned long *ap;
1190         ap = ia64_rse_skip_regs(*state, 0);
1191         errno = 0;
1192         ptrace(PTRACE_POKEDATA, tcp->pid, (void *) ap, val);
1193         return errno ? -1 : 0;
1194 }
1195
1196 static int
1197 set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1198 {
1199         unsigned long *ap;
1200         ap = ia64_rse_skip_regs(*state, 1);
1201         errno = 0;
1202         ptrace(PTRACE_POKEDATA, tcp->pid, (void *) ap, val);
1203         return errno ? -1 : 0;
1204 }
1205
1206 #elif defined (SPARC)
1207
1208 typedef struct regs arg_setup_state;
1209
1210 # define arg_setup(tcp, state) \
1211   (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1212 # define arg_finish_change(tcp, state) \
1213   (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1214
1215 # define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1216 # define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1217 # define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1218 # define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
1219 # define restore_arg0(tcp, state, val) 0
1220
1221 #else
1222
1223 # if defined S390 || defined S390X
1224 /* Note: this is only true for the `clone' system call, which handles
1225    arguments specially.  We could as well say that its first two arguments
1226    are swapped relative to other architectures, but that would just be
1227    another #ifdef in the calls.  */
1228 #  define arg0_offset   PT_GPR3
1229 #  define arg1_offset   PT_ORIGGPR2
1230 #  define restore_arg0(tcp, state, val) ((void) (state), 0)
1231 #  define restore_arg1(tcp, state, val) ((void) (state), 0)
1232 # elif defined (ALPHA) || defined (MIPS)
1233 #  define arg0_offset   REG_A0
1234 #  define arg1_offset   (REG_A0+1)
1235 # elif defined (POWERPC)
1236 #  define arg0_offset   (sizeof(unsigned long)*PT_R3)
1237 #  define arg1_offset   (sizeof(unsigned long)*PT_R4)
1238 #  define restore_arg0(tcp, state, val) ((void) (state), 0)
1239 # elif defined (HPPA)
1240 #  define arg0_offset    PT_GR26
1241 #  define arg1_offset    (PT_GR26-4)
1242 # elif defined (X86_64)
1243 #  define arg0_offset   ((long)(8*(current_personality ? RBX : RDI)))
1244 #  define arg1_offset   ((long)(8*(current_personality ? RCX : RSI)))
1245 # elif defined (SH)
1246 #  define arg0_offset   (4*(REG_REG0+4))
1247 #  define arg1_offset   (4*(REG_REG0+5))
1248 # elif defined (SHMEDIA)
1249    /* ABI defines arg0 & 1 in r2 & r3 */
1250 #  define arg0_offset   (REG_OFFSET+16)
1251 #  define arg1_offset   (REG_OFFSET+24)
1252 #  define restore_arg0(tcp, state, val) 0
1253 # else
1254 #  define arg0_offset   0
1255 #  define arg1_offset   4
1256 #  if defined ARM
1257 #   define restore_arg0(tcp, state, val) 0
1258 #  endif
1259 # endif
1260
1261 typedef int arg_setup_state;
1262
1263 # define arg_setup(tcp, state) (0)
1264 # define arg_finish_change(tcp, state)  0
1265 # define get_arg0(tcp, cookie, valp) \
1266   (upeek ((tcp)->pid, arg0_offset, (valp)))
1267 # define get_arg1(tcp, cookie, valp) \
1268   (upeek ((tcp)->pid, arg1_offset, (valp)))
1269
1270 static int
1271 set_arg0 (struct tcb *tcp, void *cookie, long val)
1272 {
1273         return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1274 }
1275
1276 static int
1277 set_arg1 (struct tcb *tcp, void *cookie, long val)
1278 {
1279         return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1280 }
1281
1282 #endif
1283
1284 #ifndef restore_arg0
1285 # define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1286 #endif
1287 #ifndef restore_arg1
1288 # define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1289 #endif
1290
1291 int
1292 setbpt(tcp)
1293 struct tcb *tcp;
1294 {
1295         extern int change_syscall(struct tcb *, int);
1296         arg_setup_state state;
1297
1298         if (tcp->flags & TCB_BPTSET) {
1299                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1300                 return -1;
1301         }
1302
1303         switch (tcp->scno) {
1304 #ifdef SYS_vfork
1305         case SYS_vfork:
1306 #endif
1307 #ifdef SYS_fork
1308         case SYS_fork:
1309 #endif
1310 #if defined SYS_fork || defined SYS_vfork
1311                 if (arg_setup (tcp, &state) < 0
1312                     || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1313                     || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1314                     || change_syscall(tcp, SYS_clone) < 0
1315                     || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1316                     || set_arg1 (tcp, &state, 0) < 0
1317                     || arg_finish_change (tcp, &state) < 0)
1318                         return -1;
1319                 tcp->u_arg[0] = CLONE_PTRACE|SIGCHLD;
1320                 tcp->u_arg[1] = 0;
1321                 tcp->flags |= TCB_BPTSET;
1322                 return 0;
1323 #endif
1324
1325         case SYS_clone:
1326 #ifdef SYS_clone2
1327         case SYS_clone2:
1328 #endif
1329                 if ((tcp->u_arg[0] & CLONE_PTRACE) == 0
1330                     && (arg_setup (tcp, &state) < 0
1331                         || set_arg0 (tcp, &state, tcp->u_arg[0] | CLONE_PTRACE) < 0
1332                         || arg_finish_change (tcp, &state) < 0))
1333                         return -1;
1334                 tcp->flags |= TCB_BPTSET;
1335                 tcp->inst[0] = tcp->u_arg[0];
1336                 tcp->inst[1] = tcp->u_arg[1];
1337                 return 0;
1338
1339         default:
1340                 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1341                         tcp->scno, tcp->pid);
1342                 break;
1343         }
1344
1345         return -1;
1346 }
1347
1348 int
1349 clearbpt(tcp)
1350 struct tcb *tcp;
1351 {
1352         arg_setup_state state;
1353         if (arg_setup (tcp, &state) < 0
1354             || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1355             || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1356             || arg_finish_change (tcp, &state))
1357                 return -1;
1358         tcp->flags &= ~TCB_BPTSET;
1359         return 0;
1360 }
1361
1362 #else
1363
1364 int
1365 setbpt(tcp)
1366 struct tcb *tcp;
1367 {
1368
1369 #ifdef LINUX
1370 #ifdef SPARC
1371         /* We simply use the SunOS breakpoint code. */
1372
1373         struct regs regs;
1374 #define LOOPA   0x30800000      /* ba,a 0 */
1375
1376         if (tcp->flags & TCB_BPTSET) {
1377                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1378                 return -1;
1379         }
1380         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1381                 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1382                 return -1;
1383         }
1384         tcp->baddr = regs.r_o7 + 8;
1385         errno = 0;
1386         tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1387         if(errno) {
1388                 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1389                 return -1;
1390         }
1391
1392         /*
1393          * XXX - BRUTAL MODE ON
1394          * We cannot set a real BPT in the child, since it will not be
1395          * traced at the moment it will reach the trap and would probably
1396          * die with a core dump.
1397          * Thus, we are force our way in by taking out two instructions
1398          * and insert an eternal loop instead, in expectance of the SIGSTOP
1399          * generated by out PTRACE_ATTACH.
1400          * Of cause, if we evaporate ourselves in the middle of all this...
1401          */
1402         errno = 0;
1403         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);
1404         if(errno) {
1405                 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1406                 return -1;
1407         }
1408         tcp->flags |= TCB_BPTSET;
1409
1410 #else /* !SPARC */
1411 #ifdef IA64
1412         if (ia32) {
1413 #               define LOOP     0x0000feeb
1414                 if (tcp->flags & TCB_BPTSET) {
1415                         fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1416                                 tcp->pid);
1417                         return -1;
1418                 }
1419                 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1420                         return -1;
1421                 if (debug)
1422                         fprintf(stderr, "[%d] setting bpt at %lx\n",
1423                                 tcp->pid, tcp->baddr);
1424                 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1425                                       (char *) tcp->baddr, 0);
1426                 if (errno) {
1427                         perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1428                         return -1;
1429                 }
1430                 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1431                 if (errno) {
1432                         perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1433                         return -1;
1434                 }
1435                 tcp->flags |= TCB_BPTSET;
1436         } else {
1437                 /*
1438                  * Our strategy here is to replace the bundle that
1439                  * contained the clone() syscall with a bundle of the
1440                  * form:
1441                  *
1442                  *      { 1: br 1b; br 1b; br 1b }
1443                  *
1444                  * This ensures that the newly forked child will loop
1445                  * endlessly until we've got a chance to attach to it.
1446                  */
1447 #               define LOOP0    0x0000100000000017
1448 #               define LOOP1    0x4000000000200000
1449                 unsigned long addr, ipsr;
1450                 pid_t pid;
1451
1452                 pid = tcp->pid;
1453                 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1454                         return -1;
1455                 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1456                         return -1;
1457                 /* store "ri" in low two bits */
1458                 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
1459
1460                 errno = 0;
1461                 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1462                                       0);
1463                 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1464                                       0);
1465                 if (errno) {
1466                         perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1467                         return -1;
1468                 }
1469
1470                 errno = 0;
1471                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1472                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1473                 if (errno) {
1474                         perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1475                         return -1;
1476                 }
1477                 tcp->flags |= TCB_BPTSET;
1478         }
1479 #else /* !IA64 */
1480
1481 #if defined (I386) || defined(X86_64)
1482 #define LOOP    0x0000feeb
1483 #elif defined (M68K)
1484 #define LOOP    0x60fe0000
1485 #elif defined (ALPHA)
1486 #define LOOP    0xc3ffffff
1487 #elif defined (POWERPC)
1488 #define LOOP    0x48000000
1489 #elif defined(ARM)
1490 #define LOOP    0xEAFFFFFE
1491 #elif defined(MIPS)
1492 #define LOOP    0x1000ffff
1493 #elif defined(S390)
1494 #define LOOP    0xa7f40000      /* BRC 15,0 */
1495 #elif defined(S390X)
1496 #define LOOP   0xa7f4000000000000UL /* BRC 15,0 */
1497 #elif defined(HPPA)
1498 #define LOOP    0xe81f1ff7      /* b,l,n <loc>,r0 */
1499 #elif defined(SH)
1500 #ifdef __LITTLE_ENDIAN__
1501 #define LOOP   0x0000affe
1502 #else
1503 #define LOOP   0xfeaf0000
1504 #endif
1505 #else
1506 #error unknown architecture
1507 #endif
1508
1509         if (tcp->flags & TCB_BPTSET) {
1510                 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1511                 return -1;
1512         }
1513 #if defined (I386)
1514         if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1515                 return -1;
1516 #elif defined (X86_64)
1517         if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1518                 return -1;
1519 #elif defined (M68K)
1520         if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1521           return -1;
1522 #elif defined (ALPHA)
1523         return -1;
1524 #elif defined (ARM)
1525         return -1;
1526 #elif defined (MIPS)
1527         return -1;              /* FIXME: I do not know what i do - Flo */
1528 #elif defined (POWERPC)
1529         if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
1530                 return -1;
1531 #elif defined(S390) || defined(S390X)
1532         if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1533                 return -1;
1534 #elif defined(HPPA)
1535         if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1536                 return -1;
1537         tcp->baddr &= ~0x03;
1538 #elif defined(SH)
1539        if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1540                return -1;
1541 #else
1542 #error unknown architecture
1543 #endif
1544         if (debug)
1545                 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1546         tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1547         if (errno) {
1548                 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1549                 return -1;
1550         }
1551         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1552         if (errno) {
1553                 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1554                 return -1;
1555         }
1556         tcp->flags |= TCB_BPTSET;
1557
1558 #endif /* !IA64 */
1559 #endif /* SPARC */
1560 #endif /* LINUX */
1561
1562 #ifdef SUNOS4
1563 #ifdef SPARC    /* This code is slightly sparc specific */
1564
1565         struct regs regs;
1566 #define BPT     0x91d02001      /* ta   1 */
1567 #define LOOP    0x10800000      /* ba   0 */
1568 #define LOOPA   0x30800000      /* ba,a 0 */
1569 #define NOP     0x01000000
1570 #if LOOPA
1571         static int loopdeloop[1] = {LOOPA};
1572 #else
1573         static int loopdeloop[2] = {LOOP, NOP};
1574 #endif
1575
1576         if (tcp->flags & TCB_BPTSET) {
1577                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1578                 return -1;
1579         }
1580         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1581                 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1582                 return -1;
1583         }
1584         tcp->baddr = regs.r_o7 + 8;
1585         if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1586                                 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1587                 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1588                 return -1;
1589         }
1590
1591         /*
1592          * XXX - BRUTAL MODE ON
1593          * We cannot set a real BPT in the child, since it will not be
1594          * traced at the moment it will reach the trap and would probably
1595          * die with a core dump.
1596          * Thus, we are force our way in by taking out two instructions
1597          * and insert an eternal loop in stead, in expectance of the SIGSTOP
1598          * generated by out PTRACE_ATTACH.
1599          * Of cause, if we evaporate ourselves in the middle of all this...
1600          */
1601         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1602                         sizeof loopdeloop, (char *) loopdeloop) < 0) {
1603                 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1604                 return -1;
1605         }
1606         tcp->flags |= TCB_BPTSET;
1607
1608 #endif /* SPARC */
1609 #endif /* SUNOS4 */
1610
1611         return 0;
1612 }
1613
1614 int
1615 clearbpt(tcp)
1616 struct tcb *tcp;
1617 {
1618
1619 #ifdef LINUX
1620 #if defined(I386) || defined(X86_64)
1621         long eip;
1622 #elif defined(POWERPC)
1623         long pc;
1624 #elif defined(M68K)
1625         long pc;
1626 #elif defined(ALPHA)
1627         long pc;
1628 #elif defined(HPPA)
1629         long iaoq;
1630 #elif defined(SH)
1631        long pc;
1632 #endif /* architecture */
1633
1634 #ifdef SPARC
1635         /* Again, we borrow the SunOS breakpoint code. */
1636         if (!(tcp->flags & TCB_BPTSET)) {
1637                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1638                 return -1;
1639         }
1640         errno = 0;
1641         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1642         if(errno) {
1643                 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1644                 return -1;
1645         }
1646         tcp->flags &= ~TCB_BPTSET;
1647 #elif defined(IA64)
1648         if (ia32) {
1649                 unsigned long addr;
1650
1651                 if (debug)
1652                         fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1653                 if (!(tcp->flags & TCB_BPTSET)) {
1654                         fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1655                         return -1;
1656                 }
1657                 errno = 0;
1658                 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1659                 if (errno) {
1660                         perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1661                         return -1;
1662                 }
1663                 tcp->flags &= ~TCB_BPTSET;
1664
1665                 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1666                         return -1;
1667                 if (addr != tcp->baddr) {
1668                         /* The breakpoint has not been reached yet.  */
1669                         if (debug)
1670                                 fprintf(stderr,
1671                                         "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1672                                                 addr, tcp->baddr);
1673                         return 0;
1674                 }
1675         } else {
1676                 unsigned long addr, ipsr;
1677                 pid_t pid;
1678
1679                 pid = tcp->pid;
1680
1681                 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1682                         return -1;
1683                 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1684                         return -1;
1685
1686                 /* restore original bundle: */
1687                 errno = 0;
1688                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1689                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1690                 if (errno) {
1691                         perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1692                         return -1;
1693                 }
1694
1695                 /* restore original "ri" in ipsr: */
1696                 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1697                 errno = 0;
1698                 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1699                 if (errno) {
1700                         perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1701                         return -1;
1702                 }
1703
1704                 tcp->flags &= ~TCB_BPTSET;
1705
1706                 if (addr != (tcp->baddr & ~0x3)) {
1707                         /* the breakpoint has not been reached yet.  */
1708                         if (debug)
1709                                 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1710                                         addr, tcp->baddr);
1711                         return 0;
1712                 }
1713         }
1714 #else /* !IA64  && ! SPARC */
1715
1716         if (debug)
1717                 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1718         if (!(tcp->flags & TCB_BPTSET)) {
1719                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1720                 return -1;
1721         }
1722         errno = 0;
1723         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1724         if (errno) {
1725                 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1726                 return -1;
1727         }
1728         tcp->flags &= ~TCB_BPTSET;
1729
1730 #ifdef I386
1731         if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1732                 return -1;
1733         if (eip != tcp->baddr) {
1734                 /* The breakpoint has not been reached yet.  */
1735                 if (debug)
1736                         fprintf(stderr,
1737                                 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1738                                         eip, tcp->baddr);
1739                 return 0;
1740         }
1741 #elif defined(X86_64)
1742         if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1743                 return -1;
1744         if (eip != tcp->baddr) {
1745                 /* The breakpoint has not been reached yet.  */
1746                 if (debug)
1747                         fprintf(stderr,
1748                                 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1749                                         eip, tcp->baddr);
1750                 return 0;
1751         }
1752 #elif defined(POWERPC)
1753         if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1754                 return -1;
1755         if (pc != tcp->baddr) {
1756                 /* The breakpoint has not been reached yet.  */
1757                 if (debug)
1758                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1759                                 pc, tcp->baddr);
1760                 return 0;
1761         }
1762 #elif defined(M68K)
1763         if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1764                 return -1;
1765         if (pc != tcp->baddr) {
1766                 /* The breakpoint has not been reached yet.  */
1767                 if (debug)
1768                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1769                                 pc, tcp->baddr);
1770                 return 0;
1771         }
1772 #elif defined(ALPHA)
1773         if (upeek(tcp->pid, REG_PC, &pc) < 0)
1774                 return -1;
1775         if (pc != tcp->baddr) {
1776                 /* The breakpoint has not been reached yet.  */
1777                 if (debug)
1778                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1779                                 pc, tcp->baddr);
1780                 return 0;
1781         }
1782 #elif defined(HPPA)
1783         if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1784                 return -1;
1785         iaoq &= ~0x03;
1786         if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1787                 /* The breakpoint has not been reached yet.  */
1788                 if (debug)
1789                         fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1790                                 iaoq, tcp->baddr);
1791                 return 0;
1792         }
1793         iaoq = tcp->baddr | 3;
1794         /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1795          * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1796          * has no significant effect.
1797          */
1798         ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1799         ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
1800 #elif defined(SH)
1801        if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1802                return -1;
1803         if (pc != tcp->baddr) {
1804                 /* The breakpoint has not been reached yet.  */
1805                 if (debug)
1806                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1807                                 pc, tcp->baddr);
1808                 return 0;
1809         }
1810
1811 #endif /* arch */
1812 #endif /* !SPARC && !IA64 */
1813 #endif /* LINUX */
1814
1815 #ifdef SUNOS4
1816 #ifdef SPARC
1817
1818 #if !LOOPA
1819         struct regs regs;
1820 #endif
1821
1822         if (!(tcp->flags & TCB_BPTSET)) {
1823                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1824                 return -1;
1825         }
1826         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1827                                 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1828                 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1829                 return -1;
1830         }
1831         tcp->flags &= ~TCB_BPTSET;
1832
1833 #if !LOOPA
1834         /*
1835          * Since we don't have a single instruction breakpoint, we may have
1836          * to adjust the program counter after removing the our `breakpoint'.
1837          */
1838         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1839                 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1840                 return -1;
1841         }
1842         if ((regs.r_pc < tcp->baddr) ||
1843                                 (regs.r_pc > tcp->baddr + 4)) {
1844                 /* The breakpoint has not been reached yet */
1845                 if (debug)
1846                         fprintf(stderr,
1847                                 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1848                                         regs.r_pc, tcp->parent->baddr);
1849                 return 0;
1850         }
1851         if (regs.r_pc != tcp->baddr)
1852                 if (debug)
1853                         fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1854                                 regs.r_pc, tcp->baddr);
1855
1856         regs.r_pc = tcp->baddr;
1857         if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1858                 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1859                 return -1;
1860         }
1861 #endif /* LOOPA */
1862 #endif /* SPARC */
1863 #endif /* SUNOS4 */
1864
1865         return 0;
1866 }
1867
1868 #endif
1869
1870 #endif /* !USE_PROCFS */
1871
1872 #ifdef SUNOS4
1873
1874 static int
1875 getex(pid, hdr)
1876 int pid;
1877 struct exec *hdr;
1878 {
1879         int n;
1880
1881         for (n = 0; n < sizeof *hdr; n += 4) {
1882                 long res;
1883                 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1884                         return -1;
1885                 memcpy(((char *) hdr) + n, &res, 4);
1886         }
1887         if (debug) {
1888                 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1889                         hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1890                 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1891                         hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1892         }
1893         return 0;
1894 }
1895
1896 int
1897 fixvfork(tcp)
1898 struct tcb *tcp;
1899 {
1900         int pid = tcp->pid;
1901         /*
1902          * Change `vfork' in a freshly exec'ed dynamically linked
1903          * executable's (internal) symbol table to plain old `fork'
1904          */
1905
1906         struct exec hdr;
1907         struct link_dynamic dyn;
1908         struct link_dynamic_2 ld;
1909         char *strtab, *cp;
1910
1911         if (getex(pid, &hdr) < 0)
1912                 return -1;
1913         if (!hdr.a_dynamic)
1914                 return -1;
1915
1916         if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1917                 fprintf(stderr, "Cannot read DYNAMIC\n");
1918                 return -1;
1919         }
1920         if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1921                 fprintf(stderr, "Cannot read link_dynamic_2\n");
1922                 return -1;
1923         }
1924         if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1925                 fprintf(stderr, "fixvfork: out of memory\n");
1926                 return -1;
1927         }
1928         if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1929                                         (int)ld.ld_symb_size, strtab) < 0)
1930                 goto err;
1931
1932 #if 0
1933         for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1934                 fprintf(stderr, "[symbol: %s]\n", cp);
1935                 cp += strlen(cp)+1;
1936         }
1937         return 0;
1938 #endif
1939         for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1940                 if (strcmp(cp, "_vfork") == 0) {
1941                         if (debug)
1942                                 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1943                         strcpy(cp, "_fork");
1944                         break;
1945                 }
1946                 cp += strlen(cp)+1;
1947         }
1948         if (cp < strtab + ld.ld_symb_size)
1949                 /*
1950                  * Write entire symbol table back to avoid
1951                  * memory alignment bugs in ptrace
1952                  */
1953                 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1954                                         (int)ld.ld_symb_size, strtab) < 0)
1955                         goto err;
1956
1957         free(strtab);
1958         return 0;
1959
1960 err:
1961         free(strtab);
1962         return -1;
1963 }
1964
1965 #endif /* SUNOS4 */