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