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)
559 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
561 struct { u_int32_t base; u_int32_t len; } *iov32;
562 struct { u_int64_t base; u_int64_t len; } *iov64;
564 #define iov iovu.iov64
566 (personality_wordsize[current_personality] == 4 \
567 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
568 #define iov_iov_base(i) \
569 (personality_wordsize[current_personality] == 4 \
570 ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
571 #define iov_iov_len(i) \
572 (personality_wordsize[current_personality] == 4 \
573 ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
576 #define sizeof_iov sizeof(*iov)
577 #define iov_iov_base(i) iov[i].iov_base
578 #define iov_iov_len(i) iov[i].iov_len
583 size = sizeof_iov * (unsigned long) len;
584 if (size / sizeof_iov != len
585 || (iov = malloc(size)) == NULL) {
586 fprintf(stderr, "out of memory\n");
589 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
590 for (i = 0; i < len; i++) {
591 /* include the buffer number to make it easy to
592 * match up the trace with the source */
593 tprintf(" * %lu bytes in buffer %d\n",
594 (unsigned long)iov_iov_len(i), i);
595 dumpstr(tcp, (long) iov_iov_base(i),
608 dumpstr(tcp, addr, len)
613 static int strsize = -1;
614 static unsigned char *str;
615 static char outstr[80];
622 if ((str = malloc(len)) == NULL) {
623 fprintf(stderr, "out of memory\n");
629 if (umoven(tcp, addr, len, (char *) str) < 0)
632 for (i = 0; i < len; i += 16) {
634 sprintf(s, " | %05x ", i);
636 for (j = 0; j < 16; j++) {
640 sprintf(s, " %02x", str[i + j]);
644 *s++ = ' '; *s++ = ' '; *s++ = ' ';
647 *s++ = ' '; *s++ = ' ';
648 for (j = 0; j < 16; j++) {
652 if (isprint(str[i + j]))
660 tprintf("%s |\n", outstr);
664 #define PAGMASK (~(PAGSIZ - 1))
666 * move `len' bytes of data from process `pid'
667 * at address `addr' to our space at `laddr'
670 umoven(tcp, addr, len, laddr)
683 char x[sizeof(long)];
686 if (addr & (sizeof(long) - 1)) {
687 /* addr not a multiple of sizeof(long) */
688 n = addr - (addr & -sizeof(long)); /* residue */
689 addr &= -sizeof(long); /* residue */
691 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
693 if (started && (errno==EPERM || errno==EIO)) {
694 /* Ran into 'end of memory' - stupid "printpath" */
697 /* But if not started, we had a bogus address. */
698 perror("ptrace: umoven");
702 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
703 addr += sizeof(long), laddr += m, len -= m;
707 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
709 if (started && (errno==EPERM || errno==EIO)) {
710 /* Ran into 'end of memory' - stupid "printpath" */
714 perror("ptrace: umoven");
718 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
719 addr += sizeof(long), laddr += m, len -= m;
729 char x[sizeof(long)];
732 if (addr & (sizeof(long) - 1)) {
733 /* addr not a multiple of sizeof(long) */
734 n = addr - (addr & -sizeof(long)); /* residue */
735 addr &= -sizeof(long); /* residue */
737 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
742 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
743 addr += sizeof(long), laddr += m, len -= m;
747 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
752 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
753 addr += sizeof(long), laddr += m, len -= m;
759 n = MIN(len, PAGSIZ);
760 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
761 if (ptrace(PTRACE_READDATA, pid,
762 (char *) addr, len, laddr) < 0) {
763 perror("umoven: ptrace(PTRACE_READDATA, ...)");
775 #ifdef HAVE_MP_PROCFS
776 int fd = tcp->pfd_as;
780 lseek(fd, addr, SEEK_SET);
781 if (read(fd, laddr, len) == -1)
783 #endif /* USE_PROCFS */
789 * like `umove' but make the additional effort of looking
790 * for a terminating zero byte.
793 umovestr(tcp, addr, len, laddr)
800 #ifdef HAVE_MP_PROCFS
801 int fd = tcp->pfd_as;
805 /* Some systems (e.g. FreeBSD) can be upset if we read off the
806 end of valid memory, avoid this by trying to read up
807 to page boundaries. But we don't know what a page is (and
808 getpagesize(2) (if it exists) doesn't necessarily return
809 hardware page size). Assume all pages >= 1024 (a-historical
812 int page = 1024; /* How to find this? */
813 int move = page - (addr & (page - 1));
816 lseek(fd, addr, SEEK_SET);
819 if (move > left) move = left;
820 if ((move = read(fd, laddr, move)) <= 0)
821 return left != len ? 0 : -1;
822 if (memchr (laddr, 0, move)) break;
828 #else /* !USE_PROCFS */
834 char x[sizeof(long)];
837 if (addr & (sizeof(long) - 1)) {
838 /* addr not a multiple of sizeof(long) */
839 n = addr - (addr & -sizeof(long)); /* residue */
840 addr &= -sizeof(long); /* residue */
842 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
844 if (started && (errno==EPERM || errno==EIO)) {
845 /* Ran into 'end of memory' - stupid "printpath" */
852 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
853 while (n & (sizeof(long) - 1))
854 if (u.x[n++] == '\0')
856 addr += sizeof(long), laddr += m, len -= m;
860 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
862 if (started && (errno==EPERM || errno==EIO)) {
863 /* Ran into 'end of memory' - stupid "printpath" */
870 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
871 for (i = 0; i < sizeof(long); i++)
875 addr += sizeof(long), laddr += m, len -= m;
877 #endif /* !USE_PROCFS */
882 #if !defined (SPARC) && !defined(SPARC64)
883 #define PTRACE_WRITETEXT 101
884 #define PTRACE_WRITEDATA 102
885 #endif /* !SPARC && !SPARC64 */
891 uload(cmd, pid, addr, len, laddr)
902 n = MIN(len, PAGSIZ);
903 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
904 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
905 perror("uload: ptrace(PTRACE_WRITE, ...)");
917 char x[sizeof(long)];
920 if (cmd == PTRACE_WRITETEXT) {
921 peek = PTRACE_PEEKTEXT;
922 poke = PTRACE_POKETEXT;
925 peek = PTRACE_PEEKDATA;
926 poke = PTRACE_POKEDATA;
928 if (addr & (sizeof(long) - 1)) {
929 /* addr not a multiple of sizeof(long) */
930 n = addr - (addr & -sizeof(long)); /* residue */
931 addr &= -sizeof(long);
933 u.val = ptrace(peek, pid, (char *) addr, 0);
935 perror("uload: POKE");
938 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
939 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
940 perror("uload: POKE");
943 addr += sizeof(long), laddr += m, len -= m;
946 if (len < sizeof(long))
947 u.val = ptrace(peek, pid, (char *) addr, 0);
948 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
949 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
950 perror("uload: POKE");
953 addr += sizeof(long), laddr += m, len -= m;
960 tload(pid, addr, len, laddr)
965 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
969 dload(pid, addr, len, laddr)
975 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
990 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
992 static int is_sun4m = -1;
995 /* Round up the usual suspects. */
996 if (is_sun4m == -1) {
997 if (uname(&name) < 0) {
998 perror("upeek: uname?");
1001 is_sun4m = strcmp(name.machine, "sun4m") == 0;
1003 extern const struct xlat struct_user_offsets[];
1004 const struct xlat *x;
1006 for (x = struct_user_offsets; x->str; x++)
1013 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
1015 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
1016 if (val == -1 && errno) {
1018 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
1026 #endif /* !USE_PROCFS */
1037 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
1039 #elif defined(X86_64)
1040 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
1043 if (upeek(tcp->pid, PT_B0, &pc) < 0)
1046 if (upeek(tcp->pid, 4*15, &pc) < 0)
1048 #elif defined(POWERPC)
1049 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1052 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1054 #elif defined(ALPHA)
1055 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1058 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1060 #elif defined(SPARC) || defined(SPARC64)
1062 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0)
1065 #elif defined(S390) || defined(S390X)
1066 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
1069 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1072 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1075 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1083 * Return current program counter for `pid'
1084 * Assumes PC is never 0xffffffff
1088 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1089 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1102 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1104 #endif /* FREEBSD */
1112 #define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1113 sizeof(long) == 8 ? "[????????????????] " : \
1120 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1124 tprintf("[%08lx] ", eip);
1126 #elif defined(S390) || defined(S390X)
1128 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
1133 tprintf("[%08lx] ", psw);
1135 tprintf("[%16lx] ", psw);
1138 #elif defined(X86_64)
1141 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1145 tprintf("[%16lx] ", rip);
1149 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1153 tprintf("[%08lx] ", ip);
1154 #elif defined(POWERPC)
1157 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1158 tprintf ("[????????] ");
1161 tprintf("[%08lx] ", pc);
1165 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1166 tprintf ("[????????] ");
1169 tprintf("[%08lx] ", pc);
1170 #elif defined(ALPHA)
1173 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1174 tprintf ("[????????????????] ");
1177 tprintf("[%08lx] ", pc);
1178 #elif defined(SPARC) || defined(SPARC64)
1180 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0) {
1184 tprintf("[%08lx] ", regs.r_pc);
1188 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1189 tprintf ("[????????] ");
1192 tprintf("[%08lx] ", pc);
1196 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1197 tprintf ("[????????] ");
1200 tprintf("[%08lx] ", pc);
1204 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1205 tprintf ("[????????] ");
1208 tprintf("[%08lx] ", pc);
1212 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1213 tprintf ("[????????????????] ");
1216 tprintf("[%08lx] ", pc);
1220 if (upeek(tcp->pid, 4*15, &pc) < 0) {
1224 tprintf("[%08lx] ", pc);
1225 #endif /* !architecture */
1231 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1232 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1236 tprintf("[%08x] ", regs.r_o7);
1246 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1247 tprintf("[%08x] ", regs.r_eip);
1248 #endif /* FREEBSD */
1255 #include <sys/syscall.h>
1256 #ifndef CLONE_PTRACE
1257 # define CLONE_PTRACE 0x00002000
1259 #ifndef CLONE_STOPPED
1260 # define CLONE_STOPPED 0x02000000
1265 /* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1266 subsystem has them for x86... */
1268 #define SYS_vfork 190
1270 typedef unsigned long *arg_setup_state;
1273 arg_setup(struct tcb *tcp, arg_setup_state *state)
1275 unsigned long *bsp, cfm, sof, sol;
1280 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1282 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1285 sof = (cfm >> 0) & 0x7f;
1286 sol = (cfm >> 7) & 0x7f;
1287 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1293 # define arg_finish_change(tcp, state) 0
1297 get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1302 ret = upeek (tcp->pid, PT_R11, valp);
1305 (unsigned long) ia64_rse_skip_regs(*state, 0),
1306 sizeof(long), (void *) valp);
1311 get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1316 ret = upeek (tcp->pid, PT_R9, valp);
1319 (unsigned long) ia64_rse_skip_regs(*state, 1),
1320 sizeof(long), (void *) valp);
1326 set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1328 int req = PTRACE_POKEDATA;
1332 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1333 req = PTRACE_POKEUSER;
1335 ap = ia64_rse_skip_regs(*state, 0);
1337 ptrace(req, tcp->pid, ap, val);
1338 return errno ? -1 : 0;
1342 set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1344 int req = PTRACE_POKEDATA;
1348 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1349 req = PTRACE_POKEUSER;
1351 ap = ia64_rse_skip_regs(*state, 1);
1353 ptrace(req, tcp->pid, ap, val);
1354 return errno ? -1 : 0;
1357 #elif defined (SPARC) || defined (SPARC64)
1359 typedef struct regs arg_setup_state;
1361 # define arg_setup(tcp, state) \
1362 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1363 # define arg_finish_change(tcp, state) \
1364 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1366 # define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1367 # define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1368 # define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1369 # define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
1370 # define restore_arg0(tcp, state, val) 0
1374 # if defined S390 || defined S390X
1375 /* Note: this is only true for the `clone' system call, which handles
1376 arguments specially. We could as well say that its first two arguments
1377 are swapped relative to other architectures, but that would just be
1378 another #ifdef in the calls. */
1379 # define arg0_offset PT_GPR3
1380 # define arg1_offset PT_ORIGGPR2
1381 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1382 # define restore_arg1(tcp, state, val) ((void) (state), 0)
1383 # define arg0_index 1
1384 # define arg1_index 0
1385 # elif defined (ALPHA) || defined (MIPS)
1386 # define arg0_offset REG_A0
1387 # define arg1_offset (REG_A0+1)
1388 # elif defined (POWERPC)
1389 # define arg0_offset (sizeof(unsigned long)*PT_R3)
1390 # define arg1_offset (sizeof(unsigned long)*PT_R4)
1391 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1392 # elif defined (HPPA)
1393 # define arg0_offset PT_GR26
1394 # define arg1_offset (PT_GR26-4)
1395 # elif defined (X86_64)
1396 # define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1397 # define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1399 # define arg0_offset (4*(REG_REG0+4))
1400 # define arg1_offset (4*(REG_REG0+5))
1401 # elif defined (SH64)
1402 /* ABI defines arg0 & 1 in r2 & r3 */
1403 # define arg0_offset (REG_OFFSET+16)
1404 # define arg1_offset (REG_OFFSET+24)
1405 # define restore_arg0(tcp, state, val) 0
1407 # define arg0_offset 0
1408 # define arg1_offset 4
1410 # define restore_arg0(tcp, state, val) 0
1414 typedef int arg_setup_state;
1416 # define arg_setup(tcp, state) (0)
1417 # define arg_finish_change(tcp, state) 0
1418 # define get_arg0(tcp, cookie, valp) \
1419 (upeek ((tcp)->pid, arg0_offset, (valp)))
1420 # define get_arg1(tcp, cookie, valp) \
1421 (upeek ((tcp)->pid, arg1_offset, (valp)))
1424 set_arg0 (struct tcb *tcp, void *cookie, long val)
1426 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1430 set_arg1 (struct tcb *tcp, void *cookie, long val)
1432 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1437 #ifndef restore_arg0
1438 # define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1440 #ifndef restore_arg1
1441 # define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1445 # define arg0_index 0
1446 # define arg1_index 1
1453 extern int change_syscall(struct tcb *, int);
1454 arg_setup_state state;
1456 if (tcp->flags & TCB_BPTSET) {
1457 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1461 switch (known_scno(tcp)) {
1468 #if defined SYS_fork || defined SYS_vfork
1469 if (arg_setup (tcp, &state) < 0
1470 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1471 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1472 || change_syscall(tcp, SYS_clone) < 0
1473 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1474 || set_arg1 (tcp, &state, 0) < 0
1475 || arg_finish_change (tcp, &state) < 0)
1477 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1478 tcp->u_arg[arg1_index] = 0;
1479 tcp->flags |= TCB_BPTSET;
1487 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
1488 && (arg_setup (tcp, &state) < 0
1489 || set_arg0 (tcp, &state,
1490 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
1491 || arg_finish_change (tcp, &state) < 0))
1493 tcp->flags |= TCB_BPTSET;
1494 tcp->inst[0] = tcp->u_arg[arg0_index];
1495 tcp->inst[1] = tcp->u_arg[arg1_index];
1499 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1500 tcp->scno, tcp->pid);
1511 arg_setup_state state;
1512 if (arg_setup (tcp, &state) < 0
1513 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1514 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1515 || arg_finish_change (tcp, &state))
1517 tcp->flags &= ~TCB_BPTSET;
1529 #if defined (SPARC) || defined (SPARC64)
1530 /* We simply use the SunOS breakpoint code. */
1534 #define LOOPA 0x30800000 /* ba,a 0 */
1536 if (tcp->flags & TCB_BPTSET) {
1537 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1540 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1541 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1544 tcp->baddr = regs.r_o7 + 8;
1546 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1548 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1553 * XXX - BRUTAL MODE ON
1554 * We cannot set a real BPT in the child, since it will not be
1555 * traced at the moment it will reach the trap and would probably
1556 * die with a core dump.
1557 * Thus, we are force our way in by taking out two instructions
1558 * and insert an eternal loop instead, in expectance of the SIGSTOP
1559 * generated by out PTRACE_ATTACH.
1560 * Of cause, if we evaporate ourselves in the middle of all this...
1564 #if defined (SPARC64)
1566 inst |= (tcp->inst[0] & 0xffffffffUL);
1568 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
1570 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1573 tcp->flags |= TCB_BPTSET;
1575 #else /* !SPARC && !SPARC64 */
1578 # define LOOP 0x0000feeb
1579 if (tcp->flags & TCB_BPTSET) {
1580 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1584 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1587 fprintf(stderr, "[%d] setting bpt at %lx\n",
1588 tcp->pid, tcp->baddr);
1589 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1590 (char *) tcp->baddr, 0);
1592 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1595 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1597 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1600 tcp->flags |= TCB_BPTSET;
1603 * Our strategy here is to replace the bundle that
1604 * contained the clone() syscall with a bundle of the
1607 * { 1: br 1b; br 1b; br 1b }
1609 * This ensures that the newly forked child will loop
1610 * endlessly until we've got a chance to attach to it.
1612 # define LOOP0 0x0000100000000017
1613 # define LOOP1 0x4000000000200000
1614 unsigned long addr, ipsr;
1618 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1620 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1622 /* store "ri" in low two bits */
1623 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
1626 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1628 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1631 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1636 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1637 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1639 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1642 tcp->flags |= TCB_BPTSET;
1646 #if defined (I386) || defined(X86_64)
1647 #define LOOP 0x0000feeb
1648 #elif defined (M68K)
1649 #define LOOP 0x60fe0000
1650 #elif defined (ALPHA)
1651 #define LOOP 0xc3ffffff
1652 #elif defined (POWERPC)
1653 #define LOOP 0x48000000
1655 #define LOOP 0xEAFFFFFE
1657 #define LOOP 0x1000ffff
1659 #define LOOP 0xa7f40000 /* BRC 15,0 */
1660 #elif defined(S390X)
1661 #define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
1663 #define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
1665 #ifdef __LITTLE_ENDIAN__
1666 #define LOOP 0x0000affe
1668 #define LOOP 0xfeaf0000
1671 #error unknown architecture
1674 if (tcp->flags & TCB_BPTSET) {
1675 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1679 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1681 #elif defined (X86_64)
1682 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1684 #elif defined (M68K)
1685 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1687 #elif defined (ALPHA)
1691 #elif defined (MIPS)
1692 return -1; /* FIXME: I do not know what i do - Flo */
1693 #elif defined (POWERPC)
1694 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
1696 #elif defined(S390) || defined(S390X)
1697 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1700 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1702 tcp->baddr &= ~0x03;
1704 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1707 #error unknown architecture
1710 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1711 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1713 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1716 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1718 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1721 tcp->flags |= TCB_BPTSET;
1724 #endif /* SPARC || SPARC64 */
1728 #ifdef SPARC /* This code is slightly sparc specific */
1731 #define BPT 0x91d02001 /* ta 1 */
1732 #define LOOP 0x10800000 /* ba 0 */
1733 #define LOOPA 0x30800000 /* ba,a 0 */
1734 #define NOP 0x01000000
1736 static int loopdeloop[1] = {LOOPA};
1738 static int loopdeloop[2] = {LOOP, NOP};
1741 if (tcp->flags & TCB_BPTSET) {
1742 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1745 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1746 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1749 tcp->baddr = regs.r_o7 + 8;
1750 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1751 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1752 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1757 * XXX - BRUTAL MODE ON
1758 * We cannot set a real BPT in the child, since it will not be
1759 * traced at the moment it will reach the trap and would probably
1760 * die with a core dump.
1761 * Thus, we are force our way in by taking out two instructions
1762 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1763 * generated by out PTRACE_ATTACH.
1764 * Of cause, if we evaporate ourselves in the middle of all this...
1766 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1767 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1768 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1771 tcp->flags |= TCB_BPTSET;
1785 #if defined(I386) || defined(X86_64)
1787 #elif defined(POWERPC)
1791 #elif defined(ALPHA)
1797 #endif /* architecture */
1799 #if defined (SPARC) || defined (SPARC64)
1800 /* Again, we borrow the SunOS breakpoint code. */
1801 if (!(tcp->flags & TCB_BPTSET)) {
1802 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1806 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1808 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1811 tcp->flags &= ~TCB_BPTSET;
1817 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1818 if (!(tcp->flags & TCB_BPTSET)) {
1819 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1823 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1825 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1828 tcp->flags &= ~TCB_BPTSET;
1830 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1832 if (addr != tcp->baddr) {
1833 /* The breakpoint has not been reached yet. */
1836 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1841 unsigned long addr, ipsr;
1846 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1848 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1851 /* restore original bundle: */
1853 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1854 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1856 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1860 /* restore original "ri" in ipsr: */
1861 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1863 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1865 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1869 tcp->flags &= ~TCB_BPTSET;
1871 if (addr != (tcp->baddr & ~0x3)) {
1872 /* the breakpoint has not been reached yet. */
1874 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1879 #else /* !IA64 && !SPARC && !SPARC64 */
1882 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1883 if (!(tcp->flags & TCB_BPTSET)) {
1884 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1888 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1890 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1893 tcp->flags &= ~TCB_BPTSET;
1896 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1898 if (eip != tcp->baddr) {
1899 /* The breakpoint has not been reached yet. */
1902 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1906 #elif defined(X86_64)
1907 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1909 if (eip != tcp->baddr) {
1910 /* The breakpoint has not been reached yet. */
1913 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1917 #elif defined(POWERPC)
1918 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1920 if (pc != tcp->baddr) {
1921 /* The breakpoint has not been reached yet. */
1923 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1928 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1930 if (pc != tcp->baddr) {
1931 /* The breakpoint has not been reached yet. */
1933 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1937 #elif defined(ALPHA)
1938 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1940 if (pc != tcp->baddr) {
1941 /* The breakpoint has not been reached yet. */
1943 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1948 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1951 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1952 /* The breakpoint has not been reached yet. */
1954 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1958 iaoq = tcp->baddr | 3;
1959 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1960 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1961 * has no significant effect.
1963 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1964 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
1966 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1968 if (pc != tcp->baddr) {
1969 /* The breakpoint has not been reached yet. */
1971 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1977 #endif /* !SPARC && !SPARC64 && !IA64 */
1987 if (!(tcp->flags & TCB_BPTSET)) {
1988 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1991 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1992 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1993 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1996 tcp->flags &= ~TCB_BPTSET;
2000 * Since we don't have a single instruction breakpoint, we may have
2001 * to adjust the program counter after removing the our `breakpoint'.
2003 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
2004 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
2007 if ((regs.r_pc < tcp->baddr) ||
2008 (regs.r_pc > tcp->baddr + 4)) {
2009 /* The breakpoint has not been reached yet */
2012 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
2013 regs.r_pc, tcp->parent->baddr);
2016 if (regs.r_pc != tcp->baddr)
2018 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
2019 regs.r_pc, tcp->baddr);
2021 regs.r_pc = tcp->baddr;
2022 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0) {
2023 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
2035 #endif /* !USE_PROCFS */
2046 for (n = 0; n < sizeof *hdr; n += 4) {
2048 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
2050 memcpy(((char *) hdr) + n, &res, 4);
2053 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2054 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2055 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2056 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2067 * Change `vfork' in a freshly exec'ed dynamically linked
2068 * executable's (internal) symbol table to plain old `fork'
2072 struct link_dynamic dyn;
2073 struct link_dynamic_2 ld;
2076 if (getex(pid, &hdr) < 0)
2081 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2082 fprintf(stderr, "Cannot read DYNAMIC\n");
2085 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2086 fprintf(stderr, "Cannot read link_dynamic_2\n");
2089 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
2090 fprintf(stderr, "out of memory\n");
2093 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2094 (int)ld.ld_symb_size, strtab) < 0)
2098 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2099 fprintf(stderr, "[symbol: %s]\n", cp);
2104 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2105 if (strcmp(cp, "_vfork") == 0) {
2107 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2108 strcpy(cp, "_fork");
2113 if (cp < strtab + ld.ld_symb_size)
2115 * Write entire symbol table back to avoid
2116 * memory alignment bugs in ptrace
2118 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2119 (int)ld.ld_symb_size, strtab) < 0)