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)
427 if (n >= sizeof path)
432 else if (umovestr(tcp, addr, n, path) < 0)
433 tprintf("%#lx", addr);
441 printstr(tcp, addr, len)
446 static unsigned char *str = NULL;
456 if ((str = malloc(max_strlen)) == NULL
457 || (outstr = malloc(2*max_strlen)) == NULL) {
458 fprintf(stderr, "out of memory\n");
459 tprintf("%#lx", addr);
463 outend = outstr + max_strlen * 2 - 10;
466 if (umovestr(tcp, addr, n, (char *) str) < 0) {
467 tprintf("%#lx", addr);
472 n = MIN(len, max_strlen);
473 if (umoven(tcp, addr, n, (char *) str) < 0) {
474 tprintf("%#lx", addr);
483 for (i = 0; i < n; i++) {
485 if (len < 0 && c == '\0')
487 if (!isprint(c) && !isspace(c)) {
498 for (i = 0; i < n; i++) {
500 if (len < 0 && c == '\0')
502 sprintf(s, "\\x%02x", c);
509 for (i = 0; i < n; i++) {
511 if (len < 0 && c == '\0')
514 case '\"': case '\'': case '\\':
515 *s++ = '\\'; *s++ = c; break;
517 *s++ = '\\'; *s++ = 'f'; break;
519 *s++ = '\\'; *s++ = 'n'; break;
521 *s++ = '\\'; *s++ = 'r'; break;
523 *s++ = '\\'; *s++ = 't'; break;
525 *s++ = '\\'; *s++ = 'v'; break;
529 else if (i < n - 1 && isdigit(str[i + 1])) {
530 sprintf(s, "\\%03o", c);
534 sprintf(s, "\\%o", c);
545 if (i < len || (len < 0 && (i == n || s > outend))) {
546 *s++ = '.'; *s++ = '.'; *s++ = '.';
549 tprintf("%s", outstr);
554 dumpiov(tcp, len, addr)
563 size = sizeof(*iov) * (unsigned long) len;
564 if (size / sizeof(*iov) != len
565 || (iov = (struct iovec *) malloc(size)) == NULL) {
566 fprintf(stderr, "out of memory\n");
569 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
570 for (i = 0; i < len; i++) {
571 /* include the buffer number to make it easy to
572 * match up the trace with the source */
573 tprintf(" * %lu bytes in buffer %d\n",
574 (unsigned long)iov[i].iov_len, i);
575 dumpstr(tcp, (long) iov[i].iov_base,
585 dumpstr(tcp, addr, len)
590 static int strsize = -1;
591 static unsigned char *str;
592 static char outstr[80];
599 if ((str = malloc(len)) == NULL) {
600 fprintf(stderr, "out of memory\n");
606 if (umoven(tcp, addr, len, (char *) str) < 0)
609 for (i = 0; i < len; i += 16) {
611 sprintf(s, " | %05x ", i);
613 for (j = 0; j < 16; j++) {
617 sprintf(s, " %02x", str[i + j]);
621 *s++ = ' '; *s++ = ' '; *s++ = ' ';
624 *s++ = ' '; *s++ = ' ';
625 for (j = 0; j < 16; j++) {
629 if (isprint(str[i + j]))
637 tprintf("%s |\n", outstr);
641 #define PAGMASK (~(PAGSIZ - 1))
643 * move `len' bytes of data from process `pid'
644 * at address `addr' to our space at `laddr'
647 umoven(tcp, addr, len, laddr)
660 char x[sizeof(long)];
663 if (addr & (sizeof(long) - 1)) {
664 /* addr not a multiple of sizeof(long) */
665 n = addr - (addr & -sizeof(long)); /* residue */
666 addr &= -sizeof(long); /* residue */
668 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
670 if (started && (errno==EPERM || errno==EIO)) {
671 /* Ran into 'end of memory' - stupid "printpath" */
674 /* But if not started, we had a bogus address. */
675 perror("ptrace: umoven");
679 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
680 addr += sizeof(long), laddr += m, len -= m;
684 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
686 if (started && (errno==EPERM || errno==EIO)) {
687 /* Ran into 'end of memory' - stupid "printpath" */
691 perror("ptrace: umoven");
695 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
696 addr += sizeof(long), laddr += m, len -= m;
706 char x[sizeof(long)];
709 if (addr & (sizeof(long) - 1)) {
710 /* addr not a multiple of sizeof(long) */
711 n = addr - (addr & -sizeof(long)); /* residue */
712 addr &= -sizeof(long); /* residue */
714 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
719 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
720 addr += sizeof(long), laddr += m, len -= m;
724 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
729 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
730 addr += sizeof(long), laddr += m, len -= m;
736 n = MIN(len, PAGSIZ);
737 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
738 if (ptrace(PTRACE_READDATA, pid,
739 (char *) addr, len, laddr) < 0) {
740 perror("umoven: ptrace(PTRACE_READDATA, ...)");
752 #ifdef HAVE_MP_PROCFS
753 int fd = tcp->pfd_as;
757 lseek(fd, addr, SEEK_SET);
758 if (read(fd, laddr, len) == -1)
760 #endif /* USE_PROCFS */
766 * like `umove' but make the additional effort of looking
767 * for a terminating zero byte.
770 umovestr(tcp, addr, len, laddr)
777 #ifdef HAVE_MP_PROCFS
778 int fd = tcp->pfd_as;
782 /* Some systems (e.g. FreeBSD) can be upset if we read off the
783 end of valid memory, avoid this by trying to read up
784 to page boundaries. But we don't know what a page is (and
785 getpagesize(2) (if it exists) doesn't necessarily return
786 hardware page size). Assume all pages >= 1024 (a-historical
789 int page = 1024; /* How to find this? */
790 int move = page - (addr & (page - 1));
793 lseek(fd, addr, SEEK_SET);
796 if (move > left) move = left;
797 if ((move = read(fd, laddr, move)) <= 0)
798 return left != len ? 0 : -1;
799 if (memchr (laddr, 0, move)) break;
805 #else /* !USE_PROCFS */
811 char x[sizeof(long)];
814 if (addr & (sizeof(long) - 1)) {
815 /* addr not a multiple of sizeof(long) */
816 n = addr - (addr & -sizeof(long)); /* residue */
817 addr &= -sizeof(long); /* residue */
819 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
821 if (started && (errno==EPERM || errno==EIO)) {
822 /* Ran into 'end of memory' - stupid "printpath" */
829 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
830 while (n & (sizeof(long) - 1))
831 if (u.x[n++] == '\0')
833 addr += sizeof(long), laddr += m, len -= m;
837 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
839 if (started && (errno==EPERM || errno==EIO)) {
840 /* Ran into 'end of memory' - stupid "printpath" */
847 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
848 for (i = 0; i < sizeof(long); i++)
852 addr += sizeof(long), laddr += m, len -= m;
854 #endif /* !USE_PROCFS */
859 #if !defined (SPARC) && !defined(SPARC64)
860 #define PTRACE_WRITETEXT 101
861 #define PTRACE_WRITEDATA 102
862 #endif /* !SPARC && !SPARC64 */
868 uload(cmd, pid, addr, len, laddr)
879 n = MIN(len, PAGSIZ);
880 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
881 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
882 perror("uload: ptrace(PTRACE_WRITE, ...)");
894 char x[sizeof(long)];
897 if (cmd == PTRACE_WRITETEXT) {
898 peek = PTRACE_PEEKTEXT;
899 poke = PTRACE_POKETEXT;
902 peek = PTRACE_PEEKDATA;
903 poke = PTRACE_POKEDATA;
905 if (addr & (sizeof(long) - 1)) {
906 /* addr not a multiple of sizeof(long) */
907 n = addr - (addr & -sizeof(long)); /* residue */
908 addr &= -sizeof(long);
910 u.val = ptrace(peek, pid, (char *) addr, 0);
912 perror("uload: POKE");
915 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
916 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
917 perror("uload: POKE");
920 addr += sizeof(long), laddr += m, len -= m;
923 if (len < sizeof(long))
924 u.val = ptrace(peek, pid, (char *) addr, 0);
925 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
926 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
927 perror("uload: POKE");
930 addr += sizeof(long), laddr += m, len -= m;
937 tload(pid, addr, len, laddr)
942 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
946 dload(pid, addr, len, laddr)
952 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
967 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
969 static int is_sun4m = -1;
972 /* Round up the usual suspects. */
973 if (is_sun4m == -1) {
974 if (uname(&name) < 0) {
975 perror("upeek: uname?");
978 is_sun4m = strcmp(name.machine, "sun4m") == 0;
980 extern const struct xlat struct_user_offsets[];
981 const struct xlat *x;
983 for (x = struct_user_offsets; x->str; x++)
990 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
992 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
993 if (val == -1 && errno) {
995 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
1003 #endif /* !USE_PROCFS */
1014 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
1016 #elif defined(X86_64)
1017 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
1020 if (upeek(tcp->pid, PT_B0, &pc) < 0)
1023 if (upeek(tcp->pid, 4*15, &pc) < 0)
1025 #elif defined(POWERPC)
1026 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1029 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1031 #elif defined(ALPHA)
1032 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1035 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1037 #elif defined(SPARC) || defined(SPARC64)
1039 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0)
1042 #elif defined(S390) || defined(S390X)
1043 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
1046 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1049 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1052 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1060 * Return current program counter for `pid'
1061 * Assumes PC is never 0xffffffff
1065 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1066 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1079 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1081 #endif /* FREEBSD */
1089 #define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1090 sizeof(long) == 8 ? "[????????????????] " : \
1097 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1101 tprintf("[%08lx] ", eip);
1103 #elif defined(S390) || defined(S390X)
1105 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
1110 tprintf("[%08lx] ", psw);
1112 tprintf("[%16lx] ", psw);
1115 #elif defined(X86_64)
1118 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1122 tprintf("[%16lx] ", rip);
1126 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1130 tprintf("[%08lx] ", ip);
1131 #elif defined(POWERPC)
1134 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1135 tprintf ("[????????] ");
1138 tprintf("[%08lx] ", pc);
1142 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1143 tprintf ("[????????] ");
1146 tprintf("[%08lx] ", pc);
1147 #elif defined(ALPHA)
1150 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1151 tprintf ("[????????????????] ");
1154 tprintf("[%08lx] ", pc);
1155 #elif defined(SPARC) || defined(SPARC64)
1157 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0) {
1161 tprintf("[%08lx] ", regs.r_pc);
1165 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1166 tprintf ("[????????] ");
1169 tprintf("[%08lx] ", pc);
1173 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1174 tprintf ("[????????] ");
1177 tprintf("[%08lx] ", pc);
1181 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1182 tprintf ("[????????] ");
1185 tprintf("[%08lx] ", pc);
1189 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1190 tprintf ("[????????????????] ");
1193 tprintf("[%08lx] ", pc);
1197 if (upeek(tcp->pid, 4*15, &pc) < 0) {
1201 tprintf("[%08lx] ", pc);
1202 #endif /* !architecture */
1208 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1209 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1213 tprintf("[%08x] ", regs.r_o7);
1223 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1224 tprintf("[%08x] ", regs.r_eip);
1225 #endif /* FREEBSD */
1232 #include <sys/syscall.h>
1233 #ifndef CLONE_PTRACE
1234 # define CLONE_PTRACE 0x00002000
1236 #ifndef CLONE_STOPPED
1237 # define CLONE_STOPPED 0x02000000
1242 /* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1243 subsystem has them for x86... */
1245 #define SYS_vfork 190
1247 typedef unsigned long *arg_setup_state;
1250 arg_setup(struct tcb *tcp, arg_setup_state *state)
1252 unsigned long *bsp, cfm, sof, sol;
1257 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1259 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1262 sof = (cfm >> 0) & 0x7f;
1263 sol = (cfm >> 7) & 0x7f;
1264 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1270 # define arg_finish_change(tcp, state) 0
1274 get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1279 ret = upeek (tcp->pid, PT_R11, valp);
1282 (unsigned long) ia64_rse_skip_regs(*state, 0),
1283 sizeof(long), (void *) valp);
1288 get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1293 ret = upeek (tcp->pid, PT_R9, valp);
1296 (unsigned long) ia64_rse_skip_regs(*state, 1),
1297 sizeof(long), (void *) valp);
1303 set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1305 int req = PTRACE_POKEDATA;
1309 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1310 req = PTRACE_POKEUSER;
1312 ap = ia64_rse_skip_regs(*state, 0);
1314 ptrace(req, tcp->pid, ap, val);
1315 return errno ? -1 : 0;
1319 set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1321 int req = PTRACE_POKEDATA;
1325 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1326 req = PTRACE_POKEUSER;
1328 ap = ia64_rse_skip_regs(*state, 1);
1330 ptrace(req, tcp->pid, ap, val);
1331 return errno ? -1 : 0;
1334 #elif defined (SPARC) || defined (SPARC64)
1336 typedef struct regs arg_setup_state;
1338 # define arg_setup(tcp, state) \
1339 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1340 # define arg_finish_change(tcp, state) \
1341 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1343 # define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1344 # define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1345 # define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1346 # define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
1347 # define restore_arg0(tcp, state, val) 0
1351 # if defined S390 || defined S390X
1352 /* Note: this is only true for the `clone' system call, which handles
1353 arguments specially. We could as well say that its first two arguments
1354 are swapped relative to other architectures, but that would just be
1355 another #ifdef in the calls. */
1356 # define arg0_offset PT_GPR3
1357 # define arg1_offset PT_ORIGGPR2
1358 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1359 # define restore_arg1(tcp, state, val) ((void) (state), 0)
1360 # define arg0_index 1
1361 # define arg1_index 0
1362 # elif defined (ALPHA) || defined (MIPS)
1363 # define arg0_offset REG_A0
1364 # define arg1_offset (REG_A0+1)
1365 # elif defined (POWERPC)
1366 # define arg0_offset (sizeof(unsigned long)*PT_R3)
1367 # define arg1_offset (sizeof(unsigned long)*PT_R4)
1368 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1369 # elif defined (HPPA)
1370 # define arg0_offset PT_GR26
1371 # define arg1_offset (PT_GR26-4)
1372 # elif defined (X86_64)
1373 # define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1374 # define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1376 # define arg0_offset (4*(REG_REG0+4))
1377 # define arg1_offset (4*(REG_REG0+5))
1378 # elif defined (SH64)
1379 /* ABI defines arg0 & 1 in r2 & r3 */
1380 # define arg0_offset (REG_OFFSET+16)
1381 # define arg1_offset (REG_OFFSET+24)
1382 # define restore_arg0(tcp, state, val) 0
1384 # define arg0_offset 0
1385 # define arg1_offset 4
1387 # define restore_arg0(tcp, state, val) 0
1391 typedef int arg_setup_state;
1393 # define arg_setup(tcp, state) (0)
1394 # define arg_finish_change(tcp, state) 0
1395 # define get_arg0(tcp, cookie, valp) \
1396 (upeek ((tcp)->pid, arg0_offset, (valp)))
1397 # define get_arg1(tcp, cookie, valp) \
1398 (upeek ((tcp)->pid, arg1_offset, (valp)))
1401 set_arg0 (struct tcb *tcp, void *cookie, long val)
1403 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1407 set_arg1 (struct tcb *tcp, void *cookie, long val)
1409 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1414 #ifndef restore_arg0
1415 # define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1417 #ifndef restore_arg1
1418 # define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1422 # define arg0_index 0
1423 # define arg1_index 1
1430 extern int change_syscall(struct tcb *, int);
1431 arg_setup_state state;
1433 if (tcp->flags & TCB_BPTSET) {
1434 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1438 switch (known_scno(tcp)) {
1445 #if defined SYS_fork || defined SYS_vfork
1446 if (arg_setup (tcp, &state) < 0
1447 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1448 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1449 || change_syscall(tcp, SYS_clone) < 0
1450 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1451 || set_arg1 (tcp, &state, 0) < 0
1452 || arg_finish_change (tcp, &state) < 0)
1454 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1455 tcp->u_arg[arg1_index] = 0;
1456 tcp->flags |= TCB_BPTSET;
1464 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
1465 && (arg_setup (tcp, &state) < 0
1466 || set_arg0 (tcp, &state,
1467 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
1468 || arg_finish_change (tcp, &state) < 0))
1470 tcp->flags |= TCB_BPTSET;
1471 tcp->inst[0] = tcp->u_arg[arg0_index];
1472 tcp->inst[1] = tcp->u_arg[arg1_index];
1476 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1477 tcp->scno, tcp->pid);
1488 arg_setup_state state;
1489 if (arg_setup (tcp, &state) < 0
1490 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1491 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1492 || arg_finish_change (tcp, &state))
1494 tcp->flags &= ~TCB_BPTSET;
1506 #if defined (SPARC) || defined (SPARC64)
1507 /* We simply use the SunOS breakpoint code. */
1511 #define LOOPA 0x30800000 /* ba,a 0 */
1513 if (tcp->flags & TCB_BPTSET) {
1514 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1517 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1518 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1521 tcp->baddr = regs.r_o7 + 8;
1523 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1525 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1530 * XXX - BRUTAL MODE ON
1531 * We cannot set a real BPT in the child, since it will not be
1532 * traced at the moment it will reach the trap and would probably
1533 * die with a core dump.
1534 * Thus, we are force our way in by taking out two instructions
1535 * and insert an eternal loop instead, in expectance of the SIGSTOP
1536 * generated by out PTRACE_ATTACH.
1537 * Of cause, if we evaporate ourselves in the middle of all this...
1541 #if defined (SPARC64)
1543 inst |= (tcp->inst[0] & 0xffffffffUL);
1545 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
1547 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1550 tcp->flags |= TCB_BPTSET;
1552 #else /* !SPARC && !SPARC64 */
1555 # define LOOP 0x0000feeb
1556 if (tcp->flags & TCB_BPTSET) {
1557 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1561 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1564 fprintf(stderr, "[%d] setting bpt at %lx\n",
1565 tcp->pid, tcp->baddr);
1566 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1567 (char *) tcp->baddr, 0);
1569 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1572 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1574 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1577 tcp->flags |= TCB_BPTSET;
1580 * Our strategy here is to replace the bundle that
1581 * contained the clone() syscall with a bundle of the
1584 * { 1: br 1b; br 1b; br 1b }
1586 * This ensures that the newly forked child will loop
1587 * endlessly until we've got a chance to attach to it.
1589 # define LOOP0 0x0000100000000017
1590 # define LOOP1 0x4000000000200000
1591 unsigned long addr, ipsr;
1595 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1597 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1599 /* store "ri" in low two bits */
1600 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
1603 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1605 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1608 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1613 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1614 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1616 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1619 tcp->flags |= TCB_BPTSET;
1623 #if defined (I386) || defined(X86_64)
1624 #define LOOP 0x0000feeb
1625 #elif defined (M68K)
1626 #define LOOP 0x60fe0000
1627 #elif defined (ALPHA)
1628 #define LOOP 0xc3ffffff
1629 #elif defined (POWERPC)
1630 #define LOOP 0x48000000
1632 #define LOOP 0xEAFFFFFE
1634 #define LOOP 0x1000ffff
1636 #define LOOP 0xa7f40000 /* BRC 15,0 */
1637 #elif defined(S390X)
1638 #define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
1640 #define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
1642 #ifdef __LITTLE_ENDIAN__
1643 #define LOOP 0x0000affe
1645 #define LOOP 0xfeaf0000
1648 #error unknown architecture
1651 if (tcp->flags & TCB_BPTSET) {
1652 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1656 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1658 #elif defined (X86_64)
1659 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1661 #elif defined (M68K)
1662 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1664 #elif defined (ALPHA)
1668 #elif defined (MIPS)
1669 return -1; /* FIXME: I do not know what i do - Flo */
1670 #elif defined (POWERPC)
1671 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
1673 #elif defined(S390) || defined(S390X)
1674 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1677 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1679 tcp->baddr &= ~0x03;
1681 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1684 #error unknown architecture
1687 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1688 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1690 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1693 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1695 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1698 tcp->flags |= TCB_BPTSET;
1701 #endif /* SPARC || SPARC64 */
1705 #ifdef SPARC /* This code is slightly sparc specific */
1708 #define BPT 0x91d02001 /* ta 1 */
1709 #define LOOP 0x10800000 /* ba 0 */
1710 #define LOOPA 0x30800000 /* ba,a 0 */
1711 #define NOP 0x01000000
1713 static int loopdeloop[1] = {LOOPA};
1715 static int loopdeloop[2] = {LOOP, NOP};
1718 if (tcp->flags & TCB_BPTSET) {
1719 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1722 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1723 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1726 tcp->baddr = regs.r_o7 + 8;
1727 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1728 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1729 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1734 * XXX - BRUTAL MODE ON
1735 * We cannot set a real BPT in the child, since it will not be
1736 * traced at the moment it will reach the trap and would probably
1737 * die with a core dump.
1738 * Thus, we are force our way in by taking out two instructions
1739 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1740 * generated by out PTRACE_ATTACH.
1741 * Of cause, if we evaporate ourselves in the middle of all this...
1743 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1744 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1745 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1748 tcp->flags |= TCB_BPTSET;
1762 #if defined(I386) || defined(X86_64)
1764 #elif defined(POWERPC)
1768 #elif defined(ALPHA)
1774 #endif /* architecture */
1776 #if defined (SPARC) || defined (SPARC64)
1777 /* Again, we borrow the SunOS breakpoint code. */
1778 if (!(tcp->flags & TCB_BPTSET)) {
1779 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1783 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1785 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1788 tcp->flags &= ~TCB_BPTSET;
1794 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1795 if (!(tcp->flags & TCB_BPTSET)) {
1796 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1800 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1802 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1805 tcp->flags &= ~TCB_BPTSET;
1807 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1809 if (addr != tcp->baddr) {
1810 /* The breakpoint has not been reached yet. */
1813 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1818 unsigned long addr, ipsr;
1823 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1825 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1828 /* restore original bundle: */
1830 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1831 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1833 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1837 /* restore original "ri" in ipsr: */
1838 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1840 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1842 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1846 tcp->flags &= ~TCB_BPTSET;
1848 if (addr != (tcp->baddr & ~0x3)) {
1849 /* the breakpoint has not been reached yet. */
1851 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1856 #else /* !IA64 && !SPARC && !SPARC64 */
1859 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1860 if (!(tcp->flags & TCB_BPTSET)) {
1861 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1865 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1867 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1870 tcp->flags &= ~TCB_BPTSET;
1873 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1875 if (eip != tcp->baddr) {
1876 /* The breakpoint has not been reached yet. */
1879 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1883 #elif defined(X86_64)
1884 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1886 if (eip != tcp->baddr) {
1887 /* The breakpoint has not been reached yet. */
1890 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1894 #elif defined(POWERPC)
1895 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1897 if (pc != tcp->baddr) {
1898 /* The breakpoint has not been reached yet. */
1900 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1905 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1907 if (pc != tcp->baddr) {
1908 /* The breakpoint has not been reached yet. */
1910 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1914 #elif defined(ALPHA)
1915 if (upeek(tcp->pid, 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",
1925 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1928 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1929 /* The breakpoint has not been reached yet. */
1931 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1935 iaoq = tcp->baddr | 3;
1936 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1937 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1938 * has no significant effect.
1940 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1941 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
1943 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1945 if (pc != tcp->baddr) {
1946 /* The breakpoint has not been reached yet. */
1948 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1954 #endif /* !SPARC && !SPARC64 && !IA64 */
1964 if (!(tcp->flags & TCB_BPTSET)) {
1965 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1968 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1969 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1970 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1973 tcp->flags &= ~TCB_BPTSET;
1977 * Since we don't have a single instruction breakpoint, we may have
1978 * to adjust the program counter after removing the our `breakpoint'.
1980 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1981 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1984 if ((regs.r_pc < tcp->baddr) ||
1985 (regs.r_pc > tcp->baddr + 4)) {
1986 /* The breakpoint has not been reached yet */
1989 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1990 regs.r_pc, tcp->parent->baddr);
1993 if (regs.r_pc != tcp->baddr)
1995 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1996 regs.r_pc, tcp->baddr);
1998 regs.r_pc = tcp->baddr;
1999 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0) {
2000 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
2012 #endif /* !USE_PROCFS */
2023 for (n = 0; n < sizeof *hdr; n += 4) {
2025 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
2027 memcpy(((char *) hdr) + n, &res, 4);
2030 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2031 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2032 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2033 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2044 * Change `vfork' in a freshly exec'ed dynamically linked
2045 * executable's (internal) symbol table to plain old `fork'
2049 struct link_dynamic dyn;
2050 struct link_dynamic_2 ld;
2053 if (getex(pid, &hdr) < 0)
2058 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2059 fprintf(stderr, "Cannot read DYNAMIC\n");
2062 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2063 fprintf(stderr, "Cannot read link_dynamic_2\n");
2066 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
2067 fprintf(stderr, "out of memory\n");
2070 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2071 (int)ld.ld_symb_size, strtab) < 0)
2075 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2076 fprintf(stderr, "[symbol: %s]\n", cp);
2081 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2082 if (strcmp(cp, "_vfork") == 0) {
2084 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2085 strcpy(cp, "_fork");
2090 if (cp < strtab + ld.ld_symb_size)
2092 * Write entire symbol table back to avoid
2093 * memory alignment bugs in ptrace
2095 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2096 (int)ld.ld_symb_size, strtab) < 0)