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