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)
288 const struct xlat *xlat;
294 if (flags == 0 && xlat->val == 0) {
295 tprintf("%s", xlat->str);
300 for (n = 0; xlat->str; xlat++) {
301 if (xlat->val && (flags & xlat->val) == xlat->val) {
302 tprintf("%s%s", sep, xlat->str);
309 tprintf("%s%#x", sep, flags);
316 printnum(tcp, addr, fmt)
327 if (umove(tcp, addr, &num) < 0) {
328 tprintf("%#lx", addr);
342 tprintf((uid == -1) ? "%ld" : "%lu", uid);
345 static char path[MAXPATHLEN + 1];
351 char buf[2 * MAXPATHLEN + 1];
354 if (!strpbrk(str, "\"\'\\")) {
355 tprintf("\"%s\"", str);
358 for (s = buf; *str; str++) {
360 case '\"': case '\'': case '\\':
361 *s++ = '\\'; *s++ = *str; break;
367 tprintf("\"%s\"", buf);
377 else if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
378 tprintf("%#lx", addr);
385 printpathn(tcp, addr, n)
392 else if (umovestr(tcp, addr, n, path) < 0)
393 tprintf("%#lx", addr);
401 printstr(tcp, addr, len)
406 static unsigned char *str = NULL;
416 if ((str = malloc(max_strlen)) == NULL
417 || (outstr = malloc(2*max_strlen)) == NULL) {
418 fprintf(stderr, "printstr: no memory\n");
419 tprintf("%#lx", addr);
423 outend = outstr + max_strlen * 2 - 10;
426 if (umovestr(tcp, addr, n, (char *) str) < 0) {
427 tprintf("%#lx", addr);
432 n = MIN(len, max_strlen);
433 if (umoven(tcp, addr, n, (char *) str) < 0) {
434 tprintf("%#lx", addr);
443 for (i = 0; i < n; i++) {
445 if (len < 0 && c == '\0')
447 if (!isprint(c) && !isspace(c)) {
458 for (i = 0; i < n; i++) {
460 if (len < 0 && c == '\0')
462 sprintf(s, "\\x%02x", c);
469 for (i = 0; i < n; i++) {
471 if (len < 0 && c == '\0')
474 case '\"': case '\'': case '\\':
475 *s++ = '\\'; *s++ = c; break;
477 *s++ = '\\'; *s++ = 'f'; break;
479 *s++ = '\\'; *s++ = 'n'; break;
481 *s++ = '\\'; *s++ = 'r'; break;
483 *s++ = '\\'; *s++ = 't'; break;
485 *s++ = '\\'; *s++ = 'v'; break;
489 else if (i < n - 1 && isdigit(str[i + 1])) {
490 sprintf(s, "\\%03o", c);
494 sprintf(s, "\\%o", c);
505 if (i < len || (len < 0 && (i == n || s > outend))) {
506 *s++ = '.'; *s++ = '.'; *s++ = '.';
509 tprintf("%s", outstr);
514 dumpiov(tcp, len, addr)
523 if ((iov = (struct iovec *) malloc(len * sizeof *iov)) == NULL) {
524 fprintf(stderr, "dump: No memory");
527 if (umoven(tcp, addr,
528 len * sizeof *iov, (char *) iov) >= 0) {
530 for (i = 0; i < len; i++) {
531 /* include the buffer number to make it easy to
532 * match up the trace with the source */
533 tprintf(" * %lu bytes in buffer %d\n",
534 (unsigned long)iov[i].iov_len, i);
535 dumpstr(tcp, (long) iov[i].iov_base,
545 dumpstr(tcp, addr, len)
550 static int strsize = -1;
551 static unsigned char *str;
552 static char outstr[80];
559 if ((str = malloc(len)) == NULL) {
560 fprintf(stderr, "dump: no memory\n");
566 if (umoven(tcp, addr, len, (char *) str) < 0)
569 for (i = 0; i < len; i += 16) {
571 sprintf(s, " | %05x ", i);
573 for (j = 0; j < 16; j++) {
577 sprintf(s, " %02x", str[i + j]);
581 *s++ = ' '; *s++ = ' '; *s++ = ' ';
584 *s++ = ' '; *s++ = ' ';
585 for (j = 0; j < 16; j++) {
589 if (isprint(str[i + j]))
597 tprintf("%s |\n", outstr);
601 #define PAGMASK (~(PAGSIZ - 1))
603 * move `len' bytes of data from process `pid'
604 * at address `addr' to our space at `laddr'
607 umoven(tcp, addr, len, laddr)
620 char x[sizeof(long)];
623 if (addr & (sizeof(long) - 1)) {
624 /* addr not a multiple of sizeof(long) */
625 n = addr - (addr & -sizeof(long)); /* residue */
626 addr &= -sizeof(long); /* residue */
628 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
630 if (started && (errno==EPERM || errno==EIO)) {
631 /* Ran into 'end of memory' - stupid "printpath" */
634 /* But if not started, we had a bogus address. */
635 perror("ptrace: umoven");
639 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
640 addr += sizeof(long), laddr += m, len -= m;
644 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
646 if (started && (errno==EPERM || errno==EIO)) {
647 /* Ran into 'end of memory' - stupid "printpath" */
651 perror("ptrace: umoven");
655 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
656 addr += sizeof(long), laddr += m, len -= m;
666 char x[sizeof(long)];
669 if (addr & (sizeof(long) - 1)) {
670 /* addr not a multiple of sizeof(long) */
671 n = addr - (addr & -sizeof(long)); /* residue */
672 addr &= -sizeof(long); /* residue */
674 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
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);
689 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
690 addr += sizeof(long), laddr += m, len -= m;
696 n = MIN(len, PAGSIZ);
697 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
698 if (ptrace(PTRACE_READDATA, pid,
699 (char *) addr, len, laddr) < 0) {
700 perror("umoven: ptrace(PTRACE_READDATA, ...)");
712 #ifdef HAVE_MP_PROCFS
713 int fd = tcp->pfd_as;
717 lseek(fd, addr, SEEK_SET);
718 if (read(fd, laddr, len) == -1)
720 #endif /* USE_PROCFS */
726 * like `umove' but make the additional effort of looking
727 * for a terminating zero byte.
730 umovestr(tcp, addr, len, laddr)
737 #ifdef HAVE_MP_PROCFS
738 int fd = tcp->pfd_as;
742 /* Some systems (e.g. FreeBSD) can be upset if we read off the
743 end of valid memory, avoid this by trying to read up
744 to page boundaries. But we don't know what a page is (and
745 getpagesize(2) (if it exists) doesn't necessarily return
746 hardware page size). Assume all pages >= 1024 (a-historical
749 int page = 1024; /* How to find this? */
750 int move = page - (addr & (page - 1));
753 lseek(fd, addr, SEEK_SET);
756 if (move > left) move = left;
757 if ((move = read(fd, laddr, move)) <= 0)
758 return left != len ? 0 : -1;
759 if (memchr (laddr, 0, move)) break;
765 #else /* !USE_PROCFS */
771 char x[sizeof(long)];
774 if (addr & (sizeof(long) - 1)) {
775 /* addr not a multiple of sizeof(long) */
776 n = addr - (addr & -sizeof(long)); /* residue */
777 addr &= -sizeof(long); /* residue */
779 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
781 if (started && (errno==EPERM || errno==EIO)) {
782 /* Ran into 'end of memory' - stupid "printpath" */
789 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
790 while (n & (sizeof(long) - 1))
791 if (u.x[n++] == '\0')
793 addr += sizeof(long), laddr += m, len -= m;
797 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
799 if (started && (errno==EPERM || errno==EIO)) {
800 /* Ran into 'end of memory' - stupid "printpath" */
807 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
808 for (i = 0; i < sizeof(long); i++)
812 addr += sizeof(long), laddr += m, len -= m;
814 #endif /* !USE_PROCFS */
819 #if !defined (SPARC) && !defined(SPARC64)
820 #define PTRACE_WRITETEXT 101
821 #define PTRACE_WRITEDATA 102
822 #endif /* !SPARC && !SPARC64 */
828 uload(cmd, pid, addr, len, laddr)
839 n = MIN(len, PAGSIZ);
840 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
841 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
842 perror("uload: ptrace(PTRACE_WRITE, ...)");
854 char x[sizeof(long)];
857 if (cmd == PTRACE_WRITETEXT) {
858 peek = PTRACE_PEEKTEXT;
859 poke = PTRACE_POKETEXT;
862 peek = PTRACE_PEEKDATA;
863 poke = PTRACE_POKEDATA;
865 if (addr & (sizeof(long) - 1)) {
866 /* addr not a multiple of sizeof(long) */
867 n = addr - (addr & -sizeof(long)); /* residue */
868 addr &= -sizeof(long);
870 u.val = ptrace(peek, pid, (char *) addr, 0);
872 perror("uload: POKE");
875 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
876 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
877 perror("uload: POKE");
880 addr += sizeof(long), laddr += m, len -= m;
883 if (len < sizeof(long))
884 u.val = ptrace(peek, pid, (char *) addr, 0);
885 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
886 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
887 perror("uload: POKE");
890 addr += sizeof(long), laddr += m, len -= m;
897 tload(pid, addr, len, laddr)
902 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
906 dload(pid, addr, len, laddr)
912 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
927 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
929 static int is_sun4m = -1;
932 /* Round up the usual suspects. */
933 if (is_sun4m == -1) {
934 if (uname(&name) < 0) {
935 perror("upeek: uname?");
938 is_sun4m = strcmp(name.machine, "sun4m") == 0;
940 extern const struct xlat struct_user_offsets[];
941 const struct xlat *x;
943 for (x = struct_user_offsets; x->str; x++)
950 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
952 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
953 if (val == -1 && errno) {
955 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
963 #endif /* !USE_PROCFS */
973 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
975 #elif defined(X86_64)
976 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
979 if (upeek(tcp->pid, PT_B0, &pc) < 0)
982 if (upeek(tcp->pid, 4*15, &pc) < 0)
984 #elif defined(POWERPC)
985 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
988 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
991 if (upeek(tcp->pid, REG_PC, &pc) < 0)
994 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
996 #elif defined(SPARC) || defined(SPARC64)
998 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0)
1001 #elif defined(S390) || defined(S390X)
1002 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
1005 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1008 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1011 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1019 * Return current program counter for `pid'
1020 * Assumes PC is never 0xffffffff
1024 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1025 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1038 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1040 #endif /* FREEBSD */
1047 #define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1048 sizeof(long) == 8 ? "[????????????????] " : \
1055 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1059 tprintf("[%08lx] ", eip);
1061 #elif defined(S390) || defined(S390X)
1063 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
1068 tprintf("[%08lx] ", psw);
1070 tprintf("[%16lx] ", psw);
1073 #elif defined(X86_64)
1076 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1080 tprintf("[%16lx] ", rip);
1084 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1088 tprintf("[%08lx] ", ip);
1089 #elif defined(POWERPC)
1092 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1093 tprintf ("[????????] ");
1096 tprintf("[%08lx] ", pc);
1100 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1101 tprintf ("[????????] ");
1104 tprintf("[%08lx] ", pc);
1105 #elif defined(ALPHA)
1108 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1109 tprintf ("[????????????????] ");
1112 tprintf("[%08lx] ", pc);
1113 #elif defined(SPARC) || defined(SPARC64)
1115 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0) {
1119 tprintf("[%08lx] ", regs.r_pc);
1123 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1124 tprintf ("[????????] ");
1127 tprintf("[%08lx] ", pc);
1131 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1132 tprintf ("[????????] ");
1135 tprintf("[%08lx] ", pc);
1139 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1140 tprintf ("[????????] ");
1143 tprintf("[%08lx] ", pc);
1147 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1148 tprintf ("[????????????????] ");
1151 tprintf("[%08lx] ", pc);
1155 if (upeek(tcp->pid, 4*15, &pc) < 0) {
1159 tprintf("[%08lx] ", pc);
1160 #endif /* !architecture */
1166 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1167 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1171 tprintf("[%08x] ", regs.r_o7);
1181 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1182 tprintf("[%08x] ", regs.r_eip);
1183 #endif /* FREEBSD */
1190 #include <sys/syscall.h>
1191 #ifndef CLONE_PTRACE
1192 # define CLONE_PTRACE 0x00002000
1197 /* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1198 subsystem has them for x86... */
1200 #define SYS_vfork 190
1202 typedef unsigned long *arg_setup_state;
1205 arg_setup(struct tcb *tcp, arg_setup_state *state)
1207 unsigned long *bsp, cfm, sof, sol;
1212 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1214 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1217 sof = (cfm >> 0) & 0x7f;
1218 sol = (cfm >> 7) & 0x7f;
1219 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1225 # define arg_finish_change(tcp, state) 0
1229 get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1234 ret = upeek (tcp->pid, PT_R11, valp);
1237 (unsigned long) ia64_rse_skip_regs(*state, 0),
1238 sizeof(long), (void *) valp);
1243 get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1248 ret = upeek (tcp->pid, PT_R9, valp);
1251 (unsigned long) ia64_rse_skip_regs(*state, 1),
1252 sizeof(long), (void *) valp);
1258 set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1260 int req = PTRACE_POKEDATA;
1264 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1265 req = PTRACE_POKEUSER;
1267 ap = ia64_rse_skip_regs(*state, 0);
1269 ptrace(req, tcp->pid, ap, val);
1270 return errno ? -1 : 0;
1274 set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1276 int req = PTRACE_POKEDATA;
1280 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1281 req = PTRACE_POKEUSER;
1283 ap = ia64_rse_skip_regs(*state, 1);
1285 ptrace(req, tcp->pid, ap, val);
1286 return errno ? -1 : 0;
1289 #elif defined (SPARC) || defined (SPARC64)
1291 typedef struct regs arg_setup_state;
1293 # define arg_setup(tcp, state) \
1294 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1295 # define arg_finish_change(tcp, state) \
1296 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1298 # define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1299 # define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1300 # define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1301 # define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
1302 # define restore_arg0(tcp, state, val) 0
1306 # if defined S390 || defined S390X
1307 /* Note: this is only true for the `clone' system call, which handles
1308 arguments specially. We could as well say that its first two arguments
1309 are swapped relative to other architectures, but that would just be
1310 another #ifdef in the calls. */
1311 # define arg0_offset PT_GPR3
1312 # define arg1_offset PT_ORIGGPR2
1313 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1314 # define restore_arg1(tcp, state, val) ((void) (state), 0)
1315 # define arg0_index 1
1316 # define arg1_index 0
1317 # elif defined (ALPHA) || defined (MIPS)
1318 # define arg0_offset REG_A0
1319 # define arg1_offset (REG_A0+1)
1320 # elif defined (POWERPC)
1321 # define arg0_offset (sizeof(unsigned long)*PT_R3)
1322 # define arg1_offset (sizeof(unsigned long)*PT_R4)
1323 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1324 # elif defined (HPPA)
1325 # define arg0_offset PT_GR26
1326 # define arg1_offset (PT_GR26-4)
1327 # elif defined (X86_64)
1328 # define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1329 # define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1331 # define arg0_offset (4*(REG_REG0+4))
1332 # define arg1_offset (4*(REG_REG0+5))
1333 # elif defined (SH64)
1334 /* ABI defines arg0 & 1 in r2 & r3 */
1335 # define arg0_offset (REG_OFFSET+16)
1336 # define arg1_offset (REG_OFFSET+24)
1337 # define restore_arg0(tcp, state, val) 0
1339 # define arg0_offset 0
1340 # define arg1_offset 4
1342 # define restore_arg0(tcp, state, val) 0
1346 typedef int arg_setup_state;
1348 # define arg_setup(tcp, state) (0)
1349 # define arg_finish_change(tcp, state) 0
1350 # define get_arg0(tcp, cookie, valp) \
1351 (upeek ((tcp)->pid, arg0_offset, (valp)))
1352 # define get_arg1(tcp, cookie, valp) \
1353 (upeek ((tcp)->pid, arg1_offset, (valp)))
1356 set_arg0 (struct tcb *tcp, void *cookie, long val)
1358 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1362 set_arg1 (struct tcb *tcp, void *cookie, long val)
1364 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1369 #ifndef restore_arg0
1370 # define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1372 #ifndef restore_arg1
1373 # define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1377 # define arg0_index 0
1378 # define arg1_index 1
1385 extern int change_syscall(struct tcb *, int);
1386 arg_setup_state state;
1388 if (tcp->flags & TCB_BPTSET) {
1389 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1393 switch (tcp->scno) {
1400 #if defined SYS_fork || defined SYS_vfork
1401 if (arg_setup (tcp, &state) < 0
1402 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1403 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1404 || change_syscall(tcp, SYS_clone) < 0
1405 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1406 || set_arg1 (tcp, &state, 0) < 0
1407 || arg_finish_change (tcp, &state) < 0)
1409 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1410 tcp->u_arg[arg1_index] = 0;
1411 tcp->flags |= TCB_BPTSET;
1419 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
1420 && (arg_setup (tcp, &state) < 0
1421 || set_arg0 (tcp, &state,
1422 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
1423 || arg_finish_change (tcp, &state) < 0))
1425 tcp->flags |= TCB_BPTSET;
1426 tcp->inst[0] = tcp->u_arg[arg0_index];
1427 tcp->inst[1] = tcp->u_arg[arg1_index];
1431 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1432 tcp->scno, tcp->pid);
1443 arg_setup_state state;
1444 if (arg_setup (tcp, &state) < 0
1445 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1446 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1447 || arg_finish_change (tcp, &state))
1449 tcp->flags &= ~TCB_BPTSET;
1461 #if defined (SPARC) || defined (SPARC64)
1462 /* We simply use the SunOS breakpoint code. */
1466 #define LOOPA 0x30800000 /* ba,a 0 */
1468 if (tcp->flags & TCB_BPTSET) {
1469 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1472 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1473 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1476 tcp->baddr = regs.r_o7 + 8;
1478 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1480 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1485 * XXX - BRUTAL MODE ON
1486 * We cannot set a real BPT in the child, since it will not be
1487 * traced at the moment it will reach the trap and would probably
1488 * die with a core dump.
1489 * Thus, we are force our way in by taking out two instructions
1490 * and insert an eternal loop instead, in expectance of the SIGSTOP
1491 * generated by out PTRACE_ATTACH.
1492 * Of cause, if we evaporate ourselves in the middle of all this...
1496 #if defined (SPARC64)
1498 inst |= (tcp->inst[0] & 0xffffffffUL);
1500 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
1502 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1505 tcp->flags |= TCB_BPTSET;
1507 #else /* !SPARC && !SPARC64 */
1510 # define LOOP 0x0000feeb
1511 if (tcp->flags & TCB_BPTSET) {
1512 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1516 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1519 fprintf(stderr, "[%d] setting bpt at %lx\n",
1520 tcp->pid, tcp->baddr);
1521 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1522 (char *) tcp->baddr, 0);
1524 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1527 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1529 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1532 tcp->flags |= TCB_BPTSET;
1535 * Our strategy here is to replace the bundle that
1536 * contained the clone() syscall with a bundle of the
1539 * { 1: br 1b; br 1b; br 1b }
1541 * This ensures that the newly forked child will loop
1542 * endlessly until we've got a chance to attach to it.
1544 # define LOOP0 0x0000100000000017
1545 # define LOOP1 0x4000000000200000
1546 unsigned long addr, ipsr;
1550 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1552 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1554 /* store "ri" in low two bits */
1555 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
1558 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1560 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1563 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1568 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1569 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1571 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1574 tcp->flags |= TCB_BPTSET;
1578 #if defined (I386) || defined(X86_64)
1579 #define LOOP 0x0000feeb
1580 #elif defined (M68K)
1581 #define LOOP 0x60fe0000
1582 #elif defined (ALPHA)
1583 #define LOOP 0xc3ffffff
1584 #elif defined (POWERPC)
1585 #define LOOP 0x48000000
1587 #define LOOP 0xEAFFFFFE
1589 #define LOOP 0x1000ffff
1591 #define LOOP 0xa7f40000 /* BRC 15,0 */
1592 #elif defined(S390X)
1593 #define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
1595 #define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
1597 #ifdef __LITTLE_ENDIAN__
1598 #define LOOP 0x0000affe
1600 #define LOOP 0xfeaf0000
1603 #error unknown architecture
1606 if (tcp->flags & TCB_BPTSET) {
1607 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1611 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1613 #elif defined (X86_64)
1614 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1616 #elif defined (M68K)
1617 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1619 #elif defined (ALPHA)
1623 #elif defined (MIPS)
1624 return -1; /* FIXME: I do not know what i do - Flo */
1625 #elif defined (POWERPC)
1626 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
1628 #elif defined(S390) || defined(S390X)
1629 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1632 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1634 tcp->baddr &= ~0x03;
1636 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1639 #error unknown architecture
1642 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1643 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1645 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1648 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1650 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1653 tcp->flags |= TCB_BPTSET;
1656 #endif /* SPARC || SPARC64 */
1660 #ifdef SPARC /* This code is slightly sparc specific */
1663 #define BPT 0x91d02001 /* ta 1 */
1664 #define LOOP 0x10800000 /* ba 0 */
1665 #define LOOPA 0x30800000 /* ba,a 0 */
1666 #define NOP 0x01000000
1668 static int loopdeloop[1] = {LOOPA};
1670 static int loopdeloop[2] = {LOOP, NOP};
1673 if (tcp->flags & TCB_BPTSET) {
1674 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1677 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1678 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1681 tcp->baddr = regs.r_o7 + 8;
1682 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1683 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1684 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1689 * XXX - BRUTAL MODE ON
1690 * We cannot set a real BPT in the child, since it will not be
1691 * traced at the moment it will reach the trap and would probably
1692 * die with a core dump.
1693 * Thus, we are force our way in by taking out two instructions
1694 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1695 * generated by out PTRACE_ATTACH.
1696 * Of cause, if we evaporate ourselves in the middle of all this...
1698 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1699 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1700 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1703 tcp->flags |= TCB_BPTSET;
1717 #if defined(I386) || defined(X86_64)
1719 #elif defined(POWERPC)
1723 #elif defined(ALPHA)
1729 #endif /* architecture */
1731 #if defined (SPARC) || defined (SPARC64)
1732 /* Again, we borrow the SunOS breakpoint code. */
1733 if (!(tcp->flags & TCB_BPTSET)) {
1734 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1738 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1740 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1743 tcp->flags &= ~TCB_BPTSET;
1749 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1750 if (!(tcp->flags & TCB_BPTSET)) {
1751 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1755 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1757 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1760 tcp->flags &= ~TCB_BPTSET;
1762 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1764 if (addr != tcp->baddr) {
1765 /* The breakpoint has not been reached yet. */
1768 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1773 unsigned long addr, ipsr;
1778 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1780 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1783 /* restore original bundle: */
1785 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1786 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1788 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1792 /* restore original "ri" in ipsr: */
1793 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1795 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1797 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1801 tcp->flags &= ~TCB_BPTSET;
1803 if (addr != (tcp->baddr & ~0x3)) {
1804 /* the breakpoint has not been reached yet. */
1806 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1811 #else /* !IA64 && !SPARC && !SPARC64 */
1814 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1815 if (!(tcp->flags & TCB_BPTSET)) {
1816 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1820 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1822 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1825 tcp->flags &= ~TCB_BPTSET;
1828 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1830 if (eip != tcp->baddr) {
1831 /* The breakpoint has not been reached yet. */
1834 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1838 #elif defined(X86_64)
1839 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1841 if (eip != tcp->baddr) {
1842 /* The breakpoint has not been reached yet. */
1845 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1849 #elif defined(POWERPC)
1850 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1852 if (pc != tcp->baddr) {
1853 /* The breakpoint has not been reached yet. */
1855 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1860 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1862 if (pc != tcp->baddr) {
1863 /* The breakpoint has not been reached yet. */
1865 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1869 #elif defined(ALPHA)
1870 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1872 if (pc != tcp->baddr) {
1873 /* The breakpoint has not been reached yet. */
1875 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1880 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1883 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1884 /* The breakpoint has not been reached yet. */
1886 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1890 iaoq = tcp->baddr | 3;
1891 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1892 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1893 * has no significant effect.
1895 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1896 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
1898 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1900 if (pc != tcp->baddr) {
1901 /* The breakpoint has not been reached yet. */
1903 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1909 #endif /* !SPARC && !SPARC64 && !IA64 */
1919 if (!(tcp->flags & TCB_BPTSET)) {
1920 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1923 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1924 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1925 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1928 tcp->flags &= ~TCB_BPTSET;
1932 * Since we don't have a single instruction breakpoint, we may have
1933 * to adjust the program counter after removing the our `breakpoint'.
1935 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1936 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1939 if ((regs.r_pc < tcp->baddr) ||
1940 (regs.r_pc > tcp->baddr + 4)) {
1941 /* The breakpoint has not been reached yet */
1944 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1945 regs.r_pc, tcp->parent->baddr);
1948 if (regs.r_pc != tcp->baddr)
1950 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1951 regs.r_pc, tcp->baddr);
1953 regs.r_pc = tcp->baddr;
1954 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0) {
1955 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1967 #endif /* !USE_PROCFS */
1978 for (n = 0; n < sizeof *hdr; n += 4) {
1980 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1982 memcpy(((char *) hdr) + n, &res, 4);
1985 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1986 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1987 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1988 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1999 * Change `vfork' in a freshly exec'ed dynamically linked
2000 * executable's (internal) symbol table to plain old `fork'
2004 struct link_dynamic dyn;
2005 struct link_dynamic_2 ld;
2008 if (getex(pid, &hdr) < 0)
2013 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2014 fprintf(stderr, "Cannot read DYNAMIC\n");
2017 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2018 fprintf(stderr, "Cannot read link_dynamic_2\n");
2021 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
2022 fprintf(stderr, "fixvfork: out of memory\n");
2025 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2026 (int)ld.ld_symb_size, strtab) < 0)
2030 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2031 fprintf(stderr, "[symbol: %s]\n", cp);
2036 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2037 if (strcmp(cp, "_vfork") == 0) {
2039 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2040 strcpy(cp, "_fork");
2045 if (cp < strtab + ld.ld_symb_size)
2047 * Write entire symbol table back to avoid
2048 * memory alignment bugs in ptrace
2050 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2051 (int)ld.ld_symb_size, strtab) < 0)