]> granicus.if.org Git - strace/blob - util.c
.
[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 #endif
978         return pc;
979 #endif /* LINUX */
980
981 #ifdef SUNOS4
982         /*
983          * Return current program counter for `pid'
984          * Assumes PC is never 0xffffffff
985          */
986         struct regs regs;
987
988         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
989                 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
990                 return -1;
991         }
992         return regs.r_pc;
993 #endif /* SUNOS4 */
994
995 #ifdef SVR4
996         /* XXX */
997         return 0;
998 #endif /* SVR4 */
999
1000 #ifdef FREEBSD
1001         struct reg regs;
1002         pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1003         return regs.r_eip;
1004 #endif /* FREEBSD */
1005 }
1006
1007 void
1008 printcall(tcp)
1009 struct tcb *tcp;
1010 {
1011
1012 #ifdef LINUX
1013 #ifdef I386
1014         long eip;
1015
1016         if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1017                 tprintf("[????????] ");
1018                 return;
1019         }
1020         tprintf("[%08lx] ", eip);
1021 #elif defined(X86_64)
1022         long rip;
1023
1024         if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1025                 tprintf("[????????] ");
1026                 return;
1027         }
1028         tprintf("[%16lx] ", rip);
1029 #elif defined(IA62)
1030         long ip;
1031
1032         if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1033                 tprintf("[????????] ");
1034                 return;
1035         }
1036         tprintf("[%08lx] ", ip);
1037 #elif defined(POWERPC)
1038         long pc;
1039
1040         if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1041                 tprintf ("[????????] ");
1042                 return;
1043         }
1044         tprintf("[%08lx] ", pc);
1045 #elif defined(M68k)
1046         long pc;
1047
1048         if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1049                 tprintf ("[????????] ");
1050                 return;
1051         }
1052         tprintf("[%08lx] ", pc);
1053 #elif defined(ALPHA)
1054         long pc;
1055
1056         if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1057                 tprintf ("[????????] ");
1058                 return;
1059         }
1060         tprintf("[%08lx] ", pc);
1061 #elif defined(SPARC)
1062         struct regs regs;
1063         if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
1064                 tprintf("[????????] ");
1065                 return;
1066         }
1067         tprintf("[%08lx] ", regs.r_pc);
1068 #elif defined(HPPA)
1069         long pc;
1070
1071         if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1072                 tprintf ("[????????] ");
1073                 return;
1074         }
1075         tprintf("[%08lx] ", pc);
1076 #elif defined(MIPS)
1077         long pc;
1078
1079         if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1080                 tprintf ("[????????] ");
1081                 return;
1082         }
1083         tprintf("[%08lx] ", pc);
1084 #elif defined(SH)
1085        long pc;
1086
1087        if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1088                tprintf ("[????????] ");
1089                return;
1090        }
1091        tprintf("[%08lx] ", pc);
1092 #endif /* !architecture */
1093 #endif /* LINUX */
1094
1095 #ifdef SUNOS4
1096         struct regs regs;
1097
1098         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1099                 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1100                 tprintf("[????????] ");
1101                 return;
1102         }
1103         tprintf("[%08x] ", regs.r_o7);
1104 #endif /* SUNOS4 */
1105
1106 #ifdef SVR4
1107         /* XXX */
1108         tprintf("[????????] ");
1109 #endif
1110
1111 #ifdef FREEBSD
1112         struct reg regs;
1113         pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1114         tprintf("[%08x] ", regs.r_eip);
1115 #endif /* FREEBSD */
1116 }
1117
1118 #ifndef USE_PROCFS
1119
1120 #if defined LINUX
1121
1122 #include <sys/syscall.h>
1123 #ifndef CLONE_PTRACE
1124 # define CLONE_PTRACE    0x00002000
1125 #endif
1126
1127 #ifdef IA64
1128
1129 typedef unsigned long *arg_setup_state;
1130
1131 static int
1132 arg_setup(struct tcb *tcp, arg_setup_state *state)
1133 {
1134         unsigned long *bsp, cfm, sof, sol;
1135
1136         if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1137                 return -1;
1138         if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1139                 return -1;
1140
1141         sof = (cfm >> 0) & 0x7f;
1142         sol = (cfm >> 7) & 0x7f;
1143         bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1144
1145         *state = bsp;
1146         return 0;
1147 }
1148
1149 # define arg_finish_change(tcp, state)  0
1150
1151 #ifdef SYS_fork
1152 static int
1153 get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1154 {
1155         return umoven (tcp, (unsigned long) ia64_rse_skip_regs(*state, 0),
1156                        sizeof(long), (void *) valp);
1157 }
1158
1159 static int
1160 get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1161 {
1162         return umoven (tcp, (unsigned long) ia64_rse_skip_regs(*state, 1),
1163                        sizeof(long), (void *) valp);
1164 }
1165 #endif
1166
1167 static int
1168 set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1169 {
1170         unsigned long *ap;
1171         ap = ia64_rse_skip_regs(*state, 0);
1172         errno = 0;
1173         ptrace(PTRACE_POKEDATA, tcp->pid, (void *) ap, val);
1174         return errno ? -1 : 0;
1175 }
1176
1177 static int
1178 set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1179 {
1180         unsigned long *ap;
1181         ap = ia64_rse_skip_regs(*state, 1);
1182         errno = 0;
1183         ptrace(PTRACE_POKEDATA, tcp->pid, (void *) ap, val);
1184         return errno ? -1 : 0;
1185 }
1186
1187 #elif defined (SPARC)
1188
1189 typedef struct regs arg_setup_state;
1190
1191 # define arg_setup(tcp, state) \
1192   (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1193 # define arg_finish_change(tcp, state) \
1194   (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1195
1196 # define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1197 # define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1198 # define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1199 # define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
1200 # define restore_arg0(tcp, state, val) 0
1201
1202 #else
1203
1204 # if defined S390 || defined S390X
1205 /* Note: this is only true for the `clone' system call, which handles
1206    arguments specially.  We could as well say that its first two arguments
1207    are swapped relative to other architectures, but that would just be
1208    another #ifdef in the calls.  */
1209 #  define arg0_offset   PT_GPR3
1210 #  define arg1_offset   PT_ORIGGPR2
1211 #  define restore_arg0(tcp, state, val) ((void) (state), 0)
1212 #  define restore_arg1(tcp, state, val) ((void) (state), 0)
1213 # elif defined (ALPHA) || defined (MIPS)
1214 #  define arg0_offset   REG_A0
1215 #  define arg1_offset   (REG_A0+1)
1216 # elif defined (POWERPC)
1217 #  define arg0_offset   (sizeof(unsigned long)*PT_R3)
1218 #  define arg1_offset   (sizeof(unsigned long)*PT_R4)
1219 #  define restore_arg0(tcp, state, val) ((void) (state), 0)
1220 # elif defined (HPPA)
1221 #  define arg0_offset    PT_GR26
1222 #  define arg1_offset    (PT_GR26-4)
1223 # elif defined (X86_64)
1224 #  define arg0_offset   ((long)(8*(current_personality ? RBX : RDI)))
1225 #  define arg1_offset   ((long)(8*(current_personality ? RCX : RSI)))
1226 # else
1227 #  define arg0_offset   0
1228 #  define arg1_offset   4
1229 #  if defined SH || defined ARM
1230 #   define restore_arg0(tcp, state, val) 0
1231 #  endif
1232 # endif
1233
1234 typedef int arg_setup_state;
1235
1236 # define arg_setup(tcp, state) (0)
1237 # define arg_finish_change(tcp, state)  0
1238 # define get_arg0(tcp, cookie, valp) \
1239   (upeek ((tcp)->pid, arg0_offset, (valp)))
1240 # define get_arg1(tcp, cookie, valp) \
1241   (upeek ((tcp)->pid, arg1_offset, (valp)))
1242
1243 static int
1244 set_arg0 (struct tcb *tcp, void *cookie, long val)
1245 {
1246         return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1247 }
1248
1249 static int
1250 set_arg1 (struct tcb *tcp, void *cookie, long val)
1251 {
1252         return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1253 }
1254
1255 #endif
1256
1257 #ifndef restore_arg0
1258 # define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1259 #endif
1260 #ifndef restore_arg1
1261 # define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1262 #endif
1263
1264 int
1265 setbpt(tcp)
1266 struct tcb *tcp;
1267 {
1268         extern int change_syscall(struct tcb *, int);
1269         arg_setup_state state;
1270
1271         if (tcp->flags & TCB_BPTSET) {
1272                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1273                 return -1;
1274         }
1275
1276         switch (tcp->scno) {
1277 #ifdef SYS_vfork
1278         case SYS_vfork:
1279 #endif
1280 #ifdef SYS_fork
1281         case SYS_fork:
1282 #endif
1283 #if defined SYS_fork || defined SYS_vfork
1284                 if (arg_setup (tcp, &state) < 0
1285                     || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1286                     || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1287                     || change_syscall(tcp, SYS_clone) < 0
1288                     || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1289                     || set_arg1 (tcp, &state, 0) < 0
1290                     || arg_finish_change (tcp, &state) < 0)
1291                         return -1;
1292                 tcp->u_arg[0] = CLONE_PTRACE|SIGCHLD;
1293                 tcp->u_arg[1] = 0;
1294                 tcp->flags |= TCB_BPTSET;
1295                 return 0;
1296 #endif
1297
1298         case SYS_clone:
1299 #ifdef SYS_clone2
1300         case SYS_clone2:
1301 #endif
1302                 if ((tcp->u_arg[0] & CLONE_PTRACE) == 0
1303                     && (arg_setup (tcp, &state) < 0
1304                         || set_arg0 (tcp, &state, tcp->u_arg[0] | CLONE_PTRACE) < 0
1305                         || arg_finish_change (tcp, &state) < 0))
1306                         return -1;
1307                 tcp->flags |= TCB_BPTSET;
1308                 tcp->inst[0] = tcp->u_arg[0];
1309                 tcp->inst[1] = tcp->u_arg[1];
1310                 return 0;
1311
1312         default:
1313                 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1314                         tcp->scno, tcp->pid);
1315                 break;
1316         }
1317
1318         return -1;
1319 }
1320
1321 int
1322 clearbpt(tcp)
1323 struct tcb *tcp;
1324 {
1325         arg_setup_state state;
1326         if (arg_setup (tcp, &state) < 0
1327             || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1328             || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1329             || arg_finish_change (tcp, &state))
1330                 return -1;
1331         tcp->flags &= ~TCB_BPTSET;
1332         return 0;
1333 }
1334
1335 #else
1336
1337 int
1338 setbpt(tcp)
1339 struct tcb *tcp;
1340 {
1341
1342 #ifdef LINUX
1343 #ifdef SPARC
1344         /* We simply use the SunOS breakpoint code. */
1345
1346         struct regs regs;
1347 #define LOOPA   0x30800000      /* ba,a 0 */
1348
1349         if (tcp->flags & TCB_BPTSET) {
1350                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1351                 return -1;
1352         }
1353         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1354                 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1355                 return -1;
1356         }
1357         tcp->baddr = regs.r_o7 + 8;
1358         errno = 0;
1359         tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1360         if(errno) {
1361                 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1362                 return -1;
1363         }
1364
1365         /*
1366          * XXX - BRUTAL MODE ON
1367          * We cannot set a real BPT in the child, since it will not be
1368          * traced at the moment it will reach the trap and would probably
1369          * die with a core dump.
1370          * Thus, we are force our way in by taking out two instructions
1371          * and insert an eternal loop instead, in expectance of the SIGSTOP
1372          * generated by out PTRACE_ATTACH.
1373          * Of cause, if we evaporate ourselves in the middle of all this...
1374          */
1375         errno = 0;
1376         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);
1377         if(errno) {
1378                 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1379                 return -1;
1380         }
1381         tcp->flags |= TCB_BPTSET;
1382
1383 #else /* !SPARC */
1384 #ifdef IA64
1385         if (ia32) {
1386 #               define LOOP     0x0000feeb
1387                 if (tcp->flags & TCB_BPTSET) {
1388                         fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1389                                 tcp->pid);
1390                         return -1;
1391                 }
1392                 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1393                         return -1;
1394                 if (debug)
1395                         fprintf(stderr, "[%d] setting bpt at %lx\n",
1396                                 tcp->pid, tcp->baddr);
1397                 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1398                                       (char *) tcp->baddr, 0);
1399                 if (errno) {
1400                         perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1401                         return -1;
1402                 }
1403                 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1404                 if (errno) {
1405                         perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1406                         return -1;
1407                 }
1408                 tcp->flags |= TCB_BPTSET;
1409         } else {
1410                 /*
1411                  * Our strategy here is to replace the bundle that
1412                  * contained the clone() syscall with a bundle of the
1413                  * form:
1414                  *
1415                  *      { 1: br 1b; br 1b; br 1b }
1416                  *
1417                  * This ensures that the newly forked child will loop
1418                  * endlessly until we've got a chance to attach to it.
1419                  */
1420 #               define LOOP0    0x0000100000000017
1421 #               define LOOP1    0x4000000000200000
1422                 unsigned long addr, ipsr;
1423                 pid_t pid;
1424
1425                 pid = tcp->pid;
1426                 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1427                         return -1;
1428                 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1429                         return -1;
1430                 /* store "ri" in low two bits */
1431                 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
1432
1433                 errno = 0;
1434                 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1435                                       0);
1436                 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1437                                       0);
1438                 if (errno) {
1439                         perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1440                         return -1;
1441                 }
1442
1443                 errno = 0;
1444                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1445                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1446                 if (errno) {
1447                         perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1448                         return -1;
1449                 }
1450                 tcp->flags |= TCB_BPTSET;
1451         }
1452 #else /* !IA64 */
1453
1454 #if defined (I386) || defined(X86_64)
1455 #define LOOP    0x0000feeb
1456 #elif defined (M68K)
1457 #define LOOP    0x60fe0000
1458 #elif defined (ALPHA)
1459 #define LOOP    0xc3ffffff
1460 #elif defined (POWERPC)
1461 #define LOOP    0x48000000
1462 #elif defined(ARM)
1463 #define LOOP    0xEAFFFFFE
1464 #elif defined(MIPS)
1465 #define LOOP    0x1000ffff
1466 #elif defined(S390)
1467 #define LOOP    0xa7f40000      /* BRC 15,0 */
1468 #elif defined(S390X)
1469 #define LOOP   0xa7f4000000000000UL /* BRC 15,0 */
1470 #elif defined(HPPA)
1471 #define LOOP    0xe81f1ff7      /* b,l,n <loc>,r0 */
1472 #elif defined(SH)
1473 #ifdef __LITTLE_ENDIAN__
1474 #define LOOP   0x0000affe
1475 #else
1476 #define LOOP   0xfeaf0000
1477 #endif
1478 #else
1479 #error unknown architecture
1480 #endif
1481
1482         if (tcp->flags & TCB_BPTSET) {
1483                 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1484                 return -1;
1485         }
1486 #if defined (I386)
1487         if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1488                 return -1;
1489 #elif defined (X86_64)
1490         if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1491                 return -1;
1492 #elif defined (M68K)
1493         if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1494           return -1;
1495 #elif defined (ALPHA)
1496         return -1;
1497 #elif defined (ARM)
1498         return -1;
1499 #elif defined (MIPS)
1500         return -1;              /* FIXME: I do not know what i do - Flo */
1501 #elif defined (POWERPC)
1502         if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
1503                 return -1;
1504 #elif defined(S390) || defined(S390X)
1505         if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1506                 return -1;
1507 #elif defined(HPPA)
1508         if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1509                 return -1;
1510         tcp->baddr &= ~0x03;
1511 #elif defined(SH)
1512        if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1513                return -1;
1514 #else
1515 #error unknown architecture
1516 #endif
1517         if (debug)
1518                 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1519         tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1520         if (errno) {
1521                 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1522                 return -1;
1523         }
1524         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1525         if (errno) {
1526                 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1527                 return -1;
1528         }
1529         tcp->flags |= TCB_BPTSET;
1530
1531 #endif /* !IA64 */
1532 #endif /* SPARC */
1533 #endif /* LINUX */
1534
1535 #ifdef SUNOS4
1536 #ifdef SPARC    /* This code is slightly sparc specific */
1537
1538         struct regs regs;
1539 #define BPT     0x91d02001      /* ta   1 */
1540 #define LOOP    0x10800000      /* ba   0 */
1541 #define LOOPA   0x30800000      /* ba,a 0 */
1542 #define NOP     0x01000000
1543 #if LOOPA
1544         static int loopdeloop[1] = {LOOPA};
1545 #else
1546         static int loopdeloop[2] = {LOOP, NOP};
1547 #endif
1548
1549         if (tcp->flags & TCB_BPTSET) {
1550                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1551                 return -1;
1552         }
1553         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1554                 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1555                 return -1;
1556         }
1557         tcp->baddr = regs.r_o7 + 8;
1558         if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1559                                 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1560                 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1561                 return -1;
1562         }
1563
1564         /*
1565          * XXX - BRUTAL MODE ON
1566          * We cannot set a real BPT in the child, since it will not be
1567          * traced at the moment it will reach the trap and would probably
1568          * die with a core dump.
1569          * Thus, we are force our way in by taking out two instructions
1570          * and insert an eternal loop in stead, in expectance of the SIGSTOP
1571          * generated by out PTRACE_ATTACH.
1572          * Of cause, if we evaporate ourselves in the middle of all this...
1573          */
1574         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1575                         sizeof loopdeloop, (char *) loopdeloop) < 0) {
1576                 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1577                 return -1;
1578         }
1579         tcp->flags |= TCB_BPTSET;
1580
1581 #endif /* SPARC */
1582 #endif /* SUNOS4 */
1583
1584         return 0;
1585 }
1586
1587 int
1588 clearbpt(tcp)
1589 struct tcb *tcp;
1590 {
1591
1592 #ifdef LINUX
1593 #if defined(I386) || defined(X86_64)
1594         long eip;
1595 #elif defined(POWERPC)
1596         long pc;
1597 #elif defined(M68K)
1598         long pc;
1599 #elif defined(ALPHA)
1600         long pc;
1601 #elif defined(HPPA)
1602         long iaoq;
1603 #elif defined(SH)
1604        long pc;
1605 #endif /* architecture */
1606
1607 #ifdef SPARC
1608         /* Again, we borrow the SunOS breakpoint code. */
1609         if (!(tcp->flags & TCB_BPTSET)) {
1610                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1611                 return -1;
1612         }
1613         errno = 0;
1614         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1615         if(errno) {
1616                 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1617                 return -1;
1618         }
1619         tcp->flags &= ~TCB_BPTSET;
1620 #elif defined(IA64)
1621         if (ia32) {
1622                 unsigned long addr;
1623
1624                 if (debug)
1625                         fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1626                 if (!(tcp->flags & TCB_BPTSET)) {
1627                         fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1628                         return -1;
1629                 }
1630                 errno = 0;
1631                 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1632                 if (errno) {
1633                         perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1634                         return -1;
1635                 }
1636                 tcp->flags &= ~TCB_BPTSET;
1637
1638                 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1639                         return -1;
1640                 if (addr != tcp->baddr) {
1641                         /* The breakpoint has not been reached yet.  */
1642                         if (debug)
1643                                 fprintf(stderr,
1644                                         "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1645                                                 addr, tcp->baddr);
1646                         return 0;
1647                 }
1648         } else {
1649                 unsigned long addr, ipsr;
1650                 pid_t pid;
1651
1652                 pid = tcp->pid;
1653
1654                 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1655                         return -1;
1656                 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1657                         return -1;
1658
1659                 /* restore original bundle: */
1660                 errno = 0;
1661                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1662                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1663                 if (errno) {
1664                         perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1665                         return -1;
1666                 }
1667
1668                 /* restore original "ri" in ipsr: */
1669                 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1670                 errno = 0;
1671                 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1672                 if (errno) {
1673                         perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1674                         return -1;
1675                 }
1676
1677                 tcp->flags &= ~TCB_BPTSET;
1678
1679                 if (addr != (tcp->baddr & ~0x3)) {
1680                         /* the breakpoint has not been reached yet.  */
1681                         if (debug)
1682                                 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1683                                         addr, tcp->baddr);
1684                         return 0;
1685                 }
1686         }
1687 #else /* !IA64  && ! SPARC */
1688
1689         if (debug)
1690                 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1691         if (!(tcp->flags & TCB_BPTSET)) {
1692                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1693                 return -1;
1694         }
1695         errno = 0;
1696         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1697         if (errno) {
1698                 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1699                 return -1;
1700         }
1701         tcp->flags &= ~TCB_BPTSET;
1702
1703 #ifdef I386
1704         if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1705                 return -1;
1706         if (eip != tcp->baddr) {
1707                 /* The breakpoint has not been reached yet.  */
1708                 if (debug)
1709                         fprintf(stderr,
1710                                 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1711                                         eip, tcp->baddr);
1712                 return 0;
1713         }
1714 #elif defined(X86_64)
1715         if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1716                 return -1;
1717         if (eip != tcp->baddr) {
1718                 /* The breakpoint has not been reached yet.  */
1719                 if (debug)
1720                         fprintf(stderr,
1721                                 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1722                                         eip, tcp->baddr);
1723                 return 0;
1724         }
1725 #elif defined(POWERPC)
1726         if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1727                 return -1;
1728         if (pc != tcp->baddr) {
1729                 /* The breakpoint has not been reached yet.  */
1730                 if (debug)
1731                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1732                                 pc, tcp->baddr);
1733                 return 0;
1734         }
1735 #elif defined(M68K)
1736         if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1737                 return -1;
1738         if (pc != tcp->baddr) {
1739                 /* The breakpoint has not been reached yet.  */
1740                 if (debug)
1741                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1742                                 pc, tcp->baddr);
1743                 return 0;
1744         }
1745 #elif defined(ALPHA)
1746         if (upeek(tcp->pid, REG_PC, &pc) < 0)
1747                 return -1;
1748         if (pc != tcp->baddr) {
1749                 /* The breakpoint has not been reached yet.  */
1750                 if (debug)
1751                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1752                                 pc, tcp->baddr);
1753                 return 0;
1754         }
1755 #elif defined(HPPA)
1756         if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1757                 return -1;
1758         iaoq &= ~0x03;
1759         if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1760                 /* The breakpoint has not been reached yet.  */
1761                 if (debug)
1762                         fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1763                                 iaoq, tcp->baddr);
1764                 return 0;
1765         }
1766         iaoq = tcp->baddr | 3;
1767         /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1768          * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1769          * has no significant effect.
1770          */
1771         ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1772         ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
1773 #elif defined(SH)
1774        if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1775                return -1;
1776         if (pc != tcp->baddr) {
1777                 /* The breakpoint has not been reached yet.  */
1778                 if (debug)
1779                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1780                                 pc, tcp->baddr);
1781                 return 0;
1782         }
1783
1784 #endif /* arch */
1785 #endif /* !SPARC && !IA64 */
1786 #endif /* LINUX */
1787
1788 #ifdef SUNOS4
1789 #ifdef SPARC
1790
1791 #if !LOOPA
1792         struct regs regs;
1793 #endif
1794
1795         if (!(tcp->flags & TCB_BPTSET)) {
1796                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1797                 return -1;
1798         }
1799         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1800                                 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1801                 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1802                 return -1;
1803         }
1804         tcp->flags &= ~TCB_BPTSET;
1805
1806 #if !LOOPA
1807         /*
1808          * Since we don't have a single instruction breakpoint, we may have
1809          * to adjust the program counter after removing the our `breakpoint'.
1810          */
1811         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1812                 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1813                 return -1;
1814         }
1815         if ((regs.r_pc < tcp->baddr) ||
1816                                 (regs.r_pc > tcp->baddr + 4)) {
1817                 /* The breakpoint has not been reached yet */
1818                 if (debug)
1819                         fprintf(stderr,
1820                                 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1821                                         regs.r_pc, tcp->parent->baddr);
1822                 return 0;
1823         }
1824         if (regs.r_pc != tcp->baddr)
1825                 if (debug)
1826                         fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1827                                 regs.r_pc, tcp->baddr);
1828
1829         regs.r_pc = tcp->baddr;
1830         if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1831                 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1832                 return -1;
1833         }
1834 #endif /* LOOPA */
1835 #endif /* SPARC */
1836 #endif /* SUNOS4 */
1837
1838         return 0;
1839 }
1840
1841 #endif
1842
1843 #endif /* !USE_PROCFS */
1844
1845 #ifdef SUNOS4
1846
1847 static int
1848 getex(pid, hdr)
1849 int pid;
1850 struct exec *hdr;
1851 {
1852         int n;
1853
1854         for (n = 0; n < sizeof *hdr; n += 4) {
1855                 long res;
1856                 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1857                         return -1;
1858                 memcpy(((char *) hdr) + n, &res, 4);
1859         }
1860         if (debug) {
1861                 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1862                         hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1863                 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1864                         hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1865         }
1866         return 0;
1867 }
1868
1869 int
1870 fixvfork(tcp)
1871 struct tcb *tcp;
1872 {
1873         int pid = tcp->pid;
1874         /*
1875          * Change `vfork' in a freshly exec'ed dynamically linked
1876          * executable's (internal) symbol table to plain old `fork'
1877          */
1878
1879         struct exec hdr;
1880         struct link_dynamic dyn;
1881         struct link_dynamic_2 ld;
1882         char *strtab, *cp;
1883
1884         if (getex(pid, &hdr) < 0)
1885                 return -1;
1886         if (!hdr.a_dynamic)
1887                 return -1;
1888
1889         if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1890                 fprintf(stderr, "Cannot read DYNAMIC\n");
1891                 return -1;
1892         }
1893         if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1894                 fprintf(stderr, "Cannot read link_dynamic_2\n");
1895                 return -1;
1896         }
1897         if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1898                 fprintf(stderr, "fixvfork: out of memory\n");
1899                 return -1;
1900         }
1901         if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1902                                         (int)ld.ld_symb_size, strtab) < 0)
1903                 goto err;
1904
1905 #if 0
1906         for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1907                 fprintf(stderr, "[symbol: %s]\n", cp);
1908                 cp += strlen(cp)+1;
1909         }
1910         return 0;
1911 #endif
1912         for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1913                 if (strcmp(cp, "_vfork") == 0) {
1914                         if (debug)
1915                                 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1916                         strcpy(cp, "_fork");
1917                         break;
1918                 }
1919                 cp += strlen(cp)+1;
1920         }
1921         if (cp < strtab + ld.ld_symb_size)
1922                 /*
1923                  * Write entire symbol table back to avoid
1924                  * memory alignment bugs in ptrace
1925                  */
1926                 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1927                                         (int)ld.ld_symb_size, strtab) < 0)
1928                         goto err;
1929
1930         free(strtab);
1931         return 0;
1932
1933 err:
1934         free(strtab);
1935         return -1;
1936 }
1937
1938 #endif /* SUNOS4 */