2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 #include <sys/syscall.h>
41 #include <sys/param.h>
47 #include <machine/reg.h>
52 #if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
53 #include <linux/ptrace.h>
56 #if defined(LINUX) && defined(IA64)
57 # include <asm/ptrace_offsets.h>
63 # define PTRACE_PEEKUSR PTRACE_PEEKUSER
64 #elif defined(HAVE_LINUX_PTRACE_H)
66 # ifdef HAVE_STRUCT_IA64_FPREG
67 # define ia64_fpreg XXX_ia64_fpreg
69 # ifdef HAVE_STRUCT_PT_ALL_USER_REGS
70 # define pt_all_user_regs XXX_pt_all_user_regs
72 #include <linux/ptrace.h>
74 # undef pt_all_user_regs
77 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
78 #include <sys/utsname.h>
79 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
81 #if defined(LINUXSPARC)
83 # define fpq kernel_fpq
85 # define fpu kernel_fpu
93 # undef PTRACE_GETREGS
94 # define PTRACE_GETREGS PTRACE_GETREGS64
95 # undef PTRACE_SETREGS
96 # define PTRACE_SETREGS PTRACE_SETREGS64
99 #if !defined(__GLIBC__)
101 #include <linux/unistd.h>
103 #define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
104 type5,arg5,syscall) \
105 type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
109 __asm__ volatile ("or %%g0, %1, %%o0\n\t" \
110 "or %%g0, %2, %%o1\n\t" \
111 "or %%g0, %3, %%o2\n\t" \
112 "or %%g0, %4, %%o3\n\t" \
113 "or %%g0, %5, %%o4\n\t" \
114 "or %%g0, %6, %%g1\n\t" \
115 #if defined (SPARC64)
121 "or %%g0, %%o0, %0\n\t" \
122 "sub %%g0, %%o0, %0\n\t" \
125 : "0" ((long)(arg1)),"1" ((long)(arg2)), \
126 "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
127 "i" (__NR_##syscall) \
128 : "g1", "o0", "o1", "o2", "o3", "o4"); \
130 return (type) __res; \
135 static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
145 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
148 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
165 return a->tv_sec || a->tv_usec;
170 struct timeval *a, *b;
172 if (a->tv_sec < b->tv_sec
173 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
175 if (a->tv_sec > b->tv_sec
176 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
185 return tv->tv_sec + tv->tv_usec/1000000.0;
190 struct timeval *tv, *a, *b;
192 tv->tv_sec = a->tv_sec + b->tv_sec;
193 tv->tv_usec = a->tv_usec + b->tv_usec;
194 if (tv->tv_usec > 1000000) {
196 tv->tv_usec -= 1000000;
202 struct timeval *tv, *a, *b;
204 tv->tv_sec = a->tv_sec - b->tv_sec;
205 tv->tv_usec = a->tv_usec - b->tv_usec;
206 if (((long) tv->tv_usec) < 0) {
208 tv->tv_usec += 1000000;
214 struct timeval *tv, *a;
217 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
218 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
219 tv->tv_usec %= 1000000;
224 struct timeval *tv, *a;
227 tv->tv_usec = a->tv_usec * n;
228 tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
229 tv->tv_usec %= 1000000;
234 const struct xlat *xlat;
237 for (; xlat->str != NULL; xlat++)
238 if (xlat->val == val)
244 * Print entry in struct xlat table, if there.
247 printxval(xlat, val, dflt)
248 const struct xlat *xlat;
252 char *str = xlookup(xlat, val);
257 tprintf("%#x /* %s */", val, dflt);
261 * Interpret `xlat' as an array of flags
262 * print the entries whose bits are on in `flags'
263 * return # of flags printed.
266 addflags(xlat, flags)
267 const struct xlat *xlat;
272 for (n = 0; xlat->str; xlat++) {
273 if (xlat->val && (flags & xlat->val) == xlat->val) {
274 tprintf("|%s", xlat->str);
280 tprintf("|%#x", flags);
287 printflags(xlat, flags, dflt)
288 const struct xlat *xlat;
295 if (flags == 0 && xlat->val == 0) {
296 tprintf("%s", xlat->str);
301 for (n = 0; xlat->str; xlat++) {
302 if (xlat->val && (flags & xlat->val) == xlat->val) {
303 tprintf("%s%s", sep, xlat->str);
312 tprintf("%s%#x", sep, flags);
317 tprintf("%#x", flags);
319 tprintf(" /* %s */", dflt);
330 printnum(tcp, addr, fmt)
341 if (umove(tcp, addr, &num) < 0) {
342 tprintf("%#lx", addr);
356 tprintf((uid == -1) ? "%ld" : "%lu", uid);
359 static char path[MAXPATHLEN + 1];
365 char buf[2 * MAXPATHLEN + 1];
368 if (!strpbrk(str, "\"\'\\")) {
369 tprintf("\"%s\"", str);
372 for (s = buf; *str; str++) {
374 case '\"': case '\'': case '\\':
375 *s++ = '\\'; *s++ = *str; break;
381 tprintf("\"%s\"", buf);
391 else if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
392 tprintf("%#lx", addr);
399 printpathn(tcp, addr, n)
406 else if (umovestr(tcp, addr, n, path) < 0)
407 tprintf("%#lx", addr);
415 printstr(tcp, addr, len)
420 static unsigned char *str = NULL;
430 if ((str = malloc(max_strlen)) == NULL
431 || (outstr = malloc(2*max_strlen)) == NULL) {
432 fprintf(stderr, "out of memory\n");
433 tprintf("%#lx", addr);
437 outend = outstr + max_strlen * 2 - 10;
440 if (umovestr(tcp, addr, n, (char *) str) < 0) {
441 tprintf("%#lx", addr);
446 n = MIN(len, max_strlen);
447 if (umoven(tcp, addr, n, (char *) str) < 0) {
448 tprintf("%#lx", addr);
457 for (i = 0; i < n; i++) {
459 if (len < 0 && c == '\0')
461 if (!isprint(c) && !isspace(c)) {
472 for (i = 0; i < n; i++) {
474 if (len < 0 && c == '\0')
476 sprintf(s, "\\x%02x", c);
483 for (i = 0; i < n; i++) {
485 if (len < 0 && c == '\0')
488 case '\"': case '\'': case '\\':
489 *s++ = '\\'; *s++ = c; break;
491 *s++ = '\\'; *s++ = 'f'; break;
493 *s++ = '\\'; *s++ = 'n'; break;
495 *s++ = '\\'; *s++ = 'r'; break;
497 *s++ = '\\'; *s++ = 't'; break;
499 *s++ = '\\'; *s++ = 'v'; break;
503 else if (i < n - 1 && isdigit(str[i + 1])) {
504 sprintf(s, "\\%03o", c);
508 sprintf(s, "\\%o", c);
519 if (i < len || (len < 0 && (i == n || s > outend))) {
520 *s++ = '.'; *s++ = '.'; *s++ = '.';
523 tprintf("%s", outstr);
528 dumpiov(tcp, len, addr)
537 size = sizeof(*iov) * (unsigned long) len;
538 if (size / sizeof(*iov) != len
539 || (iov = (struct iovec *) malloc(size)) == NULL) {
540 fprintf(stderr, "out of memory\n");
543 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
544 for (i = 0; i < len; i++) {
545 /* include the buffer number to make it easy to
546 * match up the trace with the source */
547 tprintf(" * %lu bytes in buffer %d\n",
548 (unsigned long)iov[i].iov_len, i);
549 dumpstr(tcp, (long) iov[i].iov_base,
559 dumpstr(tcp, addr, len)
564 static int strsize = -1;
565 static unsigned char *str;
566 static char outstr[80];
573 if ((str = malloc(len)) == NULL) {
574 fprintf(stderr, "out of memory\n");
580 if (umoven(tcp, addr, len, (char *) str) < 0)
583 for (i = 0; i < len; i += 16) {
585 sprintf(s, " | %05x ", i);
587 for (j = 0; j < 16; j++) {
591 sprintf(s, " %02x", str[i + j]);
595 *s++ = ' '; *s++ = ' '; *s++ = ' ';
598 *s++ = ' '; *s++ = ' ';
599 for (j = 0; j < 16; j++) {
603 if (isprint(str[i + j]))
611 tprintf("%s |\n", outstr);
615 #define PAGMASK (~(PAGSIZ - 1))
617 * move `len' bytes of data from process `pid'
618 * at address `addr' to our space at `laddr'
621 umoven(tcp, addr, len, laddr)
634 char x[sizeof(long)];
637 if (addr & (sizeof(long) - 1)) {
638 /* addr not a multiple of sizeof(long) */
639 n = addr - (addr & -sizeof(long)); /* residue */
640 addr &= -sizeof(long); /* residue */
642 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
644 if (started && (errno==EPERM || errno==EIO)) {
645 /* Ran into 'end of memory' - stupid "printpath" */
648 /* But if not started, we had a bogus address. */
649 perror("ptrace: umoven");
653 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
654 addr += sizeof(long), laddr += m, len -= m;
658 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
660 if (started && (errno==EPERM || errno==EIO)) {
661 /* Ran into 'end of memory' - stupid "printpath" */
665 perror("ptrace: umoven");
669 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
670 addr += sizeof(long), laddr += m, len -= m;
680 char x[sizeof(long)];
683 if (addr & (sizeof(long) - 1)) {
684 /* addr not a multiple of sizeof(long) */
685 n = addr - (addr & -sizeof(long)); /* residue */
686 addr &= -sizeof(long); /* residue */
688 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
693 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
694 addr += sizeof(long), laddr += m, len -= m;
698 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
703 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
704 addr += sizeof(long), laddr += m, len -= m;
710 n = MIN(len, PAGSIZ);
711 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
712 if (ptrace(PTRACE_READDATA, pid,
713 (char *) addr, len, laddr) < 0) {
714 perror("umoven: ptrace(PTRACE_READDATA, ...)");
726 #ifdef HAVE_MP_PROCFS
727 int fd = tcp->pfd_as;
731 lseek(fd, addr, SEEK_SET);
732 if (read(fd, laddr, len) == -1)
734 #endif /* USE_PROCFS */
740 * like `umove' but make the additional effort of looking
741 * for a terminating zero byte.
744 umovestr(tcp, addr, len, laddr)
751 #ifdef HAVE_MP_PROCFS
752 int fd = tcp->pfd_as;
756 /* Some systems (e.g. FreeBSD) can be upset if we read off the
757 end of valid memory, avoid this by trying to read up
758 to page boundaries. But we don't know what a page is (and
759 getpagesize(2) (if it exists) doesn't necessarily return
760 hardware page size). Assume all pages >= 1024 (a-historical
763 int page = 1024; /* How to find this? */
764 int move = page - (addr & (page - 1));
767 lseek(fd, addr, SEEK_SET);
770 if (move > left) move = left;
771 if ((move = read(fd, laddr, move)) <= 0)
772 return left != len ? 0 : -1;
773 if (memchr (laddr, 0, move)) break;
779 #else /* !USE_PROCFS */
785 char x[sizeof(long)];
788 if (addr & (sizeof(long) - 1)) {
789 /* addr not a multiple of sizeof(long) */
790 n = addr - (addr & -sizeof(long)); /* residue */
791 addr &= -sizeof(long); /* residue */
793 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
795 if (started && (errno==EPERM || errno==EIO)) {
796 /* Ran into 'end of memory' - stupid "printpath" */
803 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
804 while (n & (sizeof(long) - 1))
805 if (u.x[n++] == '\0')
807 addr += sizeof(long), laddr += m, len -= m;
811 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
813 if (started && (errno==EPERM || errno==EIO)) {
814 /* Ran into 'end of memory' - stupid "printpath" */
821 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
822 for (i = 0; i < sizeof(long); i++)
826 addr += sizeof(long), laddr += m, len -= m;
828 #endif /* !USE_PROCFS */
833 #if !defined (SPARC) && !defined(SPARC64)
834 #define PTRACE_WRITETEXT 101
835 #define PTRACE_WRITEDATA 102
836 #endif /* !SPARC && !SPARC64 */
842 uload(cmd, pid, addr, len, laddr)
853 n = MIN(len, PAGSIZ);
854 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
855 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
856 perror("uload: ptrace(PTRACE_WRITE, ...)");
868 char x[sizeof(long)];
871 if (cmd == PTRACE_WRITETEXT) {
872 peek = PTRACE_PEEKTEXT;
873 poke = PTRACE_POKETEXT;
876 peek = PTRACE_PEEKDATA;
877 poke = PTRACE_POKEDATA;
879 if (addr & (sizeof(long) - 1)) {
880 /* addr not a multiple of sizeof(long) */
881 n = addr - (addr & -sizeof(long)); /* residue */
882 addr &= -sizeof(long);
884 u.val = ptrace(peek, pid, (char *) addr, 0);
886 perror("uload: POKE");
889 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
890 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
891 perror("uload: POKE");
894 addr += sizeof(long), laddr += m, len -= m;
897 if (len < sizeof(long))
898 u.val = ptrace(peek, pid, (char *) addr, 0);
899 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
900 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
901 perror("uload: POKE");
904 addr += sizeof(long), laddr += m, len -= m;
911 tload(pid, addr, len, laddr)
916 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
920 dload(pid, addr, len, laddr)
926 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
941 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
943 static int is_sun4m = -1;
946 /* Round up the usual suspects. */
947 if (is_sun4m == -1) {
948 if (uname(&name) < 0) {
949 perror("upeek: uname?");
952 is_sun4m = strcmp(name.machine, "sun4m") == 0;
954 extern const struct xlat struct_user_offsets[];
955 const struct xlat *x;
957 for (x = struct_user_offsets; x->str; x++)
964 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
966 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
967 if (val == -1 && errno) {
969 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
977 #endif /* !USE_PROCFS */
987 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
989 #elif defined(X86_64)
990 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
993 if (upeek(tcp->pid, PT_B0, &pc) < 0)
996 if (upeek(tcp->pid, 4*15, &pc) < 0)
998 #elif defined(POWERPC)
999 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1002 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1004 #elif defined(ALPHA)
1005 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1008 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1010 #elif defined(SPARC) || defined(SPARC64)
1012 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0)
1015 #elif defined(S390) || defined(S390X)
1016 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
1019 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1022 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1025 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1033 * Return current program counter for `pid'
1034 * Assumes PC is never 0xffffffff
1038 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1039 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1052 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1054 #endif /* FREEBSD */
1061 #define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1062 sizeof(long) == 8 ? "[????????????????] " : \
1069 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1073 tprintf("[%08lx] ", eip);
1075 #elif defined(S390) || defined(S390X)
1077 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
1082 tprintf("[%08lx] ", psw);
1084 tprintf("[%16lx] ", psw);
1087 #elif defined(X86_64)
1090 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1094 tprintf("[%16lx] ", rip);
1098 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1102 tprintf("[%08lx] ", ip);
1103 #elif defined(POWERPC)
1106 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1107 tprintf ("[????????] ");
1110 tprintf("[%08lx] ", pc);
1114 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1115 tprintf ("[????????] ");
1118 tprintf("[%08lx] ", pc);
1119 #elif defined(ALPHA)
1122 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1123 tprintf ("[????????????????] ");
1126 tprintf("[%08lx] ", pc);
1127 #elif defined(SPARC) || defined(SPARC64)
1129 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0) {
1133 tprintf("[%08lx] ", regs.r_pc);
1137 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1138 tprintf ("[????????] ");
1141 tprintf("[%08lx] ", pc);
1145 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1146 tprintf ("[????????] ");
1149 tprintf("[%08lx] ", pc);
1153 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1154 tprintf ("[????????] ");
1157 tprintf("[%08lx] ", pc);
1161 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1162 tprintf ("[????????????????] ");
1165 tprintf("[%08lx] ", pc);
1169 if (upeek(tcp->pid, 4*15, &pc) < 0) {
1173 tprintf("[%08lx] ", pc);
1174 #endif /* !architecture */
1180 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1181 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1185 tprintf("[%08x] ", regs.r_o7);
1195 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1196 tprintf("[%08x] ", regs.r_eip);
1197 #endif /* FREEBSD */
1204 #include <sys/syscall.h>
1205 #ifndef CLONE_PTRACE
1206 # define CLONE_PTRACE 0x00002000
1211 /* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1212 subsystem has them for x86... */
1214 #define SYS_vfork 190
1216 typedef unsigned long *arg_setup_state;
1219 arg_setup(struct tcb *tcp, arg_setup_state *state)
1221 unsigned long *bsp, cfm, sof, sol;
1226 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1228 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1231 sof = (cfm >> 0) & 0x7f;
1232 sol = (cfm >> 7) & 0x7f;
1233 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1239 # define arg_finish_change(tcp, state) 0
1243 get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1248 ret = upeek (tcp->pid, PT_R11, valp);
1251 (unsigned long) ia64_rse_skip_regs(*state, 0),
1252 sizeof(long), (void *) valp);
1257 get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1262 ret = upeek (tcp->pid, PT_R9, valp);
1265 (unsigned long) ia64_rse_skip_regs(*state, 1),
1266 sizeof(long), (void *) valp);
1272 set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1274 int req = PTRACE_POKEDATA;
1278 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1279 req = PTRACE_POKEUSER;
1281 ap = ia64_rse_skip_regs(*state, 0);
1283 ptrace(req, tcp->pid, ap, val);
1284 return errno ? -1 : 0;
1288 set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1290 int req = PTRACE_POKEDATA;
1294 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1295 req = PTRACE_POKEUSER;
1297 ap = ia64_rse_skip_regs(*state, 1);
1299 ptrace(req, tcp->pid, ap, val);
1300 return errno ? -1 : 0;
1303 #elif defined (SPARC) || defined (SPARC64)
1305 typedef struct regs arg_setup_state;
1307 # define arg_setup(tcp, state) \
1308 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1309 # define arg_finish_change(tcp, state) \
1310 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1312 # define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1313 # define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1314 # define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1315 # define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
1316 # define restore_arg0(tcp, state, val) 0
1320 # if defined S390 || defined S390X
1321 /* Note: this is only true for the `clone' system call, which handles
1322 arguments specially. We could as well say that its first two arguments
1323 are swapped relative to other architectures, but that would just be
1324 another #ifdef in the calls. */
1325 # define arg0_offset PT_GPR3
1326 # define arg1_offset PT_ORIGGPR2
1327 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1328 # define restore_arg1(tcp, state, val) ((void) (state), 0)
1329 # define arg0_index 1
1330 # define arg1_index 0
1331 # elif defined (ALPHA) || defined (MIPS)
1332 # define arg0_offset REG_A0
1333 # define arg1_offset (REG_A0+1)
1334 # elif defined (POWERPC)
1335 # define arg0_offset (sizeof(unsigned long)*PT_R3)
1336 # define arg1_offset (sizeof(unsigned long)*PT_R4)
1337 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1338 # elif defined (HPPA)
1339 # define arg0_offset PT_GR26
1340 # define arg1_offset (PT_GR26-4)
1341 # elif defined (X86_64)
1342 # define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1343 # define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1345 # define arg0_offset (4*(REG_REG0+4))
1346 # define arg1_offset (4*(REG_REG0+5))
1347 # elif defined (SH64)
1348 /* ABI defines arg0 & 1 in r2 & r3 */
1349 # define arg0_offset (REG_OFFSET+16)
1350 # define arg1_offset (REG_OFFSET+24)
1351 # define restore_arg0(tcp, state, val) 0
1353 # define arg0_offset 0
1354 # define arg1_offset 4
1356 # define restore_arg0(tcp, state, val) 0
1360 typedef int arg_setup_state;
1362 # define arg_setup(tcp, state) (0)
1363 # define arg_finish_change(tcp, state) 0
1364 # define get_arg0(tcp, cookie, valp) \
1365 (upeek ((tcp)->pid, arg0_offset, (valp)))
1366 # define get_arg1(tcp, cookie, valp) \
1367 (upeek ((tcp)->pid, arg1_offset, (valp)))
1370 set_arg0 (struct tcb *tcp, void *cookie, long val)
1372 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1376 set_arg1 (struct tcb *tcp, void *cookie, long val)
1378 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1383 #ifndef restore_arg0
1384 # define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1386 #ifndef restore_arg1
1387 # define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1391 # define arg0_index 0
1392 # define arg1_index 1
1399 extern int change_syscall(struct tcb *, int);
1400 arg_setup_state state;
1402 if (tcp->flags & TCB_BPTSET) {
1403 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1407 switch (tcp->scno) {
1414 #if defined SYS_fork || defined SYS_vfork
1415 if (arg_setup (tcp, &state) < 0
1416 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1417 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1418 || change_syscall(tcp, SYS_clone) < 0
1419 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1420 || set_arg1 (tcp, &state, 0) < 0
1421 || arg_finish_change (tcp, &state) < 0)
1423 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1424 tcp->u_arg[arg1_index] = 0;
1425 tcp->flags |= TCB_BPTSET;
1433 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
1434 && (arg_setup (tcp, &state) < 0
1435 || set_arg0 (tcp, &state,
1436 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
1437 || arg_finish_change (tcp, &state) < 0))
1439 tcp->flags |= TCB_BPTSET;
1440 tcp->inst[0] = tcp->u_arg[arg0_index];
1441 tcp->inst[1] = tcp->u_arg[arg1_index];
1445 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1446 tcp->scno, tcp->pid);
1457 arg_setup_state state;
1458 if (arg_setup (tcp, &state) < 0
1459 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1460 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1461 || arg_finish_change (tcp, &state))
1463 tcp->flags &= ~TCB_BPTSET;
1475 #if defined (SPARC) || defined (SPARC64)
1476 /* We simply use the SunOS breakpoint code. */
1480 #define LOOPA 0x30800000 /* ba,a 0 */
1482 if (tcp->flags & TCB_BPTSET) {
1483 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1486 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1487 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1490 tcp->baddr = regs.r_o7 + 8;
1492 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1494 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1499 * XXX - BRUTAL MODE ON
1500 * We cannot set a real BPT in the child, since it will not be
1501 * traced at the moment it will reach the trap and would probably
1502 * die with a core dump.
1503 * Thus, we are force our way in by taking out two instructions
1504 * and insert an eternal loop instead, in expectance of the SIGSTOP
1505 * generated by out PTRACE_ATTACH.
1506 * Of cause, if we evaporate ourselves in the middle of all this...
1510 #if defined (SPARC64)
1512 inst |= (tcp->inst[0] & 0xffffffffUL);
1514 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
1516 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1519 tcp->flags |= TCB_BPTSET;
1521 #else /* !SPARC && !SPARC64 */
1524 # define LOOP 0x0000feeb
1525 if (tcp->flags & TCB_BPTSET) {
1526 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1530 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1533 fprintf(stderr, "[%d] setting bpt at %lx\n",
1534 tcp->pid, tcp->baddr);
1535 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1536 (char *) tcp->baddr, 0);
1538 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1541 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1543 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1546 tcp->flags |= TCB_BPTSET;
1549 * Our strategy here is to replace the bundle that
1550 * contained the clone() syscall with a bundle of the
1553 * { 1: br 1b; br 1b; br 1b }
1555 * This ensures that the newly forked child will loop
1556 * endlessly until we've got a chance to attach to it.
1558 # define LOOP0 0x0000100000000017
1559 # define LOOP1 0x4000000000200000
1560 unsigned long addr, ipsr;
1564 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1566 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1568 /* store "ri" in low two bits */
1569 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
1572 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1574 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1577 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1582 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1583 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1585 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1588 tcp->flags |= TCB_BPTSET;
1592 #if defined (I386) || defined(X86_64)
1593 #define LOOP 0x0000feeb
1594 #elif defined (M68K)
1595 #define LOOP 0x60fe0000
1596 #elif defined (ALPHA)
1597 #define LOOP 0xc3ffffff
1598 #elif defined (POWERPC)
1599 #define LOOP 0x48000000
1601 #define LOOP 0xEAFFFFFE
1603 #define LOOP 0x1000ffff
1605 #define LOOP 0xa7f40000 /* BRC 15,0 */
1606 #elif defined(S390X)
1607 #define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
1609 #define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
1611 #ifdef __LITTLE_ENDIAN__
1612 #define LOOP 0x0000affe
1614 #define LOOP 0xfeaf0000
1617 #error unknown architecture
1620 if (tcp->flags & TCB_BPTSET) {
1621 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1625 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1627 #elif defined (X86_64)
1628 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1630 #elif defined (M68K)
1631 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1633 #elif defined (ALPHA)
1637 #elif defined (MIPS)
1638 return -1; /* FIXME: I do not know what i do - Flo */
1639 #elif defined (POWERPC)
1640 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
1642 #elif defined(S390) || defined(S390X)
1643 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1646 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1648 tcp->baddr &= ~0x03;
1650 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1653 #error unknown architecture
1656 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1657 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1659 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1662 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1664 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1667 tcp->flags |= TCB_BPTSET;
1670 #endif /* SPARC || SPARC64 */
1674 #ifdef SPARC /* This code is slightly sparc specific */
1677 #define BPT 0x91d02001 /* ta 1 */
1678 #define LOOP 0x10800000 /* ba 0 */
1679 #define LOOPA 0x30800000 /* ba,a 0 */
1680 #define NOP 0x01000000
1682 static int loopdeloop[1] = {LOOPA};
1684 static int loopdeloop[2] = {LOOP, NOP};
1687 if (tcp->flags & TCB_BPTSET) {
1688 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1691 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1692 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1695 tcp->baddr = regs.r_o7 + 8;
1696 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1697 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1698 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1703 * XXX - BRUTAL MODE ON
1704 * We cannot set a real BPT in the child, since it will not be
1705 * traced at the moment it will reach the trap and would probably
1706 * die with a core dump.
1707 * Thus, we are force our way in by taking out two instructions
1708 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1709 * generated by out PTRACE_ATTACH.
1710 * Of cause, if we evaporate ourselves in the middle of all this...
1712 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1713 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1714 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1717 tcp->flags |= TCB_BPTSET;
1731 #if defined(I386) || defined(X86_64)
1733 #elif defined(POWERPC)
1737 #elif defined(ALPHA)
1743 #endif /* architecture */
1745 #if defined (SPARC) || defined (SPARC64)
1746 /* Again, we borrow the SunOS breakpoint code. */
1747 if (!(tcp->flags & TCB_BPTSET)) {
1748 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1752 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1754 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1757 tcp->flags &= ~TCB_BPTSET;
1763 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1764 if (!(tcp->flags & TCB_BPTSET)) {
1765 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1769 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1771 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1774 tcp->flags &= ~TCB_BPTSET;
1776 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1778 if (addr != tcp->baddr) {
1779 /* The breakpoint has not been reached yet. */
1782 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1787 unsigned long addr, ipsr;
1792 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1794 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1797 /* restore original bundle: */
1799 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1800 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1802 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1806 /* restore original "ri" in ipsr: */
1807 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1809 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1811 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1815 tcp->flags &= ~TCB_BPTSET;
1817 if (addr != (tcp->baddr & ~0x3)) {
1818 /* the breakpoint has not been reached yet. */
1820 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1825 #else /* !IA64 && !SPARC && !SPARC64 */
1828 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1829 if (!(tcp->flags & TCB_BPTSET)) {
1830 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1834 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1836 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1839 tcp->flags &= ~TCB_BPTSET;
1842 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1844 if (eip != tcp->baddr) {
1845 /* The breakpoint has not been reached yet. */
1848 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1852 #elif defined(X86_64)
1853 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1855 if (eip != tcp->baddr) {
1856 /* The breakpoint has not been reached yet. */
1859 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1863 #elif defined(POWERPC)
1864 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1866 if (pc != tcp->baddr) {
1867 /* The breakpoint has not been reached yet. */
1869 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1874 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1876 if (pc != tcp->baddr) {
1877 /* The breakpoint has not been reached yet. */
1879 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1883 #elif defined(ALPHA)
1884 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1886 if (pc != tcp->baddr) {
1887 /* The breakpoint has not been reached yet. */
1889 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1894 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1897 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1898 /* The breakpoint has not been reached yet. */
1900 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1904 iaoq = tcp->baddr | 3;
1905 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1906 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1907 * has no significant effect.
1909 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1910 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
1912 if (upeek(tcp->pid, 4*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",
1923 #endif /* !SPARC && !SPARC64 && !IA64 */
1933 if (!(tcp->flags & TCB_BPTSET)) {
1934 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1937 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1938 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1939 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1942 tcp->flags &= ~TCB_BPTSET;
1946 * Since we don't have a single instruction breakpoint, we may have
1947 * to adjust the program counter after removing the our `breakpoint'.
1949 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1950 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1953 if ((regs.r_pc < tcp->baddr) ||
1954 (regs.r_pc > tcp->baddr + 4)) {
1955 /* The breakpoint has not been reached yet */
1958 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1959 regs.r_pc, tcp->parent->baddr);
1962 if (regs.r_pc != tcp->baddr)
1964 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1965 regs.r_pc, tcp->baddr);
1967 regs.r_pc = tcp->baddr;
1968 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0) {
1969 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1981 #endif /* !USE_PROCFS */
1992 for (n = 0; n < sizeof *hdr; n += 4) {
1994 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1996 memcpy(((char *) hdr) + n, &res, 4);
1999 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2000 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2001 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2002 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2013 * Change `vfork' in a freshly exec'ed dynamically linked
2014 * executable's (internal) symbol table to plain old `fork'
2018 struct link_dynamic dyn;
2019 struct link_dynamic_2 ld;
2022 if (getex(pid, &hdr) < 0)
2027 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2028 fprintf(stderr, "Cannot read DYNAMIC\n");
2031 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2032 fprintf(stderr, "Cannot read link_dynamic_2\n");
2035 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
2036 fprintf(stderr, "out of memory\n");
2039 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2040 (int)ld.ld_symb_size, strtab) < 0)
2044 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2045 fprintf(stderr, "[symbol: %s]\n", cp);
2050 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2051 if (strcmp(cp, "_vfork") == 0) {
2053 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2054 strcpy(cp, "_fork");
2059 if (cp < strtab + ld.ld_symb_size)
2061 * Write entire symbol table back to avoid
2062 * memory alignment bugs in ptrace
2064 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2065 (int)ld.ld_symb_size, strtab) < 0)