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