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);
353 printnum_int(tcp, addr, fmt)
364 if (umove(tcp, addr, &num) < 0) {
365 tprintf("%#lx", addr);
379 tprintf((uid == -1) ? "%ld" : "%lu", uid);
382 static char path[MAXPATHLEN + 1];
388 char buf[2 * MAXPATHLEN + 1];
391 if (!strpbrk(str, "\"\'\\")) {
392 tprintf("\"%s\"", str);
395 for (s = buf; *str; str++) {
397 case '\"': case '\'': case '\\':
398 *s++ = '\\'; *s++ = *str; break;
404 tprintf("\"%s\"", buf);
414 else if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
415 tprintf("%#lx", addr);
422 printpathn(tcp, addr, n)
429 else if (umovestr(tcp, addr, n, path) < 0)
430 tprintf("%#lx", addr);
438 printstr(tcp, addr, len)
443 static unsigned char *str = NULL;
453 if ((str = malloc(max_strlen)) == NULL
454 || (outstr = malloc(2*max_strlen)) == NULL) {
455 fprintf(stderr, "out of memory\n");
456 tprintf("%#lx", addr);
460 outend = outstr + max_strlen * 2 - 10;
463 if (umovestr(tcp, addr, n, (char *) str) < 0) {
464 tprintf("%#lx", addr);
469 n = MIN(len, max_strlen);
470 if (umoven(tcp, addr, n, (char *) str) < 0) {
471 tprintf("%#lx", addr);
480 for (i = 0; i < n; i++) {
482 if (len < 0 && c == '\0')
484 if (!isprint(c) && !isspace(c)) {
495 for (i = 0; i < n; i++) {
497 if (len < 0 && c == '\0')
499 sprintf(s, "\\x%02x", c);
506 for (i = 0; i < n; i++) {
508 if (len < 0 && c == '\0')
511 case '\"': case '\'': case '\\':
512 *s++ = '\\'; *s++ = c; break;
514 *s++ = '\\'; *s++ = 'f'; break;
516 *s++ = '\\'; *s++ = 'n'; break;
518 *s++ = '\\'; *s++ = 'r'; break;
520 *s++ = '\\'; *s++ = 't'; break;
522 *s++ = '\\'; *s++ = 'v'; break;
526 else if (i < n - 1 && isdigit(str[i + 1])) {
527 sprintf(s, "\\%03o", c);
531 sprintf(s, "\\%o", c);
542 if (i < len || (len < 0 && (i == n || s > outend))) {
543 *s++ = '.'; *s++ = '.'; *s++ = '.';
546 tprintf("%s", outstr);
551 dumpiov(tcp, len, addr)
560 size = sizeof(*iov) * (unsigned long) len;
561 if (size / sizeof(*iov) != len
562 || (iov = (struct iovec *) malloc(size)) == NULL) {
563 fprintf(stderr, "out of memory\n");
566 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
567 for (i = 0; i < len; i++) {
568 /* include the buffer number to make it easy to
569 * match up the trace with the source */
570 tprintf(" * %lu bytes in buffer %d\n",
571 (unsigned long)iov[i].iov_len, i);
572 dumpstr(tcp, (long) iov[i].iov_base,
582 dumpstr(tcp, addr, len)
587 static int strsize = -1;
588 static unsigned char *str;
589 static char outstr[80];
596 if ((str = malloc(len)) == NULL) {
597 fprintf(stderr, "out of memory\n");
603 if (umoven(tcp, addr, len, (char *) str) < 0)
606 for (i = 0; i < len; i += 16) {
608 sprintf(s, " | %05x ", i);
610 for (j = 0; j < 16; j++) {
614 sprintf(s, " %02x", str[i + j]);
618 *s++ = ' '; *s++ = ' '; *s++ = ' ';
621 *s++ = ' '; *s++ = ' ';
622 for (j = 0; j < 16; j++) {
626 if (isprint(str[i + j]))
634 tprintf("%s |\n", outstr);
638 #define PAGMASK (~(PAGSIZ - 1))
640 * move `len' bytes of data from process `pid'
641 * at address `addr' to our space at `laddr'
644 umoven(tcp, addr, len, laddr)
657 char x[sizeof(long)];
660 if (addr & (sizeof(long) - 1)) {
661 /* addr not a multiple of sizeof(long) */
662 n = addr - (addr & -sizeof(long)); /* residue */
663 addr &= -sizeof(long); /* residue */
665 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
667 if (started && (errno==EPERM || errno==EIO)) {
668 /* Ran into 'end of memory' - stupid "printpath" */
671 /* But if not started, we had a bogus address. */
672 perror("ptrace: umoven");
676 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
677 addr += sizeof(long), laddr += m, len -= m;
681 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
683 if (started && (errno==EPERM || errno==EIO)) {
684 /* Ran into 'end of memory' - stupid "printpath" */
688 perror("ptrace: umoven");
692 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
693 addr += sizeof(long), laddr += m, len -= m;
703 char x[sizeof(long)];
706 if (addr & (sizeof(long) - 1)) {
707 /* addr not a multiple of sizeof(long) */
708 n = addr - (addr & -sizeof(long)); /* residue */
709 addr &= -sizeof(long); /* residue */
711 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
716 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
717 addr += sizeof(long), laddr += m, len -= m;
721 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
726 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
727 addr += sizeof(long), laddr += m, len -= m;
733 n = MIN(len, PAGSIZ);
734 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
735 if (ptrace(PTRACE_READDATA, pid,
736 (char *) addr, len, laddr) < 0) {
737 perror("umoven: ptrace(PTRACE_READDATA, ...)");
749 #ifdef HAVE_MP_PROCFS
750 int fd = tcp->pfd_as;
754 lseek(fd, addr, SEEK_SET);
755 if (read(fd, laddr, len) == -1)
757 #endif /* USE_PROCFS */
763 * like `umove' but make the additional effort of looking
764 * for a terminating zero byte.
767 umovestr(tcp, addr, len, laddr)
774 #ifdef HAVE_MP_PROCFS
775 int fd = tcp->pfd_as;
779 /* Some systems (e.g. FreeBSD) can be upset if we read off the
780 end of valid memory, avoid this by trying to read up
781 to page boundaries. But we don't know what a page is (and
782 getpagesize(2) (if it exists) doesn't necessarily return
783 hardware page size). Assume all pages >= 1024 (a-historical
786 int page = 1024; /* How to find this? */
787 int move = page - (addr & (page - 1));
790 lseek(fd, addr, SEEK_SET);
793 if (move > left) move = left;
794 if ((move = read(fd, laddr, move)) <= 0)
795 return left != len ? 0 : -1;
796 if (memchr (laddr, 0, move)) break;
802 #else /* !USE_PROCFS */
808 char x[sizeof(long)];
811 if (addr & (sizeof(long) - 1)) {
812 /* addr not a multiple of sizeof(long) */
813 n = addr - (addr & -sizeof(long)); /* residue */
814 addr &= -sizeof(long); /* residue */
816 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
818 if (started && (errno==EPERM || errno==EIO)) {
819 /* Ran into 'end of memory' - stupid "printpath" */
826 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
827 while (n & (sizeof(long) - 1))
828 if (u.x[n++] == '\0')
830 addr += sizeof(long), laddr += m, len -= m;
834 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
836 if (started && (errno==EPERM || errno==EIO)) {
837 /* Ran into 'end of memory' - stupid "printpath" */
844 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
845 for (i = 0; i < sizeof(long); i++)
849 addr += sizeof(long), laddr += m, len -= m;
851 #endif /* !USE_PROCFS */
856 #if !defined (SPARC) && !defined(SPARC64)
857 #define PTRACE_WRITETEXT 101
858 #define PTRACE_WRITEDATA 102
859 #endif /* !SPARC && !SPARC64 */
865 uload(cmd, pid, addr, len, laddr)
876 n = MIN(len, PAGSIZ);
877 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
878 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
879 perror("uload: ptrace(PTRACE_WRITE, ...)");
891 char x[sizeof(long)];
894 if (cmd == PTRACE_WRITETEXT) {
895 peek = PTRACE_PEEKTEXT;
896 poke = PTRACE_POKETEXT;
899 peek = PTRACE_PEEKDATA;
900 poke = PTRACE_POKEDATA;
902 if (addr & (sizeof(long) - 1)) {
903 /* addr not a multiple of sizeof(long) */
904 n = addr - (addr & -sizeof(long)); /* residue */
905 addr &= -sizeof(long);
907 u.val = ptrace(peek, pid, (char *) addr, 0);
909 perror("uload: POKE");
912 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
913 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
914 perror("uload: POKE");
917 addr += sizeof(long), laddr += m, len -= m;
920 if (len < sizeof(long))
921 u.val = ptrace(peek, pid, (char *) addr, 0);
922 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
923 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
924 perror("uload: POKE");
927 addr += sizeof(long), laddr += m, len -= m;
934 tload(pid, addr, len, laddr)
939 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
943 dload(pid, addr, len, laddr)
949 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
964 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
966 static int is_sun4m = -1;
969 /* Round up the usual suspects. */
970 if (is_sun4m == -1) {
971 if (uname(&name) < 0) {
972 perror("upeek: uname?");
975 is_sun4m = strcmp(name.machine, "sun4m") == 0;
977 extern const struct xlat struct_user_offsets[];
978 const struct xlat *x;
980 for (x = struct_user_offsets; x->str; x++)
987 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
989 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
990 if (val == -1 && errno) {
992 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
1000 #endif /* !USE_PROCFS */
1011 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
1013 #elif defined(X86_64)
1014 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
1017 if (upeek(tcp->pid, PT_B0, &pc) < 0)
1020 if (upeek(tcp->pid, 4*15, &pc) < 0)
1022 #elif defined(POWERPC)
1023 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1026 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1028 #elif defined(ALPHA)
1029 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1032 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1034 #elif defined(SPARC) || defined(SPARC64)
1036 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0)
1039 #elif defined(S390) || defined(S390X)
1040 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
1043 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1046 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1049 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1057 * Return current program counter for `pid'
1058 * Assumes PC is never 0xffffffff
1062 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1063 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1076 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1078 #endif /* FREEBSD */
1086 #define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1087 sizeof(long) == 8 ? "[????????????????] " : \
1094 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1098 tprintf("[%08lx] ", eip);
1100 #elif defined(S390) || defined(S390X)
1102 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
1107 tprintf("[%08lx] ", psw);
1109 tprintf("[%16lx] ", psw);
1112 #elif defined(X86_64)
1115 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1119 tprintf("[%16lx] ", rip);
1123 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1127 tprintf("[%08lx] ", ip);
1128 #elif defined(POWERPC)
1131 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1132 tprintf ("[????????] ");
1135 tprintf("[%08lx] ", pc);
1139 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1140 tprintf ("[????????] ");
1143 tprintf("[%08lx] ", pc);
1144 #elif defined(ALPHA)
1147 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1148 tprintf ("[????????????????] ");
1151 tprintf("[%08lx] ", pc);
1152 #elif defined(SPARC) || defined(SPARC64)
1154 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0) {
1158 tprintf("[%08lx] ", regs.r_pc);
1162 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1163 tprintf ("[????????] ");
1166 tprintf("[%08lx] ", pc);
1170 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1171 tprintf ("[????????] ");
1174 tprintf("[%08lx] ", pc);
1178 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1179 tprintf ("[????????] ");
1182 tprintf("[%08lx] ", pc);
1186 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1187 tprintf ("[????????????????] ");
1190 tprintf("[%08lx] ", pc);
1194 if (upeek(tcp->pid, 4*15, &pc) < 0) {
1198 tprintf("[%08lx] ", pc);
1199 #endif /* !architecture */
1205 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1206 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1210 tprintf("[%08x] ", regs.r_o7);
1220 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1221 tprintf("[%08x] ", regs.r_eip);
1222 #endif /* FREEBSD */
1229 #include <sys/syscall.h>
1230 #ifndef CLONE_PTRACE
1231 # define CLONE_PTRACE 0x00002000
1233 #ifndef CLONE_STOPPED
1234 # define CLONE_STOPPED 0x02000000
1239 /* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1240 subsystem has them for x86... */
1242 #define SYS_vfork 190
1244 typedef unsigned long *arg_setup_state;
1247 arg_setup(struct tcb *tcp, arg_setup_state *state)
1249 unsigned long *bsp, cfm, sof, sol;
1254 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1256 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1259 sof = (cfm >> 0) & 0x7f;
1260 sol = (cfm >> 7) & 0x7f;
1261 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1267 # define arg_finish_change(tcp, state) 0
1271 get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1276 ret = upeek (tcp->pid, PT_R11, valp);
1279 (unsigned long) ia64_rse_skip_regs(*state, 0),
1280 sizeof(long), (void *) valp);
1285 get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1290 ret = upeek (tcp->pid, PT_R9, valp);
1293 (unsigned long) ia64_rse_skip_regs(*state, 1),
1294 sizeof(long), (void *) valp);
1300 set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1302 int req = PTRACE_POKEDATA;
1306 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1307 req = PTRACE_POKEUSER;
1309 ap = ia64_rse_skip_regs(*state, 0);
1311 ptrace(req, tcp->pid, ap, val);
1312 return errno ? -1 : 0;
1316 set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1318 int req = PTRACE_POKEDATA;
1322 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1323 req = PTRACE_POKEUSER;
1325 ap = ia64_rse_skip_regs(*state, 1);
1327 ptrace(req, tcp->pid, ap, val);
1328 return errno ? -1 : 0;
1331 #elif defined (SPARC) || defined (SPARC64)
1333 typedef struct regs arg_setup_state;
1335 # define arg_setup(tcp, state) \
1336 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1337 # define arg_finish_change(tcp, state) \
1338 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1340 # define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1341 # define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1342 # define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1343 # define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
1344 # define restore_arg0(tcp, state, val) 0
1348 # if defined S390 || defined S390X
1349 /* Note: this is only true for the `clone' system call, which handles
1350 arguments specially. We could as well say that its first two arguments
1351 are swapped relative to other architectures, but that would just be
1352 another #ifdef in the calls. */
1353 # define arg0_offset PT_GPR3
1354 # define arg1_offset PT_ORIGGPR2
1355 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1356 # define restore_arg1(tcp, state, val) ((void) (state), 0)
1357 # define arg0_index 1
1358 # define arg1_index 0
1359 # elif defined (ALPHA) || defined (MIPS)
1360 # define arg0_offset REG_A0
1361 # define arg1_offset (REG_A0+1)
1362 # elif defined (POWERPC)
1363 # define arg0_offset (sizeof(unsigned long)*PT_R3)
1364 # define arg1_offset (sizeof(unsigned long)*PT_R4)
1365 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1366 # elif defined (HPPA)
1367 # define arg0_offset PT_GR26
1368 # define arg1_offset (PT_GR26-4)
1369 # elif defined (X86_64)
1370 # define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1371 # define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1373 # define arg0_offset (4*(REG_REG0+4))
1374 # define arg1_offset (4*(REG_REG0+5))
1375 # elif defined (SH64)
1376 /* ABI defines arg0 & 1 in r2 & r3 */
1377 # define arg0_offset (REG_OFFSET+16)
1378 # define arg1_offset (REG_OFFSET+24)
1379 # define restore_arg0(tcp, state, val) 0
1381 # define arg0_offset 0
1382 # define arg1_offset 4
1384 # define restore_arg0(tcp, state, val) 0
1388 typedef int arg_setup_state;
1390 # define arg_setup(tcp, state) (0)
1391 # define arg_finish_change(tcp, state) 0
1392 # define get_arg0(tcp, cookie, valp) \
1393 (upeek ((tcp)->pid, arg0_offset, (valp)))
1394 # define get_arg1(tcp, cookie, valp) \
1395 (upeek ((tcp)->pid, arg1_offset, (valp)))
1398 set_arg0 (struct tcb *tcp, void *cookie, long val)
1400 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1404 set_arg1 (struct tcb *tcp, void *cookie, long val)
1406 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1411 #ifndef restore_arg0
1412 # define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1414 #ifndef restore_arg1
1415 # define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1419 # define arg0_index 0
1420 # define arg1_index 1
1427 extern int change_syscall(struct tcb *, int);
1428 arg_setup_state state;
1430 if (tcp->flags & TCB_BPTSET) {
1431 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1435 switch (known_scno(tcp)) {
1442 #if defined SYS_fork || defined SYS_vfork
1443 if (arg_setup (tcp, &state) < 0
1444 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1445 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1446 || change_syscall(tcp, SYS_clone) < 0
1447 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1448 || set_arg1 (tcp, &state, 0) < 0
1449 || arg_finish_change (tcp, &state) < 0)
1451 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1452 tcp->u_arg[arg1_index] = 0;
1453 tcp->flags |= TCB_BPTSET;
1461 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
1462 && (arg_setup (tcp, &state) < 0
1463 || set_arg0 (tcp, &state,
1464 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
1465 || arg_finish_change (tcp, &state) < 0))
1467 tcp->flags |= TCB_BPTSET;
1468 tcp->inst[0] = tcp->u_arg[arg0_index];
1469 tcp->inst[1] = tcp->u_arg[arg1_index];
1473 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1474 tcp->scno, tcp->pid);
1485 arg_setup_state state;
1486 if (arg_setup (tcp, &state) < 0
1487 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1488 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1489 || arg_finish_change (tcp, &state))
1491 tcp->flags &= ~TCB_BPTSET;
1503 #if defined (SPARC) || defined (SPARC64)
1504 /* We simply use the SunOS breakpoint code. */
1508 #define LOOPA 0x30800000 /* ba,a 0 */
1510 if (tcp->flags & TCB_BPTSET) {
1511 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1514 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1515 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1518 tcp->baddr = regs.r_o7 + 8;
1520 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1522 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1527 * XXX - BRUTAL MODE ON
1528 * We cannot set a real BPT in the child, since it will not be
1529 * traced at the moment it will reach the trap and would probably
1530 * die with a core dump.
1531 * Thus, we are force our way in by taking out two instructions
1532 * and insert an eternal loop instead, in expectance of the SIGSTOP
1533 * generated by out PTRACE_ATTACH.
1534 * Of cause, if we evaporate ourselves in the middle of all this...
1538 #if defined (SPARC64)
1540 inst |= (tcp->inst[0] & 0xffffffffUL);
1542 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
1544 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1547 tcp->flags |= TCB_BPTSET;
1549 #else /* !SPARC && !SPARC64 */
1552 # define LOOP 0x0000feeb
1553 if (tcp->flags & TCB_BPTSET) {
1554 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1558 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1561 fprintf(stderr, "[%d] setting bpt at %lx\n",
1562 tcp->pid, tcp->baddr);
1563 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1564 (char *) tcp->baddr, 0);
1566 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1569 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1571 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1574 tcp->flags |= TCB_BPTSET;
1577 * Our strategy here is to replace the bundle that
1578 * contained the clone() syscall with a bundle of the
1581 * { 1: br 1b; br 1b; br 1b }
1583 * This ensures that the newly forked child will loop
1584 * endlessly until we've got a chance to attach to it.
1586 # define LOOP0 0x0000100000000017
1587 # define LOOP1 0x4000000000200000
1588 unsigned long addr, ipsr;
1592 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1594 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1596 /* store "ri" in low two bits */
1597 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
1600 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1602 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1605 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1610 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1611 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1613 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1616 tcp->flags |= TCB_BPTSET;
1620 #if defined (I386) || defined(X86_64)
1621 #define LOOP 0x0000feeb
1622 #elif defined (M68K)
1623 #define LOOP 0x60fe0000
1624 #elif defined (ALPHA)
1625 #define LOOP 0xc3ffffff
1626 #elif defined (POWERPC)
1627 #define LOOP 0x48000000
1629 #define LOOP 0xEAFFFFFE
1631 #define LOOP 0x1000ffff
1633 #define LOOP 0xa7f40000 /* BRC 15,0 */
1634 #elif defined(S390X)
1635 #define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
1637 #define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
1639 #ifdef __LITTLE_ENDIAN__
1640 #define LOOP 0x0000affe
1642 #define LOOP 0xfeaf0000
1645 #error unknown architecture
1648 if (tcp->flags & TCB_BPTSET) {
1649 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1653 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1655 #elif defined (X86_64)
1656 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1658 #elif defined (M68K)
1659 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1661 #elif defined (ALPHA)
1665 #elif defined (MIPS)
1666 return -1; /* FIXME: I do not know what i do - Flo */
1667 #elif defined (POWERPC)
1668 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
1670 #elif defined(S390) || defined(S390X)
1671 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1674 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1676 tcp->baddr &= ~0x03;
1678 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1681 #error unknown architecture
1684 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1685 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1687 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1690 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1692 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1695 tcp->flags |= TCB_BPTSET;
1698 #endif /* SPARC || SPARC64 */
1702 #ifdef SPARC /* This code is slightly sparc specific */
1705 #define BPT 0x91d02001 /* ta 1 */
1706 #define LOOP 0x10800000 /* ba 0 */
1707 #define LOOPA 0x30800000 /* ba,a 0 */
1708 #define NOP 0x01000000
1710 static int loopdeloop[1] = {LOOPA};
1712 static int loopdeloop[2] = {LOOP, NOP};
1715 if (tcp->flags & TCB_BPTSET) {
1716 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1719 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1720 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1723 tcp->baddr = regs.r_o7 + 8;
1724 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1725 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1726 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1731 * XXX - BRUTAL MODE ON
1732 * We cannot set a real BPT in the child, since it will not be
1733 * traced at the moment it will reach the trap and would probably
1734 * die with a core dump.
1735 * Thus, we are force our way in by taking out two instructions
1736 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1737 * generated by out PTRACE_ATTACH.
1738 * Of cause, if we evaporate ourselves in the middle of all this...
1740 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1741 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1742 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1745 tcp->flags |= TCB_BPTSET;
1759 #if defined(I386) || defined(X86_64)
1761 #elif defined(POWERPC)
1765 #elif defined(ALPHA)
1771 #endif /* architecture */
1773 #if defined (SPARC) || defined (SPARC64)
1774 /* Again, we borrow the SunOS breakpoint code. */
1775 if (!(tcp->flags & TCB_BPTSET)) {
1776 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1780 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1782 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1785 tcp->flags &= ~TCB_BPTSET;
1791 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1792 if (!(tcp->flags & TCB_BPTSET)) {
1793 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1797 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1799 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1802 tcp->flags &= ~TCB_BPTSET;
1804 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1806 if (addr != tcp->baddr) {
1807 /* The breakpoint has not been reached yet. */
1810 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1815 unsigned long addr, ipsr;
1820 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1822 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1825 /* restore original bundle: */
1827 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1828 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1830 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1834 /* restore original "ri" in ipsr: */
1835 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1837 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1839 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1843 tcp->flags &= ~TCB_BPTSET;
1845 if (addr != (tcp->baddr & ~0x3)) {
1846 /* the breakpoint has not been reached yet. */
1848 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1853 #else /* !IA64 && !SPARC && !SPARC64 */
1856 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1857 if (!(tcp->flags & TCB_BPTSET)) {
1858 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1862 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1864 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1867 tcp->flags &= ~TCB_BPTSET;
1870 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1872 if (eip != tcp->baddr) {
1873 /* The breakpoint has not been reached yet. */
1876 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1880 #elif defined(X86_64)
1881 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1883 if (eip != tcp->baddr) {
1884 /* The breakpoint has not been reached yet. */
1887 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1891 #elif defined(POWERPC)
1892 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1894 if (pc != tcp->baddr) {
1895 /* The breakpoint has not been reached yet. */
1897 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1902 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1904 if (pc != tcp->baddr) {
1905 /* The breakpoint has not been reached yet. */
1907 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1911 #elif defined(ALPHA)
1912 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1914 if (pc != tcp->baddr) {
1915 /* The breakpoint has not been reached yet. */
1917 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1922 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1925 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1926 /* The breakpoint has not been reached yet. */
1928 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1932 iaoq = tcp->baddr | 3;
1933 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1934 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1935 * has no significant effect.
1937 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1938 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
1940 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1942 if (pc != tcp->baddr) {
1943 /* The breakpoint has not been reached yet. */
1945 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1951 #endif /* !SPARC && !SPARC64 && !IA64 */
1961 if (!(tcp->flags & TCB_BPTSET)) {
1962 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1965 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1966 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1967 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1970 tcp->flags &= ~TCB_BPTSET;
1974 * Since we don't have a single instruction breakpoint, we may have
1975 * to adjust the program counter after removing the our `breakpoint'.
1977 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1978 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1981 if ((regs.r_pc < tcp->baddr) ||
1982 (regs.r_pc > tcp->baddr + 4)) {
1983 /* The breakpoint has not been reached yet */
1986 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1987 regs.r_pc, tcp->parent->baddr);
1990 if (regs.r_pc != tcp->baddr)
1992 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1993 regs.r_pc, tcp->baddr);
1995 regs.r_pc = tcp->baddr;
1996 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0) {
1997 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
2009 #endif /* !USE_PROCFS */
2020 for (n = 0; n < sizeof *hdr; n += 4) {
2022 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
2024 memcpy(((char *) hdr) + n, &res, 4);
2027 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2028 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2029 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2030 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2041 * Change `vfork' in a freshly exec'ed dynamically linked
2042 * executable's (internal) symbol table to plain old `fork'
2046 struct link_dynamic dyn;
2047 struct link_dynamic_2 ld;
2050 if (getex(pid, &hdr) < 0)
2055 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2056 fprintf(stderr, "Cannot read DYNAMIC\n");
2059 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2060 fprintf(stderr, "Cannot read link_dynamic_2\n");
2063 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
2064 fprintf(stderr, "out of memory\n");
2067 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2068 (int)ld.ld_symb_size, strtab) < 0)
2072 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2073 fprintf(stderr, "[symbol: %s]\n", cp);
2078 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2079 if (strcmp(cp, "_vfork") == 0) {
2081 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2082 strcpy(cp, "_fork");
2087 if (cp < strtab + ld.ld_symb_size)
2089 * Write entire symbol table back to avoid
2090 * memory alignment bugs in ptrace
2092 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2093 (int)ld.ld_symb_size, strtab) < 0)