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))
167 return a->tv_sec || a->tv_usec;
172 struct timeval *a, *b;
174 if (a->tv_sec < b->tv_sec
175 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
177 if (a->tv_sec > b->tv_sec
178 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
187 return tv->tv_sec + tv->tv_usec/1000000.0;
192 struct timeval *tv, *a, *b;
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) {
198 tv->tv_usec -= 1000000;
204 struct timeval *tv, *a, *b;
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) {
210 tv->tv_usec += 1000000;
216 struct timeval *tv, *a;
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;
226 struct timeval *tv, *a;
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;
236 const struct xlat *xlat;
239 for (; xlat->str != NULL; xlat++)
240 if (xlat->val == val)
246 * Print entry in struct xlat table, if there.
249 printxval(xlat, val, dflt)
250 const struct xlat *xlat;
254 char *str = xlookup(xlat, val);
259 tprintf("%#x /* %s */", val, dflt);
263 * Interpret `xlat' as an array of flags
264 * print the entries whose bits are on in `flags'
265 * return # of flags printed.
268 addflags(xlat, flags)
269 const struct xlat *xlat;
274 for (n = 0; xlat->str; xlat++) {
275 if (xlat->val && (flags & xlat->val) == xlat->val) {
276 tprintf("|%s", xlat->str);
282 tprintf("|%#x", flags);
289 printflags(xlat, flags, dflt)
290 const struct xlat *xlat;
297 if (flags == 0 && xlat->val == 0) {
298 tprintf("%s", xlat->str);
303 for (n = 0; xlat->str; xlat++) {
304 if (xlat->val && (flags & xlat->val) == xlat->val) {
305 tprintf("%s%s", sep, xlat->str);
314 tprintf("%s%#x", sep, flags);
319 tprintf("%#x", flags);
321 tprintf(" /* %s */", dflt);
332 printnum(tcp, addr, fmt)
343 if (umove(tcp, addr, &num) < 0) {
344 tprintf("%#lx", addr);
358 tprintf((uid == -1) ? "%ld" : "%lu", uid);
361 static char path[MAXPATHLEN + 1];
367 char buf[2 * MAXPATHLEN + 1];
370 if (!strpbrk(str, "\"\'\\")) {
371 tprintf("\"%s\"", str);
374 for (s = buf; *str; str++) {
376 case '\"': case '\'': case '\\':
377 *s++ = '\\'; *s++ = *str; break;
383 tprintf("\"%s\"", buf);
393 else if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
394 tprintf("%#lx", addr);
401 printpathn(tcp, addr, n)
408 else if (umovestr(tcp, addr, n, path) < 0)
409 tprintf("%#lx", addr);
417 printstr(tcp, addr, len)
422 static unsigned char *str = NULL;
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);
439 outend = outstr + max_strlen * 2 - 10;
442 if (umovestr(tcp, addr, n, (char *) str) < 0) {
443 tprintf("%#lx", addr);
448 n = MIN(len, max_strlen);
449 if (umoven(tcp, addr, n, (char *) str) < 0) {
450 tprintf("%#lx", addr);
459 for (i = 0; i < n; i++) {
461 if (len < 0 && c == '\0')
463 if (!isprint(c) && !isspace(c)) {
474 for (i = 0; i < n; i++) {
476 if (len < 0 && c == '\0')
478 sprintf(s, "\\x%02x", c);
485 for (i = 0; i < n; i++) {
487 if (len < 0 && c == '\0')
490 case '\"': case '\'': case '\\':
491 *s++ = '\\'; *s++ = c; break;
493 *s++ = '\\'; *s++ = 'f'; break;
495 *s++ = '\\'; *s++ = 'n'; break;
497 *s++ = '\\'; *s++ = 'r'; break;
499 *s++ = '\\'; *s++ = 't'; break;
501 *s++ = '\\'; *s++ = 'v'; break;
505 else if (i < n - 1 && isdigit(str[i + 1])) {
506 sprintf(s, "\\%03o", c);
510 sprintf(s, "\\%o", c);
521 if (i < len || (len < 0 && (i == n || s > outend))) {
522 *s++ = '.'; *s++ = '.'; *s++ = '.';
525 tprintf("%s", outstr);
530 dumpiov(tcp, len, addr)
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");
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,
561 dumpstr(tcp, addr, len)
566 static int strsize = -1;
567 static unsigned char *str;
568 static char outstr[80];
575 if ((str = malloc(len)) == NULL) {
576 fprintf(stderr, "out of memory\n");
582 if (umoven(tcp, addr, len, (char *) str) < 0)
585 for (i = 0; i < len; i += 16) {
587 sprintf(s, " | %05x ", i);
589 for (j = 0; j < 16; j++) {
593 sprintf(s, " %02x", str[i + j]);
597 *s++ = ' '; *s++ = ' '; *s++ = ' ';
600 *s++ = ' '; *s++ = ' ';
601 for (j = 0; j < 16; j++) {
605 if (isprint(str[i + j]))
613 tprintf("%s |\n", outstr);
617 #define PAGMASK (~(PAGSIZ - 1))
619 * move `len' bytes of data from process `pid'
620 * at address `addr' to our space at `laddr'
623 umoven(tcp, addr, len, laddr)
636 char x[sizeof(long)];
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 */
644 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
646 if (started && (errno==EPERM || errno==EIO)) {
647 /* Ran into 'end of memory' - stupid "printpath" */
650 /* But if not started, we had a bogus address. */
651 perror("ptrace: umoven");
655 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
656 addr += sizeof(long), laddr += m, len -= m;
660 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
662 if (started && (errno==EPERM || errno==EIO)) {
663 /* Ran into 'end of memory' - stupid "printpath" */
667 perror("ptrace: umoven");
671 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
672 addr += sizeof(long), laddr += m, len -= m;
682 char x[sizeof(long)];
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 */
690 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
695 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
696 addr += sizeof(long), laddr += m, len -= m;
700 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
705 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
706 addr += sizeof(long), laddr += m, len -= m;
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, ...)");
728 #ifdef HAVE_MP_PROCFS
729 int fd = tcp->pfd_as;
733 lseek(fd, addr, SEEK_SET);
734 if (read(fd, laddr, len) == -1)
736 #endif /* USE_PROCFS */
742 * like `umove' but make the additional effort of looking
743 * for a terminating zero byte.
746 umovestr(tcp, addr, len, laddr)
753 #ifdef HAVE_MP_PROCFS
754 int fd = tcp->pfd_as;
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
765 int page = 1024; /* How to find this? */
766 int move = page - (addr & (page - 1));
769 lseek(fd, addr, SEEK_SET);
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;
781 #else /* !USE_PROCFS */
787 char x[sizeof(long)];
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 */
795 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
797 if (started && (errno==EPERM || errno==EIO)) {
798 /* Ran into 'end of memory' - stupid "printpath" */
805 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
806 while (n & (sizeof(long) - 1))
807 if (u.x[n++] == '\0')
809 addr += sizeof(long), laddr += m, len -= m;
813 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
815 if (started && (errno==EPERM || errno==EIO)) {
816 /* Ran into 'end of memory' - stupid "printpath" */
823 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
824 for (i = 0; i < sizeof(long); i++)
828 addr += sizeof(long), laddr += m, len -= m;
830 #endif /* !USE_PROCFS */
835 #if !defined (SPARC) && !defined(SPARC64)
836 #define PTRACE_WRITETEXT 101
837 #define PTRACE_WRITEDATA 102
838 #endif /* !SPARC && !SPARC64 */
844 uload(cmd, pid, addr, len, laddr)
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, ...)");
870 char x[sizeof(long)];
873 if (cmd == PTRACE_WRITETEXT) {
874 peek = PTRACE_PEEKTEXT;
875 poke = PTRACE_POKETEXT;
878 peek = PTRACE_PEEKDATA;
879 poke = PTRACE_POKEDATA;
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);
886 u.val = ptrace(peek, pid, (char *) addr, 0);
888 perror("uload: POKE");
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");
896 addr += sizeof(long), laddr += m, len -= m;
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");
906 addr += sizeof(long), laddr += m, len -= m;
913 tload(pid, addr, len, laddr)
918 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
922 dload(pid, addr, len, laddr)
928 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
943 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
945 static int is_sun4m = -1;
948 /* Round up the usual suspects. */
949 if (is_sun4m == -1) {
950 if (uname(&name) < 0) {
951 perror("upeek: uname?");
954 is_sun4m = strcmp(name.machine, "sun4m") == 0;
956 extern const struct xlat struct_user_offsets[];
957 const struct xlat *x;
959 for (x = struct_user_offsets; x->str; x++)
966 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
968 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
969 if (val == -1 && errno) {
971 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
979 #endif /* !USE_PROCFS */
990 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
992 #elif defined(X86_64)
993 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
996 if (upeek(tcp->pid, PT_B0, &pc) < 0)
999 if (upeek(tcp->pid, 4*15, &pc) < 0)
1001 #elif defined(POWERPC)
1002 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1005 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1007 #elif defined(ALPHA)
1008 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1011 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1013 #elif defined(SPARC) || defined(SPARC64)
1015 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0)
1018 #elif defined(S390) || defined(S390X)
1019 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
1022 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1025 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1028 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1036 * Return current program counter for `pid'
1037 * Assumes PC is never 0xffffffff
1041 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1042 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1055 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1057 #endif /* FREEBSD */
1065 #define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1066 sizeof(long) == 8 ? "[????????????????] " : \
1073 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1077 tprintf("[%08lx] ", eip);
1079 #elif defined(S390) || defined(S390X)
1081 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
1086 tprintf("[%08lx] ", psw);
1088 tprintf("[%16lx] ", psw);
1091 #elif defined(X86_64)
1094 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1098 tprintf("[%16lx] ", rip);
1102 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1106 tprintf("[%08lx] ", ip);
1107 #elif defined(POWERPC)
1110 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1111 tprintf ("[????????] ");
1114 tprintf("[%08lx] ", pc);
1118 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1119 tprintf ("[????????] ");
1122 tprintf("[%08lx] ", pc);
1123 #elif defined(ALPHA)
1126 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1127 tprintf ("[????????????????] ");
1130 tprintf("[%08lx] ", pc);
1131 #elif defined(SPARC) || defined(SPARC64)
1133 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0) {
1137 tprintf("[%08lx] ", regs.r_pc);
1141 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1142 tprintf ("[????????] ");
1145 tprintf("[%08lx] ", pc);
1149 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1150 tprintf ("[????????] ");
1153 tprintf("[%08lx] ", pc);
1157 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1158 tprintf ("[????????] ");
1161 tprintf("[%08lx] ", pc);
1165 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1166 tprintf ("[????????????????] ");
1169 tprintf("[%08lx] ", pc);
1173 if (upeek(tcp->pid, 4*15, &pc) < 0) {
1177 tprintf("[%08lx] ", pc);
1178 #endif /* !architecture */
1184 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1185 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1189 tprintf("[%08x] ", regs.r_o7);
1199 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1200 tprintf("[%08x] ", regs.r_eip);
1201 #endif /* FREEBSD */
1208 #include <sys/syscall.h>
1209 #ifndef CLONE_PTRACE
1210 # define CLONE_PTRACE 0x00002000
1212 #ifndef CLONE_STOPPED
1213 # define CLONE_STOPPED 0x02000000
1218 /* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1219 subsystem has them for x86... */
1221 #define SYS_vfork 190
1223 typedef unsigned long *arg_setup_state;
1226 arg_setup(struct tcb *tcp, arg_setup_state *state)
1228 unsigned long *bsp, cfm, sof, sol;
1233 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1235 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1238 sof = (cfm >> 0) & 0x7f;
1239 sol = (cfm >> 7) & 0x7f;
1240 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1246 # define arg_finish_change(tcp, state) 0
1250 get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1255 ret = upeek (tcp->pid, PT_R11, valp);
1258 (unsigned long) ia64_rse_skip_regs(*state, 0),
1259 sizeof(long), (void *) valp);
1264 get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1269 ret = upeek (tcp->pid, PT_R9, valp);
1272 (unsigned long) ia64_rse_skip_regs(*state, 1),
1273 sizeof(long), (void *) valp);
1279 set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1281 int req = PTRACE_POKEDATA;
1285 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1286 req = PTRACE_POKEUSER;
1288 ap = ia64_rse_skip_regs(*state, 0);
1290 ptrace(req, tcp->pid, ap, val);
1291 return errno ? -1 : 0;
1295 set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1297 int req = PTRACE_POKEDATA;
1301 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1302 req = PTRACE_POKEUSER;
1304 ap = ia64_rse_skip_regs(*state, 1);
1306 ptrace(req, tcp->pid, ap, val);
1307 return errno ? -1 : 0;
1310 #elif defined (SPARC) || defined (SPARC64)
1312 typedef struct regs arg_setup_state;
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))
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
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)))
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
1360 # define arg0_offset 0
1361 # define arg1_offset 4
1363 # define restore_arg0(tcp, state, val) 0
1367 typedef int arg_setup_state;
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)))
1377 set_arg0 (struct tcb *tcp, void *cookie, long val)
1379 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1383 set_arg1 (struct tcb *tcp, void *cookie, long val)
1385 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1390 #ifndef restore_arg0
1391 # define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1393 #ifndef restore_arg1
1394 # define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1398 # define arg0_index 0
1399 # define arg1_index 1
1406 extern int change_syscall(struct tcb *, int);
1407 arg_setup_state state;
1409 if (tcp->flags & TCB_BPTSET) {
1410 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1414 switch (known_scno(tcp)) {
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)
1430 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1431 tcp->u_arg[arg1_index] = 0;
1432 tcp->flags |= TCB_BPTSET;
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))
1446 tcp->flags |= TCB_BPTSET;
1447 tcp->inst[0] = tcp->u_arg[arg0_index];
1448 tcp->inst[1] = tcp->u_arg[arg1_index];
1452 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1453 tcp->scno, tcp->pid);
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))
1470 tcp->flags &= ~TCB_BPTSET;
1482 #if defined (SPARC) || defined (SPARC64)
1483 /* We simply use the SunOS breakpoint code. */
1487 #define LOOPA 0x30800000 /* ba,a 0 */
1489 if (tcp->flags & TCB_BPTSET) {
1490 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1493 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1494 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1497 tcp->baddr = regs.r_o7 + 8;
1499 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1501 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
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...
1517 #if defined (SPARC64)
1519 inst |= (tcp->inst[0] & 0xffffffffUL);
1521 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
1523 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1526 tcp->flags |= TCB_BPTSET;
1528 #else /* !SPARC && !SPARC64 */
1531 # define LOOP 0x0000feeb
1532 if (tcp->flags & TCB_BPTSET) {
1533 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1537 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
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);
1545 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1548 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1550 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1553 tcp->flags |= TCB_BPTSET;
1556 * Our strategy here is to replace the bundle that
1557 * contained the clone() syscall with a bundle of the
1560 * { 1: br 1b; br 1b; br 1b }
1562 * This ensures that the newly forked child will loop
1563 * endlessly until we've got a chance to attach to it.
1565 # define LOOP0 0x0000100000000017
1566 # define LOOP1 0x4000000000200000
1567 unsigned long addr, ipsr;
1571 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1573 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1575 /* store "ri" in low two bits */
1576 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
1579 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1581 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1584 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1589 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1590 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1592 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1595 tcp->flags |= TCB_BPTSET;
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
1608 #define LOOP 0xEAFFFFFE
1610 #define LOOP 0x1000ffff
1612 #define LOOP 0xa7f40000 /* BRC 15,0 */
1613 #elif defined(S390X)
1614 #define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
1616 #define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
1618 #ifdef __LITTLE_ENDIAN__
1619 #define LOOP 0x0000affe
1621 #define LOOP 0xfeaf0000
1624 #error unknown architecture
1627 if (tcp->flags & TCB_BPTSET) {
1628 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1632 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1634 #elif defined (X86_64)
1635 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1637 #elif defined (M68K)
1638 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1640 #elif defined (ALPHA)
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)
1649 #elif defined(S390) || defined(S390X)
1650 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1653 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1655 tcp->baddr &= ~0x03;
1657 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1660 #error unknown architecture
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);
1666 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1669 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1671 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1674 tcp->flags |= TCB_BPTSET;
1677 #endif /* SPARC || SPARC64 */
1681 #ifdef SPARC /* This code is slightly sparc specific */
1684 #define BPT 0x91d02001 /* ta 1 */
1685 #define LOOP 0x10800000 /* ba 0 */
1686 #define LOOPA 0x30800000 /* ba,a 0 */
1687 #define NOP 0x01000000
1689 static int loopdeloop[1] = {LOOPA};
1691 static int loopdeloop[2] = {LOOP, NOP};
1694 if (tcp->flags & TCB_BPTSET) {
1695 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1698 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1699 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
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, ...)");
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...
1719 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1720 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1721 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1724 tcp->flags |= TCB_BPTSET;
1738 #if defined(I386) || defined(X86_64)
1740 #elif defined(POWERPC)
1744 #elif defined(ALPHA)
1750 #endif /* architecture */
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);
1759 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1761 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1764 tcp->flags &= ~TCB_BPTSET;
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);
1776 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1778 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1781 tcp->flags &= ~TCB_BPTSET;
1783 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1785 if (addr != tcp->baddr) {
1786 /* The breakpoint has not been reached yet. */
1789 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1794 unsigned long addr, ipsr;
1799 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1801 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1804 /* restore original bundle: */
1806 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1807 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1809 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1813 /* restore original "ri" in ipsr: */
1814 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1816 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1818 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1822 tcp->flags &= ~TCB_BPTSET;
1824 if (addr != (tcp->baddr & ~0x3)) {
1825 /* the breakpoint has not been reached yet. */
1827 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1832 #else /* !IA64 && !SPARC && !SPARC64 */
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);
1841 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1843 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1846 tcp->flags &= ~TCB_BPTSET;
1849 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1851 if (eip != tcp->baddr) {
1852 /* The breakpoint has not been reached yet. */
1855 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1859 #elif defined(X86_64)
1860 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1862 if (eip != tcp->baddr) {
1863 /* The breakpoint has not been reached yet. */
1866 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1870 #elif defined(POWERPC)
1871 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1873 if (pc != tcp->baddr) {
1874 /* The breakpoint has not been reached yet. */
1876 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1881 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1883 if (pc != tcp->baddr) {
1884 /* The breakpoint has not been reached yet. */
1886 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1890 #elif defined(ALPHA)
1891 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1893 if (pc != tcp->baddr) {
1894 /* The breakpoint has not been reached yet. */
1896 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1901 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1904 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1905 /* The breakpoint has not been reached yet. */
1907 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
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.
1916 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1917 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
1919 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1921 if (pc != tcp->baddr) {
1922 /* The breakpoint has not been reached yet. */
1924 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1930 #endif /* !SPARC && !SPARC64 && !IA64 */
1940 if (!(tcp->flags & TCB_BPTSET)) {
1941 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1944 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1945 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1946 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1949 tcp->flags &= ~TCB_BPTSET;
1953 * Since we don't have a single instruction breakpoint, we may have
1954 * to adjust the program counter after removing the our `breakpoint'.
1956 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1957 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1960 if ((regs.r_pc < tcp->baddr) ||
1961 (regs.r_pc > tcp->baddr + 4)) {
1962 /* The breakpoint has not been reached yet */
1965 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1966 regs.r_pc, tcp->parent->baddr);
1969 if (regs.r_pc != tcp->baddr)
1971 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1972 regs.r_pc, tcp->baddr);
1974 regs.r_pc = tcp->baddr;
1975 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0) {
1976 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1988 #endif /* !USE_PROCFS */
1999 for (n = 0; n < sizeof *hdr; n += 4) {
2001 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
2003 memcpy(((char *) hdr) + n, &res, 4);
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);
2020 * Change `vfork' in a freshly exec'ed dynamically linked
2021 * executable's (internal) symbol table to plain old `fork'
2025 struct link_dynamic dyn;
2026 struct link_dynamic_2 ld;
2029 if (getex(pid, &hdr) < 0)
2034 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2035 fprintf(stderr, "Cannot read DYNAMIC\n");
2038 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2039 fprintf(stderr, "Cannot read link_dynamic_2\n");
2042 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
2043 fprintf(stderr, "out of memory\n");
2046 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2047 (int)ld.ld_symb_size, strtab) < 0)
2051 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2052 fprintf(stderr, "[symbol: %s]\n", cp);
2057 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2058 if (strcmp(cp, "_vfork") == 0) {
2060 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2061 strcpy(cp, "_fork");
2066 if (cp < strtab + ld.ld_symb_size)
2068 * Write entire symbol table back to avoid
2069 * memory alignment bugs in ptrace
2071 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2072 (int)ld.ld_symb_size, strtab) < 0)