]> 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 # elif defined (SH)
1227 #  define arg0_offset   (4*(REG_REG0+4))
1228 #  define arg1_offset   (4*(REG_REG0+5))
1229 # else
1230 #  define arg0_offset   0
1231 #  define arg1_offset   4
1232 #  if defined ARM
1233 #   define restore_arg0(tcp, state, val) 0
1234 #  endif
1235 # endif
1236
1237 typedef int arg_setup_state;
1238
1239 # define arg_setup(tcp, state) (0)
1240 # define arg_finish_change(tcp, state)  0
1241 # define get_arg0(tcp, cookie, valp) \
1242   (upeek ((tcp)->pid, arg0_offset, (valp)))
1243 # define get_arg1(tcp, cookie, valp) \
1244   (upeek ((tcp)->pid, arg1_offset, (valp)))
1245
1246 static int
1247 set_arg0 (struct tcb *tcp, void *cookie, long val)
1248 {
1249         return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1250 }
1251
1252 static int
1253 set_arg1 (struct tcb *tcp, void *cookie, long val)
1254 {
1255         return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1256 }
1257
1258 #endif
1259
1260 #ifndef restore_arg0
1261 # define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1262 #endif
1263 #ifndef restore_arg1
1264 # define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1265 #endif
1266
1267 int
1268 setbpt(tcp)
1269 struct tcb *tcp;
1270 {
1271         extern int change_syscall(struct tcb *, int);
1272         arg_setup_state state;
1273
1274         if (tcp->flags & TCB_BPTSET) {
1275                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1276                 return -1;
1277         }
1278
1279         switch (tcp->scno) {
1280 #ifdef SYS_vfork
1281         case SYS_vfork:
1282 #endif
1283 #ifdef SYS_fork
1284         case SYS_fork:
1285 #endif
1286 #if defined SYS_fork || defined SYS_vfork
1287                 if (arg_setup (tcp, &state) < 0
1288                     || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1289                     || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1290                     || change_syscall(tcp, SYS_clone) < 0
1291                     || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1292                     || set_arg1 (tcp, &state, 0) < 0
1293                     || arg_finish_change (tcp, &state) < 0)
1294                         return -1;
1295                 tcp->u_arg[0] = CLONE_PTRACE|SIGCHLD;
1296                 tcp->u_arg[1] = 0;
1297                 tcp->flags |= TCB_BPTSET;
1298                 return 0;
1299 #endif
1300
1301         case SYS_clone:
1302 #ifdef SYS_clone2
1303         case SYS_clone2:
1304 #endif
1305                 if ((tcp->u_arg[0] & CLONE_PTRACE) == 0
1306                     && (arg_setup (tcp, &state) < 0
1307                         || set_arg0 (tcp, &state, tcp->u_arg[0] | CLONE_PTRACE) < 0
1308                         || arg_finish_change (tcp, &state) < 0))
1309                         return -1;
1310                 tcp->flags |= TCB_BPTSET;
1311                 tcp->inst[0] = tcp->u_arg[0];
1312                 tcp->inst[1] = tcp->u_arg[1];
1313                 return 0;
1314
1315         default:
1316                 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1317                         tcp->scno, tcp->pid);
1318                 break;
1319         }
1320
1321         return -1;
1322 }
1323
1324 int
1325 clearbpt(tcp)
1326 struct tcb *tcp;
1327 {
1328         arg_setup_state state;
1329         if (arg_setup (tcp, &state) < 0
1330             || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1331             || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1332             || arg_finish_change (tcp, &state))
1333                 return -1;
1334         tcp->flags &= ~TCB_BPTSET;
1335         return 0;
1336 }
1337
1338 #else
1339
1340 int
1341 setbpt(tcp)
1342 struct tcb *tcp;
1343 {
1344
1345 #ifdef LINUX
1346 #ifdef SPARC
1347         /* We simply use the SunOS breakpoint code. */
1348
1349         struct regs regs;
1350 #define LOOPA   0x30800000      /* ba,a 0 */
1351
1352         if (tcp->flags & TCB_BPTSET) {
1353                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1354                 return -1;
1355         }
1356         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1357                 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1358                 return -1;
1359         }
1360         tcp->baddr = regs.r_o7 + 8;
1361         errno = 0;
1362         tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1363         if(errno) {
1364                 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1365                 return -1;
1366         }
1367
1368         /*
1369          * XXX - BRUTAL MODE ON
1370          * We cannot set a real BPT in the child, since it will not be
1371          * traced at the moment it will reach the trap and would probably
1372          * die with a core dump.
1373          * Thus, we are force our way in by taking out two instructions
1374          * and insert an eternal loop instead, in expectance of the SIGSTOP
1375          * generated by out PTRACE_ATTACH.
1376          * Of cause, if we evaporate ourselves in the middle of all this...
1377          */
1378         errno = 0;
1379         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);
1380         if(errno) {
1381                 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1382                 return -1;
1383         }
1384         tcp->flags |= TCB_BPTSET;
1385
1386 #else /* !SPARC */
1387 #ifdef IA64
1388         if (ia32) {
1389 #               define LOOP     0x0000feeb
1390                 if (tcp->flags & TCB_BPTSET) {
1391                         fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1392                                 tcp->pid);
1393                         return -1;
1394                 }
1395                 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1396                         return -1;
1397                 if (debug)
1398                         fprintf(stderr, "[%d] setting bpt at %lx\n",
1399                                 tcp->pid, tcp->baddr);
1400                 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1401                                       (char *) tcp->baddr, 0);
1402                 if (errno) {
1403                         perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1404                         return -1;
1405                 }
1406                 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1407                 if (errno) {
1408                         perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1409                         return -1;
1410                 }
1411                 tcp->flags |= TCB_BPTSET;
1412         } else {
1413                 /*
1414                  * Our strategy here is to replace the bundle that
1415                  * contained the clone() syscall with a bundle of the
1416                  * form:
1417                  *
1418                  *      { 1: br 1b; br 1b; br 1b }
1419                  *
1420                  * This ensures that the newly forked child will loop
1421                  * endlessly until we've got a chance to attach to it.
1422                  */
1423 #               define LOOP0    0x0000100000000017
1424 #               define LOOP1    0x4000000000200000
1425                 unsigned long addr, ipsr;
1426                 pid_t pid;
1427
1428                 pid = tcp->pid;
1429                 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1430                         return -1;
1431                 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1432                         return -1;
1433                 /* store "ri" in low two bits */
1434                 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
1435
1436                 errno = 0;
1437                 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1438                                       0);
1439                 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1440                                       0);
1441                 if (errno) {
1442                         perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1443                         return -1;
1444                 }
1445
1446                 errno = 0;
1447                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1448                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1449                 if (errno) {
1450                         perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1451                         return -1;
1452                 }
1453                 tcp->flags |= TCB_BPTSET;
1454         }
1455 #else /* !IA64 */
1456
1457 #if defined (I386) || defined(X86_64)
1458 #define LOOP    0x0000feeb
1459 #elif defined (M68K)
1460 #define LOOP    0x60fe0000
1461 #elif defined (ALPHA)
1462 #define LOOP    0xc3ffffff
1463 #elif defined (POWERPC)
1464 #define LOOP    0x48000000
1465 #elif defined(ARM)
1466 #define LOOP    0xEAFFFFFE
1467 #elif defined(MIPS)
1468 #define LOOP    0x1000ffff
1469 #elif defined(S390)
1470 #define LOOP    0xa7f40000      /* BRC 15,0 */
1471 #elif defined(S390X)
1472 #define LOOP   0xa7f4000000000000UL /* BRC 15,0 */
1473 #elif defined(HPPA)
1474 #define LOOP    0xe81f1ff7      /* b,l,n <loc>,r0 */
1475 #elif defined(SH)
1476 #ifdef __LITTLE_ENDIAN__
1477 #define LOOP   0x0000affe
1478 #else
1479 #define LOOP   0xfeaf0000
1480 #endif
1481 #else
1482 #error unknown architecture
1483 #endif
1484
1485         if (tcp->flags & TCB_BPTSET) {
1486                 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1487                 return -1;
1488         }
1489 #if defined (I386)
1490         if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1491                 return -1;
1492 #elif defined (X86_64)
1493         if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1494                 return -1;
1495 #elif defined (M68K)
1496         if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1497           return -1;
1498 #elif defined (ALPHA)
1499         return -1;
1500 #elif defined (ARM)
1501         return -1;
1502 #elif defined (MIPS)
1503         return -1;              /* FIXME: I do not know what i do - Flo */
1504 #elif defined (POWERPC)
1505         if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
1506                 return -1;
1507 #elif defined(S390) || defined(S390X)
1508         if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1509                 return -1;
1510 #elif defined(HPPA)
1511         if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1512                 return -1;
1513         tcp->baddr &= ~0x03;
1514 #elif defined(SH)
1515        if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1516                return -1;
1517 #else
1518 #error unknown architecture
1519 #endif
1520         if (debug)
1521                 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1522         tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1523         if (errno) {
1524                 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1525                 return -1;
1526         }
1527         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1528         if (errno) {
1529                 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1530                 return -1;
1531         }
1532         tcp->flags |= TCB_BPTSET;
1533
1534 #endif /* !IA64 */
1535 #endif /* SPARC */
1536 #endif /* LINUX */
1537
1538 #ifdef SUNOS4
1539 #ifdef SPARC    /* This code is slightly sparc specific */
1540
1541         struct regs regs;
1542 #define BPT     0x91d02001      /* ta   1 */
1543 #define LOOP    0x10800000      /* ba   0 */
1544 #define LOOPA   0x30800000      /* ba,a 0 */
1545 #define NOP     0x01000000
1546 #if LOOPA
1547         static int loopdeloop[1] = {LOOPA};
1548 #else
1549         static int loopdeloop[2] = {LOOP, NOP};
1550 #endif
1551
1552         if (tcp->flags & TCB_BPTSET) {
1553                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1554                 return -1;
1555         }
1556         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1557                 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1558                 return -1;
1559         }
1560         tcp->baddr = regs.r_o7 + 8;
1561         if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1562                                 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1563                 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1564                 return -1;
1565         }
1566
1567         /*
1568          * XXX - BRUTAL MODE ON
1569          * We cannot set a real BPT in the child, since it will not be
1570          * traced at the moment it will reach the trap and would probably
1571          * die with a core dump.
1572          * Thus, we are force our way in by taking out two instructions
1573          * and insert an eternal loop in stead, in expectance of the SIGSTOP
1574          * generated by out PTRACE_ATTACH.
1575          * Of cause, if we evaporate ourselves in the middle of all this...
1576          */
1577         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1578                         sizeof loopdeloop, (char *) loopdeloop) < 0) {
1579                 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1580                 return -1;
1581         }
1582         tcp->flags |= TCB_BPTSET;
1583
1584 #endif /* SPARC */
1585 #endif /* SUNOS4 */
1586
1587         return 0;
1588 }
1589
1590 int
1591 clearbpt(tcp)
1592 struct tcb *tcp;
1593 {
1594
1595 #ifdef LINUX
1596 #if defined(I386) || defined(X86_64)
1597         long eip;
1598 #elif defined(POWERPC)
1599         long pc;
1600 #elif defined(M68K)
1601         long pc;
1602 #elif defined(ALPHA)
1603         long pc;
1604 #elif defined(HPPA)
1605         long iaoq;
1606 #elif defined(SH)
1607        long pc;
1608 #endif /* architecture */
1609
1610 #ifdef SPARC
1611         /* Again, we borrow the SunOS breakpoint code. */
1612         if (!(tcp->flags & TCB_BPTSET)) {
1613                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1614                 return -1;
1615         }
1616         errno = 0;
1617         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1618         if(errno) {
1619                 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1620                 return -1;
1621         }
1622         tcp->flags &= ~TCB_BPTSET;
1623 #elif defined(IA64)
1624         if (ia32) {
1625                 unsigned long addr;
1626
1627                 if (debug)
1628                         fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1629                 if (!(tcp->flags & TCB_BPTSET)) {
1630                         fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1631                         return -1;
1632                 }
1633                 errno = 0;
1634                 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1635                 if (errno) {
1636                         perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1637                         return -1;
1638                 }
1639                 tcp->flags &= ~TCB_BPTSET;
1640
1641                 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1642                         return -1;
1643                 if (addr != tcp->baddr) {
1644                         /* The breakpoint has not been reached yet.  */
1645                         if (debug)
1646                                 fprintf(stderr,
1647                                         "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1648                                                 addr, tcp->baddr);
1649                         return 0;
1650                 }
1651         } else {
1652                 unsigned long addr, ipsr;
1653                 pid_t pid;
1654
1655                 pid = tcp->pid;
1656
1657                 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1658                         return -1;
1659                 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1660                         return -1;
1661
1662                 /* restore original bundle: */
1663                 errno = 0;
1664                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1665                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1666                 if (errno) {
1667                         perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1668                         return -1;
1669                 }
1670
1671                 /* restore original "ri" in ipsr: */
1672                 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1673                 errno = 0;
1674                 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1675                 if (errno) {
1676                         perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1677                         return -1;
1678                 }
1679
1680                 tcp->flags &= ~TCB_BPTSET;
1681
1682                 if (addr != (tcp->baddr & ~0x3)) {
1683                         /* the breakpoint has not been reached yet.  */
1684                         if (debug)
1685                                 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1686                                         addr, tcp->baddr);
1687                         return 0;
1688                 }
1689         }
1690 #else /* !IA64  && ! SPARC */
1691
1692         if (debug)
1693                 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1694         if (!(tcp->flags & TCB_BPTSET)) {
1695                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1696                 return -1;
1697         }
1698         errno = 0;
1699         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1700         if (errno) {
1701                 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1702                 return -1;
1703         }
1704         tcp->flags &= ~TCB_BPTSET;
1705
1706 #ifdef I386
1707         if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1708                 return -1;
1709         if (eip != tcp->baddr) {
1710                 /* The breakpoint has not been reached yet.  */
1711                 if (debug)
1712                         fprintf(stderr,
1713                                 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1714                                         eip, tcp->baddr);
1715                 return 0;
1716         }
1717 #elif defined(X86_64)
1718         if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1719                 return -1;
1720         if (eip != tcp->baddr) {
1721                 /* The breakpoint has not been reached yet.  */
1722                 if (debug)
1723                         fprintf(stderr,
1724                                 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1725                                         eip, tcp->baddr);
1726                 return 0;
1727         }
1728 #elif defined(POWERPC)
1729         if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1730                 return -1;
1731         if (pc != tcp->baddr) {
1732                 /* The breakpoint has not been reached yet.  */
1733                 if (debug)
1734                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1735                                 pc, tcp->baddr);
1736                 return 0;
1737         }
1738 #elif defined(M68K)
1739         if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1740                 return -1;
1741         if (pc != tcp->baddr) {
1742                 /* The breakpoint has not been reached yet.  */
1743                 if (debug)
1744                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1745                                 pc, tcp->baddr);
1746                 return 0;
1747         }
1748 #elif defined(ALPHA)
1749         if (upeek(tcp->pid, REG_PC, &pc) < 0)
1750                 return -1;
1751         if (pc != tcp->baddr) {
1752                 /* The breakpoint has not been reached yet.  */
1753                 if (debug)
1754                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1755                                 pc, tcp->baddr);
1756                 return 0;
1757         }
1758 #elif defined(HPPA)
1759         if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1760                 return -1;
1761         iaoq &= ~0x03;
1762         if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1763                 /* The breakpoint has not been reached yet.  */
1764                 if (debug)
1765                         fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1766                                 iaoq, tcp->baddr);
1767                 return 0;
1768         }
1769         iaoq = tcp->baddr | 3;
1770         /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1771          * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1772          * has no significant effect.
1773          */
1774         ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1775         ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
1776 #elif defined(SH)
1777        if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1778                return -1;
1779         if (pc != tcp->baddr) {
1780                 /* The breakpoint has not been reached yet.  */
1781                 if (debug)
1782                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1783                                 pc, tcp->baddr);
1784                 return 0;
1785         }
1786
1787 #endif /* arch */
1788 #endif /* !SPARC && !IA64 */
1789 #endif /* LINUX */
1790
1791 #ifdef SUNOS4
1792 #ifdef SPARC
1793
1794 #if !LOOPA
1795         struct regs regs;
1796 #endif
1797
1798         if (!(tcp->flags & TCB_BPTSET)) {
1799                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1800                 return -1;
1801         }
1802         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1803                                 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1804                 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1805                 return -1;
1806         }
1807         tcp->flags &= ~TCB_BPTSET;
1808
1809 #if !LOOPA
1810         /*
1811          * Since we don't have a single instruction breakpoint, we may have
1812          * to adjust the program counter after removing the our `breakpoint'.
1813          */
1814         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1815                 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1816                 return -1;
1817         }
1818         if ((regs.r_pc < tcp->baddr) ||
1819                                 (regs.r_pc > tcp->baddr + 4)) {
1820                 /* The breakpoint has not been reached yet */
1821                 if (debug)
1822                         fprintf(stderr,
1823                                 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1824                                         regs.r_pc, tcp->parent->baddr);
1825                 return 0;
1826         }
1827         if (regs.r_pc != tcp->baddr)
1828                 if (debug)
1829                         fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1830                                 regs.r_pc, tcp->baddr);
1831
1832         regs.r_pc = tcp->baddr;
1833         if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1834                 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1835                 return -1;
1836         }
1837 #endif /* LOOPA */
1838 #endif /* SPARC */
1839 #endif /* SUNOS4 */
1840
1841         return 0;
1842 }
1843
1844 #endif
1845
1846 #endif /* !USE_PROCFS */
1847
1848 #ifdef SUNOS4
1849
1850 static int
1851 getex(pid, hdr)
1852 int pid;
1853 struct exec *hdr;
1854 {
1855         int n;
1856
1857         for (n = 0; n < sizeof *hdr; n += 4) {
1858                 long res;
1859                 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1860                         return -1;
1861                 memcpy(((char *) hdr) + n, &res, 4);
1862         }
1863         if (debug) {
1864                 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1865                         hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1866                 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1867                         hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1868         }
1869         return 0;
1870 }
1871
1872 int
1873 fixvfork(tcp)
1874 struct tcb *tcp;
1875 {
1876         int pid = tcp->pid;
1877         /*
1878          * Change `vfork' in a freshly exec'ed dynamically linked
1879          * executable's (internal) symbol table to plain old `fork'
1880          */
1881
1882         struct exec hdr;
1883         struct link_dynamic dyn;
1884         struct link_dynamic_2 ld;
1885         char *strtab, *cp;
1886
1887         if (getex(pid, &hdr) < 0)
1888                 return -1;
1889         if (!hdr.a_dynamic)
1890                 return -1;
1891
1892         if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1893                 fprintf(stderr, "Cannot read DYNAMIC\n");
1894                 return -1;
1895         }
1896         if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1897                 fprintf(stderr, "Cannot read link_dynamic_2\n");
1898                 return -1;
1899         }
1900         if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1901                 fprintf(stderr, "fixvfork: out of memory\n");
1902                 return -1;
1903         }
1904         if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1905                                         (int)ld.ld_symb_size, strtab) < 0)
1906                 goto err;
1907
1908 #if 0
1909         for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1910                 fprintf(stderr, "[symbol: %s]\n", cp);
1911                 cp += strlen(cp)+1;
1912         }
1913         return 0;
1914 #endif
1915         for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1916                 if (strcmp(cp, "_vfork") == 0) {
1917                         if (debug)
1918                                 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1919                         strcpy(cp, "_fork");
1920                         break;
1921                 }
1922                 cp += strlen(cp)+1;
1923         }
1924         if (cp < strtab + ld.ld_symb_size)
1925                 /*
1926                  * Write entire symbol table back to avoid
1927                  * memory alignment bugs in ptrace
1928                  */
1929                 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1930                                         (int)ld.ld_symb_size, strtab) < 0)
1931                         goto err;
1932
1933         free(strtab);
1934         return 0;
1935
1936 err:
1937         free(strtab);
1938         return -1;
1939 }
1940
1941 #endif /* SUNOS4 */