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