]> granicus.if.org Git - strace/blob - util.c
2003-01-14 Roland McGrath <roland@redhat.com>
[strace] / util.c
1 /*
2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5  * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6  * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7  *                     Linux for s390 port by D.J. Barrow
8  *                    <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  *      $Id$
34  */
35
36 #include "defs.h"
37
38 #include <signal.h>
39 #include <sys/syscall.h>
40 #include <sys/user.h>
41 #include <sys/param.h>
42 #include <fcntl.h>
43 #if HAVE_SYS_UIO_H
44 #include <sys/uio.h>
45 #endif
46 #ifdef SUNOS4
47 #include <machine/reg.h>
48 #include <a.out.h>
49 #include <link.h>
50 #endif /* SUNOS4 */
51
52 #if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
53 #include <linux/ptrace.h>
54 #endif
55
56 #if defined(LINUX) && defined(IA64)
57 # include <asm/ptrace_offsets.h>
58 # include <asm/rse.h>
59 #endif
60
61 #ifdef HAVE_SYS_REG_H
62 #include <sys/reg.h>
63 # define PTRACE_PEEKUSR PTRACE_PEEKUSER
64 #elif defined(HAVE_LINUX_PTRACE_H)
65 #undef PTRACE_SYSCALL
66 #include <linux/ptrace.h>
67 #endif
68
69 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
70 #include <sys/utsname.h>
71 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
72
73 #if defined(LINUX) && defined(SPARC)
74
75 #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         int 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, 4*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, 4*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   (4*PT_R3)
1207 #  define arg1_offset   (4*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_fork
1267         case SYS_fork:
1268                 if (arg_setup (tcp, &state) < 0
1269                     || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1270                     || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1271                     || change_syscall(tcp, SYS_clone) < 0
1272                     || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1273                     || set_arg1 (tcp, &state, 0) < 0
1274                     || arg_finish_change (tcp, &state) < 0)
1275                         return -1;
1276                 tcp->u_arg[0] = CLONE_PTRACE|SIGCHLD;
1277                 tcp->u_arg[1] = 0;
1278                 tcp->flags |= TCB_BPTSET;
1279                 return 0;
1280 #endif
1281
1282         case SYS_clone:
1283 #ifdef SYS_clone2
1284         case SYS_clone2:
1285 #endif
1286                 if ((tcp->u_arg[0] & CLONE_PTRACE) == 0
1287                     && (arg_setup (tcp, &state) < 0
1288                         || set_arg0 (tcp, &state, tcp->u_arg[0] | CLONE_PTRACE) < 0
1289                         || arg_finish_change (tcp, &state) < 0))
1290                         return -1;
1291                 tcp->flags |= TCB_BPTSET;
1292                 tcp->inst[0] = tcp->u_arg[0];
1293                 tcp->inst[1] = tcp->u_arg[1];
1294                 return 0;
1295
1296         default:
1297                 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1298                         tcp->scno, tcp->pid);
1299                 break;
1300         }
1301
1302         return -1;
1303 }
1304
1305 int
1306 clearbpt(tcp)
1307 struct tcb *tcp;
1308 {
1309         arg_setup_state state;
1310         if (arg_setup (tcp, &state) < 0
1311             || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1312             || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1313             || arg_finish_change (tcp, &state))
1314                 return -1;
1315         tcp->flags &= ~TCB_BPTSET;
1316         return 0;
1317 }
1318
1319 #else
1320
1321 int
1322 setbpt(tcp)
1323 struct tcb *tcp;
1324 {
1325
1326 #ifdef LINUX
1327 #ifdef SPARC
1328         /* We simply use the SunOS breakpoint code. */
1329
1330         struct regs regs;
1331 #define LOOPA   0x30800000      /* ba,a 0 */
1332
1333         if (tcp->flags & TCB_BPTSET) {
1334                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1335                 return -1;
1336         }
1337         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1338                 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1339                 return -1;
1340         }
1341         tcp->baddr = regs.r_o7 + 8;
1342         errno = 0;
1343         tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1344         if(errno) {
1345                 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1346                 return -1;
1347         }
1348
1349         /*
1350          * XXX - BRUTAL MODE ON
1351          * We cannot set a real BPT in the child, since it will not be
1352          * traced at the moment it will reach the trap and would probably
1353          * die with a core dump.
1354          * Thus, we are force our way in by taking out two instructions
1355          * and insert an eternal loop instead, in expectance of the SIGSTOP
1356          * generated by out PTRACE_ATTACH.
1357          * Of cause, if we evaporate ourselves in the middle of all this...
1358          */
1359         errno = 0;
1360         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);
1361         if(errno) {
1362                 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1363                 return -1;
1364         }
1365         tcp->flags |= TCB_BPTSET;
1366
1367 #else /* !SPARC */
1368 #ifdef IA64
1369         if (ia32) {
1370 #               define LOOP     0x0000feeb
1371                 if (tcp->flags & TCB_BPTSET) {
1372                         fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1373                                 tcp->pid);
1374                         return -1;
1375                 }
1376                 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1377                         return -1;
1378                 if (debug)
1379                         fprintf(stderr, "[%d] setting bpt at %lx\n",
1380                                 tcp->pid, tcp->baddr);
1381                 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1382                                       (char *) tcp->baddr, 0);
1383                 if (errno) {
1384                         perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1385                         return -1;
1386                 }
1387                 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1388                 if (errno) {
1389                         perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1390                         return -1;
1391                 }
1392                 tcp->flags |= TCB_BPTSET;
1393         } else {
1394                 /*
1395                  * Our strategy here is to replace the bundle that
1396                  * contained the clone() syscall with a bundle of the
1397                  * form:
1398                  *
1399                  *      { 1: br 1b; br 1b; br 1b }
1400                  *
1401                  * This ensures that the newly forked child will loop
1402                  * endlessly until we've got a chance to attach to it.
1403                  */
1404 #               define LOOP0    0x0000100000000017
1405 #               define LOOP1    0x4000000000200000
1406                 unsigned long addr, ipsr;
1407                 pid_t pid;
1408
1409                 pid = tcp->pid;
1410                 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1411                         return -1;
1412                 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1413                         return -1;
1414                 /* store "ri" in low two bits */
1415                 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
1416
1417                 errno = 0;
1418                 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1419                                       0);
1420                 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1421                                       0);
1422                 if (errno) {
1423                         perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1424                         return -1;
1425                 }
1426
1427                 errno = 0;
1428                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1429                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1430                 if (errno) {
1431                         perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1432                         return -1;
1433                 }
1434                 tcp->flags |= TCB_BPTSET;
1435         }
1436 #else /* !IA64 */
1437
1438 #if defined (I386) || defined(X86_64)
1439 #define LOOP    0x0000feeb
1440 #elif defined (M68K)
1441 #define LOOP    0x60fe0000
1442 #elif defined (ALPHA)
1443 #define LOOP    0xc3ffffff
1444 #elif defined (POWERPC)
1445 #define LOOP    0x48000000
1446 #elif defined(ARM)
1447 #define LOOP    0xEAFFFFFE
1448 #elif defined(MIPS)
1449 #define LOOP    0x1000ffff
1450 #elif defined(S390)
1451 #define LOOP    0xa7f40000      /* BRC 15,0 */
1452 #elif defined(S390X)
1453 #define LOOP   0xa7f4000000000000UL /* BRC 15,0 */
1454 #elif defined(HPPA)
1455 #define LOOP    0xe81f1ff7      /* b,l,n <loc>,r0 */
1456 #elif defined(SH)
1457 #ifdef __LITTLE_ENDIAN__
1458 #define LOOP   0x0000affe
1459 #else
1460 #define LOOP   0xfeaf0000
1461 #endif
1462 #else
1463 #error unknown architecture
1464 #endif
1465
1466         if (tcp->flags & TCB_BPTSET) {
1467                 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1468                 return -1;
1469         }
1470 #if defined (I386)
1471         if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1472                 return -1;
1473 #elif defined (X86_64)
1474         if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1475                 return -1;
1476 #elif defined (M68K)
1477         if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1478           return -1;
1479 #elif defined (ALPHA)
1480         return -1;
1481 #elif defined (ARM)
1482         return -1;
1483 #elif defined (MIPS)
1484         return -1;              /* FIXME: I do not know what i do - Flo */
1485 #elif defined (POWERPC)
1486         if (upeek(tcp->pid, 4*PT_NIP, &tcp->baddr) < 0)
1487                 return -1;
1488 #elif defined(S390) || defined(S390X)
1489         if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1490                 return -1;
1491 #elif defined(HPPA)
1492         if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1493                 return -1;
1494         tcp->baddr &= ~0x03;
1495 #elif defined(SH)
1496        if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1497                return -1;
1498 #else
1499 #error unknown architecture
1500 #endif
1501         if (debug)
1502                 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1503         tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1504         if (errno) {
1505                 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1506                 return -1;
1507         }
1508         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1509         if (errno) {
1510                 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1511                 return -1;
1512         }
1513         tcp->flags |= TCB_BPTSET;
1514
1515 #endif /* !IA64 */
1516 #endif /* SPARC */
1517 #endif /* LINUX */
1518
1519 #ifdef SUNOS4
1520 #ifdef SPARC    /* This code is slightly sparc specific */
1521
1522         struct regs regs;
1523 #define BPT     0x91d02001      /* ta   1 */
1524 #define LOOP    0x10800000      /* ba   0 */
1525 #define LOOPA   0x30800000      /* ba,a 0 */
1526 #define NOP     0x01000000
1527 #if LOOPA
1528         static int loopdeloop[1] = {LOOPA};
1529 #else
1530         static int loopdeloop[2] = {LOOP, NOP};
1531 #endif
1532
1533         if (tcp->flags & TCB_BPTSET) {
1534                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1535                 return -1;
1536         }
1537         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1538                 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1539                 return -1;
1540         }
1541         tcp->baddr = regs.r_o7 + 8;
1542         if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1543                                 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1544                 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1545                 return -1;
1546         }
1547
1548         /*
1549          * XXX - BRUTAL MODE ON
1550          * We cannot set a real BPT in the child, since it will not be
1551          * traced at the moment it will reach the trap and would probably
1552          * die with a core dump.
1553          * Thus, we are force our way in by taking out two instructions
1554          * and insert an eternal loop in stead, in expectance of the SIGSTOP
1555          * generated by out PTRACE_ATTACH.
1556          * Of cause, if we evaporate ourselves in the middle of all this...
1557          */
1558         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1559                         sizeof loopdeloop, (char *) loopdeloop) < 0) {
1560                 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1561                 return -1;
1562         }
1563         tcp->flags |= TCB_BPTSET;
1564
1565 #endif /* SPARC */
1566 #endif /* SUNOS4 */
1567
1568         return 0;
1569 }
1570
1571 int
1572 clearbpt(tcp)
1573 struct tcb *tcp;
1574 {
1575
1576 #ifdef LINUX
1577 #if defined(I386) || defined(X86_64)
1578         long eip;
1579 #elif defined(POWERPC)
1580         long pc;
1581 #elif defined(M68K)
1582         long pc;
1583 #elif defined(ALPHA)
1584         long pc;
1585 #elif defined(HPPA)
1586         long iaoq;
1587 #elif defined(SH)
1588        long pc;
1589 #endif /* architecture */
1590
1591 #ifdef SPARC
1592         /* Again, we borrow the SunOS breakpoint code. */
1593         if (!(tcp->flags & TCB_BPTSET)) {
1594                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1595                 return -1;
1596         }
1597         errno = 0;
1598         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1599         if(errno) {
1600                 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1601                 return -1;
1602         }
1603         tcp->flags &= ~TCB_BPTSET;
1604 #elif defined(IA64)
1605         if (ia32) {
1606                 unsigned long addr;
1607
1608                 if (debug)
1609                         fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1610                 if (!(tcp->flags & TCB_BPTSET)) {
1611                         fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1612                         return -1;
1613                 }
1614                 errno = 0;
1615                 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1616                 if (errno) {
1617                         perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1618                         return -1;
1619                 }
1620                 tcp->flags &= ~TCB_BPTSET;
1621
1622                 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1623                         return -1;
1624                 if (addr != tcp->baddr) {
1625                         /* The breakpoint has not been reached yet.  */
1626                         if (debug)
1627                                 fprintf(stderr,
1628                                         "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1629                                                 addr, tcp->baddr);
1630                         return 0;
1631                 }
1632         } else {
1633                 unsigned long addr, ipsr;
1634                 pid_t pid;
1635
1636                 pid = tcp->pid;
1637
1638                 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1639                         return -1;
1640                 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1641                         return -1;
1642
1643                 /* restore original bundle: */
1644                 errno = 0;
1645                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1646                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1647                 if (errno) {
1648                         perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1649                         return -1;
1650                 }
1651
1652                 /* restore original "ri" in ipsr: */
1653                 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1654                 errno = 0;
1655                 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1656                 if (errno) {
1657                         perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1658                         return -1;
1659                 }
1660
1661                 tcp->flags &= ~TCB_BPTSET;
1662
1663                 if (addr != (tcp->baddr & ~0x3)) {
1664                         /* the breakpoint has not been reached yet.  */
1665                         if (debug)
1666                                 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1667                                         addr, tcp->baddr);
1668                         return 0;
1669                 }
1670         }
1671 #else /* !IA64  && ! SPARC */
1672
1673         if (debug)
1674                 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1675         if (!(tcp->flags & TCB_BPTSET)) {
1676                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1677                 return -1;
1678         }
1679         errno = 0;
1680         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1681         if (errno) {
1682                 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1683                 return -1;
1684         }
1685         tcp->flags &= ~TCB_BPTSET;
1686
1687 #ifdef I386
1688         if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1689                 return -1;
1690         if (eip != tcp->baddr) {
1691                 /* The breakpoint has not been reached yet.  */
1692                 if (debug)
1693                         fprintf(stderr,
1694                                 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1695                                         eip, tcp->baddr);
1696                 return 0;
1697         }
1698 #elif defined(X86_64)
1699         if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1700                 return -1;
1701         if (eip != tcp->baddr) {
1702                 /* The breakpoint has not been reached yet.  */
1703                 if (debug)
1704                         fprintf(stderr,
1705                                 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1706                                         eip, tcp->baddr);
1707                 return 0;
1708         }
1709 #elif defined(POWERPC)
1710         if (upeek(tcp->pid, 4*PT_NIP, &pc) < 0)
1711                 return -1;
1712         if (pc != tcp->baddr) {
1713                 /* The breakpoint has not been reached yet.  */
1714                 if (debug)
1715                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1716                                 pc, tcp->baddr);
1717                 return 0;
1718         }
1719 #elif defined(M68K)
1720         if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1721                 return -1;
1722         if (pc != tcp->baddr) {
1723                 /* The breakpoint has not been reached yet.  */
1724                 if (debug)
1725                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1726                                 pc, tcp->baddr);
1727                 return 0;
1728         }
1729 #elif defined(ALPHA)
1730         if (upeek(tcp->pid, REG_PC, &pc) < 0)
1731                 return -1;
1732         if (pc != tcp->baddr) {
1733                 /* The breakpoint has not been reached yet.  */
1734                 if (debug)
1735                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1736                                 pc, tcp->baddr);
1737                 return 0;
1738         }
1739 #elif defined(HPPA)
1740         if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1741                 return -1;
1742         iaoq &= ~0x03;
1743         if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1744                 /* The breakpoint has not been reached yet.  */
1745                 if (debug)
1746                         fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1747                                 iaoq, tcp->baddr);
1748                 return 0;
1749         }
1750         iaoq = tcp->baddr | 3;
1751         /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1752          * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1753          * has no significant effect.
1754          */
1755         ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1756         ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
1757 #elif defined(SH)
1758        if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1759                return -1;
1760         if (pc != tcp->baddr) {
1761                 /* The breakpoint has not been reached yet.  */
1762                 if (debug)
1763                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1764                                 pc, tcp->baddr);
1765                 return 0;
1766         }
1767
1768 #endif /* arch */
1769 #endif /* !SPARC && !IA64 */
1770 #endif /* LINUX */
1771
1772 #ifdef SUNOS4
1773 #ifdef SPARC
1774
1775 #if !LOOPA
1776         struct regs regs;
1777 #endif
1778
1779         if (!(tcp->flags & TCB_BPTSET)) {
1780                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1781                 return -1;
1782         }
1783         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1784                                 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1785                 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1786                 return -1;
1787         }
1788         tcp->flags &= ~TCB_BPTSET;
1789
1790 #if !LOOPA
1791         /*
1792          * Since we don't have a single instruction breakpoint, we may have
1793          * to adjust the program counter after removing the our `breakpoint'.
1794          */
1795         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1796                 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1797                 return -1;
1798         }
1799         if ((regs.r_pc < tcp->baddr) ||
1800                                 (regs.r_pc > tcp->baddr + 4)) {
1801                 /* The breakpoint has not been reached yet */
1802                 if (debug)
1803                         fprintf(stderr,
1804                                 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1805                                         regs.r_pc, tcp->parent->baddr);
1806                 return 0;
1807         }
1808         if (regs.r_pc != tcp->baddr)
1809                 if (debug)
1810                         fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1811                                 regs.r_pc, tcp->baddr);
1812
1813         regs.r_pc = tcp->baddr;
1814         if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1815                 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1816                 return -1;
1817         }
1818 #endif /* LOOPA */
1819 #endif /* SPARC */
1820 #endif /* SUNOS4 */
1821
1822         return 0;
1823 }
1824
1825 #endif
1826
1827 #endif /* !USE_PROCFS */
1828
1829 #ifdef SUNOS4
1830
1831 static int
1832 getex(pid, hdr)
1833 int pid;
1834 struct exec *hdr;
1835 {
1836         int n;
1837
1838         for (n = 0; n < sizeof *hdr; n += 4) {
1839                 long res;
1840                 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1841                         return -1;
1842                 memcpy(((char *) hdr) + n, &res, 4);
1843         }
1844         if (debug) {
1845                 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1846                         hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1847                 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1848                         hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1849         }
1850         return 0;
1851 }
1852
1853 int
1854 fixvfork(tcp)
1855 struct tcb *tcp;
1856 {
1857         int pid = tcp->pid;
1858         /*
1859          * Change `vfork' in a freshly exec'ed dynamically linked
1860          * executable's (internal) symbol table to plain old `fork'
1861          */
1862
1863         struct exec hdr;
1864         struct link_dynamic dyn;
1865         struct link_dynamic_2 ld;
1866         char *strtab, *cp;
1867
1868         if (getex(pid, &hdr) < 0)
1869                 return -1;
1870         if (!hdr.a_dynamic)
1871                 return -1;
1872
1873         if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1874                 fprintf(stderr, "Cannot read DYNAMIC\n");
1875                 return -1;
1876         }
1877         if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1878                 fprintf(stderr, "Cannot read link_dynamic_2\n");
1879                 return -1;
1880         }
1881         if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1882                 fprintf(stderr, "fixvfork: out of memory\n");
1883                 return -1;
1884         }
1885         if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1886                                         (int)ld.ld_symb_size, strtab) < 0)
1887                 goto err;
1888
1889 #if 0
1890         for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1891                 fprintf(stderr, "[symbol: %s]\n", cp);
1892                 cp += strlen(cp)+1;
1893         }
1894         return 0;
1895 #endif
1896         for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1897                 if (strcmp(cp, "_vfork") == 0) {
1898                         if (debug)
1899                                 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1900                         strcpy(cp, "_fork");
1901                         break;
1902                 }
1903                 cp += strlen(cp)+1;
1904         }
1905         if (cp < strtab + ld.ld_symb_size)
1906                 /*
1907                  * Write entire symbol table back to avoid
1908                  * memory alignment bugs in ptrace
1909                  */
1910                 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1911                                         (int)ld.ld_symb_size, strtab) < 0)
1912                         goto err;
1913
1914         free(strtab);
1915         return 0;
1916
1917 err:
1918         free(strtab);
1919         return -1;
1920 }
1921
1922 #endif /* SUNOS4 */