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