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