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