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