#include <sys/utsname.h>
#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
-#if defined(LINUXSPARC)
-
-# define fpq kernel_fpq
-# define fq kernel_fq
-# define fpu kernel_fpu
-# include <asm/reg.h>
-# undef fpq
-# undef fq
-# undef fpu
-
-#if defined (SPARC64)
-# define r_pc r_tpc
+#if defined(LINUXSPARC) && defined (SPARC64)
# undef PTRACE_GETREGS
# define PTRACE_GETREGS PTRACE_GETREGS64
# undef PTRACE_SETREGS
# define PTRACE_SETREGS PTRACE_SETREGS64
-#endif /* SPARC64 */
-
-#if !defined(__GLIBC__)
-
-#include <linux/unistd.h>
-
-#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
- type5,arg5,syscall) \
-type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
-{ \
- long __res; \
-\
-__asm__ volatile ("or %%g0, %1, %%o0\n\t" \
- "or %%g0, %2, %%o1\n\t" \
- "or %%g0, %3, %%o2\n\t" \
- "or %%g0, %4, %%o3\n\t" \
- "or %%g0, %5, %%o4\n\t" \
- "or %%g0, %6, %%g1\n\t" \
-#if defined (SPARC64)
- "t 0x6d\n\t" \
-#else
- "t 0x10\n\t" \
-#endif
- "bcc 1f\n\t" \
- "or %%g0, %%o0, %0\n\t" \
- "sub %%g0, %%o0, %0\n\t" \
- "1:\n\t" \
- : "=r" (__res) \
- : "0" ((long)(arg1)),"1" ((long)(arg2)), \
- "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
- "i" (__NR_##syscall) \
- : "g1", "o0", "o1", "o2", "o3", "o4"); \
-if (__res>=0) \
- return (type) __res; \
-errno = -__res; \
-return -1; \
-}
-
-static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
-
-#define _ptrace
-
-#endif
-
#endif
/* macros */
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
-#if 0
-void
-tv_tv(tv, a, b)
-struct timeval *tv;
-int a;
-int b;
-{
- tv->tv_sec = a;
- tv->tv_usec = b;
-}
-#endif
-
int
tv_nz(a)
struct timeval *a;
}
/*
- * Generic ptrace wrapper which tracks ptrace errors
- * by setting tcp->ptrace_errno.
+ * Generic ptrace wrapper which tracks ESRCH errors
+ * by setting tcp->ptrace_errno to ESRCH.
*
* We assume that ESRCH indicates likely process death (SIGKILL?),
* modulo bugs where process somehow ended up not stopped.
* Unfortunately kernel uses ESRCH for that case too. Oh well.
+ *
+ * Currently used by upeek() only.
+ * TODO: use this in all other ptrace() calls while decoding.
*/
-static const char *
-str_PTRACE_xxx(int request)
-{
- const char *s;
- static char msg[sizeof(int) * 3 + sizeof("PTRACE_<%d>")];
-
- s = xlookup(ptrace_cmds, request);
- if (s)
- return s;
- sprintf(msg, "PTRACE_<%d>", request);
- return msg;
-}
-
long
-do_ptrace(int request, struct tcb *tcp, void *addr, long data)
+do_ptrace(int request, struct tcb *tcp, void *addr, void *data)
{
- int err;
long l;
errno = 0;
- l = ptrace(request, tcp->pid, addr, data);
- err = errno;
- if (err) {
- tcp->ptrace_errno = err;
- if (err != ESRCH) {
- fprintf(stderr, "strace: ptrace(%s,%u,%p,%lu): %s\n",
- str_PTRACE_xxx(request),
- (int) tcp->pid, addr, data, strerror(err));
- errno = err; /* fprintf can clobber it, restore */
- }
- return -1;
- }
+ l = ptrace(request, tcp->pid, addr, (long) data);
+ /* Non-ESRCH errors might be our invalid reg/mem accesses,
+ * we do not record them. */
+ if (errno == ESRCH)
+ tcp->ptrace_errno = ESRCH;
return l;
}
-static long
-do_ptrace_peekdata(struct tcb *tcp, void *addr, int started)
-{
- int err;
- long l;
-
- errno = 0;
- l = ptrace(PTRACE_PEEKDATA, tcp->pid, addr, 0);
- err = errno;
- if (err) {
- if (started && (err == EPERM || err == EIO)) {
- /* Ran into 'end of memory' - not an error.
- * NB: errno is nonzero, caller uses this to detect
- * "end of string" condition.
- */
- return 0;
- }
- /* If error happens at first call, we have a bogus address. */
- if (addr != NULL && err != EIO) {
- if (err != ESRCH) {
- fprintf(stderr, "strace: ptrace(PTRACE_PEEKDATA,%u,%p,0): %s\n",
- (int) tcp->pid, addr, strerror(err));
- errno = err; /* fprintf can clobber it, restore */
- }
- tcp->ptrace_errno = err;
- return -1;
- }
- }
- return l;
-}
-
-#ifdef SUNOS4
-static long
-do_ptrace5(int request, struct tcb *tcp, void *addr, long data, char *data2)
-{
- int err;
- long l;
-
- errno = 0;
- l = ptrace(request, tcp->pid, addr, data, data2);
- err = errno;
- if (err) {
- tcp->ptrace_errno = err;
- if (err != ESRCH) {
- fprintf(stderr, "strace: ptrace(%s,%u,%p,%lu,%p): %s\n",
- str_PTRACE_xxx(request),
- (int) tcp->pid, addr, data, data2, strerror(err));
- errno = err; /* fprintf can clobber it, restore */
- }
- return -1;
- }
- return l;
-}
-#endif
-
/*
* Used when we want to unblock stopped traced process.
* Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
* Otherwise prints error message and returns -1.
*/
int
-ptrace_restart(int request, struct tcb *tcp, int sig)
+ptrace_restart(int op, struct tcb *tcp, int sig)
{
int err;
+ const char *msg;
errno = 0;
- ptrace(request, tcp->pid, (void *) 1, (long) sig);
+ ptrace(op, tcp->pid, (void *) 1, (long) sig);
err = errno;
if (!err || err == ESRCH)
return 0;
tcp->ptrace_errno = err;
- fprintf(stderr, "strace: ptrace(%s,%u,1,%d): %s\n",
- str_PTRACE_xxx(request),
- (int)tcp->pid, sig, strerror(err));
- errno = err; /* fprintf can clobber it, restore */
+ msg = "SYSCALL";
+ if (op == PTRACE_CONT)
+ msg = "CONT";
+ if (op == PTRACE_DETACH)
+ msg = "DETACH";
+ fprintf(stderr, "strace: ptrace(PTRACE_%s,1,%d): %s\n",
+ msg, sig, strerror(err));
return -1;
}
tprintf("%#x /* %s */", val, dflt);
}
+#if HAVE_LONG_LONG
+/*
+ * Print 64bit argument at position llarg and return the index of the next
+ * argument.
+ */
+int
+printllval(struct tcb *tcp, const char *format, int llarg)
+{
+# if defined(FREEBSD) \
+ || (defined(LINUX) && defined(POWERPC) && !defined(POWERPC64)) \
+ || defined (LINUX_MIPSO32)
+ /* Align 64bit argument to 64bit boundary. */
+ if (llarg % 2) llarg++;
+# endif
+# if defined LINUX && (defined X86_64 || defined POWERPC64)
+ if (current_personality == 0) {
+ tprintf(format, tcp->u_arg[llarg]);
+ llarg++;
+ } else {
+# ifdef POWERPC64
+ /* Align 64bit argument to 64bit boundary. */
+ if (llarg % 2) llarg++;
+# endif
+ tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
+ llarg += 2;
+ }
+# elif defined IA64 || defined ALPHA
+ tprintf(format, tcp->u_arg[llarg]);
+ llarg++;
+# elif defined LINUX_MIPSN32
+ tprintf(format, tcp->ext_arg[llarg]);
+ llarg++;
+# else
+ tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
+ llarg += 2;
+# endif
+ return llarg;
+}
+#endif
+
/*
* Interpret `xlat' as an array of flags
* print the entries whose bits are on in `flags'
}
int
-printflags(xlat, flags, dflt)
-const struct xlat *xlat;
-int flags;
-const char *dflt;
+printflags(const struct xlat *xlat, int flags, const char *dflt)
{
int n;
- char *sep;
+ const char *sep;
if (flags == 0 && xlat->val == 0) {
tprintf("%s", xlat->str);
}
void
-printnum(tcp, addr, fmt)
-struct tcb *tcp;
-long addr;
-char *fmt;
+printnum(struct tcb *tcp, long addr, const char *fmt)
{
long num;
}
void
-printnum_int(tcp, addr, fmt)
-struct tcb *tcp;
-long addr;
-char *fmt;
+printnum_int(struct tcb *tcp, long addr, const char *fmt)
{
int num;
tprintf("]");
}
+void
+printfd(struct tcb *tcp, int fd)
+{
+ tprintf("%d", fd);
+}
+
void
printuid(text, uid)
const char *text;
umoven(struct tcb *tcp, long addr, int len, char *laddr)
{
#ifdef LINUX
+ int pid = tcp->pid;
int n, m;
int started = 0;
union {
/* addr not a multiple of sizeof(long) */
n = addr - (addr & -sizeof(long)); /* residue */
addr &= -sizeof(long); /* residue */
- u.val = do_ptrace_peekdata(tcp, (char *) addr, started);
- if (errno)
- return u.val; /* 0 or -1 */
+ errno = 0;
+ u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
+ if (errno) {
+ if (started && (errno==EPERM || errno==EIO)) {
+ /* Ran into 'end of memory' - stupid "printpath" */
+ return 0;
+ }
+ /* But if not started, we had a bogus address. */
+ if (addr != 0 && errno != EIO && errno != ESRCH)
+ perror("ptrace: umoven");
+ return -1;
+ }
started = 1;
memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
addr += sizeof(long), laddr += m, len -= m;
}
while (len) {
- u.val = do_ptrace_peekdata(tcp, (char *) addr, started);
- if (errno)
- return u.val; /* 0 or -1 */
+ errno = 0;
+ u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
+ if (errno) {
+ if (started && (errno==EPERM || errno==EIO)) {
+ /* Ran into 'end of memory' - stupid "printpath" */
+ return 0;
+ }
+ if (addr != 0 && errno != EIO && errno != ESRCH)
+ perror("ptrace: umoven");
+ return -1;
+ }
started = 1;
memcpy(laddr, u.x, m = MIN(sizeof(long), len));
addr += sizeof(long), laddr += m, len -= m;
#ifdef SUNOS4
int pid = tcp->pid;
-#if 0
- int n, m;
- union {
- long val;
- char x[sizeof(long)];
- } u;
-
- if (addr & (sizeof(long) - 1)) {
- /* addr not a multiple of sizeof(long) */
- n = addr - (addr & -sizeof(long)); /* residue */
- addr &= -sizeof(long); /* residue */
- u.val = do_ptrace(PTRACE_PEEKDATA, tcp, (char *) addr, 0);
- if (errno)
- return -1;
- memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
- addr += sizeof(long), laddr += m, len -= m;
- }
- while (len) {
- u.val = do_ptrace(PTRACE_PEEKDATA, tcp, (char *) addr, 0);
- if (errno)
- return -1;
- memcpy(laddr, u.x, m = MIN(sizeof(long), len));
- addr += sizeof(long), laddr += m, len -= m;
- }
-#else /* !oldway */
int n;
while (len) {
n = MIN(len, PAGSIZ);
n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
- if (do_ptrace5(PTRACE_READDATA, tcp, (char *) addr, len, laddr) < 0) {
+ if (ptrace(PTRACE_READDATA, pid,
+ (char *) addr, len, laddr) < 0) {
+ if (errno != ESRCH) {
+ perror("umoven: ptrace(PTRACE_READDATA, ...)");
+ abort();
+ }
return -1;
}
len -= n;
addr += n;
laddr += n;
}
-#endif /* !oldway */
#endif /* SUNOS4 */
#ifdef USE_PROCFS
}
#else /* !USE_PROCFS */
int started = 0;
+ int pid = tcp->pid;
int i, n, m;
union {
long val;
/* addr not a multiple of sizeof(long) */
n = addr - (addr & -sizeof(long)); /* residue */
addr &= -sizeof(long); /* residue */
- u.val = do_ptrace_peekdata(tcp, (char *)addr, started);
- if (errno)
- return u.val; /* 0 or -1 */
+ errno = 0;
+ u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
+ if (errno) {
+ if (started && (errno==EPERM || errno==EIO)) {
+ /* Ran into 'end of memory' - stupid "printpath" */
+ return 0;
+ }
+ if (addr != 0 && errno != EIO && errno != ESRCH)
+ perror("umovestr");
+ return -1;
+ }
started = 1;
memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
while (n & (sizeof(long) - 1))
addr += sizeof(long), laddr += m, len -= m;
}
while (len) {
- u.val = do_ptrace_peekdata(tcp, (char *)addr, started);
- if (errno)
- return u.val; /* 0 or -1 */
+ errno = 0;
+ u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
+ if (errno) {
+ if (started && (errno==EPERM || errno==EIO)) {
+ /* Ran into 'end of memory' - stupid "printpath" */
+ return 0;
+ }
+ if (addr != 0 && errno != EIO && errno != ESRCH)
+ perror("umovestr");
+ return -1;
+ }
started = 1;
memcpy(laddr, u.x, m = MIN(sizeof(long), len));
for (i = 0; i < sizeof(long); i++)
#ifdef SUNOS4
static int
-uload(int cmd, struct tcb *tcp, long addr, int len, char *laddr)
+uload(cmd, pid, addr, len, laddr)
+int cmd;
+int pid;
+long addr;
+int len;
+char *laddr;
{
-# if 0
- int n;
-
- while (len) {
- n = MIN(len, PAGSIZ);
- n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
- if (do_ptrace5(cmd, tcp, (char *)addr, n, laddr) < 0) {
- return -1;
- }
- len -= n;
- addr += n;
- laddr += n;
- }
-# else
int peek, poke;
int n, m;
union {
/* addr not a multiple of sizeof(long) */
n = addr - (addr & -sizeof(long)); /* residue */
addr &= -sizeof(long);
- u.val = do_ptrace(peek, tcp, (char *) addr, 0);
- if (errno)
+ errno = 0;
+ u.val = ptrace(peek, pid, (char *) addr, 0);
+ if (errno) {
+ perror("uload: POKE");
return -1;
- m = MIN(sizeof(long) - n;
- memcpy(&u.x[n], laddr, m, len));
- if (do_ptrace(poke, tcp, (char *)addr, u.val) < 0) {
+ }
+ memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
+ if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
+ perror("uload: POKE");
return -1;
}
- addr += sizeof(long);
- laddr += m;
- len -= m;
+ addr += sizeof(long), laddr += m, len -= m;
}
- errno = 0;
while (len) {
if (len < sizeof(long))
- u.val = do_ptrace(peek, tcp, (char *) addr, 0);
- m = MIN(sizeof(long), len);
- memcpy(u.x, laddr, m);
- if (errno || do_ptrace(poke, tcp, (char *) addr, u.val) < 0) {
+ u.val = ptrace(peek, pid, (char *) addr, 0);
+ memcpy(u.x, laddr, m = MIN(sizeof(long), len));
+ if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
+ perror("uload: POKE");
return -1;
}
- addr += sizeof(long);
- laddr += m;
- len -= m;
+ addr += sizeof(long), laddr += m, len -= m;
}
-# endif
return 0;
}
-static int
-tload(struct tcb *tcp, int addr, int len, char *laddr)
+int
+tload(pid, addr, len, laddr)
+int pid;
+int addr, len;
+char *laddr;
{
- return uload(PTRACE_WRITETEXT, tcp, addr, len, laddr);
+ return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
+}
+
+int
+dload(pid, addr, len, laddr)
+int pid;
+int addr;
+int len;
+char *laddr;
+{
+ return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
}
#endif /* SUNOS4 */
#ifndef USE_PROCFS
int
-upeek(struct tcb *tcp, long off, long *res)
+upeek(tcp, off, res)
+struct tcb *tcp;
+long off;
+long *res;
{
long val;
off += 1024;
}
# endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
+ errno = 0;
val = do_ptrace(PTRACE_PEEKUSER, tcp, (char *) off, 0);
- if (errno)
+ if (val == -1 && errno) {
+ if (errno != ESRCH) {
+ char buf[60];
+ sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)", tcp->pid, off);
+ perror(buf);
+ }
return -1;
+ }
*res = val;
return 0;
}
#endif /* !USE_PROCFS */
-#if 0
-long
-getpc(tcp)
-struct tcb *tcp;
-{
-
-#ifdef LINUX
- long pc;
-# if defined(I386)
- if (upeek(tcp, 4*EIP, &pc) < 0)
- return -1;
-# elif defined(X86_64)
- if (upeek(tcp, 8*RIP, &pc) < 0)
- return -1;
-# elif defined(IA64)
- if (upeek(tcp, PT_B0, &pc) < 0)
- return -1;
-# elif defined(ARM)
- if (upeek(tcp, 4*15, &pc) < 0)
- return -1;
-# elif defined(BFIN)
- if (upeek(tcp, REG_PC, &pc) < 0)
- return -1;
-# elif defined(POWERPC)
- if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0)
- return -1;
-# elif defined(M68K)
- if (upeek(tcp, 4*PT_PC, &pc) < 0)
- return -1;
-# elif defined(ALPHA)
- if (upeek(tcp, REG_PC, &pc) < 0)
- return -1;
-# elif defined(MIPS)
- if (upeek(tcp, REG_EPC, &pc) < 0)
- return -1;
-# elif defined(SPARC) || defined(SPARC64)
- struct regs regs;
- if (do_ptrace(PTRACE_GETREGS, tcp, (char *) ®s, 0) < 0)
- return -1;
- pc = regs.r_pc;
-# elif defined(S390) || defined(S390X)
- if (upeek(tcp, PT_PSWADDR, &pc) < 0)
- return -1;
-# elif defined(HPPA)
- if (upeek(tcp, PT_IAOQ0, &pc) < 0)
- return -1;
-# elif defined(SH)
- if (upeek(tcp, 4*REG_PC, &pc) < 0)
- return -1;
-# elif defined(SH64)
- if (upeek(tcp, REG_PC ,&pc) < 0)
- return -1;
-# endif
- return pc;
-#endif /* LINUX */
-
-#ifdef SUNOS4
- /*
- * Return current program counter for `pid'
- * Assumes PC is never 0xffffffff
- */
- struct regs regs;
-
- if (do_ptrace(PTRACE_GETREGS, tcp, (char *) ®s, 0) < 0)
- return -1;
- return regs.r_pc;
-#endif /* SUNOS4 */
-
-#ifdef SVR4
- /* XXX */
- return 0;
-#endif /* SVR4 */
-
-#ifdef FREEBSD
- struct reg regs;
- pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
- return regs.r_eip;
-#endif /* FREEBSD */
-}
-#endif /* 0 */
-
void
printcall(struct tcb *tcp)
{
# elif defined(S390) || defined(S390X)
long psw;
- if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
+ if(upeek(tcp,PT_PSWADDR,&psw) < 0) {
PRINTBADPC;
return;
}
long pc;
if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
- tprintf ("[????????] ");
+ PRINTBADPC;
return;
}
+# ifdef POWERPC64
+ tprintf("[%016lx] ", pc);
+# else
tprintf("[%08lx] ", pc);
+# endif
# elif defined(M68K)
long pc;
}
tprintf("[%08lx] ", pc);
# elif defined(SPARC) || defined(SPARC64)
- struct regs regs;
- if (do_ptrace(PTRACE_GETREGS, tcp, (char *) ®s, 0) < 0) {
+ struct pt_regs regs;
+ if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0) {
PRINTBADPC;
return;
}
- tprintf("[%08lx] ", regs.r_pc);
+# if defined(SPARC64)
+ tprintf("[%08lx] ", regs.tpc);
+# else
+ tprintf("[%08lx] ", regs.pc);
+# endif
# elif defined(HPPA)
long pc;
- if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
+ if(upeek(tcp,PT_IAOQ0,&pc) < 0) {
tprintf ("[????????] ");
return;
}
return;
}
tprintf("[%08lx] ", pc);
+# elif defined(AVR32)
+ long pc;
+
+ if (upeek(tcp, REG_PC, &pc) < 0) {
+ tprintf("[????????] ");
+ return;
+ }
+ tprintf("[%08lx] ", pc);
# elif defined(BFIN)
long pc;
#elif defined(CRISV10)
long pc;
- if (upeek(tcp->pid, 4*PT_IRP, &pc) < 0) {
+ if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
PRINTBADPC;
return;
}
#elif defined(CRISV32)
long pc;
- if (upeek(tcp->pid, 4*PT_ERP, &pc) < 0) {
+ if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
PRINTBADPC;
return;
}
#ifdef SUNOS4
struct regs regs;
- if (do_ptrace(PTRACE_GETREGS, tcp, (char *) ®s, 0) < 0) {
+ if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
+ perror("printcall: ptrace(PTRACE_GETREGS, ...)");
PRINTBADPC;
return;
}
*/
#ifndef USE_PROCFS
-# if defined LINUX
+#ifdef LINUX
# include "syscall.h"
req = PTRACE_POKEUSER;
} else
ap = ia64_rse_skip_regs(*state, 0);
- if (do_ptrace(req, tcp, ap, val) < 0)
- return -1;
- return 0;
+ errno = 0;
+ ptrace(req, tcp->pid, ap, val);
+ return errno ? -1 : 0;
}
static int
req = PTRACE_POKEUSER;
} else
ap = ia64_rse_skip_regs(*state, 1);
- if (do_ptrace(req, tcp, ap, val) < 0)
- return -1;
- return 0;
+ errno = 0;
+ ptrace(req, tcp->pid, ap, val);
+ return errno ? -1 : 0;
}
/* ia64 does not return the input arguments from functions (and syscalls)
# elif defined (SPARC) || defined (SPARC64)
-typedef struct regs arg_setup_state;
+typedef struct pt_regs arg_setup_state;
# define arg_setup(tcp, state) \
- (do_ptrace(PTRACE_GETREGS, tcp, (char *) (state), 0))
+ (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
# define arg_finish_change(tcp, state) \
- (do_ptrace(PTRACE_SETREGS, tcp, (char *) (state), 0))
+ (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
-# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
-# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
-# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
-# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
+# define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
+# define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
+# define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
+# define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
# define restore_arg0(tcp, state, val) 0
# else /* other architectures */
# elif defined (ALPHA) || defined (MIPS)
# define arg0_offset REG_A0
# define arg1_offset (REG_A0+1)
+# elif defined (AVR32)
+# define arg0_offset (REG_R12)
+# define arg1_offset (REG_R11)
# elif defined (POWERPC)
# define arg0_offset (sizeof(unsigned long)*PT_R3)
# define arg1_offset (sizeof(unsigned long)*PT_R4)
(upeek ((tcp), arg1_offset, (valp)))
static int
-set_arg0(struct tcb *tcp, void *cookie, long val)
+set_arg0 (struct tcb *tcp, void *cookie, long val)
{
- return do_ptrace(PTRACE_POKEUSER, tcp, (char*)arg0_offset, val);
+ return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
}
static int
-set_arg1(struct tcb *tcp, void *cookie, long val)
+set_arg1 (struct tcb *tcp, void *cookie, long val)
{
- return do_ptrace(PTRACE_POKEUSER, tcp, (char*)arg1_offset, val);
+ return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
}
# endif /* architectures */
& ~(tcp->u_arg[arg0_index] & CLONE_VFORK
? CLONE_VFORK | CLONE_VM : 0)) < 0
|| arg_finish_change (tcp, &state) < 0))
- return -1;
+ return -1;
tcp->flags |= TCB_BPTSET;
tcp->inst[0] = tcp->u_arg[arg0_index];
tcp->inst[1] = tcp->u_arg[arg1_index];
|| restore_arg0 (tcp, &state, tcp->inst[0]) < 0
|| restore_arg1 (tcp, &state, tcp->inst[1]) < 0
|| arg_finish_change (tcp, &state))
- return -1;
+ if (errno != ESRCH) return -1;
tcp->flags &= ~TCB_BPTSET;
return 0;
}
setbpt(tcp)
struct tcb *tcp;
{
-# ifdef LINUX
- DEAD CODE HERE? WE ARE IN 'else !defined LINUX'
-# if defined (SPARC) || defined (SPARC64)
- /* We simply use the SunOS breakpoint code. */
-
- struct regs regs;
- unsigned long inst;
-# define LOOPA 0x30800000 /* ba,a 0 */
-
- if (tcp->flags & TCB_BPTSET) {
- fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
- return -1;
- }
- if (do_ptrace(PTRACE_GETREGS, tcp, (char *)®s, 0) < 0) {
- return -1;
- }
- tcp->baddr = regs.r_o7 + 8;
- tcp->inst[0] = do_ptrace(PTRACE_PEEKTEXT, tcp, (char *)tcp->baddr, 0);
- if (errno)
- return -1;
-
- /*
- * XXX - BRUTAL MODE ON
- * We cannot set a real BPT in the child, since it will not be
- * traced at the moment it will reach the trap and would probably
- * die with a core dump.
- * Thus, we are force our way in by taking out two instructions
- * and insert an eternal loop instead, in expectance of the SIGSTOP
- * generated by our PTRACE_ATTACH.
- * Of cause, if we evaporate ourselves in the middle of all this...
- */
- errno = 0;
- inst = LOOPA;
-# if defined (SPARC64)
- inst <<= 32;
- inst |= (tcp->inst[0] & 0xffffffffUL);
-# endif
- if (do_ptrace(PTRACE_POKETEXT, tcp, (char *) tcp->baddr, inst) < 0)
- return -1;
- tcp->flags |= TCB_BPTSET;
-
-# else /* !SPARC && !SPARC64 */
-# ifdef IA64
- if (ia32) {
-# define LOOP 0x0000feeb
- if (tcp->flags & TCB_BPTSET) {
- fprintf(stderr, "PANIC: bpt already set in pid %u\n",
- tcp->pid);
- return -1;
- }
- if (upeek(tcp, PT_CR_IIP, &tcp->baddr) < 0)
- return -1;
- if (debug)
- fprintf(stderr, "[%d] setting bpt at %lx\n",
- tcp->pid, tcp->baddr);
- tcp->inst[0] = do_ptrace(PTRACE_PEEKTEXT, tcp, (char *) tcp->baddr, 0);
- if (errno)
- return -1;
- if (do_ptrace(PTRACE_POKETEXT, tcp, (char *) tcp->baddr, LOOP) < 0)
- return -1;
- tcp->flags |= TCB_BPTSET;
- } else {
- /*
- * Our strategy here is to replace the bundle that
- * contained the clone() syscall with a bundle of the
- * form:
- *
- * { 1: br 1b; br 1b; br 1b }
- *
- * This ensures that the newly forked child will loop
- * endlessly until we've got a chance to attach to it.
- */
-# define LOOP0 0x0000100000000017
-# define LOOP1 0x4000000000200000
- unsigned long addr, ipsr;
- pid_t pid;
-
- pid = tcp->pid;
- if (upeek(tcp, PT_CR_IPSR, &ipsr) < 0)
- return -1;
- if (upeek(tcp, PT_CR_IIP, &addr) < 0)
- return -1;
- /* store "ri" in low two bits */
- tcp->baddr = addr | ((ipsr >> 41) & 0x3);
-
- tcp->inst[0] = do_ptrace(PTRACE_PEEKTEXT, tcp, (char *) addr + 0, 0);
- if (!errno)
- tcp->inst[1] = do_ptrace(PTRACE_PEEKTEXT, tcp, (char *) addr + 8, 0);
- if (errno)
- return -1;
-
- if (do_ptrace(PTRACE_POKETEXT, tcp, (char *) addr + 0, LOOP0) < 0
- || do_ptrace(PTRACE_POKETEXT, tcp, (char *) addr + 8, LOOP1) < 0
- ) {
- return -1;
- }
- tcp->flags |= TCB_BPTSET;
- }
-# else /* !IA64 */
-
-# if defined (I386) || defined(X86_64)
-# define LOOP 0x0000feeb
-# elif defined (M68K)
-# define LOOP 0x60fe0000
-# elif defined (ALPHA)
-# define LOOP 0xc3ffffff
-# elif defined (POWERPC)
-# define LOOP 0x48000000
-# elif defined(ARM)
-# define LOOP 0xEAFFFFFE
-# elif defined(MIPS)
-# define LOOP 0x1000ffff
-# elif defined(S390)
-# define LOOP 0xa7f40000 /* BRC 15,0 */
-# elif defined(S390X)
-# define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
-# elif defined(HPPA)
-# define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
-# elif defined(SH)
-# ifdef __LITTLE_ENDIAN__
-# define LOOP 0x0000affe
-# else
-# define LOOP 0xfeaf0000
-# endif
-# else
-# error unknown architecture
-# endif
-
- if (tcp->flags & TCB_BPTSET) {
- fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
- return -1;
- }
-# if defined (I386)
- if (upeek(tcp, 4*EIP, &tcp->baddr) < 0)
- return -1;
-# elif defined (X86_64)
- if (upeek(tcp, 8*RIP, &tcp->baddr) < 0)
- return -1;
-# elif defined (M68K)
- if (upeek(tcp, 4*PT_PC, &tcp->baddr) < 0)
- return -1;
-# elif defined (ALPHA)
- return -1;
-# elif defined (ARM)
- return -1;
-# elif defined (MIPS)
- return -1; /* FIXME: I do not know what i do - Flo */
-# elif defined (POWERPC)
- if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
- return -1;
-# elif defined(S390) || defined(S390X)
- if (upeek(tcp,PT_PSWADDR, &tcp->baddr) < 0)
- return -1;
-# elif defined(HPPA)
- if (upeek(tcp, PT_IAOQ0, &tcp->baddr) < 0)
- return -1;
- tcp->baddr &= ~0x03;
-# elif defined(SH)
- if (upeek(tcp, 4*REG_PC, &tcp->baddr) < 0)
- return -1;
-# else
-# error unknown architecture
-# endif
- if (debug)
- fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
- tcp->inst[0] = do_ptrace(PTRACE_PEEKTEXT, tcp, (char *) tcp->baddr, 0);
- if (errno)
- return -1;
- if (do_ptrace(PTRACE_POKETEXT, tcp, (char *) tcp->baddr, LOOP) < 0) {
- return -1;
- }
- tcp->flags |= TCB_BPTSET;
-
-# endif /* !IA64 */
-# endif /* !SPARC && !SPARC64 */
-# endif /* LINUX */
-
# ifdef SUNOS4
# ifdef SPARC /* This code is slightly sparc specific */
fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
return -1;
}
- if (do_ptrace(PTRACE_GETREGS, tcp, (char *)®s, 0) < 0) {
+ if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
+ perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
return -1;
}
tcp->baddr = regs.r_o7 + 8;
- if (do_ptrace5(PTRACE_READTEXT, tcp, (char *)tcp->baddr,
- sizeof tcp->inst, (char *)tcp->inst, "READTEXT") < 0) {
+ if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
+ sizeof tcp->inst, (char *)tcp->inst) < 0) {
+ perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
return -1;
}
* generated by out PTRACE_ATTACH.
* Of cause, if we evaporate ourselves in the middle of all this...
*/
- if (do_ptrace5(PTRACE_WRITETEXT, tcp, (char *) tcp->baddr,
+ if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
sizeof loopdeloop, (char *) loopdeloop) < 0) {
+ perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
return -1;
}
tcp->flags |= TCB_BPTSET;
clearbpt(tcp)
struct tcb *tcp;
{
-
-# ifdef LINUX
- DEAD CODE HERE? WE ARE IN 'else !defined LINUX'
-# if defined(I386) || defined(X86_64)
- long eip;
-# elif defined(POWERPC)
- long pc;
-# elif defined(M68K)
- long pc;
-# elif defined(ALPHA)
- long pc;
-# elif defined(HPPA)
- long iaoq;
-# elif defined(SH)
- long pc;
-# endif /* architecture */
-
-# if defined (SPARC) || defined (SPARC64)
- /* Again, we borrow the SunOS breakpoint code. */
- if (!(tcp->flags & TCB_BPTSET)) {
- fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
- return -1;
- }
- if (do_ptrace(PTRACE_POKETEXT, tcp, (char *) tcp->baddr, tcp->inst[0]) < 0) {
- return -1;
- }
- tcp->flags &= ~TCB_BPTSET;
-# elif defined(IA64)
- if (ia32) {
- unsigned long addr;
-
- if (debug)
- fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
- if (!(tcp->flags & TCB_BPTSET)) {
- fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
- return -1;
- }
- if (do_ptrace(PTRACE_POKETEXT, tcp, (char *) tcp->baddr, tcp->inst[0]) < 0) {
- return -1;
- }
- tcp->flags &= ~TCB_BPTSET;
-
- if (upeek(tcp, PT_CR_IIP, &addr) < 0)
- return -1;
- if (addr != tcp->baddr) {
- /* The breakpoint has not been reached yet. */
- if (debug)
- fprintf(stderr,
- "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
- addr, tcp->baddr);
- return 0;
- }
- } else {
- unsigned long addr, ipsr;
- pid_t pid;
-
- pid = tcp->pid;
-
- if (upeek(tcp, PT_CR_IPSR, &ipsr) < 0)
- return -1;
- if (upeek(tcp, PT_CR_IIP, &addr) < 0)
- return -1;
-
- /* restore original bundle: */
- if (do_ptrace(PTRACE_POKETEXT, tcp, (char *) addr + 0, tcp->inst[0]) < 0
- || do_ptrace(PTRACE_POKETEXT, tcp, (char *) addr + 8, tcp->inst[1]) < 0
- ) {
- return -1;
- }
-
- /* restore original "ri" in ipsr: */
- ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
- if (do_ptrace(PTRACE_POKEUSER, tcp, (char *) PT_CR_IPSR, ipsr) < 0) {
- return -1;
- }
-
- tcp->flags &= ~TCB_BPTSET;
-
- if (addr != (tcp->baddr & ~0x3)) {
- /* the breakpoint has not been reached yet. */
- if (debug)
- fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
- addr, tcp->baddr);
- return 0;
- }
- }
-# else /* !IA64 && !SPARC && !SPARC64 */
-
- if (debug)
- fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
- if (!(tcp->flags & TCB_BPTSET)) {
- fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
- return -1;
- }
- if (do_ptrace(PTRACE_POKETEXT, tcp, (char *) tcp->baddr, tcp->inst[0]) < 0) {
- return -1;
- }
- tcp->flags &= ~TCB_BPTSET;
-
-# ifdef I386
- if (upeek(tcp, 4*EIP, &eip) < 0)
- return -1;
- if (eip != tcp->baddr) {
- /* The breakpoint has not been reached yet. */
- if (debug)
- fprintf(stderr,
- "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
- eip, tcp->baddr);
- return 0;
- }
-# elif defined(X86_64)
- if (upeek(tcp, 8*RIP, &eip) < 0)
- return -1;
- if (eip != tcp->baddr) {
- /* The breakpoint has not been reached yet. */
- if (debug)
- fprintf(stderr,
- "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
- eip, tcp->baddr);
- return 0;
- }
-# elif defined(POWERPC)
- if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0)
- return -1;
- if (pc != tcp->baddr) {
- /* The breakpoint has not been reached yet. */
- if (debug)
- fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
- pc, tcp->baddr);
- return 0;
- }
-# elif defined(M68K)
- if (upeek(tcp, 4*PT_PC, &pc) < 0)
- return -1;
- if (pc != tcp->baddr) {
- /* The breakpoint has not been reached yet. */
- if (debug)
- fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
- pc, tcp->baddr);
- return 0;
- }
-# elif defined(ALPHA)
- if (upeek(tcp, REG_PC, &pc) < 0)
- return -1;
- if (pc != tcp->baddr) {
- /* The breakpoint has not been reached yet. */
- if (debug)
- fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
- pc, tcp->baddr);
- return 0;
- }
-# elif defined(HPPA)
- if (upeek(tcp, PT_IAOQ0, &iaoq) < 0)
- return -1;
- iaoq &= ~0x03;
- if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
- /* The breakpoint has not been reached yet. */
- if (debug)
- fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
- iaoq, tcp->baddr);
- return 0;
- }
- iaoq = tcp->baddr | 3;
- /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
- * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
- * has no significant effect.
- */
- if (do_ptrace(PTRACE_POKEUSER, tcp, (void *)PT_IAOQ0, iaoq) < 0
- || do_ptrace(PTRACE_POKEUSER, tcp, (void *)PT_IAOQ1, iaoq) < 0
- ) {
- return -1;
- }
-# elif defined(SH)
- if (upeek(tcp, 4*REG_PC, &pc) < 0)
- return -1;
- if (pc != tcp->baddr) {
- /* The breakpoint has not been reached yet. */
- if (debug)
- fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
- pc, tcp->baddr);
- return 0;
- }
-
-# endif /* arch */
-# endif /* !SPARC && !SPARC64 && !IA64 */
-# endif /* LINUX */
-
# ifdef SUNOS4
# ifdef SPARC
fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
return -1;
}
- if (do_ptrace5(PTRACE_WRITETEXT, tcp, (char *) tcp->baddr,
+ if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
sizeof tcp->inst, (char *) tcp->inst) < 0) {
+ perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
return -1;
}
tcp->flags &= ~TCB_BPTSET;
* Since we don't have a single instruction breakpoint, we may have
* to adjust the program counter after removing our `breakpoint'.
*/
- if (do_ptrace(PTRACE_GETREGS, tcp, (char *)®s, 0) < 0) {
+ if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
+ perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
return -1;
}
- if ((regs.r_pc < tcp->baddr) || (regs.r_pc > tcp->baddr + 4)) {
+ if ((regs.r_pc < tcp->baddr) ||
+ (regs.r_pc > tcp->baddr + 4)) {
/* The breakpoint has not been reached yet */
if (debug)
fprintf(stderr,
regs.r_pc, tcp->baddr);
regs.r_pc = tcp->baddr;
- if (do_ptrace(PTRACE_SETREGS, tcp, (char *)®s, 0) < 0) {
+ if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0) {
+ perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
return -1;
}
# endif /* LOOPA */
fprintf(stderr, "out of memory\n");
return -1;
}
- if (umoven(tcp, (int)ld.ld_symbols + (int)N_TXTADDR(hdr),
+ if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
(int)ld.ld_symb_size, strtab) < 0)
goto err;
-# if 0
- for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
- fprintf(stderr, "[symbol: %s]\n", cp);
- cp += strlen(cp)+1;
- }
- return 0;
-# endif
for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
if (strcmp(cp, "_vfork") == 0) {
if (debug)
* Write entire symbol table back to avoid
* memory alignment bugs in ptrace
*/
- if (tload(tcp, (int)ld.ld_symbols + (int)N_TXTADDR(hdr),
+ if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
(int)ld.ld_symb_size, strtab) < 0)
goto err;