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;
235 xlookup(const struct xlat *xlat, int val)
237 for (; xlat->str != NULL; xlat++)
238 if (xlat->val == val)
244 * Print entry in struct xlat table, if there.
247 printxval(const struct xlat *xlat, int val, const char *dflt)
249 const char *str = xlookup(xlat, val);
254 tprintf("%#x /* %s */", val, dflt);
258 * Interpret `xlat' as an array of flags
259 * print the entries whose bits are on in `flags'
260 * return # of flags printed.
263 addflags(xlat, flags)
264 const struct xlat *xlat;
269 for (n = 0; xlat->str; xlat++) {
270 if (xlat->val && (flags & xlat->val) == xlat->val) {
271 tprintf("|%s", xlat->str);
277 tprintf("|%#x", flags);
284 printflags(xlat, flags, dflt)
285 const struct xlat *xlat;
292 if (flags == 0 && xlat->val == 0) {
293 tprintf("%s", xlat->str);
298 for (n = 0; xlat->str; xlat++) {
299 if (xlat->val && (flags & xlat->val) == xlat->val) {
300 tprintf("%s%s", sep, xlat->str);
309 tprintf("%s%#x", sep, flags);
314 tprintf("%#x", flags);
316 tprintf(" /* %s */", dflt);
327 printnum(tcp, addr, fmt)
338 if (umove(tcp, addr, &num) < 0) {
339 tprintf("%#lx", addr);
348 printnum_int(tcp, addr, fmt)
359 if (umove(tcp, addr, &num) < 0) {
360 tprintf("%#lx", addr);
374 tprintf((uid == -1) ? "%ld" : "%lu", uid);
377 static char path[MAXPATHLEN + 1];
383 char buf[2 * MAXPATHLEN + 1];
386 if (!strpbrk(str, "\"\'\\")) {
387 tprintf("\"%s\"", str);
390 for (s = buf; *str; str++) {
392 case '\"': case '\'': case '\\':
393 *s++ = '\\'; *s++ = *str; break;
399 tprintf("\"%s\"", buf);
409 else if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
410 tprintf("%#lx", addr);
417 printpathn(tcp, addr, n)
422 if (n >= sizeof path)
427 else if (umovestr(tcp, addr, n, path) < 0)
428 tprintf("%#lx", addr);
436 printstr(tcp, addr, len)
441 static unsigned char *str = NULL;
451 if ((str = malloc(max_strlen)) == NULL
452 || (outstr = malloc(2*max_strlen)) == NULL) {
453 fprintf(stderr, "out of memory\n");
454 tprintf("%#lx", addr);
458 outend = outstr + max_strlen * 2 - 10;
461 if (umovestr(tcp, addr, n, (char *) str) < 0) {
462 tprintf("%#lx", addr);
467 n = MIN(len, max_strlen);
468 if (umoven(tcp, addr, n, (char *) str) < 0) {
469 tprintf("%#lx", addr);
478 for (i = 0; i < n; i++) {
480 if (len < 0 && c == '\0')
482 if (!isprint(c) && !isspace(c)) {
493 for (i = 0; i < n; i++) {
495 if (len < 0 && c == '\0')
497 sprintf(s, "\\x%02x", c);
504 for (i = 0; i < n; i++) {
506 if (len < 0 && c == '\0')
509 case '\"': case '\'': case '\\':
510 *s++ = '\\'; *s++ = c; break;
512 *s++ = '\\'; *s++ = 'f'; break;
514 *s++ = '\\'; *s++ = 'n'; break;
516 *s++ = '\\'; *s++ = 'r'; break;
518 *s++ = '\\'; *s++ = 't'; break;
520 *s++ = '\\'; *s++ = 'v'; break;
524 else if (i < n - 1 && isdigit(str[i + 1])) {
525 sprintf(s, "\\%03o", c);
529 sprintf(s, "\\%o", c);
540 if (i < len || (len < 0 && (i == n || s > outend))) {
541 *s++ = '.'; *s++ = '.'; *s++ = '.';
544 tprintf("%s", outstr);
549 dumpiov(tcp, len, addr)
554 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
556 struct { u_int32_t base; u_int32_t len; } *iov32;
557 struct { u_int64_t base; u_int64_t len; } *iov64;
559 #define iov iovu.iov64
561 (personality_wordsize[current_personality] == 4 \
562 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
563 #define iov_iov_base(i) \
564 (personality_wordsize[current_personality] == 4 \
565 ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
566 #define iov_iov_len(i) \
567 (personality_wordsize[current_personality] == 4 \
568 ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
571 #define sizeof_iov sizeof(*iov)
572 #define iov_iov_base(i) iov[i].iov_base
573 #define iov_iov_len(i) iov[i].iov_len
578 size = sizeof_iov * (unsigned long) len;
579 if (size / sizeof_iov != len
580 || (iov = malloc(size)) == NULL) {
581 fprintf(stderr, "out of memory\n");
584 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
585 for (i = 0; i < len; i++) {
586 /* include the buffer number to make it easy to
587 * match up the trace with the source */
588 tprintf(" * %lu bytes in buffer %d\n",
589 (unsigned long)iov_iov_len(i), i);
590 dumpstr(tcp, (long) iov_iov_base(i),
603 dumpstr(tcp, addr, len)
608 static int strsize = -1;
609 static unsigned char *str;
610 static char outstr[80];
617 if ((str = malloc(len)) == NULL) {
618 fprintf(stderr, "out of memory\n");
624 if (umoven(tcp, addr, len, (char *) str) < 0)
627 for (i = 0; i < len; i += 16) {
629 sprintf(s, " | %05x ", i);
631 for (j = 0; j < 16; j++) {
635 sprintf(s, " %02x", str[i + j]);
639 *s++ = ' '; *s++ = ' '; *s++ = ' ';
642 *s++ = ' '; *s++ = ' ';
643 for (j = 0; j < 16; j++) {
647 if (isprint(str[i + j]))
655 tprintf("%s |\n", outstr);
659 #define PAGMASK (~(PAGSIZ - 1))
661 * move `len' bytes of data from process `pid'
662 * at address `addr' to our space at `laddr'
665 umoven(tcp, addr, len, laddr)
678 char x[sizeof(long)];
681 if (addr & (sizeof(long) - 1)) {
682 /* addr not a multiple of sizeof(long) */
683 n = addr - (addr & -sizeof(long)); /* residue */
684 addr &= -sizeof(long); /* residue */
686 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
688 if (started && (errno==EPERM || errno==EIO)) {
689 /* Ran into 'end of memory' - stupid "printpath" */
692 /* But if not started, we had a bogus address. */
693 perror("ptrace: umoven");
697 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
698 addr += sizeof(long), laddr += m, len -= m;
702 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
704 if (started && (errno==EPERM || errno==EIO)) {
705 /* Ran into 'end of memory' - stupid "printpath" */
709 perror("ptrace: umoven");
713 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
714 addr += sizeof(long), laddr += m, len -= m;
724 char x[sizeof(long)];
727 if (addr & (sizeof(long) - 1)) {
728 /* addr not a multiple of sizeof(long) */
729 n = addr - (addr & -sizeof(long)); /* residue */
730 addr &= -sizeof(long); /* residue */
732 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
737 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
738 addr += sizeof(long), laddr += m, len -= m;
742 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
747 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
748 addr += sizeof(long), laddr += m, len -= m;
754 n = MIN(len, PAGSIZ);
755 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
756 if (ptrace(PTRACE_READDATA, pid,
757 (char *) addr, len, laddr) < 0) {
758 perror("umoven: ptrace(PTRACE_READDATA, ...)");
770 #ifdef HAVE_MP_PROCFS
771 int fd = tcp->pfd_as;
775 lseek(fd, addr, SEEK_SET);
776 if (read(fd, laddr, len) == -1)
778 #endif /* USE_PROCFS */
784 * like `umove' but make the additional effort of looking
785 * for a terminating zero byte.
788 umovestr(tcp, addr, len, laddr)
795 #ifdef HAVE_MP_PROCFS
796 int fd = tcp->pfd_as;
800 /* Some systems (e.g. FreeBSD) can be upset if we read off the
801 end of valid memory, avoid this by trying to read up
802 to page boundaries. But we don't know what a page is (and
803 getpagesize(2) (if it exists) doesn't necessarily return
804 hardware page size). Assume all pages >= 1024 (a-historical
807 int page = 1024; /* How to find this? */
808 int move = page - (addr & (page - 1));
811 lseek(fd, addr, SEEK_SET);
814 if (move > left) move = left;
815 if ((move = read(fd, laddr, move)) <= 0)
816 return left != len ? 0 : -1;
817 if (memchr (laddr, 0, move)) break;
823 #else /* !USE_PROCFS */
829 char x[sizeof(long)];
832 if (addr & (sizeof(long) - 1)) {
833 /* addr not a multiple of sizeof(long) */
834 n = addr - (addr & -sizeof(long)); /* residue */
835 addr &= -sizeof(long); /* residue */
837 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
839 if (started && (errno==EPERM || errno==EIO)) {
840 /* Ran into 'end of memory' - stupid "printpath" */
847 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
848 while (n & (sizeof(long) - 1))
849 if (u.x[n++] == '\0')
851 addr += sizeof(long), laddr += m, len -= m;
855 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
857 if (started && (errno==EPERM || errno==EIO)) {
858 /* Ran into 'end of memory' - stupid "printpath" */
865 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
866 for (i = 0; i < sizeof(long); i++)
870 addr += sizeof(long), laddr += m, len -= m;
872 #endif /* !USE_PROCFS */
877 #if !defined (SPARC) && !defined(SPARC64)
878 #define PTRACE_WRITETEXT 101
879 #define PTRACE_WRITEDATA 102
880 #endif /* !SPARC && !SPARC64 */
886 uload(cmd, pid, addr, len, laddr)
897 n = MIN(len, PAGSIZ);
898 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
899 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
900 perror("uload: ptrace(PTRACE_WRITE, ...)");
912 char x[sizeof(long)];
915 if (cmd == PTRACE_WRITETEXT) {
916 peek = PTRACE_PEEKTEXT;
917 poke = PTRACE_POKETEXT;
920 peek = PTRACE_PEEKDATA;
921 poke = PTRACE_POKEDATA;
923 if (addr & (sizeof(long) - 1)) {
924 /* addr not a multiple of sizeof(long) */
925 n = addr - (addr & -sizeof(long)); /* residue */
926 addr &= -sizeof(long);
928 u.val = ptrace(peek, pid, (char *) addr, 0);
930 perror("uload: POKE");
933 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
934 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
935 perror("uload: POKE");
938 addr += sizeof(long), laddr += m, len -= m;
941 if (len < sizeof(long))
942 u.val = ptrace(peek, pid, (char *) addr, 0);
943 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
944 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
945 perror("uload: POKE");
948 addr += sizeof(long), laddr += m, len -= m;
955 tload(pid, addr, len, laddr)
960 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
964 dload(pid, addr, len, laddr)
970 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
985 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
987 static int is_sun4m = -1;
990 /* Round up the usual suspects. */
991 if (is_sun4m == -1) {
992 if (uname(&name) < 0) {
993 perror("upeek: uname?");
996 is_sun4m = strcmp(name.machine, "sun4m") == 0;
998 extern const struct xlat struct_user_offsets[];
999 const struct xlat *x;
1001 for (x = struct_user_offsets; x->str; x++)
1008 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
1010 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
1011 if (val == -1 && errno) {
1013 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
1021 #endif /* !USE_PROCFS */
1032 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
1034 #elif defined(X86_64)
1035 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
1038 if (upeek(tcp->pid, PT_B0, &pc) < 0)
1041 if (upeek(tcp->pid, 4*15, &pc) < 0)
1043 #elif defined(POWERPC)
1044 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1047 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1049 #elif defined(ALPHA)
1050 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1053 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1055 #elif defined(SPARC) || defined(SPARC64)
1057 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0)
1060 #elif defined(S390) || defined(S390X)
1061 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
1064 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1067 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1070 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1078 * Return current program counter for `pid'
1079 * Assumes PC is never 0xffffffff
1083 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1084 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1097 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1099 #endif /* FREEBSD */
1107 #define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1108 sizeof(long) == 8 ? "[????????????????] " : \
1115 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1119 tprintf("[%08lx] ", eip);
1121 #elif defined(S390) || defined(S390X)
1123 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
1128 tprintf("[%08lx] ", psw);
1130 tprintf("[%16lx] ", psw);
1133 #elif defined(X86_64)
1136 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1140 tprintf("[%16lx] ", rip);
1144 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1148 tprintf("[%08lx] ", ip);
1149 #elif defined(POWERPC)
1152 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1153 tprintf ("[????????] ");
1156 tprintf("[%08lx] ", pc);
1160 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1161 tprintf ("[????????] ");
1164 tprintf("[%08lx] ", pc);
1165 #elif defined(ALPHA)
1168 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1169 tprintf ("[????????????????] ");
1172 tprintf("[%08lx] ", pc);
1173 #elif defined(SPARC) || defined(SPARC64)
1175 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0) {
1179 tprintf("[%08lx] ", regs.r_pc);
1183 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1184 tprintf ("[????????] ");
1187 tprintf("[%08lx] ", pc);
1191 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1192 tprintf ("[????????] ");
1195 tprintf("[%08lx] ", pc);
1199 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1200 tprintf ("[????????] ");
1203 tprintf("[%08lx] ", pc);
1207 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1208 tprintf ("[????????????????] ");
1211 tprintf("[%08lx] ", pc);
1215 if (upeek(tcp->pid, 4*15, &pc) < 0) {
1219 tprintf("[%08lx] ", pc);
1220 #endif /* !architecture */
1226 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1227 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1231 tprintf("[%08x] ", regs.r_o7);
1241 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1242 tprintf("[%08x] ", regs.r_eip);
1243 #endif /* FREEBSD */
1250 #include <sys/syscall.h>
1251 #ifndef CLONE_PTRACE
1252 # define CLONE_PTRACE 0x00002000
1254 #ifndef CLONE_STOPPED
1255 # define CLONE_STOPPED 0x02000000
1260 /* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1261 subsystem has them for x86... */
1263 #define SYS_vfork 190
1265 typedef unsigned long *arg_setup_state;
1268 arg_setup(struct tcb *tcp, arg_setup_state *state)
1270 unsigned long *bsp, cfm, sof, sol;
1275 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1277 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1280 sof = (cfm >> 0) & 0x7f;
1281 sol = (cfm >> 7) & 0x7f;
1282 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1288 # define arg_finish_change(tcp, state) 0
1292 get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1297 ret = upeek (tcp->pid, PT_R11, valp);
1300 (unsigned long) ia64_rse_skip_regs(*state, 0),
1301 sizeof(long), (void *) valp);
1306 get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1311 ret = upeek (tcp->pid, PT_R9, valp);
1314 (unsigned long) ia64_rse_skip_regs(*state, 1),
1315 sizeof(long), (void *) valp);
1321 set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1323 int req = PTRACE_POKEDATA;
1327 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1328 req = PTRACE_POKEUSER;
1330 ap = ia64_rse_skip_regs(*state, 0);
1332 ptrace(req, tcp->pid, ap, val);
1333 return errno ? -1 : 0;
1337 set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1339 int req = PTRACE_POKEDATA;
1343 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1344 req = PTRACE_POKEUSER;
1346 ap = ia64_rse_skip_regs(*state, 1);
1348 ptrace(req, tcp->pid, ap, val);
1349 return errno ? -1 : 0;
1352 #elif defined (SPARC) || defined (SPARC64)
1354 typedef struct regs arg_setup_state;
1356 # define arg_setup(tcp, state) \
1357 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1358 # define arg_finish_change(tcp, state) \
1359 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1361 # define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1362 # define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1363 # define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1364 # define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
1365 # define restore_arg0(tcp, state, val) 0
1369 # if defined S390 || defined S390X
1370 /* Note: this is only true for the `clone' system call, which handles
1371 arguments specially. We could as well say that its first two arguments
1372 are swapped relative to other architectures, but that would just be
1373 another #ifdef in the calls. */
1374 # define arg0_offset PT_GPR3
1375 # define arg1_offset PT_ORIGGPR2
1376 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1377 # define restore_arg1(tcp, state, val) ((void) (state), 0)
1378 # define arg0_index 1
1379 # define arg1_index 0
1380 # elif defined (ALPHA) || defined (MIPS)
1381 # define arg0_offset REG_A0
1382 # define arg1_offset (REG_A0+1)
1383 # elif defined (POWERPC)
1384 # define arg0_offset (sizeof(unsigned long)*PT_R3)
1385 # define arg1_offset (sizeof(unsigned long)*PT_R4)
1386 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1387 # elif defined (HPPA)
1388 # define arg0_offset PT_GR26
1389 # define arg1_offset (PT_GR26-4)
1390 # elif defined (X86_64)
1391 # define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1392 # define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1394 # define arg0_offset (4*(REG_REG0+4))
1395 # define arg1_offset (4*(REG_REG0+5))
1396 # elif defined (SH64)
1397 /* ABI defines arg0 & 1 in r2 & r3 */
1398 # define arg0_offset (REG_OFFSET+16)
1399 # define arg1_offset (REG_OFFSET+24)
1400 # define restore_arg0(tcp, state, val) 0
1402 # define arg0_offset 0
1403 # define arg1_offset 4
1405 # define restore_arg0(tcp, state, val) 0
1409 typedef int arg_setup_state;
1411 # define arg_setup(tcp, state) (0)
1412 # define arg_finish_change(tcp, state) 0
1413 # define get_arg0(tcp, cookie, valp) \
1414 (upeek ((tcp)->pid, arg0_offset, (valp)))
1415 # define get_arg1(tcp, cookie, valp) \
1416 (upeek ((tcp)->pid, arg1_offset, (valp)))
1419 set_arg0 (struct tcb *tcp, void *cookie, long val)
1421 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1425 set_arg1 (struct tcb *tcp, void *cookie, long val)
1427 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1432 #ifndef restore_arg0
1433 # define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1435 #ifndef restore_arg1
1436 # define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1440 # define arg0_index 0
1441 # define arg1_index 1
1448 extern int change_syscall(struct tcb *, int);
1449 arg_setup_state state;
1451 if (tcp->flags & TCB_BPTSET) {
1452 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1456 switch (known_scno(tcp)) {
1463 #if defined SYS_fork || defined SYS_vfork
1464 if (arg_setup (tcp, &state) < 0
1465 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1466 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1467 || change_syscall(tcp, SYS_clone) < 0
1468 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1469 || set_arg1 (tcp, &state, 0) < 0
1470 || arg_finish_change (tcp, &state) < 0)
1472 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1473 tcp->u_arg[arg1_index] = 0;
1474 tcp->flags |= TCB_BPTSET;
1482 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
1483 && (arg_setup (tcp, &state) < 0
1484 || set_arg0 (tcp, &state,
1485 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
1486 || arg_finish_change (tcp, &state) < 0))
1488 tcp->flags |= TCB_BPTSET;
1489 tcp->inst[0] = tcp->u_arg[arg0_index];
1490 tcp->inst[1] = tcp->u_arg[arg1_index];
1494 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1495 tcp->scno, tcp->pid);
1506 arg_setup_state state;
1507 if (arg_setup (tcp, &state) < 0
1508 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1509 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1510 || arg_finish_change (tcp, &state))
1512 tcp->flags &= ~TCB_BPTSET;
1524 #if defined (SPARC) || defined (SPARC64)
1525 /* We simply use the SunOS breakpoint code. */
1529 #define LOOPA 0x30800000 /* ba,a 0 */
1531 if (tcp->flags & TCB_BPTSET) {
1532 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1535 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1536 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1539 tcp->baddr = regs.r_o7 + 8;
1541 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1543 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1548 * XXX - BRUTAL MODE ON
1549 * We cannot set a real BPT in the child, since it will not be
1550 * traced at the moment it will reach the trap and would probably
1551 * die with a core dump.
1552 * Thus, we are force our way in by taking out two instructions
1553 * and insert an eternal loop instead, in expectance of the SIGSTOP
1554 * generated by out PTRACE_ATTACH.
1555 * Of cause, if we evaporate ourselves in the middle of all this...
1559 #if defined (SPARC64)
1561 inst |= (tcp->inst[0] & 0xffffffffUL);
1563 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
1565 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1568 tcp->flags |= TCB_BPTSET;
1570 #else /* !SPARC && !SPARC64 */
1573 # define LOOP 0x0000feeb
1574 if (tcp->flags & TCB_BPTSET) {
1575 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1579 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1582 fprintf(stderr, "[%d] setting bpt at %lx\n",
1583 tcp->pid, tcp->baddr);
1584 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1585 (char *) tcp->baddr, 0);
1587 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1590 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1592 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1595 tcp->flags |= TCB_BPTSET;
1598 * Our strategy here is to replace the bundle that
1599 * contained the clone() syscall with a bundle of the
1602 * { 1: br 1b; br 1b; br 1b }
1604 * This ensures that the newly forked child will loop
1605 * endlessly until we've got a chance to attach to it.
1607 # define LOOP0 0x0000100000000017
1608 # define LOOP1 0x4000000000200000
1609 unsigned long addr, ipsr;
1613 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1615 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1617 /* store "ri" in low two bits */
1618 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
1621 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1623 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1626 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1631 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1632 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1634 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1637 tcp->flags |= TCB_BPTSET;
1641 #if defined (I386) || defined(X86_64)
1642 #define LOOP 0x0000feeb
1643 #elif defined (M68K)
1644 #define LOOP 0x60fe0000
1645 #elif defined (ALPHA)
1646 #define LOOP 0xc3ffffff
1647 #elif defined (POWERPC)
1648 #define LOOP 0x48000000
1650 #define LOOP 0xEAFFFFFE
1652 #define LOOP 0x1000ffff
1654 #define LOOP 0xa7f40000 /* BRC 15,0 */
1655 #elif defined(S390X)
1656 #define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
1658 #define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
1660 #ifdef __LITTLE_ENDIAN__
1661 #define LOOP 0x0000affe
1663 #define LOOP 0xfeaf0000
1666 #error unknown architecture
1669 if (tcp->flags & TCB_BPTSET) {
1670 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1674 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1676 #elif defined (X86_64)
1677 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1679 #elif defined (M68K)
1680 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1682 #elif defined (ALPHA)
1686 #elif defined (MIPS)
1687 return -1; /* FIXME: I do not know what i do - Flo */
1688 #elif defined (POWERPC)
1689 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
1691 #elif defined(S390) || defined(S390X)
1692 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1695 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1697 tcp->baddr &= ~0x03;
1699 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1702 #error unknown architecture
1705 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1706 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1708 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1711 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1713 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1716 tcp->flags |= TCB_BPTSET;
1719 #endif /* SPARC || SPARC64 */
1723 #ifdef SPARC /* This code is slightly sparc specific */
1726 #define BPT 0x91d02001 /* ta 1 */
1727 #define LOOP 0x10800000 /* ba 0 */
1728 #define LOOPA 0x30800000 /* ba,a 0 */
1729 #define NOP 0x01000000
1731 static int loopdeloop[1] = {LOOPA};
1733 static int loopdeloop[2] = {LOOP, NOP};
1736 if (tcp->flags & TCB_BPTSET) {
1737 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1740 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1741 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1744 tcp->baddr = regs.r_o7 + 8;
1745 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1746 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1747 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1752 * XXX - BRUTAL MODE ON
1753 * We cannot set a real BPT in the child, since it will not be
1754 * traced at the moment it will reach the trap and would probably
1755 * die with a core dump.
1756 * Thus, we are force our way in by taking out two instructions
1757 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1758 * generated by out PTRACE_ATTACH.
1759 * Of cause, if we evaporate ourselves in the middle of all this...
1761 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1762 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1763 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1766 tcp->flags |= TCB_BPTSET;
1780 #if defined(I386) || defined(X86_64)
1782 #elif defined(POWERPC)
1786 #elif defined(ALPHA)
1792 #endif /* architecture */
1794 #if defined (SPARC) || defined (SPARC64)
1795 /* Again, we borrow the SunOS breakpoint code. */
1796 if (!(tcp->flags & TCB_BPTSET)) {
1797 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1801 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1803 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1806 tcp->flags &= ~TCB_BPTSET;
1812 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1813 if (!(tcp->flags & TCB_BPTSET)) {
1814 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1818 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1820 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1823 tcp->flags &= ~TCB_BPTSET;
1825 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1827 if (addr != tcp->baddr) {
1828 /* The breakpoint has not been reached yet. */
1831 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1836 unsigned long addr, ipsr;
1841 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1843 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1846 /* restore original bundle: */
1848 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1849 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1851 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1855 /* restore original "ri" in ipsr: */
1856 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1858 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1860 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1864 tcp->flags &= ~TCB_BPTSET;
1866 if (addr != (tcp->baddr & ~0x3)) {
1867 /* the breakpoint has not been reached yet. */
1869 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1874 #else /* !IA64 && !SPARC && !SPARC64 */
1877 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1878 if (!(tcp->flags & TCB_BPTSET)) {
1879 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1883 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1885 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1888 tcp->flags &= ~TCB_BPTSET;
1891 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1893 if (eip != tcp->baddr) {
1894 /* The breakpoint has not been reached yet. */
1897 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1901 #elif defined(X86_64)
1902 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1904 if (eip != tcp->baddr) {
1905 /* The breakpoint has not been reached yet. */
1908 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1912 #elif defined(POWERPC)
1913 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1915 if (pc != tcp->baddr) {
1916 /* The breakpoint has not been reached yet. */
1918 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1923 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1925 if (pc != tcp->baddr) {
1926 /* The breakpoint has not been reached yet. */
1928 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1932 #elif defined(ALPHA)
1933 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1935 if (pc != tcp->baddr) {
1936 /* The breakpoint has not been reached yet. */
1938 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1943 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1946 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1947 /* The breakpoint has not been reached yet. */
1949 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1953 iaoq = tcp->baddr | 3;
1954 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1955 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1956 * has no significant effect.
1958 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1959 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
1961 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1963 if (pc != tcp->baddr) {
1964 /* The breakpoint has not been reached yet. */
1966 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1972 #endif /* !SPARC && !SPARC64 && !IA64 */
1982 if (!(tcp->flags & TCB_BPTSET)) {
1983 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1986 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1987 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1988 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1991 tcp->flags &= ~TCB_BPTSET;
1995 * Since we don't have a single instruction breakpoint, we may have
1996 * to adjust the program counter after removing the our `breakpoint'.
1998 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1999 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
2002 if ((regs.r_pc < tcp->baddr) ||
2003 (regs.r_pc > tcp->baddr + 4)) {
2004 /* The breakpoint has not been reached yet */
2007 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
2008 regs.r_pc, tcp->parent->baddr);
2011 if (regs.r_pc != tcp->baddr)
2013 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
2014 regs.r_pc, tcp->baddr);
2016 regs.r_pc = tcp->baddr;
2017 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0) {
2018 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
2030 #endif /* !USE_PROCFS */
2041 for (n = 0; n < sizeof *hdr; n += 4) {
2043 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
2045 memcpy(((char *) hdr) + n, &res, 4);
2048 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2049 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2050 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2051 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2062 * Change `vfork' in a freshly exec'ed dynamically linked
2063 * executable's (internal) symbol table to plain old `fork'
2067 struct link_dynamic dyn;
2068 struct link_dynamic_2 ld;
2071 if (getex(pid, &hdr) < 0)
2076 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2077 fprintf(stderr, "Cannot read DYNAMIC\n");
2080 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2081 fprintf(stderr, "Cannot read link_dynamic_2\n");
2084 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
2085 fprintf(stderr, "out of memory\n");
2088 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2089 (int)ld.ld_symb_size, strtab) < 0)
2093 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2094 fprintf(stderr, "[symbol: %s]\n", cp);
2099 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2100 if (strcmp(cp, "_vfork") == 0) {
2102 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2103 strcpy(cp, "_fork");
2108 if (cp < strtab + ld.ld_symb_size)
2110 * Write entire symbol table back to avoid
2111 * memory alignment bugs in ptrace
2113 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2114 (int)ld.ld_symb_size, strtab) < 0)