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 + tv->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(4*max_strlen
453 + sizeof "\"\"...")) == NULL) {
454 fprintf(stderr, "out of memory\n");
455 tprintf("%#lx", addr);
459 outend = outstr + max_strlen * 4;
462 if (umovestr(tcp, addr, n, (char *) str) < 0) {
463 tprintf("%#lx", addr);
468 n = MIN(len, max_strlen);
469 if (umoven(tcp, addr, n, (char *) str) < 0) {
470 tprintf("%#lx", addr);
479 for (i = 0; i < n; i++) {
481 if (len < 0 && c == '\0')
483 if (!isprint(c) && !isspace(c)) {
494 for (i = 0; i < n; i++) {
496 if (len < 0 && c == '\0')
498 sprintf(s, "\\x%02x", c);
505 for (i = 0; i < n; i++) {
507 if (len < 0 && c == '\0')
510 case '\"': case '\'': case '\\':
511 *s++ = '\\'; *s++ = c; break;
513 *s++ = '\\'; *s++ = 'f'; break;
515 *s++ = '\\'; *s++ = 'n'; break;
517 *s++ = '\\'; *s++ = 'r'; break;
519 *s++ = '\\'; *s++ = 't'; break;
521 *s++ = '\\'; *s++ = 'v'; break;
525 else if (i < n - 1 && isdigit(str[i + 1])) {
526 sprintf(s, "\\%03o", c);
530 sprintf(s, "\\%o", c);
541 if (i < len || (len < 0 && (i == n || s > outend))) {
542 *s++ = '.'; *s++ = '.'; *s++ = '.';
545 tprintf("%s", outstr);
550 dumpiov(tcp, len, addr)
555 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
557 struct { u_int32_t base; u_int32_t len; } *iov32;
558 struct { u_int64_t base; u_int64_t len; } *iov64;
560 #define iov iovu.iov64
562 (personality_wordsize[current_personality] == 4 \
563 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
564 #define iov_iov_base(i) \
565 (personality_wordsize[current_personality] == 4 \
566 ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
567 #define iov_iov_len(i) \
568 (personality_wordsize[current_personality] == 4 \
569 ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
572 #define sizeof_iov sizeof(*iov)
573 #define iov_iov_base(i) iov[i].iov_base
574 #define iov_iov_len(i) iov[i].iov_len
579 size = sizeof_iov * (unsigned long) len;
580 if (size / sizeof_iov != len
581 || (iov = malloc(size)) == NULL) {
582 fprintf(stderr, "out of memory\n");
585 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
586 for (i = 0; i < len; i++) {
587 /* include the buffer number to make it easy to
588 * match up the trace with the source */
589 tprintf(" * %lu bytes in buffer %d\n",
590 (unsigned long)iov_iov_len(i), i);
591 dumpstr(tcp, (long) iov_iov_base(i),
604 dumpstr(tcp, addr, len)
609 static int strsize = -1;
610 static unsigned char *str;
611 static char outstr[80];
618 if ((str = malloc(len)) == NULL) {
619 fprintf(stderr, "out of memory\n");
625 if (umoven(tcp, addr, len, (char *) str) < 0)
628 for (i = 0; i < len; i += 16) {
630 sprintf(s, " | %05x ", i);
632 for (j = 0; j < 16; j++) {
636 sprintf(s, " %02x", str[i + j]);
640 *s++ = ' '; *s++ = ' '; *s++ = ' ';
643 *s++ = ' '; *s++ = ' ';
644 for (j = 0; j < 16; j++) {
648 if (isprint(str[i + j]))
656 tprintf("%s |\n", outstr);
660 #define PAGMASK (~(PAGSIZ - 1))
662 * move `len' bytes of data from process `pid'
663 * at address `addr' to our space at `laddr'
666 umoven(tcp, addr, len, laddr)
679 char x[sizeof(long)];
682 if (addr & (sizeof(long) - 1)) {
683 /* addr not a multiple of sizeof(long) */
684 n = addr - (addr & -sizeof(long)); /* residue */
685 addr &= -sizeof(long); /* residue */
687 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
689 if (started && (errno==EPERM || errno==EIO)) {
690 /* Ran into 'end of memory' - stupid "printpath" */
693 /* But if not started, we had a bogus address. */
694 perror("ptrace: umoven");
698 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
699 addr += sizeof(long), laddr += m, len -= m;
703 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
705 if (started && (errno==EPERM || errno==EIO)) {
706 /* Ran into 'end of memory' - stupid "printpath" */
710 perror("ptrace: umoven");
714 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
715 addr += sizeof(long), laddr += m, len -= m;
725 char x[sizeof(long)];
728 if (addr & (sizeof(long) - 1)) {
729 /* addr not a multiple of sizeof(long) */
730 n = addr - (addr & -sizeof(long)); /* residue */
731 addr &= -sizeof(long); /* residue */
733 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
738 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
739 addr += sizeof(long), laddr += m, len -= m;
743 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
748 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
749 addr += sizeof(long), laddr += m, len -= m;
755 n = MIN(len, PAGSIZ);
756 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
757 if (ptrace(PTRACE_READDATA, pid,
758 (char *) addr, len, laddr) < 0) {
759 perror("umoven: ptrace(PTRACE_READDATA, ...)");
771 #ifdef HAVE_MP_PROCFS
772 int fd = tcp->pfd_as;
776 lseek(fd, addr, SEEK_SET);
777 if (read(fd, laddr, len) == -1)
779 #endif /* USE_PROCFS */
785 * like `umove' but make the additional effort of looking
786 * for a terminating zero byte.
789 umovestr(tcp, addr, len, laddr)
796 #ifdef HAVE_MP_PROCFS
797 int fd = tcp->pfd_as;
801 /* Some systems (e.g. FreeBSD) can be upset if we read off the
802 end of valid memory, avoid this by trying to read up
803 to page boundaries. But we don't know what a page is (and
804 getpagesize(2) (if it exists) doesn't necessarily return
805 hardware page size). Assume all pages >= 1024 (a-historical
808 int page = 1024; /* How to find this? */
809 int move = page - (addr & (page - 1));
812 lseek(fd, addr, SEEK_SET);
815 if (move > left) move = left;
816 if ((move = read(fd, laddr, move)) <= 0)
817 return left != len ? 0 : -1;
818 if (memchr (laddr, 0, move)) break;
824 #else /* !USE_PROCFS */
830 char x[sizeof(long)];
833 if (addr & (sizeof(long) - 1)) {
834 /* addr not a multiple of sizeof(long) */
835 n = addr - (addr & -sizeof(long)); /* residue */
836 addr &= -sizeof(long); /* residue */
838 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
840 if (started && (errno==EPERM || errno==EIO)) {
841 /* Ran into 'end of memory' - stupid "printpath" */
848 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
849 while (n & (sizeof(long) - 1))
850 if (u.x[n++] == '\0')
852 addr += sizeof(long), laddr += m, len -= m;
856 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
858 if (started && (errno==EPERM || errno==EIO)) {
859 /* Ran into 'end of memory' - stupid "printpath" */
866 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
867 for (i = 0; i < sizeof(long); i++)
871 addr += sizeof(long), laddr += m, len -= m;
873 #endif /* !USE_PROCFS */
878 #if !defined (SPARC) && !defined(SPARC64)
879 #define PTRACE_WRITETEXT 101
880 #define PTRACE_WRITEDATA 102
881 #endif /* !SPARC && !SPARC64 */
887 uload(cmd, pid, addr, len, laddr)
898 n = MIN(len, PAGSIZ);
899 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
900 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
901 perror("uload: ptrace(PTRACE_WRITE, ...)");
913 char x[sizeof(long)];
916 if (cmd == PTRACE_WRITETEXT) {
917 peek = PTRACE_PEEKTEXT;
918 poke = PTRACE_POKETEXT;
921 peek = PTRACE_PEEKDATA;
922 poke = PTRACE_POKEDATA;
924 if (addr & (sizeof(long) - 1)) {
925 /* addr not a multiple of sizeof(long) */
926 n = addr - (addr & -sizeof(long)); /* residue */
927 addr &= -sizeof(long);
929 u.val = ptrace(peek, pid, (char *) addr, 0);
931 perror("uload: POKE");
934 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
935 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
936 perror("uload: POKE");
939 addr += sizeof(long), laddr += m, len -= m;
942 if (len < sizeof(long))
943 u.val = ptrace(peek, pid, (char *) addr, 0);
944 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
945 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
946 perror("uload: POKE");
949 addr += sizeof(long), laddr += m, len -= m;
956 tload(pid, addr, len, laddr)
961 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
965 dload(pid, addr, len, laddr)
971 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
986 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
988 static int is_sun4m = -1;
991 /* Round up the usual suspects. */
992 if (is_sun4m == -1) {
993 if (uname(&name) < 0) {
994 perror("upeek: uname?");
997 is_sun4m = strcmp(name.machine, "sun4m") == 0;
999 extern const struct xlat struct_user_offsets[];
1000 const struct xlat *x;
1002 for (x = struct_user_offsets; x->str; x++)
1009 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
1011 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
1012 if (val == -1 && errno) {
1014 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
1022 #endif /* !USE_PROCFS */
1033 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
1035 #elif defined(X86_64)
1036 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
1039 if (upeek(tcp->pid, PT_B0, &pc) < 0)
1042 if (upeek(tcp->pid, 4*15, &pc) < 0)
1044 #elif defined(POWERPC)
1045 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1048 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1050 #elif defined(ALPHA)
1051 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1054 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1056 #elif defined(SPARC) || defined(SPARC64)
1058 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0)
1061 #elif defined(S390) || defined(S390X)
1062 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
1065 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1068 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1071 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1079 * Return current program counter for `pid'
1080 * Assumes PC is never 0xffffffff
1084 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1085 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1098 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1100 #endif /* FREEBSD */
1108 #define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1109 sizeof(long) == 8 ? "[????????????????] " : \
1116 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1120 tprintf("[%08lx] ", eip);
1122 #elif defined(S390) || defined(S390X)
1124 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
1129 tprintf("[%08lx] ", psw);
1131 tprintf("[%16lx] ", psw);
1134 #elif defined(X86_64)
1137 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1141 tprintf("[%16lx] ", rip);
1145 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1149 tprintf("[%08lx] ", ip);
1150 #elif defined(POWERPC)
1153 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1154 tprintf ("[????????] ");
1157 tprintf("[%08lx] ", pc);
1161 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1162 tprintf ("[????????] ");
1165 tprintf("[%08lx] ", pc);
1166 #elif defined(ALPHA)
1169 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1170 tprintf ("[????????????????] ");
1173 tprintf("[%08lx] ", pc);
1174 #elif defined(SPARC) || defined(SPARC64)
1176 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0) {
1180 tprintf("[%08lx] ", regs.r_pc);
1184 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1185 tprintf ("[????????] ");
1188 tprintf("[%08lx] ", pc);
1192 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1193 tprintf ("[????????] ");
1196 tprintf("[%08lx] ", pc);
1200 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1201 tprintf ("[????????] ");
1204 tprintf("[%08lx] ", pc);
1208 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1209 tprintf ("[????????????????] ");
1212 tprintf("[%08lx] ", pc);
1216 if (upeek(tcp->pid, 4*15, &pc) < 0) {
1220 tprintf("[%08lx] ", pc);
1221 #endif /* !architecture */
1227 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
1228 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1232 tprintf("[%08x] ", regs.r_o7);
1242 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
1243 tprintf("[%08x] ", regs.r_eip);
1244 #endif /* FREEBSD */
1251 #include <sys/syscall.h>
1252 #ifndef CLONE_PTRACE
1253 # define CLONE_PTRACE 0x00002000
1255 #ifndef CLONE_STOPPED
1256 # define CLONE_STOPPED 0x02000000
1261 /* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1262 subsystem has them for x86... */
1264 #define SYS_vfork 190
1266 typedef unsigned long *arg_setup_state;
1269 arg_setup(struct tcb *tcp, arg_setup_state *state)
1271 unsigned long *bsp, cfm, sof, sol;
1276 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1278 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1281 sof = (cfm >> 0) & 0x7f;
1282 sol = (cfm >> 7) & 0x7f;
1283 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1289 # define arg_finish_change(tcp, state) 0
1293 get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1298 ret = upeek (tcp->pid, PT_R11, valp);
1301 (unsigned long) ia64_rse_skip_regs(*state, 0),
1302 sizeof(long), (void *) valp);
1307 get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1312 ret = upeek (tcp->pid, PT_R9, valp);
1315 (unsigned long) ia64_rse_skip_regs(*state, 1),
1316 sizeof(long), (void *) valp);
1322 set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1324 int req = PTRACE_POKEDATA;
1328 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1329 req = PTRACE_POKEUSER;
1331 ap = ia64_rse_skip_regs(*state, 0);
1333 ptrace(req, tcp->pid, ap, val);
1334 return errno ? -1 : 0;
1338 set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1340 int req = PTRACE_POKEDATA;
1344 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1345 req = PTRACE_POKEUSER;
1347 ap = ia64_rse_skip_regs(*state, 1);
1349 ptrace(req, tcp->pid, ap, val);
1350 return errno ? -1 : 0;
1353 #elif defined (SPARC) || defined (SPARC64)
1355 typedef struct regs arg_setup_state;
1357 # define arg_setup(tcp, state) \
1358 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1359 # define arg_finish_change(tcp, state) \
1360 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1362 # define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1363 # define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1364 # define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1365 # define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
1366 # define restore_arg0(tcp, state, val) 0
1370 # if defined S390 || defined S390X
1371 /* Note: this is only true for the `clone' system call, which handles
1372 arguments specially. We could as well say that its first two arguments
1373 are swapped relative to other architectures, but that would just be
1374 another #ifdef in the calls. */
1375 # define arg0_offset PT_GPR3
1376 # define arg1_offset PT_ORIGGPR2
1377 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1378 # define restore_arg1(tcp, state, val) ((void) (state), 0)
1379 # define arg0_index 1
1380 # define arg1_index 0
1381 # elif defined (ALPHA) || defined (MIPS)
1382 # define arg0_offset REG_A0
1383 # define arg1_offset (REG_A0+1)
1384 # elif defined (POWERPC)
1385 # define arg0_offset (sizeof(unsigned long)*PT_R3)
1386 # define arg1_offset (sizeof(unsigned long)*PT_R4)
1387 # define restore_arg0(tcp, state, val) ((void) (state), 0)
1388 # elif defined (HPPA)
1389 # define arg0_offset PT_GR26
1390 # define arg1_offset (PT_GR26-4)
1391 # elif defined (X86_64)
1392 # define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1393 # define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1395 # define arg0_offset (4*(REG_REG0+4))
1396 # define arg1_offset (4*(REG_REG0+5))
1397 # elif defined (SH64)
1398 /* ABI defines arg0 & 1 in r2 & r3 */
1399 # define arg0_offset (REG_OFFSET+16)
1400 # define arg1_offset (REG_OFFSET+24)
1401 # define restore_arg0(tcp, state, val) 0
1403 # define arg0_offset 0
1404 # define arg1_offset 4
1406 # define restore_arg0(tcp, state, val) 0
1410 typedef int arg_setup_state;
1412 # define arg_setup(tcp, state) (0)
1413 # define arg_finish_change(tcp, state) 0
1414 # define get_arg0(tcp, cookie, valp) \
1415 (upeek ((tcp)->pid, arg0_offset, (valp)))
1416 # define get_arg1(tcp, cookie, valp) \
1417 (upeek ((tcp)->pid, arg1_offset, (valp)))
1420 set_arg0 (struct tcb *tcp, void *cookie, long val)
1422 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1426 set_arg1 (struct tcb *tcp, void *cookie, long val)
1428 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1433 #ifndef restore_arg0
1434 # define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1436 #ifndef restore_arg1
1437 # define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1441 # define arg0_index 0
1442 # define arg1_index 1
1449 extern int change_syscall(struct tcb *, int);
1450 arg_setup_state state;
1452 if (tcp->flags & TCB_BPTSET) {
1453 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1457 switch (known_scno(tcp)) {
1464 #if defined SYS_fork || defined SYS_vfork
1465 if (arg_setup (tcp, &state) < 0
1466 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1467 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1468 || change_syscall(tcp, SYS_clone) < 0
1469 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1470 || set_arg1 (tcp, &state, 0) < 0
1471 || arg_finish_change (tcp, &state) < 0)
1473 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1474 tcp->u_arg[arg1_index] = 0;
1475 tcp->flags |= TCB_BPTSET;
1483 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
1484 && (arg_setup (tcp, &state) < 0
1485 || set_arg0 (tcp, &state,
1486 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
1487 || arg_finish_change (tcp, &state) < 0))
1489 tcp->flags |= TCB_BPTSET;
1490 tcp->inst[0] = tcp->u_arg[arg0_index];
1491 tcp->inst[1] = tcp->u_arg[arg1_index];
1495 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1496 tcp->scno, tcp->pid);
1507 arg_setup_state state;
1508 if (arg_setup (tcp, &state) < 0
1509 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1510 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1511 || arg_finish_change (tcp, &state))
1513 tcp->flags &= ~TCB_BPTSET;
1525 #if defined (SPARC) || defined (SPARC64)
1526 /* We simply use the SunOS breakpoint code. */
1530 #define LOOPA 0x30800000 /* ba,a 0 */
1532 if (tcp->flags & TCB_BPTSET) {
1533 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1536 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1537 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1540 tcp->baddr = regs.r_o7 + 8;
1542 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1544 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1549 * XXX - BRUTAL MODE ON
1550 * We cannot set a real BPT in the child, since it will not be
1551 * traced at the moment it will reach the trap and would probably
1552 * die with a core dump.
1553 * Thus, we are force our way in by taking out two instructions
1554 * and insert an eternal loop instead, in expectance of the SIGSTOP
1555 * generated by out PTRACE_ATTACH.
1556 * Of cause, if we evaporate ourselves in the middle of all this...
1560 #if defined (SPARC64)
1562 inst |= (tcp->inst[0] & 0xffffffffUL);
1564 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
1566 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1569 tcp->flags |= TCB_BPTSET;
1571 #else /* !SPARC && !SPARC64 */
1574 # define LOOP 0x0000feeb
1575 if (tcp->flags & TCB_BPTSET) {
1576 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1580 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1583 fprintf(stderr, "[%d] setting bpt at %lx\n",
1584 tcp->pid, tcp->baddr);
1585 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1586 (char *) tcp->baddr, 0);
1588 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1591 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1593 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1596 tcp->flags |= TCB_BPTSET;
1599 * Our strategy here is to replace the bundle that
1600 * contained the clone() syscall with a bundle of the
1603 * { 1: br 1b; br 1b; br 1b }
1605 * This ensures that the newly forked child will loop
1606 * endlessly until we've got a chance to attach to it.
1608 # define LOOP0 0x0000100000000017
1609 # define LOOP1 0x4000000000200000
1610 unsigned long addr, ipsr;
1614 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1616 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1618 /* store "ri" in low two bits */
1619 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
1622 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1624 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1627 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1632 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1633 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1635 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1638 tcp->flags |= TCB_BPTSET;
1642 #if defined (I386) || defined(X86_64)
1643 #define LOOP 0x0000feeb
1644 #elif defined (M68K)
1645 #define LOOP 0x60fe0000
1646 #elif defined (ALPHA)
1647 #define LOOP 0xc3ffffff
1648 #elif defined (POWERPC)
1649 #define LOOP 0x48000000
1651 #define LOOP 0xEAFFFFFE
1653 #define LOOP 0x1000ffff
1655 #define LOOP 0xa7f40000 /* BRC 15,0 */
1656 #elif defined(S390X)
1657 #define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
1659 #define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
1661 #ifdef __LITTLE_ENDIAN__
1662 #define LOOP 0x0000affe
1664 #define LOOP 0xfeaf0000
1667 #error unknown architecture
1670 if (tcp->flags & TCB_BPTSET) {
1671 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1675 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1677 #elif defined (X86_64)
1678 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1680 #elif defined (M68K)
1681 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1683 #elif defined (ALPHA)
1687 #elif defined (MIPS)
1688 return -1; /* FIXME: I do not know what i do - Flo */
1689 #elif defined (POWERPC)
1690 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
1692 #elif defined(S390) || defined(S390X)
1693 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1696 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1698 tcp->baddr &= ~0x03;
1700 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1703 #error unknown architecture
1706 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1707 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1709 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1712 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1714 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1717 tcp->flags |= TCB_BPTSET;
1720 #endif /* SPARC || SPARC64 */
1724 #ifdef SPARC /* This code is slightly sparc specific */
1727 #define BPT 0x91d02001 /* ta 1 */
1728 #define LOOP 0x10800000 /* ba 0 */
1729 #define LOOPA 0x30800000 /* ba,a 0 */
1730 #define NOP 0x01000000
1732 static int loopdeloop[1] = {LOOPA};
1734 static int loopdeloop[2] = {LOOP, NOP};
1737 if (tcp->flags & TCB_BPTSET) {
1738 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1741 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
1742 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1745 tcp->baddr = regs.r_o7 + 8;
1746 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1747 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1748 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1753 * XXX - BRUTAL MODE ON
1754 * We cannot set a real BPT in the child, since it will not be
1755 * traced at the moment it will reach the trap and would probably
1756 * die with a core dump.
1757 * Thus, we are force our way in by taking out two instructions
1758 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1759 * generated by out PTRACE_ATTACH.
1760 * Of cause, if we evaporate ourselves in the middle of all this...
1762 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1763 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1764 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1767 tcp->flags |= TCB_BPTSET;
1781 #if defined(I386) || defined(X86_64)
1783 #elif defined(POWERPC)
1787 #elif defined(ALPHA)
1793 #endif /* architecture */
1795 #if defined (SPARC) || defined (SPARC64)
1796 /* Again, we borrow the SunOS breakpoint code. */
1797 if (!(tcp->flags & TCB_BPTSET)) {
1798 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1802 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1804 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1807 tcp->flags &= ~TCB_BPTSET;
1813 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1814 if (!(tcp->flags & TCB_BPTSET)) {
1815 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1819 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1821 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1824 tcp->flags &= ~TCB_BPTSET;
1826 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1828 if (addr != tcp->baddr) {
1829 /* The breakpoint has not been reached yet. */
1832 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1837 unsigned long addr, ipsr;
1842 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1844 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1847 /* restore original bundle: */
1849 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1850 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1852 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1856 /* restore original "ri" in ipsr: */
1857 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1859 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1861 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1865 tcp->flags &= ~TCB_BPTSET;
1867 if (addr != (tcp->baddr & ~0x3)) {
1868 /* the breakpoint has not been reached yet. */
1870 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1875 #else /* !IA64 && !SPARC && !SPARC64 */
1878 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1879 if (!(tcp->flags & TCB_BPTSET)) {
1880 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1884 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1886 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1889 tcp->flags &= ~TCB_BPTSET;
1892 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1894 if (eip != tcp->baddr) {
1895 /* The breakpoint has not been reached yet. */
1898 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1902 #elif defined(X86_64)
1903 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1905 if (eip != tcp->baddr) {
1906 /* The breakpoint has not been reached yet. */
1909 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1913 #elif defined(POWERPC)
1914 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1916 if (pc != tcp->baddr) {
1917 /* The breakpoint has not been reached yet. */
1919 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1924 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1926 if (pc != tcp->baddr) {
1927 /* The breakpoint has not been reached yet. */
1929 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1933 #elif defined(ALPHA)
1934 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1936 if (pc != tcp->baddr) {
1937 /* The breakpoint has not been reached yet. */
1939 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1944 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1947 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1948 /* The breakpoint has not been reached yet. */
1950 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1954 iaoq = tcp->baddr | 3;
1955 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1956 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1957 * has no significant effect.
1959 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1960 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
1962 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1964 if (pc != tcp->baddr) {
1965 /* The breakpoint has not been reached yet. */
1967 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1973 #endif /* !SPARC && !SPARC64 && !IA64 */
1983 if (!(tcp->flags & TCB_BPTSET)) {
1984 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1987 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1988 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1989 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1992 tcp->flags &= ~TCB_BPTSET;
1996 * Since we don't have a single instruction breakpoint, we may have
1997 * to adjust the program counter after removing the our `breakpoint'.
1999 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
2000 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
2003 if ((regs.r_pc < tcp->baddr) ||
2004 (regs.r_pc > tcp->baddr + 4)) {
2005 /* The breakpoint has not been reached yet */
2008 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
2009 regs.r_pc, tcp->parent->baddr);
2012 if (regs.r_pc != tcp->baddr)
2014 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
2015 regs.r_pc, tcp->baddr);
2017 regs.r_pc = tcp->baddr;
2018 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0) {
2019 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
2031 #endif /* !USE_PROCFS */
2042 for (n = 0; n < sizeof *hdr; n += 4) {
2044 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
2046 memcpy(((char *) hdr) + n, &res, 4);
2049 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2050 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2051 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2052 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2063 * Change `vfork' in a freshly exec'ed dynamically linked
2064 * executable's (internal) symbol table to plain old `fork'
2068 struct link_dynamic dyn;
2069 struct link_dynamic_2 ld;
2072 if (getex(pid, &hdr) < 0)
2077 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2078 fprintf(stderr, "Cannot read DYNAMIC\n");
2081 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2082 fprintf(stderr, "Cannot read link_dynamic_2\n");
2085 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
2086 fprintf(stderr, "out of memory\n");
2089 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2090 (int)ld.ld_symb_size, strtab) < 0)
2094 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2095 fprintf(stderr, "[symbol: %s]\n", cp);
2100 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2101 if (strcmp(cp, "_vfork") == 0) {
2103 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2104 strcpy(cp, "_fork");
2109 if (cp < strtab + ld.ld_symb_size)
2111 * Write entire symbol table back to avoid
2112 * memory alignment bugs in ptrace
2114 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2115 (int)ld.ld_symb_size, strtab) < 0)