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