Replace many more bare ptrace calls with calls to wrappers
which do proper error-checking and set tcp->ptrace_errno. In some cases, missing error checking is added. Error handling for trace_syscall() failures and other cases where tcp->ptrace_errno is nonzero is cleaned up a bit and made more verbose if we see error other than ESRC. Some comments are added or expanded. * defs.h: Declare ptrace_cmds[]. Modify do_ptrace declaration (last parameter is long, not void *). * process.c: Make ptrace_cmds[] non-static. (change_syscall): Use do_ptrace() instead of bare ptrace(). * signal.c: Use do_ptrace() instead of bare ptrace(). * strace.c: Update trace_syscall() failure handling. * syscall.c: Use do_ptrace() instead of bare ptrace(). * util.c: Use do_ptrace() instead of bare ptrace(). Update do_ptrace() wrapper. (str_PTRACE_xxx): New function - helper returning "PTRACE_xxx". (do_ptrace_peekdata): New function - wrapper for PTRACE_PEEKDATA (do_ptrace5): New function - wrapper for 5-argument ptrace calls.
This commit is contained in:
parent
c7e837154d
commit
4dedd561d6
22
ChangeLog
22
ChangeLog
@ -1,3 +1,25 @@
|
||||
2009-02-24 Denys Vlasenko <dvlasenk@redhat.com>
|
||||
|
||||
Replace many more bare ptrace calls with calls to wrappers
|
||||
which do proper error-checking and set tcp->ptrace_errno.
|
||||
In some cases, missing error checking is added.
|
||||
Error handling for trace_syscall() failures and other cases
|
||||
where tcp->ptrace_errno is nonzero is cleaned up a bit
|
||||
and made more verbose if we see error other than ESRC.
|
||||
Some comments are added or expanded.
|
||||
* defs.h: Declare ptrace_cmds[]. Modify do_ptrace
|
||||
declaration (last parameter is long, not void *).
|
||||
* process.c: Make ptrace_cmds[] non-static.
|
||||
(change_syscall): Use do_ptrace() instead of bare ptrace().
|
||||
* signal.c: Use do_ptrace() instead of bare ptrace().
|
||||
* strace.c: Update trace_syscall() failure handling.
|
||||
* syscall.c: Use do_ptrace() instead of bare ptrace().
|
||||
* util.c: Use do_ptrace() instead of bare ptrace().
|
||||
Update do_ptrace() wrapper.
|
||||
(str_PTRACE_xxx): New function - helper returning "PTRACE_xxx".
|
||||
(do_ptrace_peekdata): New function - wrapper for PTRACE_PEEKDATA
|
||||
(do_ptrace5): New function - wrapper for 5-argument ptrace calls.
|
||||
|
||||
2009-02-24 Denys Vlasenko <dvlasenk@redhat.com>
|
||||
|
||||
* process.c: Indent preprocessor directives so that nesting
|
||||
|
3
defs.h
3
defs.h
@ -424,6 +424,7 @@ extern const struct xlat open_mode_flags[];
|
||||
extern const struct xlat addrfams[];
|
||||
extern const struct xlat struct_user_offsets[];
|
||||
extern const struct xlat open_access_modes[];
|
||||
extern const struct xlat ptrace_cmds[];
|
||||
|
||||
/* Format of syscall return values */
|
||||
#define RVAL_DECIMAL 000 /* decimal format */
|
||||
@ -485,7 +486,7 @@ extern void set_overhead P((int));
|
||||
extern void qualify P((char *));
|
||||
extern int get_scno P((struct tcb *));
|
||||
extern long known_scno P((struct tcb *));
|
||||
extern long do_ptrace P((int request, struct tcb *tcp, void *addr, void *data));
|
||||
extern long do_ptrace P((int request, struct tcb *tcp, void *addr, long data));
|
||||
extern int ptrace_restart P((int request, struct tcb *tcp, int sig));
|
||||
extern int trace_syscall P((struct tcb *));
|
||||
extern int count_syscall P((struct tcb *, struct timeval *));
|
||||
|
@ -771,7 +771,7 @@ change_syscall(struct tcb *tcp, int new)
|
||||
# define PTRACE_SET_SYSCALL 23
|
||||
# endif
|
||||
|
||||
if (ptrace (PTRACE_SET_SYSCALL, tcp->pid, 0, new) != 0)
|
||||
if (do_ptrace(PTRACE_SET_SYSCALL, tcp, NULL, new) != 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
@ -2276,7 +2276,7 @@ struct tcb *tcp;
|
||||
|
||||
#ifndef SVR4
|
||||
|
||||
static const struct xlat ptrace_cmds[] = {
|
||||
const struct xlat ptrace_cmds[] = {
|
||||
# ifndef FREEBSD
|
||||
{ PTRACE_TRACEME, "PTRACE_TRACEME" },
|
||||
{ PTRACE_PEEKTEXT, "PTRACE_PEEKTEXT", },
|
||||
|
7
signal.c
7
signal.c
@ -1409,14 +1409,13 @@ struct tcb *tcp;
|
||||
struct regs regs;
|
||||
m_siginfo_t si;
|
||||
|
||||
if(ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
|
||||
perror("sigreturn: PTRACE_GETREGS ");
|
||||
if (do_ptrace(PTRACE_GETREGS, tcp, (char *)®s, 0) < 0) {
|
||||
return 0;
|
||||
}
|
||||
if(entering(tcp)) {
|
||||
if (entering(tcp)) {
|
||||
tcp->u_arg[0] = 0;
|
||||
i1 = regs.r_o1;
|
||||
if(umove(tcp, i1, &si) < 0) {
|
||||
if (umove(tcp, i1, &si) < 0) {
|
||||
perror("sigreturn: umove ");
|
||||
return 0;
|
||||
}
|
||||
|
53
strace.c
53
strace.c
@ -2712,27 +2712,28 @@ handle_stopped_tcbs(struct tcb *tcp)
|
||||
/* we handled the STATUS, we are permitted to interrupt now. */
|
||||
if (interrupted)
|
||||
return 0;
|
||||
if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
|
||||
/* ptrace() failed in trace_syscall() with ESRCH.
|
||||
* Likely a result of process disappearing mid-flight.
|
||||
* Observed case: exit_group() terminating
|
||||
* all processes in thread group. In this case, threads
|
||||
* "disappear" in an unpredictable moment without any
|
||||
* notification to strace via wait().
|
||||
if (trace_syscall(tcp) < 0) {
|
||||
/* trace_syscall printed incompletely decoded syscall,
|
||||
* add error indicator.
|
||||
* NB: modulo bugs, errno must be nonzero, do not add
|
||||
* "if (err != 0)", this will hide bugs.
|
||||
*/
|
||||
int err = tcp->ptrace_errno;
|
||||
tcp->ptrace_errno = 0;
|
||||
if (err == ESRCH)
|
||||
tprintf(" <unavailable>");
|
||||
else
|
||||
tprintf(" <ptrace error %d (%s)>", err, strerror(err));
|
||||
printtrailer();
|
||||
if (err == ESRCH)
|
||||
/* Want to get death report anyway. */
|
||||
goto tracing;
|
||||
/* Strange error, we dare not continue. */
|
||||
if (tcp->flags & TCB_ATTACHED) {
|
||||
if (tcp_last) {
|
||||
/* Do we have dangling line "syscall(param, param"?
|
||||
* Finish the line then. We cannot
|
||||
*/
|
||||
tcp_last->flags |= TCB_REPRINT;
|
||||
tprintf(" <unfinished ...>");
|
||||
printtrailer();
|
||||
}
|
||||
detach(tcp, 0);
|
||||
} else {
|
||||
ptrace(PTRACE_KILL,
|
||||
tcp->pid, (char *) 1, SIGTERM);
|
||||
ptrace(PTRACE_KILL, tcp->pid, (char *) 1, SIGTERM);
|
||||
/* [why SIGTERM? why not also kill(SIGKILL)?] */
|
||||
droptcb(tcp);
|
||||
}
|
||||
continue;
|
||||
@ -2838,13 +2839,25 @@ void
|
||||
printleader(struct tcb *tcp)
|
||||
{
|
||||
if (tcp_last) {
|
||||
if (tcp_last->ptrace_errno) {
|
||||
int err = tcp_last->ptrace_errno;
|
||||
if (err) {
|
||||
tcp_last->ptrace_errno = 0;
|
||||
if (tcp_last->flags & TCB_INSYSCALL) {
|
||||
tprintf(" <unavailable ...>\n");
|
||||
if (err == ESRCH)
|
||||
tprintf(" <unavailable ...>\n");
|
||||
else
|
||||
tprintf(" <ptrace error %d (%s) ...>\n", err, strerror(err));
|
||||
tcp_last->flags |= TCB_REPRINT;
|
||||
} else {
|
||||
tprintf("= ? <unavailable>\n");
|
||||
/* Not sure this branch can ever be reached.
|
||||
* Oh well. Using subtly different format
|
||||
* (without "?" after "=") to make it
|
||||
* noticeable (grep for '= <' in straces).
|
||||
*/
|
||||
if (err == ESRCH)
|
||||
tprintf("= <unavailable>\n");
|
||||
else
|
||||
tprintf("= <ptrace error %d (%s)>\n", err, strerror(err));
|
||||
}
|
||||
} else if (!outfname || followfork < 2 || tcp_last == tcp) {
|
||||
tprintf(" <unfinished ...>\n");
|
||||
|
68
syscall.c
68
syscall.c
@ -1103,7 +1103,7 @@ get_scno(struct tcb *tcp)
|
||||
#elif defined (LINUX_MIPSN32)
|
||||
unsigned long long regs[38];
|
||||
|
||||
if (ptrace (PTRACE_GETREGS, tcp->pid, NULL, (long) ®s) < 0)
|
||||
if (do_ptrace(PTRACE_GETREGS, tcp, NULL, (long) ®s) < 0)
|
||||
return -1;
|
||||
a3 = regs[REG_A3];
|
||||
r2 = regs[REG_V0];
|
||||
@ -1351,11 +1351,11 @@ struct tcb *tcp;
|
||||
return scno;
|
||||
}
|
||||
|
||||
/* Called in trace_syscall() at each syscall entry and exit.
|
||||
/* Called in trace_syscall at each syscall entry and exit.
|
||||
* Returns:
|
||||
* 0: "ignore this syscall", bail out of trace_syscall() silently.
|
||||
* 1: ok, continue in trace_syscall().
|
||||
* other: error, trace_syscall() should print error indicator
|
||||
* 0: "ignore this syscall", bail out of trace_syscall silently.
|
||||
* 1: ok, continue in trace_syscall.
|
||||
* other: error, trace_syscall should print error indicator
|
||||
* ("????" etc) and bail out.
|
||||
*/
|
||||
static int
|
||||
@ -1937,10 +1937,11 @@ force_result(tcp, error, rval)
|
||||
#endif /* S390 || S390X */
|
||||
#endif /* LINUX */
|
||||
#ifdef SUNOS4
|
||||
if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_error),
|
||||
error << 24) < 0 ||
|
||||
ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_rval1), rval) < 0)
|
||||
if (do_ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_error), error << 24) < 0
|
||||
|| do_ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_rval1), rval) < 0
|
||||
) {
|
||||
return -1;
|
||||
}
|
||||
#endif /* SUNOS4 */
|
||||
#ifdef SVR4
|
||||
/* XXX no clue */
|
||||
@ -2071,10 +2072,10 @@ struct tcb *tcp;
|
||||
else
|
||||
nargs = tcp->u_nargs = MAX_ARGS;
|
||||
|
||||
if (ptrace (PTRACE_GETREGS, pid, NULL, (long) ®s) < 0)
|
||||
if (do_ptrace(PTRACE_GETREGS, tcp, NULL, (long) ®s) < 0)
|
||||
return -1;
|
||||
|
||||
for(i = 0; i < nargs; i++) {
|
||||
for (i = 0; i < nargs; i++) {
|
||||
tcp->u_arg[i] = regs[REG_A0 + i];
|
||||
# if defined (LINUX_MIPSN32)
|
||||
tcp->ext_arg[i] = regs[REG_A0 + i];
|
||||
@ -2090,17 +2091,17 @@ struct tcb *tcp;
|
||||
nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
|
||||
else
|
||||
nargs = tcp->u_nargs = MAX_ARGS;
|
||||
if(nargs > 4) {
|
||||
if(upeek(tcp, REG_SP, &sp) < 0)
|
||||
if (nargs > 4) {
|
||||
if (upeek(tcp, REG_SP, &sp) < 0)
|
||||
return -1;
|
||||
for(i = 0; i < 4; i++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i])<0)
|
||||
return -1;
|
||||
}
|
||||
umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]),
|
||||
(char *)(tcp->u_arg + 4));
|
||||
} else {
|
||||
for(i = 0; i < nargs; i++) {
|
||||
for (i = 0; i < nargs; i++) {
|
||||
if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
|
||||
return -1;
|
||||
}
|
||||
@ -2349,7 +2350,12 @@ trace_syscall(struct tcb *tcp)
|
||||
if (dtime)
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
/* BTW, why we don't just memorize syscall no. on entry
|
||||
/* In code below,
|
||||
* res = 1: no error, continue
|
||||
* res = 0: return 0 at once (not an error)
|
||||
* any other value: error, complain and return the value
|
||||
*
|
||||
* BTW, why we don't just memorize syscall no. on entry
|
||||
* in tcp->something?
|
||||
*/
|
||||
scno_good = res = get_scno(tcp);
|
||||
@ -2374,14 +2380,15 @@ trace_syscall(struct tcb *tcp)
|
||||
|
||||
if (tcp->flags & TCB_REPRINT) {
|
||||
printleader(tcp);
|
||||
tprintf("<... ");
|
||||
if (scno_good != 1)
|
||||
tprintf("????");
|
||||
else if (tcp->scno >= nsyscalls || tcp->scno < 0)
|
||||
tprintf("syscall_%lu", tcp->scno);
|
||||
else
|
||||
tprintf("%s", sysent[tcp->scno].sys_name);
|
||||
tprintf(" resumed> ");
|
||||
if (scno_good != 1) {
|
||||
tprintf("<... syscall_?? resumed> ");
|
||||
} else {
|
||||
if (tcp->scno >= nsyscalls || tcp->scno < 0)
|
||||
tprintf("<... syscall_%lu resumed> ", tcp->scno);
|
||||
else
|
||||
tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
|
||||
}
|
||||
/* [do we need to clear TCB_REPRINT?...] */
|
||||
}
|
||||
|
||||
if (cflag)
|
||||
@ -2390,8 +2397,8 @@ trace_syscall(struct tcb *tcp)
|
||||
if (res != 1) {
|
||||
tprintf(") ");
|
||||
tabto(acolumn);
|
||||
tprintf("= ? <unavailable>");
|
||||
printtrailer();
|
||||
tprintf("= ?");
|
||||
/* line will be finished by error handling code */
|
||||
tcp->flags &= ~TCB_INSYSCALL;
|
||||
return res;
|
||||
}
|
||||
@ -2514,18 +2521,15 @@ trace_syscall(struct tcb *tcp)
|
||||
|
||||
if (res != 1) {
|
||||
printleader(tcp);
|
||||
tcp->flags &= ~TCB_REPRINT;
|
||||
tcp->flags &= ~TCB_REPRINT; /* why? */
|
||||
tcp_last = tcp;
|
||||
if (scno_good != 1)
|
||||
tprintf("????" /* anti-trigraph gap */ "(");
|
||||
tprintf("syscall_??" /* anti-trigraph gap */ "(");
|
||||
else if (tcp->scno >= nsyscalls || tcp->scno < 0)
|
||||
tprintf("syscall_%lu(", tcp->scno);
|
||||
else
|
||||
tprintf("%s(", sysent[tcp->scno].sys_name);
|
||||
/*
|
||||
* " <unavailable>" will be added later by the code which
|
||||
* detects ptrace errors.
|
||||
*/
|
||||
/* Line will be finished by error handling code. */
|
||||
tcp->flags |= TCB_INSYSCALL;
|
||||
return res;
|
||||
}
|
||||
@ -2679,7 +2683,7 @@ struct tcb *tcp;
|
||||
#ifdef LINUX
|
||||
#if defined (SPARC) || defined (SPARC64)
|
||||
struct regs regs;
|
||||
if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0)
|
||||
if (do_ptrace(PTRACE_GETREGS, tcp, (char *)®s, 0) < 0)
|
||||
return -1;
|
||||
val = regs.r_o1;
|
||||
#elif defined(SH)
|
||||
|
432
util.c
432
util.c
@ -241,30 +241,103 @@ xlookup(const struct xlat *xlat, int val)
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic ptrace wrapper which tracks ESRCH errors
|
||||
* by setting tcp->ptrace_errno to ESRCH.
|
||||
* Generic ptrace wrapper which tracks ptrace errors
|
||||
* by setting tcp->ptrace_errno.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
long
|
||||
do_ptrace(int request, struct tcb *tcp, void *addr, void *data)
|
||||
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)
|
||||
{
|
||||
int err;
|
||||
long l;
|
||||
|
||||
errno = 0;
|
||||
l = ptrace(request, tcp->pid, addr, data);
|
||||
/* Non-ESRCH errors might be our invalid reg/mem accesses,
|
||||
* we do not record them. */
|
||||
if (errno == ESRCH)
|
||||
tcp->ptrace_errno = ESRCH;
|
||||
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;
|
||||
}
|
||||
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.
|
||||
@ -273,25 +346,21 @@ do_ptrace(int request, struct tcb *tcp, void *addr, void *data)
|
||||
* Otherwise prints error message and returns -1.
|
||||
*/
|
||||
int
|
||||
ptrace_restart(int op, struct tcb *tcp, int sig)
|
||||
ptrace_restart(int request, struct tcb *tcp, int sig)
|
||||
{
|
||||
int err;
|
||||
const char *msg;
|
||||
|
||||
errno = 0;
|
||||
ptrace(op, tcp->pid, (void *) 1, (void *) (long) sig);
|
||||
ptrace(request, tcp->pid, (void *) 1, (long) sig);
|
||||
err = errno;
|
||||
if (!err || err == ESRCH)
|
||||
return 0;
|
||||
|
||||
tcp->ptrace_errno = err;
|
||||
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));
|
||||
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 */
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -788,7 +857,6 @@ int
|
||||
umoven(struct tcb *tcp, long addr, int len, char *laddr)
|
||||
{
|
||||
#ifdef LINUX
|
||||
int pid = tcp->pid;
|
||||
int n, m;
|
||||
int started = 0;
|
||||
union {
|
||||
@ -800,34 +868,17 @@ umoven(struct tcb *tcp, long addr, int len, char *laddr)
|
||||
/* addr not a multiple of sizeof(long) */
|
||||
n = addr - (addr & -sizeof(long)); /* residue */
|
||||
addr &= -sizeof(long); /* residue */
|
||||
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;
|
||||
}
|
||||
u.val = do_ptrace_peekdata(tcp, (char *) addr, started);
|
||||
if (errno)
|
||||
return u.val; /* 0 or -1 */
|
||||
started = 1;
|
||||
memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
|
||||
addr += sizeof(long), laddr += m, len -= m;
|
||||
}
|
||||
while (len) {
|
||||
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;
|
||||
}
|
||||
u.val = do_ptrace_peekdata(tcp, (char *) addr, started);
|
||||
if (errno)
|
||||
return u.val; /* 0 or -1 */
|
||||
started = 1;
|
||||
memcpy(laddr, u.x, m = MIN(sizeof(long), len));
|
||||
addr += sizeof(long), laddr += m, len -= m;
|
||||
@ -847,24 +898,16 @@ umoven(struct tcb *tcp, long addr, int len, char *laddr)
|
||||
/* addr not a multiple of sizeof(long) */
|
||||
n = addr - (addr & -sizeof(long)); /* residue */
|
||||
addr &= -sizeof(long); /* residue */
|
||||
errno = 0;
|
||||
u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
|
||||
if (errno) {
|
||||
if (errno != ESRCH)
|
||||
perror("umoven");
|
||||
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) {
|
||||
errno = 0;
|
||||
u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
|
||||
if (errno) {
|
||||
if (errno != ESRCH)
|
||||
perror("umoven");
|
||||
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;
|
||||
}
|
||||
@ -874,12 +917,7 @@ umoven(struct tcb *tcp, long addr, int len, char *laddr)
|
||||
while (len) {
|
||||
n = MIN(len, PAGSIZ);
|
||||
n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
|
||||
if (ptrace(PTRACE_READDATA, pid,
|
||||
(char *) addr, len, laddr) < 0) {
|
||||
if (errno != ESRCH) {
|
||||
perror("umoven: ptrace(PTRACE_READDATA, ...)");
|
||||
abort();
|
||||
}
|
||||
if (do_ptrace5(PTRACE_READDATA, tcp, (char *) addr, len, laddr) < 0) {
|
||||
return -1;
|
||||
}
|
||||
len -= n;
|
||||
@ -941,7 +979,6 @@ umovestr(struct tcb *tcp, long addr, int len, char *laddr)
|
||||
}
|
||||
#else /* !USE_PROCFS */
|
||||
int started = 0;
|
||||
int pid = tcp->pid;
|
||||
int i, n, m;
|
||||
union {
|
||||
long val;
|
||||
@ -952,17 +989,9 @@ umovestr(struct tcb *tcp, long addr, int len, char *laddr)
|
||||
/* addr not a multiple of sizeof(long) */
|
||||
n = addr - (addr & -sizeof(long)); /* residue */
|
||||
addr &= -sizeof(long); /* residue */
|
||||
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;
|
||||
}
|
||||
u.val = do_ptrace_peekdata(tcp, (char *)addr, started);
|
||||
if (errno)
|
||||
return u.val; /* 0 or -1 */
|
||||
started = 1;
|
||||
memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
|
||||
while (n & (sizeof(long) - 1))
|
||||
@ -971,17 +1000,9 @@ umovestr(struct tcb *tcp, long addr, int len, char *laddr)
|
||||
addr += sizeof(long), laddr += m, len -= m;
|
||||
}
|
||||
while (len) {
|
||||
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;
|
||||
}
|
||||
u.val = do_ptrace_peekdata(tcp, (char *)addr, started);
|
||||
if (errno)
|
||||
return u.val; /* 0 or -1 */
|
||||
started = 1;
|
||||
memcpy(laddr, u.x, m = MIN(sizeof(long), len));
|
||||
for (i = 0; i < sizeof(long); i++)
|
||||
@ -1004,12 +1025,7 @@ umovestr(struct tcb *tcp, long addr, int len, char *laddr)
|
||||
#ifdef SUNOS4
|
||||
|
||||
static int
|
||||
uload(cmd, pid, addr, len, laddr)
|
||||
int cmd;
|
||||
int pid;
|
||||
long addr;
|
||||
int len;
|
||||
char *laddr;
|
||||
uload(int cmd, struct tcb *tcp, long addr, int len, char *laddr)
|
||||
{
|
||||
# if 0
|
||||
int n;
|
||||
@ -1017,8 +1033,7 @@ char *laddr;
|
||||
while (len) {
|
||||
n = MIN(len, PAGSIZ);
|
||||
n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
|
||||
if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
|
||||
perror("uload: ptrace(PTRACE_WRITE, ...)");
|
||||
if (do_ptrace5(cmd, tcp, (char *)addr, n, laddr) < 0) {
|
||||
return -1;
|
||||
}
|
||||
len -= n;
|
||||
@ -1045,50 +1060,39 @@ char *laddr;
|
||||
/* addr not a multiple of sizeof(long) */
|
||||
n = addr - (addr & -sizeof(long)); /* residue */
|
||||
addr &= -sizeof(long);
|
||||
errno = 0;
|
||||
u.val = ptrace(peek, pid, (char *) addr, 0);
|
||||
if (errno) {
|
||||
perror("uload: POKE");
|
||||
u.val = do_ptrace(peek, tcp, (char *) addr, 0);
|
||||
if (errno)
|
||||
return -1;
|
||||
m = MIN(sizeof(long) - n;
|
||||
memcpy(&u.x[n], laddr, m, len));
|
||||
if (do_ptrace(poke, tcp, (char *)addr, u.val) < 0) {
|
||||
return -1;
|
||||
}
|
||||
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 = 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");
|
||||
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) {
|
||||
return -1;
|
||||
}
|
||||
addr += sizeof(long), laddr += m, len -= m;
|
||||
addr += sizeof(long);
|
||||
laddr += m;
|
||||
len -= m;
|
||||
}
|
||||
# endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
tload(pid, addr, len, laddr)
|
||||
int pid;
|
||||
int addr, len;
|
||||
char *laddr;
|
||||
static int
|
||||
tload(struct tcb *tcp, int addr, int len, char *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);
|
||||
return uload(PTRACE_WRITETEXT, tcp, addr, len, laddr);
|
||||
}
|
||||
|
||||
#endif /* SUNOS4 */
|
||||
@ -1096,10 +1100,7 @@ char *laddr;
|
||||
#ifndef USE_PROCFS
|
||||
|
||||
int
|
||||
upeek(tcp, off, res)
|
||||
struct tcb *tcp;
|
||||
long off;
|
||||
long *res;
|
||||
upeek(struct tcb *tcp, long off, long *res)
|
||||
{
|
||||
long val;
|
||||
|
||||
@ -1126,16 +1127,9 @@ long *res;
|
||||
off += 1024;
|
||||
}
|
||||
# endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
|
||||
errno = 0;
|
||||
val = do_ptrace(PTRACE_PEEKUSER, tcp, (char *) off, 0);
|
||||
if (val == -1 && errno) {
|
||||
if (errno != ESRCH) {
|
||||
char buf[60];
|
||||
sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)", tcp->pid, off);
|
||||
perror(buf);
|
||||
}
|
||||
if (errno)
|
||||
return -1;
|
||||
}
|
||||
*res = val;
|
||||
return 0;
|
||||
}
|
||||
@ -1179,17 +1173,17 @@ struct tcb *tcp;
|
||||
return -1;
|
||||
# elif defined(SPARC) || defined(SPARC64)
|
||||
struct regs regs;
|
||||
if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0)
|
||||
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)
|
||||
if (upeek(tcp, PT_PSWADDR, &pc) < 0)
|
||||
return -1;
|
||||
# elif defined(HPPA)
|
||||
if(upeek(tcp,PT_IAOQ0,&pc) < 0)
|
||||
if (upeek(tcp, PT_IAOQ0, &pc) < 0)
|
||||
return -1;
|
||||
# elif defined(SH)
|
||||
if (upeek(tcp, 4*REG_PC ,&pc) < 0)
|
||||
if (upeek(tcp, 4*REG_PC, &pc) < 0)
|
||||
return -1;
|
||||
# elif defined(SH64)
|
||||
if (upeek(tcp, REG_PC ,&pc) < 0)
|
||||
@ -1205,10 +1199,8 @@ struct tcb *tcp;
|
||||
*/
|
||||
struct regs regs;
|
||||
|
||||
if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
|
||||
perror("getpc: ptrace(PTRACE_GETREGS, ...)");
|
||||
if (do_ptrace(PTRACE_GETREGS, tcp, (char *) ®s, 0) < 0)
|
||||
return -1;
|
||||
}
|
||||
return regs.r_pc;
|
||||
#endif /* SUNOS4 */
|
||||
|
||||
@ -1245,7 +1237,7 @@ 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;
|
||||
}
|
||||
@ -1297,7 +1289,7 @@ struct tcb *tcp;
|
||||
tprintf("[%08lx] ", pc);
|
||||
# elif defined(SPARC) || defined(SPARC64)
|
||||
struct regs regs;
|
||||
if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0) {
|
||||
if (do_ptrace(PTRACE_GETREGS, tcp, (char *) ®s, 0) < 0) {
|
||||
PRINTBADPC;
|
||||
return;
|
||||
}
|
||||
@ -1305,7 +1297,7 @@ struct tcb *tcp;
|
||||
# elif defined(HPPA)
|
||||
long pc;
|
||||
|
||||
if(upeek(tcp,PT_IAOQ0,&pc) < 0) {
|
||||
if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
|
||||
tprintf ("[????????] ");
|
||||
return;
|
||||
}
|
||||
@ -1356,8 +1348,7 @@ struct tcb *tcp;
|
||||
#ifdef SUNOS4
|
||||
struct regs regs;
|
||||
|
||||
if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) {
|
||||
perror("printcall: ptrace(PTRACE_GETREGS, ...)");
|
||||
if (do_ptrace(PTRACE_GETREGS, tcp, (char *) ®s, 0) < 0) {
|
||||
PRINTBADPC;
|
||||
return;
|
||||
}
|
||||
@ -1478,9 +1469,9 @@ set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
|
||||
req = PTRACE_POKEUSER;
|
||||
} else
|
||||
ap = ia64_rse_skip_regs(*state, 0);
|
||||
errno = 0;
|
||||
ptrace(req, tcp->pid, ap, val);
|
||||
return errno ? -1 : 0;
|
||||
if (do_ptrace(req, tcp, ap, val) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1494,9 +1485,9 @@ set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
|
||||
req = PTRACE_POKEUSER;
|
||||
} else
|
||||
ap = ia64_rse_skip_regs(*state, 1);
|
||||
errno = 0;
|
||||
ptrace(req, tcp->pid, ap, val);
|
||||
return errno ? -1 : 0;
|
||||
if (do_ptrace(req, tcp, ap, val) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ia64 does not return the input arguments from functions (and syscalls)
|
||||
@ -1510,9 +1501,9 @@ set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
|
||||
typedef struct regs arg_setup_state;
|
||||
|
||||
# define arg_setup(tcp, state) \
|
||||
(ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
|
||||
(do_ptrace(PTRACE_GETREGS, tcp, (char *) (state), 0))
|
||||
# define arg_finish_change(tcp, state) \
|
||||
(ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
|
||||
(do_ptrace(PTRACE_SETREGS, tcp, (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)
|
||||
@ -1572,15 +1563,15 @@ typedef int arg_setup_state;
|
||||
(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 ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
|
||||
return do_ptrace(PTRACE_POKEUSER, tcp, (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 ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
|
||||
return do_ptrace(PTRACE_POKEUSER, tcp, (char*)arg1_offset, val);
|
||||
}
|
||||
|
||||
# endif /* architectures */
|
||||
@ -1710,17 +1701,13 @@ struct tcb *tcp;
|
||||
fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
|
||||
return -1;
|
||||
}
|
||||
if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
|
||||
perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
|
||||
if (do_ptrace(PTRACE_GETREGS, tcp, (char *)®s, 0) < 0) {
|
||||
return -1;
|
||||
}
|
||||
tcp->baddr = regs.r_o7 + 8;
|
||||
errno = 0;
|
||||
tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
|
||||
if(errno) {
|
||||
perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
|
||||
tcp->inst[0] = do_ptrace(PTRACE_PEEKTEXT, tcp, (char *)tcp->baddr, 0);
|
||||
if (errno)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX - BRUTAL MODE ON
|
||||
@ -1738,11 +1725,8 @@ struct tcb *tcp;
|
||||
inst <<= 32;
|
||||
inst |= (tcp->inst[0] & 0xffffffffUL);
|
||||
# endif
|
||||
ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
|
||||
if(errno) {
|
||||
perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
|
||||
if (do_ptrace(PTRACE_POKETEXT, tcp, (char *) tcp->baddr, inst) < 0)
|
||||
return -1;
|
||||
}
|
||||
tcp->flags |= TCB_BPTSET;
|
||||
|
||||
# else /* !SPARC && !SPARC64 */
|
||||
@ -1759,17 +1743,11 @@ struct tcb *tcp;
|
||||
if (debug)
|
||||
fprintf(stderr, "[%d] setting bpt at %lx\n",
|
||||
tcp->pid, tcp->baddr);
|
||||
tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
|
||||
(char *) tcp->baddr, 0);
|
||||
if (errno) {
|
||||
perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
|
||||
tcp->inst[0] = do_ptrace(PTRACE_PEEKTEXT, tcp, (char *) tcp->baddr, 0);
|
||||
if (errno)
|
||||
return -1;
|
||||
}
|
||||
ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
|
||||
if (errno) {
|
||||
perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
|
||||
if (do_ptrace(PTRACE_POKETEXT, tcp, (char *) tcp->baddr, LOOP) < 0)
|
||||
return -1;
|
||||
}
|
||||
tcp->flags |= TCB_BPTSET;
|
||||
} else {
|
||||
/*
|
||||
@ -1795,21 +1773,15 @@ struct tcb *tcp;
|
||||
/* store "ri" in low two bits */
|
||||
tcp->baddr = addr | ((ipsr >> 41) & 0x3);
|
||||
|
||||
errno = 0;
|
||||
tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
|
||||
0);
|
||||
tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
|
||||
0);
|
||||
if (errno) {
|
||||
perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
|
||||
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;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
|
||||
ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
|
||||
if (errno) {
|
||||
perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
|
||||
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;
|
||||
@ -1881,14 +1853,10 @@ struct tcb *tcp;
|
||||
# endif
|
||||
if (debug)
|
||||
fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
|
||||
tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
|
||||
if (errno) {
|
||||
perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
|
||||
tcp->inst[0] = do_ptrace(PTRACE_PEEKTEXT, tcp, (char *) tcp->baddr, 0);
|
||||
if (errno)
|
||||
return -1;
|
||||
}
|
||||
ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
|
||||
if (errno) {
|
||||
perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
|
||||
if (do_ptrace(PTRACE_POKETEXT, tcp, (char *) tcp->baddr, LOOP) < 0) {
|
||||
return -1;
|
||||
}
|
||||
tcp->flags |= TCB_BPTSET;
|
||||
@ -1915,14 +1883,12 @@ struct tcb *tcp;
|
||||
fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
|
||||
return -1;
|
||||
}
|
||||
if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
|
||||
perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
|
||||
if (do_ptrace(PTRACE_GETREGS, tcp, (char *)®s, 0) < 0) {
|
||||
return -1;
|
||||
}
|
||||
tcp->baddr = regs.r_o7 + 8;
|
||||
if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
|
||||
sizeof tcp->inst, (char *)tcp->inst) < 0) {
|
||||
perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
|
||||
if (do_ptrace5(PTRACE_READTEXT, tcp, (char *)tcp->baddr,
|
||||
sizeof tcp->inst, (char *)tcp->inst, "READTEXT") < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1936,9 +1902,8 @@ struct tcb *tcp;
|
||||
* generated by out PTRACE_ATTACH.
|
||||
* Of cause, if we evaporate ourselves in the middle of all this...
|
||||
*/
|
||||
if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
|
||||
if (do_ptrace5(PTRACE_WRITETEXT, tcp, (char *) tcp->baddr,
|
||||
sizeof loopdeloop, (char *) loopdeloop) < 0) {
|
||||
perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
|
||||
return -1;
|
||||
}
|
||||
tcp->flags |= TCB_BPTSET;
|
||||
@ -1976,10 +1941,7 @@ struct tcb *tcp;
|
||||
fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
|
||||
return -1;
|
||||
}
|
||||
errno = 0;
|
||||
ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
|
||||
if(errno) {
|
||||
perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
|
||||
if (do_ptrace(PTRACE_POKETEXT, tcp, (char *) tcp->baddr, tcp->inst[0]) < 0) {
|
||||
return -1;
|
||||
}
|
||||
tcp->flags &= ~TCB_BPTSET;
|
||||
@ -1993,10 +1955,7 @@ struct tcb *tcp;
|
||||
fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
|
||||
return -1;
|
||||
}
|
||||
errno = 0;
|
||||
ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
|
||||
if (errno) {
|
||||
perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
|
||||
if (do_ptrace(PTRACE_POKETEXT, tcp, (char *) tcp->baddr, tcp->inst[0]) < 0) {
|
||||
return -1;
|
||||
}
|
||||
tcp->flags &= ~TCB_BPTSET;
|
||||
@ -2023,20 +1982,15 @@ struct tcb *tcp;
|
||||
return -1;
|
||||
|
||||
/* restore original bundle: */
|
||||
errno = 0;
|
||||
ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
|
||||
ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
|
||||
if (errno) {
|
||||
perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
|
||||
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);
|
||||
errno = 0;
|
||||
ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
|
||||
if (errno) {
|
||||
perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
|
||||
if (do_ptrace(PTRACE_POKEUSER, tcp, (char *) PT_CR_IPSR, ipsr) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -2058,10 +2012,7 @@ struct tcb *tcp;
|
||||
fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
|
||||
return -1;
|
||||
}
|
||||
errno = 0;
|
||||
ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
|
||||
if (errno) {
|
||||
perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
|
||||
if (do_ptrace(PTRACE_POKETEXT, tcp, (char *) tcp->baddr, tcp->inst[0]) < 0) {
|
||||
return -1;
|
||||
}
|
||||
tcp->flags &= ~TCB_BPTSET;
|
||||
@ -2134,8 +2085,11 @@ struct tcb *tcp;
|
||||
* safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
|
||||
* has no significant effect.
|
||||
*/
|
||||
ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
|
||||
ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
|
||||
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;
|
||||
@ -2162,9 +2116,8 @@ struct tcb *tcp;
|
||||
fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
|
||||
return -1;
|
||||
}
|
||||
if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
|
||||
if (do_ptrace5(PTRACE_WRITETEXT, tcp, (char *) tcp->baddr,
|
||||
sizeof tcp->inst, (char *) tcp->inst) < 0) {
|
||||
perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
|
||||
return -1;
|
||||
}
|
||||
tcp->flags &= ~TCB_BPTSET;
|
||||
@ -2174,12 +2127,10 @@ struct tcb *tcp;
|
||||
* Since we don't have a single instruction breakpoint, we may have
|
||||
* to adjust the program counter after removing our `breakpoint'.
|
||||
*/
|
||||
if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) {
|
||||
perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
|
||||
if (do_ptrace(PTRACE_GETREGS, tcp, (char *)®s, 0) < 0) {
|
||||
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,
|
||||
@ -2193,8 +2144,7 @@ struct tcb *tcp;
|
||||
regs.r_pc, tcp->baddr);
|
||||
|
||||
regs.r_pc = tcp->baddr;
|
||||
if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0) {
|
||||
perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
|
||||
if (do_ptrace(PTRACE_SETREGS, tcp, (char *)®s, 0) < 0) {
|
||||
return -1;
|
||||
}
|
||||
# endif /* LOOPA */
|
||||
@ -2265,7 +2215,7 @@ struct tcb *tcp;
|
||||
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;
|
||||
|
||||
@ -2290,7 +2240,7 @@ struct tcb *tcp;
|
||||
* Write entire symbol table back to avoid
|
||||
* memory alignment bugs in ptrace
|
||||
*/
|
||||
if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
|
||||
if (tload(tcp, (int)ld.ld_symbols + (int)N_TXTADDR(hdr),
|
||||
(int)ld.ld_symb_size, strtab) < 0)
|
||||
goto err;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user