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>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
39 #include <sys/syscall.h>
41 #include <sys/param.h>
47 #include <machine/reg.h>
52 #if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
53 #include <linux/ptrace.h>
56 #if defined(LINUX) && defined(IA64)
57 # include <asm/ptrace_offsets.h>
63 # define PTRACE_PEEKUSR PTRACE_PEEKUSER
64 #elif defined(HAVE_LINUX_PTRACE_H)
66 # ifdef HAVE_STRUCT_IA64_FPREG
67 # define ia64_fpreg XXX_ia64_fpreg
69 # ifdef HAVE_STRUCT_PT_ALL_USER_REGS
70 # define pt_all_user_regs XXX_pt_all_user_regs
72 #include <linux/ptrace.h>
74 # undef pt_all_user_regs
77 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
78 #include <sys/utsname.h>
79 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
81 #if defined(LINUXSPARC)
83 # define fpq kernel_fpq
85 # define fpu kernel_fpu
93 # undef PTRACE_GETREGS
94 # define PTRACE_GETREGS PTRACE_GETREGS64
95 # undef PTRACE_SETREGS
96 # define PTRACE_SETREGS PTRACE_SETREGS64
99 #if !defined(__GLIBC__)
101 #include <linux/unistd.h>
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) \
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)
121 "or %%g0, %%o0, %0\n\t" \
122 "sub %%g0, %%o0, %0\n\t" \
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"); \
130 return (type) __res; \
135 static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
145 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
148 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
165 return a->tv_sec || a->tv_usec;
170 struct timeval *a, *b;
172 if (a->tv_sec < b->tv_sec
173 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
175 if (a->tv_sec > b->tv_sec
176 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
185 return tv->tv_sec + tv->tv_usec/1000000.0;
190 struct timeval *tv, *a, *b;
192 tv->tv_sec = a->tv_sec + b->tv_sec;
193 tv->tv_usec = a->tv_usec + b->tv_usec;
194 if (tv->tv_usec > 1000000) {
196 tv->tv_usec -= 1000000;
202 struct timeval *tv, *a, *b;
204 tv->tv_sec = a->tv_sec - b->tv_sec;
205 tv->tv_usec = a->tv_usec - b->tv_usec;
206 if (((long) tv->tv_usec) < 0) {
208 tv->tv_usec += 1000000;
214 struct timeval *tv, *a;
217 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
218 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
219 tv->tv_usec %= 1000000;
224 struct timeval *tv, *a;
227 tv->tv_usec = a->tv_usec * n;
228 tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
229 tv->tv_usec %= 1000000;
234 const struct xlat *xlat;
237 for (; xlat->str != NULL; xlat++)
238 if (xlat->val == val)
244 * Print entry in struct xlat table, if there.
247 printxval(xlat, val, dflt)
248 const struct xlat *xlat;
252 char *str = xlookup(xlat, val);
257 tprintf("%#x /* %s */", val, dflt);
261 * Interpret `xlat' as an array of flags
262 * print the entries whose bits are on in `flags'
263 * return # of flags printed.
266 addflags(xlat, flags)
267 const struct xlat *xlat;
272 for (n = 0; xlat->str; xlat++) {
273 if (xlat->val && (flags & xlat->val) == xlat->val) {
274 tprintf("|%s", xlat->str);
280 tprintf("|%#x", flags);
287 printflags(xlat, flags, dflt)
288 const struct xlat *xlat;
295 if (flags == 0 && xlat->val == 0) {
296 tprintf("%s", xlat->str);
301 for (n = 0; xlat->str; xlat++) {
302 if (xlat->val && (flags & xlat->val) == xlat->val) {
303 tprintf("%s%s", sep, xlat->str);
312 tprintf("%s%#x", sep, flags);
317 tprintf("%#x", flags);
319 tprintf(" /* %s */", dflt);
330 printnum(tcp, addr, fmt)
341 if (umove(tcp, addr, &num) < 0) {
342 tprintf("%#lx", addr);
356 tprintf((uid == -1) ? "%ld" : "%lu", uid);
359 static char path[MAXPATHLEN + 1];
365 char buf[2 * MAXPATHLEN + 1];
368 if (!strpbrk(str, "\"\'\\")) {
369 tprintf("\"%s\"", str);
372 for (s = buf; *str; str++) {
374 case '\"': case '\'': case '\\':
375 *s++ = '\\'; *s++ = *str; break;
381 tprintf("\"%s\"", buf);
391 else if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
392 tprintf("%#lx", addr);
399 printpathn(tcp, addr, n)
406 else if (umovestr(tcp, addr, n, path) < 0)
407 tprintf("%#lx", addr);
415 printstr(tcp, addr, len)
420 static unsigned char *str = NULL;
430 if ((str = malloc(max_strlen)) == NULL
431 || (outstr = malloc(2*max_strlen)) == NULL) {
432 fprintf(stderr, "out of memory\n");
433 tprintf("%#lx", addr);
437 outend = outstr + max_strlen * 2 - 10;
440 if (umovestr(tcp, addr, n, (char *) str) < 0) {
441 tprintf("%#lx", addr);
446 n = MIN(len, max_strlen);
447 if (umoven(tcp, addr, n, (char *) str) < 0) {
448 tprintf("%#lx", addr);
457 for (i = 0; i < n; i++) {
459 if (len < 0 && c == '\0')
461 if (!isprint(c) && !isspace(c)) {
472 for (i = 0; i < n; i++) {
474 if (len < 0 && c == '\0')
476 sprintf(s, "\\x%02x", c);
483 for (i = 0; i < n; i++) {
485 if (len < 0 && c == '\0')
488 case '\"': case '\'': case '\\':
489 *s++ = '\\'; *s++ = c; break;
491 *s++ = '\\'; *s++ = 'f'; break;
493 *s++ = '\\'; *s++ = 'n'; break;
495 *s++ = '\\'; *s++ = 'r'; break;
497 *s++ = '\\'; *s++ = 't'; break;
499 *s++ = '\\'; *s++ = 'v'; break;
503 else if (i < n - 1 && isdigit(str[i + 1])) {
504 sprintf(s, "\\%03o", c);
508 sprintf(s, "\\%o", c);
519 if (i < len || (len < 0 && (i == n || s > outend))) {
520 *s++ = '.'; *s++ = '.'; *s++ = '.';
523 tprintf("%s", outstr);
528 dumpiov(tcp, len, addr)
537 size = sizeof(*iov) * (unsigned long) len;
538 if (size / sizeof(*iov) != len
539 || (iov = (struct iovec *) malloc(size)) == NULL) {
540 fprintf(stderr, "out of memory\n");
543 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
544 for (i = 0; i < len; i++) {
545 /* include the buffer number to make it easy to
546 * match up the trace with the source */
547 tprintf(" * %lu bytes in buffer %d\n",
548 (unsigned long)iov[i].iov_len, i);
549 dumpstr(tcp, (long) iov[i].iov_base,
559 dumpstr(tcp, addr, len)
564 static int strsize = -1;
565 static unsigned char *str;
566 static char outstr[80];
573 if ((str = malloc(len)) == NULL) {
574 fprintf(stderr, "out of memory\n");
580 if (umoven(tcp, addr, len, (char *) str) < 0)
583 for (i = 0; i < len; i += 16) {
585 sprintf(s, " | %05x ", i);
587 for (j = 0; j < 16; j++) {
591 sprintf(s, " %02x", str[i + j]);
595 *s++ = ' '; *s++ = ' '; *s++ = ' ';
598 *s++ = ' '; *s++ = ' ';
599 for (j = 0; j < 16; j++) {
603 if (isprint(str[i + j]))
611 tprintf("%s |\n", outstr);
615 #define PAGMASK (~(PAGSIZ - 1))
617 * move `len' bytes of data from process `pid'
618 * at address `addr' to our space at `laddr'
621 umoven(tcp, addr, len, laddr)
634 char x[sizeof(long)];
637 if (addr & (sizeof(long) - 1)) {
638 /* addr not a multiple of sizeof(long) */
639 n = addr - (addr & -sizeof(long)); /* residue */
640 addr &= -sizeof(long); /* residue */
642 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
644 if (started && (errno==EPERM || errno==EIO)) {
645 /* Ran into 'end of memory' - stupid "printpath" */
648 /* But if not started, we had a bogus address. */
649 perror("ptrace: umoven");
653 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
654 addr += sizeof(long), laddr += m, len -= m;
658 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
660 if (started && (errno==EPERM || errno==EIO)) {
661 /* Ran into 'end of memory' - stupid "printpath" */
665 perror("ptrace: umoven");
669 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
670 addr += sizeof(long), laddr += m, len -= m;
680 char x[sizeof(long)];
683 if (addr & (sizeof(long) - 1)) {
684 /* addr not a multiple of sizeof(long) */
685 n = addr - (addr & -sizeof(long)); /* residue */
686 addr &= -sizeof(long); /* residue */
688 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
693 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
694 addr += sizeof(long), laddr += m, len -= m;
698 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
703 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
704 addr += sizeof(long), laddr += m, len -= m;
710 n = MIN(len, PAGSIZ);
711 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
712 if (ptrace(PTRACE_READDATA, pid,
713 (char *) addr, len, laddr) < 0) {
714 perror("umoven: ptrace(PTRACE_READDATA, ...)");
726 #ifdef HAVE_MP_PROCFS
727 int fd = tcp->pfd_as;
731 lseek(fd, addr, SEEK_SET);
732 if (read(fd, laddr, len) == -1)
734 #endif /* USE_PROCFS */
740 * like `umove' but make the additional effort of looking
741 * for a terminating zero byte.
744 umovestr(tcp, addr, len, laddr)
751 #ifdef HAVE_MP_PROCFS
752 int fd = tcp->pfd_as;
756 /* Some systems (e.g. FreeBSD) can be upset if we read off the
757 end of valid memory, avoid this by trying to read up
758 to page boundaries. But we don't know what a page is (and
759 getpagesize(2) (if it exists) doesn't necessarily return
760 hardware page size). Assume all pages >= 1024 (a-historical
763 int page = 1024; /* How to find this? */
764 int move = page - (addr & (page - 1));
767 lseek(fd, addr, SEEK_SET);
770 if (move > left) move = left;
771 if ((move = read(fd, laddr, move)) <= 0)
772 return left != len ? 0 : -1;
773 if (memchr (laddr, 0, move)) break;
779 #else /* !USE_PROCFS */
785 char x[sizeof(long)];
788 if (addr & (sizeof(long) - 1)) {
789 /* addr not a multiple of sizeof(long) */
790 n = addr - (addr & -sizeof(long)); /* residue */
791 addr &= -sizeof(long); /* residue */
793 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
795 if (started && (errno==EPERM || errno==EIO)) {
796 /* Ran into 'end of memory' - stupid "printpath" */
803 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
804 while (n & (sizeof(long) - 1))
805 if (u.x[n++] == '\0')
807 addr += sizeof(long), laddr += m, len -= m;
811 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
813 if (started && (errno==EPERM || errno==EIO)) {
814 /* Ran into 'end of memory' - stupid "printpath" */
821 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
822 for (i = 0; i < sizeof(long); i++)
826 addr += sizeof(long), laddr += m, len -= m;
828 #endif /* !USE_PROCFS */
833 #if !defined (SPARC) && !defined(SPARC64)
834 #define PTRACE_WRITETEXT 101
835 #define PTRACE_WRITEDATA 102
836 #endif /* !SPARC && !SPARC64 */
842 uload(cmd, pid, addr, len, laddr)
853 n = MIN(len, PAGSIZ);
854 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
855 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
856 perror("uload: ptrace(PTRACE_WRITE, ...)");
868 char x[sizeof(long)];
871 if (cmd == PTRACE_WRITETEXT) {
872 peek = PTRACE_PEEKTEXT;
873 poke = PTRACE_POKETEXT;
876 peek = PTRACE_PEEKDATA;
877 poke = PTRACE_POKEDATA;
879 if (addr & (sizeof(long) - 1)) {
880 /* addr not a multiple of sizeof(long) */
881 n = addr - (addr & -sizeof(long)); /* residue */
882 addr &= -sizeof(long);
884 u.val = ptrace(peek, pid, (char *) addr, 0);
886 perror("uload: POKE");
889 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
890 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
891 perror("uload: POKE");
894 addr += sizeof(long), laddr += m, len -= m;
897 if (len < sizeof(long))
898 u.val = ptrace(peek, pid, (char *) addr, 0);
899 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
900 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
901 perror("uload: POKE");
904 addr += sizeof(long), laddr += m, len -= m;
911 tload(pid, addr, len, laddr)
916 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
920 dload(pid, addr, len, laddr)
926 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
941 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
943 static int is_sun4m = -1;
946 /* Round up the usual suspects. */
947 if (is_sun4m == -1) {
948 if (uname(&name) < 0) {
949 perror("upeek: uname?");
952 is_sun4m = strcmp(name.machine, "sun4m") == 0;
954 extern const struct xlat struct_user_offsets[];
955 const struct xlat *x;
957 for (x = struct_user_offsets; x->str; x++)
964 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
966 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
967 if (val == -1 && errno) {
969 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
977 #endif /* !USE_PROCFS */
987 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
989 #elif defined(X86_64)
990 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
993 if (upeek(tcp->pid, PT_B0, &pc) < 0)
996 if (upeek(tcp->pid, 4*15, &pc) < 0)
998 #elif defined(POWERPC)
999 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1002 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1004 #elif defined(ALPHA)
1005 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1008 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1010 #elif defined(SPARC) || defined(SPARC64)
1012 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0)
1015 #elif defined(S390) || defined(S390X)
1016 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
1019 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1022 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1025 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1033 * Return current program counter for `pid'
1034 * Assumes PC is never 0xffffffff
1038 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1039 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1052 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1054 #endif /* FREEBSD */
1061 #define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1062 sizeof(long) == 8 ? "[????????????????] " : \
1069 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1073 tprintf("[%08lx] ", eip);
1075 #elif defined(S390) || defined(S390X)
1077 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
1082 tprintf("[%08lx] ", psw);
1084 tprintf("[%16lx] ", psw);
1087 #elif defined(X86_64)
1090 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1094 tprintf("[%16lx] ", rip);
1098 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1102 tprintf("[%08lx] ", ip);
1103 #elif defined(POWERPC)
1106 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1107 tprintf ("[????????] ");
1110 tprintf("[%08lx] ", pc);
1114 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1115 tprintf ("[????????] ");
1118 tprintf("[%08lx] ", pc);
1119 #elif defined(ALPHA)
1122 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1123 tprintf ("[????????????????] ");
1126 tprintf("[%08lx] ", pc);
1127 #elif defined(SPARC) || defined(SPARC64)
1129 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0) {
1133 tprintf("[%08lx] ", regs.r_pc);
1137 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1138 tprintf ("[????????] ");
1141 tprintf("[%08lx] ", pc);
1145 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1146 tprintf ("[????????] ");
1149 tprintf("[%08lx] ", pc);
1153 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1154 tprintf ("[????????] ");
1157 tprintf("[%08lx] ", pc);
1161 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1162 tprintf ("[????????????????] ");
1165 tprintf("[%08lx] ", pc);
1169 if (upeek(tcp->pid, 4*15, &pc) < 0) {
1173 tprintf("[%08lx] ", pc);
1174 #endif /* !architecture */
1180 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1181 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1185 tprintf("[%08x] ", regs.r_o7);
1195 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1196 tprintf("[%08x] ", regs.r_eip);
1197 #endif /* FREEBSD */
1204 #include <sys/syscall.h>
1205 #ifndef CLONE_PTRACE
1206 # define CLONE_PTRACE 0x00002000
1208 #ifndef CLONE_STOPPED
1209 # define CLONE_STOPPED 0x02000000
1214 /* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1215 subsystem has them for x86... */
1217 #define SYS_vfork 190
1219 typedef unsigned long *arg_setup_state;
1222 arg_setup(struct tcb *tcp, arg_setup_state *state)
1224 unsigned long *bsp, cfm, sof, sol;
1229 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1231 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1234 sof = (cfm >> 0) & 0x7f;
1235 sol = (cfm >> 7) & 0x7f;
1236 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1242 # define arg_finish_change(tcp, state) 0
1246 get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1251 ret = upeek (tcp->pid, PT_R11, valp);
1254 (unsigned long) ia64_rse_skip_regs(*state, 0),
1255 sizeof(long), (void *) valp);
1260 get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1265 ret = upeek (tcp->pid, PT_R9, valp);
1268 (unsigned long) ia64_rse_skip_regs(*state, 1),
1269 sizeof(long), (void *) valp);
1275 set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1277 int req = PTRACE_POKEDATA;
1281 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1282 req = PTRACE_POKEUSER;
1284 ap = ia64_rse_skip_regs(*state, 0);
1286 ptrace(req, tcp->pid, ap, val);
1287 return errno ? -1 : 0;
1291 set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1293 int req = PTRACE_POKEDATA;
1297 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1298 req = PTRACE_POKEUSER;
1300 ap = ia64_rse_skip_regs(*state, 1);
1302 ptrace(req, tcp->pid, ap, val);
1303 return errno ? -1 : 0;
1306 #elif defined (SPARC) || defined (SPARC64)
1308 typedef struct regs arg_setup_state;
1310 # define arg_setup(tcp, state) \
1311 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1312 # define arg_finish_change(tcp, state) \
1313 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1315 # define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1316 # define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1317 # define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1318 # define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
1319 # define restore_arg0(tcp, state, val) 0
1323 # if defined S390 || defined S390X
1324 /* Note: this is only true for the `clone' system call, which handles
1325 arguments specially. We could as well say that its first two arguments
1326 are swapped relative to other architectures, but that would just be
1327 another #ifdef in the calls. */
1328 # define arg0_offset PT_GPR3
1329 # define arg1_offset PT_ORIGGPR2
1330 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1331 # define restore_arg1(tcp, state, val) ((void) (state), 0)
1332 # define arg0_index 1
1333 # define arg1_index 0
1334 # elif defined (ALPHA) || defined (MIPS)
1335 # define arg0_offset REG_A0
1336 # define arg1_offset (REG_A0+1)
1337 # elif defined (POWERPC)
1338 # define arg0_offset (sizeof(unsigned long)*PT_R3)
1339 # define arg1_offset (sizeof(unsigned long)*PT_R4)
1340 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1341 # elif defined (HPPA)
1342 # define arg0_offset PT_GR26
1343 # define arg1_offset (PT_GR26-4)
1344 # elif defined (X86_64)
1345 # define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1346 # define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1348 # define arg0_offset (4*(REG_REG0+4))
1349 # define arg1_offset (4*(REG_REG0+5))
1350 # elif defined (SH64)
1351 /* ABI defines arg0 & 1 in r2 & r3 */
1352 # define arg0_offset (REG_OFFSET+16)
1353 # define arg1_offset (REG_OFFSET+24)
1354 # define restore_arg0(tcp, state, val) 0
1356 # define arg0_offset 0
1357 # define arg1_offset 4
1359 # define restore_arg0(tcp, state, val) 0
1363 typedef int arg_setup_state;
1365 # define arg_setup(tcp, state) (0)
1366 # define arg_finish_change(tcp, state) 0
1367 # define get_arg0(tcp, cookie, valp) \
1368 (upeek ((tcp)->pid, arg0_offset, (valp)))
1369 # define get_arg1(tcp, cookie, valp) \
1370 (upeek ((tcp)->pid, arg1_offset, (valp)))
1373 set_arg0 (struct tcb *tcp, void *cookie, long val)
1375 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1379 set_arg1 (struct tcb *tcp, void *cookie, long val)
1381 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1386 #ifndef restore_arg0
1387 # define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1389 #ifndef restore_arg1
1390 # define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1394 # define arg0_index 0
1395 # define arg1_index 1
1402 extern int change_syscall(struct tcb *, int);
1403 arg_setup_state state;
1405 if (tcp->flags & TCB_BPTSET) {
1406 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1410 switch (known_scno(tcp)) {
1417 #if defined SYS_fork || defined SYS_vfork
1418 if (arg_setup (tcp, &state) < 0
1419 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1420 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1421 || change_syscall(tcp, SYS_clone) < 0
1422 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1423 || set_arg1 (tcp, &state, 0) < 0
1424 || arg_finish_change (tcp, &state) < 0)
1426 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1427 tcp->u_arg[arg1_index] = 0;
1428 tcp->flags |= TCB_BPTSET;
1436 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
1437 && (arg_setup (tcp, &state) < 0
1438 || set_arg0 (tcp, &state,
1439 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
1440 || arg_finish_change (tcp, &state) < 0))
1442 tcp->flags |= TCB_BPTSET;
1443 tcp->inst[0] = tcp->u_arg[arg0_index];
1444 tcp->inst[1] = tcp->u_arg[arg1_index];
1448 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1449 tcp->scno, tcp->pid);
1460 arg_setup_state state;
1461 if (arg_setup (tcp, &state) < 0
1462 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1463 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1464 || arg_finish_change (tcp, &state))
1466 tcp->flags &= ~TCB_BPTSET;
1478 #if defined (SPARC) || defined (SPARC64)
1479 /* We simply use the SunOS breakpoint code. */
1483 #define LOOPA 0x30800000 /* ba,a 0 */
1485 if (tcp->flags & TCB_BPTSET) {
1486 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1489 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1490 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1493 tcp->baddr = regs.r_o7 + 8;
1495 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1497 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1502 * XXX - BRUTAL MODE ON
1503 * We cannot set a real BPT in the child, since it will not be
1504 * traced at the moment it will reach the trap and would probably
1505 * die with a core dump.
1506 * Thus, we are force our way in by taking out two instructions
1507 * and insert an eternal loop instead, in expectance of the SIGSTOP
1508 * generated by out PTRACE_ATTACH.
1509 * Of cause, if we evaporate ourselves in the middle of all this...
1513 #if defined (SPARC64)
1515 inst |= (tcp->inst[0] & 0xffffffffUL);
1517 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
1519 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1522 tcp->flags |= TCB_BPTSET;
1524 #else /* !SPARC && !SPARC64 */
1527 # define LOOP 0x0000feeb
1528 if (tcp->flags & TCB_BPTSET) {
1529 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1533 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1536 fprintf(stderr, "[%d] setting bpt at %lx\n",
1537 tcp->pid, tcp->baddr);
1538 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1539 (char *) tcp->baddr, 0);
1541 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1544 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1546 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1549 tcp->flags |= TCB_BPTSET;
1552 * Our strategy here is to replace the bundle that
1553 * contained the clone() syscall with a bundle of the
1556 * { 1: br 1b; br 1b; br 1b }
1558 * This ensures that the newly forked child will loop
1559 * endlessly until we've got a chance to attach to it.
1561 # define LOOP0 0x0000100000000017
1562 # define LOOP1 0x4000000000200000
1563 unsigned long addr, ipsr;
1567 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1569 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1571 /* store "ri" in low two bits */
1572 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
1575 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1577 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1580 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1585 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1586 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1588 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1591 tcp->flags |= TCB_BPTSET;
1595 #if defined (I386) || defined(X86_64)
1596 #define LOOP 0x0000feeb
1597 #elif defined (M68K)
1598 #define LOOP 0x60fe0000
1599 #elif defined (ALPHA)
1600 #define LOOP 0xc3ffffff
1601 #elif defined (POWERPC)
1602 #define LOOP 0x48000000
1604 #define LOOP 0xEAFFFFFE
1606 #define LOOP 0x1000ffff
1608 #define LOOP 0xa7f40000 /* BRC 15,0 */
1609 #elif defined(S390X)
1610 #define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
1612 #define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
1614 #ifdef __LITTLE_ENDIAN__
1615 #define LOOP 0x0000affe
1617 #define LOOP 0xfeaf0000
1620 #error unknown architecture
1623 if (tcp->flags & TCB_BPTSET) {
1624 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1628 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1630 #elif defined (X86_64)
1631 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1633 #elif defined (M68K)
1634 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1636 #elif defined (ALPHA)
1640 #elif defined (MIPS)
1641 return -1; /* FIXME: I do not know what i do - Flo */
1642 #elif defined (POWERPC)
1643 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
1645 #elif defined(S390) || defined(S390X)
1646 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1649 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1651 tcp->baddr &= ~0x03;
1653 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1656 #error unknown architecture
1659 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1660 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1662 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1665 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1667 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1670 tcp->flags |= TCB_BPTSET;
1673 #endif /* SPARC || SPARC64 */
1677 #ifdef SPARC /* This code is slightly sparc specific */
1680 #define BPT 0x91d02001 /* ta 1 */
1681 #define LOOP 0x10800000 /* ba 0 */
1682 #define LOOPA 0x30800000 /* ba,a 0 */
1683 #define NOP 0x01000000
1685 static int loopdeloop[1] = {LOOPA};
1687 static int loopdeloop[2] = {LOOP, NOP};
1690 if (tcp->flags & TCB_BPTSET) {
1691 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1694 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1695 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1698 tcp->baddr = regs.r_o7 + 8;
1699 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1700 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1701 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1706 * XXX - BRUTAL MODE ON
1707 * We cannot set a real BPT in the child, since it will not be
1708 * traced at the moment it will reach the trap and would probably
1709 * die with a core dump.
1710 * Thus, we are force our way in by taking out two instructions
1711 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1712 * generated by out PTRACE_ATTACH.
1713 * Of cause, if we evaporate ourselves in the middle of all this...
1715 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1716 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1717 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1720 tcp->flags |= TCB_BPTSET;
1734 #if defined(I386) || defined(X86_64)
1736 #elif defined(POWERPC)
1740 #elif defined(ALPHA)
1746 #endif /* architecture */
1748 #if defined (SPARC) || defined (SPARC64)
1749 /* Again, we borrow the SunOS breakpoint code. */
1750 if (!(tcp->flags & TCB_BPTSET)) {
1751 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1755 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1757 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1760 tcp->flags &= ~TCB_BPTSET;
1766 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1767 if (!(tcp->flags & TCB_BPTSET)) {
1768 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1772 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1774 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1777 tcp->flags &= ~TCB_BPTSET;
1779 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1781 if (addr != tcp->baddr) {
1782 /* The breakpoint has not been reached yet. */
1785 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1790 unsigned long addr, ipsr;
1795 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1797 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1800 /* restore original bundle: */
1802 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1803 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1805 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1809 /* restore original "ri" in ipsr: */
1810 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1812 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1814 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1818 tcp->flags &= ~TCB_BPTSET;
1820 if (addr != (tcp->baddr & ~0x3)) {
1821 /* the breakpoint has not been reached yet. */
1823 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1828 #else /* !IA64 && !SPARC && !SPARC64 */
1831 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1832 if (!(tcp->flags & TCB_BPTSET)) {
1833 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1837 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1839 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1842 tcp->flags &= ~TCB_BPTSET;
1845 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1847 if (eip != tcp->baddr) {
1848 /* The breakpoint has not been reached yet. */
1851 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1855 #elif defined(X86_64)
1856 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1858 if (eip != tcp->baddr) {
1859 /* The breakpoint has not been reached yet. */
1862 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1866 #elif defined(POWERPC)
1867 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1869 if (pc != tcp->baddr) {
1870 /* The breakpoint has not been reached yet. */
1872 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1877 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1879 if (pc != tcp->baddr) {
1880 /* The breakpoint has not been reached yet. */
1882 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1886 #elif defined(ALPHA)
1887 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1889 if (pc != tcp->baddr) {
1890 /* The breakpoint has not been reached yet. */
1892 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1897 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1900 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1901 /* The breakpoint has not been reached yet. */
1903 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1907 iaoq = tcp->baddr | 3;
1908 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1909 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1910 * has no significant effect.
1912 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1913 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
1915 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1917 if (pc != tcp->baddr) {
1918 /* The breakpoint has not been reached yet. */
1920 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1926 #endif /* !SPARC && !SPARC64 && !IA64 */
1936 if (!(tcp->flags & TCB_BPTSET)) {
1937 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1940 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1941 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1942 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1945 tcp->flags &= ~TCB_BPTSET;
1949 * Since we don't have a single instruction breakpoint, we may have
1950 * to adjust the program counter after removing the our `breakpoint'.
1952 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1953 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1956 if ((regs.r_pc < tcp->baddr) ||
1957 (regs.r_pc > tcp->baddr + 4)) {
1958 /* The breakpoint has not been reached yet */
1961 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1962 regs.r_pc, tcp->parent->baddr);
1965 if (regs.r_pc != tcp->baddr)
1967 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1968 regs.r_pc, tcp->baddr);
1970 regs.r_pc = tcp->baddr;
1971 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0) {
1972 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1984 #endif /* !USE_PROCFS */
1995 for (n = 0; n < sizeof *hdr; n += 4) {
1997 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1999 memcpy(((char *) hdr) + n, &res, 4);
2002 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2003 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2004 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2005 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2016 * Change `vfork' in a freshly exec'ed dynamically linked
2017 * executable's (internal) symbol table to plain old `fork'
2021 struct link_dynamic dyn;
2022 struct link_dynamic_2 ld;
2025 if (getex(pid, &hdr) < 0)
2030 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2031 fprintf(stderr, "Cannot read DYNAMIC\n");
2034 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2035 fprintf(stderr, "Cannot read link_dynamic_2\n");
2038 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
2039 fprintf(stderr, "out of memory\n");
2042 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2043 (int)ld.ld_symb_size, strtab) < 0)
2047 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2048 fprintf(stderr, "[symbol: %s]\n", cp);
2053 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2054 if (strcmp(cp, "_vfork") == 0) {
2056 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2057 strcpy(cp, "_fork");
2062 if (cp < strtab + ld.ld_symb_size)
2064 * Write entire symbol table back to avoid
2065 * memory alignment bugs in ptrace
2067 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2068 (int)ld.ld_symb_size, strtab) < 0)