summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2009-06-02 16:49:22 -0700
committerRoland McGrath <roland@redhat.com>2009-06-02 16:49:22 -0700
commiteb9e2e8904ce85a6c7390be25bb873c6db88c4d3 (patch)
tree4e967c58b6d1ff962835d0dd034ba1d1214268b4
parent4ac9d627f4b8d2022958668e5c2f3b784605cb16 (diff)
downloadstrace-eb9e2e8904ce85a6c7390be25bb873c6db88c4d3.tar.gz
strace-eb9e2e8904ce85a6c7390be25bb873c6db88c4d3.tar.bz2
strace-eb9e2e8904ce85a6c7390be25bb873c6db88c4d3.tar.xz
Revert unapproved commits.
-rw-r--r--ChangeLog136
-rw-r--r--defs.h21
-rw-r--r--desc.c2
-rw-r--r--process.c63
-rw-r--r--signal.c7
-rw-r--r--strace.c384
-rw-r--r--svr4/syscallent.h2
-rw-r--r--syscall.c132
-rw-r--r--test/childthread.c2
-rw-r--r--test/leaderkill.c2
-rw-r--r--test/many_looping_threads.c39
-rw-r--r--util.c428
12 files changed, 418 insertions, 800 deletions
diff --git a/ChangeLog b/ChangeLog
index cea9670..29e42db 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,5 @@
2009-06-01 Dmitry V. Levin <ldv@altlinux.org>
- * strace.c (handle_stopped_tcbs): Fix cast for 4th argument
- passed to ptrace().
-
* bjm.c (sys_query_module): Fix format warning reported by
gcc -Wformat-security.
* file.c (tprint_open_modes): Likewise.
@@ -24,11 +21,6 @@
Move NULL/error check for addr parameter
so that it happens before printstatsol/printstat_sparc64 calls.
-2009-04-20 Denys Vlasenko <dvlasenk@redhat.com>
-
- * strace.c (collect_stopped_tcbs): Do not enable/disable signals
- multiple times, do it just once per collecting pass.
-
2009-04-16 Denys Vlasenko <dvlasenk@redhat.com>
* file.c (print_dirfd): Use int for file descriptor, not a long.
@@ -62,12 +54,6 @@
* net.c (printcmsghdr): Fix improperly used %zu:
struct cmsghdr::cmsg_len is not a size_t.
-2009-03-17 Denys Vlasenko <dvlasenk@redhat.com>
-
- * strace.c (collect_stopped_tcbs): Check for ^C here too,
- not only in trace().
- (trace): Tweak check for ^C to not set mask (not needed).
-
2009-03-10 Denys Vlasenko <dvlasenk@redhat.com>
Decode fcntl's F_{GET,SET}LEASE, F_NOTIFY, and F_DUPFD_CLOEXEC.
@@ -117,28 +103,6 @@
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 ESRCH.
- 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
can be figured out. Add PTRACE_SET_SYSCALL to ptrace_cmds[].
* ioctlent.sh: Improved by Mike Frysinger.
@@ -192,17 +156,6 @@
[HAVE_STRUCT_SIGCONTEXT].
From Muttley Meen <muttley.meen@gmail.com>.
-2009-02-10 Denys Vlasenko <dvlasenk@redhat.com>
-
- Cleanup after tcb table expansion simplification.
- There was code which was trying to continue tracing
- even if table expansion fails. Now we treat it as fatal
- failure, so this code is removed by this change.
- * defs.h: Delete TCB_FOLLOWFORK constant.
- * process.c: Delete fork_tcb() and all calls of it.
- * strace.c (startup_attach): Remove usage of TCB_FOLLOWFORK.
- * syscall.c: Indent preprocessor directives.
-
2009-02-09 Denys Vlasenko <dvlasenk@redhat.com>
* defs.h: Correct the comment about TCB_SUSPENDED.
@@ -221,20 +174,6 @@
right before its death, it can legitimately happen.
(handle_stopped_tcbs): Ditto.
-2009-01-28 Denys Vlasenko <dvlasenk@redhat.com>
-
- * process.c (internal_clone): Check and complain if pid value
- looks insane.
- * strace.c (alloc_tcb): Clear *all* fields in reused tcb.
- (main): Query and remember uname() info on startup.
- (handle_stopped_tcbs): Do not use PTRACE_SETOPTIONS on Linux < 2.6.29.
- (printleader): Correct printing of "<unavailable>" markers.
-
-2009-01-27 Denys Vlasenko <dvlasenk@redhat.com>
-
- * strace.c (collect_stopped_tcbs): Guard against the case when
- waitpid() reports the same task multiple times.
-
2009-01-26 Denys Vlasenko <dvlasenk@redhat.com>
* process.c (printwaitn): Add comment about wait4() pid expansion.
@@ -259,12 +198,6 @@
Format '%#08lx' expects type 'long unsigned int', but
argument 2 was type 'unsigned int'.
-2009-01-21 Denys Vlasenko <dvlasenk@redhat.com>
-
- * strace.c (collect_stopped_tcbs): Do not return NULL when ECHILD
- is detected, return collected list instead. Fixes symptom when
- the last "+++ killed by SIGxxx +++" is not printed.
-
2009-01-17 Denys Vlasenko <dvlasenk@redhat.com>
Two cleanups: tcb table expansion failure is not really a survivable
@@ -287,28 +220,6 @@
(alloc_tcb): On failure to expand, print a message, clean up, and exit.
* util.c (setbpt): Remove extern declaration from function body.
-2009-01-17 Denys Vlasenko <dvlasenk@redhat.com>
-
- * defs.h: Update a comment. No code changes.
- * strace.c (handle_stopped_tcbs): Discard all execve stops
- and clear TCB_WAITEXECVE bit.
- * syscall.c (get_scno): Add the code to not mistakenly
- treat ptrace stop as execve stop (execve stops can be blocked
- by traced program).
- Fixes RH#477775 "strace hangs if the target process blocks SIGTRAP".
-
-2009-01-17 Denys Vlasenko <dvlasenk@redhat.com>
-
- * process.c: Add a comment. No code changes.
- * strace.c (collect_stopped_tcbs): Stop reversing list of stopped
- tcp's. I'm not totally convinced it is crucial, but this is surely
- fits the concept of "least surprise".
- Do not collect TCB_SUSPENDED tcp's (this is closer to how
- it was before).
- (handle_stopped_tcbs): Remove the code to reject TCB_SUSPENDED tcp's,
- it's done earlier now. In an unobvious way, this was causing
- SIGSTOPs from freshly attached children to be misinterpreted.
-
2009-01-14 Denys Vlasenko <dvlasenk@redhat.com>
* linux/bfin/syscallent.h: sys_futex has 6 parameters, not 5.
@@ -318,8 +229,6 @@
Fixes for ptrace() argument parsing.
* process.c: Add parsing of PTRACE_SETOPTIONS, PTRACE_GETEVENTMSG,
PTRACE_GETSIGINFO, PTRACE_SETSIGINFO.
- * strace.c (handle_stopped_tcbs): Make PTRACE_SETOPTIONS
- define check more robust.
* defs.h: Declare several "extern const struct xlat" arrays here.
* desc.c: Remove open_mode_flags[] and open_access_modes[]
extern declarations.
@@ -328,19 +237,6 @@
* util.c: Remove struct_user_offsets[] extern declaration.
* signal.c: Remove open_mode_flags[] extern declaration.
-2009-01-09 Denys Vlasenko <dvlasenk@redhat.com>
-
- * defs.h: Add new struct tcb fields: wait_status, next_need_service.
- make flags field wider (ints are easier to work with on many CPUs).
- * strace.c (trace): Split this function into two:
- collect_stopped_tcbs() and handle_stopped_tcbs().
- Now we collect *all* waitable tasks, then handle them all,
- then repeat.
- Fixes RH#478419 "Some threads stop when strace with -f option
- is executed on a multi-thread process"
- * test/many_looping_threads.c: example program which cna't be straced
- successfully without this fix.
-
2009-01-06 Denys Vlasenko <dvlasenk@redhat.com>
Output format fixes, improving the situation after recent
@@ -374,15 +270,6 @@
convert all remaining old style C parameter declarations
in this file.
-2009-01-02 Denys Vlasenko <dvlasenk@redhat.com>
-
- * strace.c: Fix compile failure: on some systems PTRACE_O_xxx
- and PTRACE_EVENT_xxx constants are not defined because
- those system have old kernel headers.
- OTOH, if PT_SETOPTIONS is not defined too,
- I don't risk using ptrace options, the kernel is too old.
- I've seen problems on RHEL4 ia64 when I tried to.
-
2008-11-13 Kirill A. Shutemov <kirill@shutemov.name>
* linux/arm/syscallent.h: Update syscalls.
@@ -428,29 +315,6 @@
* linux/syscallent.h: Mark sendfile(2) as network syscall.
* linux/*/syscallent.h: Same, for all architectures.
-2008-12-29 Denys Vlasenko <dvlasenk@redhat.com>
-
- * defs.h: Remove sigtrap80 field from struct tcb.
- * strace.c: Add ptrace_stop_sig static variable
- and use it in place of tcp->sigtrap80.
- Add ptrace_opts_set static flag variable.
- (trace): Set ptrace options once, not per-process.
- If unexpected SIGTRAP is later received,
- revert back to using SIGTRAP
- (assume old, broken kernel).
-
-2008-12-22 Denys Vlasenko <dvlasenk@redhat.com>
-
- Make strace correctly handle SIGTRAP produced by e.g.
- kill(2) and by trapping instruction.
- * defs.h: Add sigtrap80 field to struct tcb.
- * strace.c (alloc_tcb): Initialize it to SIGTRAP.
- (detach): Use tcp->sigtrap80 instead of SIGTRAP constant.
- (trace): Attempt to set PTRACE_O_TRACESYSGOOD and
- PTRACE_O_TRACEEXEC options on each newly attached process,
- distinquish between SIGTRAP and (SIGTRAP | 0x80) stops.
- Fixes RH#162774 "strace ignores int3 SIGTRAP".
-
2008-12-17 Denys Vlasenko <dvlasenk@redhat.com>
Make strace detect when traced process suddenly disappeared
diff --git a/defs.h b/defs.h
index 2f5683b..769ed22 100644
--- a/defs.h
+++ b/defs.h
@@ -298,11 +298,8 @@ extern int mp_ioctl (int f, int c, void *a, int s);
/* Trace Control Block */
struct tcb {
- int flags; /* See below for TCB_ values */
+ short flags; /* See below for TCB_ values */
int pid; /* Process Id of this entry */
- int wait_status; /* Status from last wait() */
- struct tcb *next_need_service;
- /* Linked list of tracees found by wait()s */
long scno; /* System call number */
int u_nargs; /* System call arguments */
long u_arg[MAX_ARGS]; /* System call arguments */
@@ -328,8 +325,8 @@ struct tcb {
int nclone_threads; /* # of nchildren with CLONE_THREAD */
int nclone_detached; /* # of nchildren with CLONE_DETACHED */
int nclone_waiting; /* clone threads in wait4 (TCB_SUSPENDED) */
- /* (1st arg of wait4()) */
#endif
+ /* (1st arg of wait4()) */
long baddr; /* `Breakpoint' address */
long inst[2]; /* Instructions on above */
int pfd; /* proc file descriptor */
@@ -359,19 +356,12 @@ struct tcb {
#define TCB_SUSPENDED 00040 /* Process can not be allowed to resume just now */
#define TCB_BPTSET 00100 /* "Breakpoint" set after fork(2) */
#define TCB_SIGTRAPPED 00200 /* Process wanted to block SIGTRAP */
+#define TCB_FOLLOWFORK 00400 /* Process should have forks followed */
#define TCB_REPRINT 01000 /* We should reprint this syscall on exit */
#ifdef LINUX
-/* TCB_WAITEXECVE bit means "ignore next SIGTRAP, it's execve exit stop".
- * it is not reliable if traced program masks SIGTRAP.
- *
- * x86 does not need TCB_WAITEXECVE.
+/* x86 does not need TCB_WAITEXECVE.
* It can detect execve's SIGTRAP by looking at eax/rax.
* See "stray syscall exit: eax = " message in syscall_fixup().
- *
- * Note that on newer kernels, we use ptrace options and therefore
- * can filter out execve stops reliably on any architecture,
- * without using TCB_WAITEXECVE flag.
- * I guess we can remove it from the source somewhere around year 2010 :)
*/
# if defined(ALPHA) || defined(AVR32) || defined(SPARC) || defined(SPARC64) \
|| defined(POWERPC) || defined(IA64) || defined(HPPA) \
@@ -430,7 +420,6 @@ 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 */
@@ -492,7 +481,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, long data));
+extern long do_ptrace P((int request, struct tcb *tcp, void *addr, void *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 *));
diff --git a/desc.c b/desc.c
index 383107e..e01b9ac 100644
--- a/desc.c
+++ b/desc.c
@@ -872,7 +872,7 @@ sys_io_cancel(struct tcb *tcp)
tprintf("{%p, %p, %ld, %ld}",
event.data, event.obj,
event.res, event.res2);
- else
+ else
#endif
tprintf("{...}");
}
diff --git a/process.c b/process.c
index 5119ede..afd36bb 100644
--- a/process.c
+++ b/process.c
@@ -484,6 +484,18 @@ struct tcb *tcp;
return 0;
}
+/* TCP is creating a child we want to follow.
+ If there will be space in tcbtab for it, set TCB_FOLLOWFORK and return 0.
+ If not, clear TCB_FOLLOWFORK, print an error, and return 1. */
+static void
+fork_tcb(struct tcb *tcp)
+{
+ if (nprocs == tcbtabsize)
+ expand_tcbtab();
+
+ tcp->flags |= TCB_FOLLOWFORK;
+}
+
#ifdef USE_PROCFS
int
@@ -533,6 +545,7 @@ struct tcb *tcp;
return 0;
if (!followfork)
return 0;
+ fork_tcb(tcp);
if (syserror(tcp))
return 0;
tcpchild = alloctcb(tcp->u_rval);
@@ -779,7 +792,7 @@ change_syscall(struct tcb *tcp, int new)
# define PTRACE_SET_SYSCALL 23
# endif
- if (do_ptrace(PTRACE_SET_SYSCALL, tcp, NULL, new) != 0)
+ if (ptrace (PTRACE_SET_SYSCALL, tcp->pid, 0, new) != 0)
return -1;
return 0;
@@ -899,18 +912,22 @@ setarg(tcp, argnum)
#if defined SYS_clone || defined SYS_clone2
int
-internal_clone(struct tcb *tcp)
+internal_clone(tcp)
+struct tcb *tcp;
{
struct tcb *tcpchild;
- int pid, bpt;
-
- if (!followfork)
- return 0;
+ int pid;
if (entering(tcp)) {
- setbpt(tcp);
- return 0;
+ if (!followfork)
+ return 0;
+ fork_tcb(tcp);
+ if (setbpt(tcp) < 0)
+ return 0;
} else {
- bpt = tcp->flags & TCB_BPTSET;
+ int bpt = tcp->flags & TCB_BPTSET;
+
+ if (!(tcp->flags & TCB_FOLLOWFORK))
+ return 0;
if (syserror(tcp)) {
if (bpt)
@@ -919,15 +936,6 @@ internal_clone(struct tcb *tcp)
}
pid = tcp->u_rval;
- /* Should not happen, but bugs often cause bogus value here. */
- if (pid <= 1
- || (sizeof(pid) != sizeof(tcp->u_rval) && pid != tcp->u_rval)
- ) {
- if (bpt)
- clearbpt(tcp);
- fprintf(stderr, "bogus clone() return value %lx!\n", tcp->u_rval);
- return 0;
- }
#ifdef CLONE_PTRACE /* See new setbpt code. */
tcpchild = pid2tcb(pid);
@@ -944,6 +952,7 @@ internal_clone(struct tcb *tcp)
else
#endif
{
+ fork_tcb(tcp);
tcpchild = alloctcb(pid);
}
@@ -979,9 +988,6 @@ internal_clone(struct tcb *tcp)
clearbpt(tcpchild);
tcpchild->flags &= ~(TCB_SUSPENDED|TCB_STARTUP);
- /* TCB_SUSPENDED tasks are not collected by waitpid
- * loop, and left stopped. Restart it:
- */
if (ptrace_restart(PTRACE_SYSCALL, tcpchild, 0) < 0)
return -1;
@@ -1045,25 +1051,27 @@ struct tcb *tcp;
struct tcb *tcpchild;
int pid;
- int follow = 1;
+ int dont_follow = 0;
#ifdef SYS_vfork
if (known_scno(tcp) == SYS_vfork) {
/* Attempt to make vfork into fork, which we can follow. */
if (change_syscall(tcp, SYS_fork) < 0)
- follow = 0;
+ dont_follow = 1;
}
#endif
- if (!followfork || !follow)
- return 0;
-
if (entering(tcp)) {
+ if (!followfork || dont_follow)
+ return 0;
+ fork_tcb(tcp);
if (setbpt(tcp) < 0)
return 0;
}
else {
int bpt = tcp->flags & TCB_BPTSET;
+ if (!(tcp->flags & TCB_FOLLOWFORK))
+ return 0;
if (bpt)
clearbpt(tcp);
@@ -1071,6 +1079,7 @@ struct tcb *tcp;
return 0;
pid = tcp->u_rval;
+ fork_tcb(tcp);
tcpchild = alloctcb(pid);
#ifdef LINUX
#ifdef HPPA
@@ -2313,7 +2322,7 @@ struct tcb *tcp;
#ifndef SVR4
-const struct xlat ptrace_cmds[] = {
+static const struct xlat ptrace_cmds[] = {
# ifndef FREEBSD
{ PTRACE_TRACEME, "PTRACE_TRACEME" },
{ PTRACE_PEEKTEXT, "PTRACE_PEEKTEXT", },
diff --git a/signal.c b/signal.c
index 3203657..76504f6 100644
--- a/signal.c
+++ b/signal.c
@@ -1403,13 +1403,14 @@ sys_sigreturn(struct tcb *tcp)
struct regs regs;
m_siginfo_t si;
- if (do_ptrace(PTRACE_GETREGS, tcp, (char *)&regs, 0) < 0) {
+ if(ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
+ perror("sigreturn: PTRACE_GETREGS ");
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;
}
diff --git a/strace.c b/strace.c
index d351dc5..da8cc4a 100644
--- a/strace.c
+++ b/strace.c
@@ -40,7 +40,6 @@
#include <sys/resource.h>
#include <sys/wait.h>
#include <sys/stat.h>
-#include <sys/utsname.h>
#include <pwd.h>
#include <grp.h>
#include <string.h>
@@ -100,17 +99,12 @@ static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
*/
static bool daemonized_tracer = 0;
-static struct utsname utsname_buf;
-
/* Sometimes we want to print only succeeding syscalls. */
int not_failing_only = 0;
static int exit_code = 0;
static int strace_child = 0;
-static int ptrace_stop_sig = SIGTRAP;
-#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
-static bool ptrace_opts_set;
-#endif
+
static char *username = NULL;
uid_t run_uid;
gid_t run_gid;
@@ -122,6 +116,7 @@ FILE *outf;
struct tcb **tcbtab;
unsigned int nprocs, tcbtabsize;
char *progname;
+extern char **environ;
static int detach P((struct tcb *tcp, int sig));
static int trace P((void));
@@ -441,7 +436,7 @@ startup_attach(void)
++nerr;
else if (tid != tcbtab[tcbi]->pid) {
tcp = alloctcb(tid);
- tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED;
+ tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
tcbtab[tcbi]->nchildren++;
tcbtab[tcbi]->nclone_threads++;
tcbtab[tcbi]->nclone_detached++;
@@ -694,8 +689,6 @@ main(int argc, char *argv[])
progname = argv[0] ? argv[0] : "strace";
- uname(&utsname_buf);
-
/* Allocate the initial tcbtab. */
tcbtabsize = argc; /* Surely enough for all -p args. */
if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
@@ -1002,10 +995,18 @@ alloc_tcb(int pid, int command_options_parsed)
for (i = 0; i < tcbtabsize; i++) {
tcp = tcbtab[i];
if ((tcp->flags & TCB_INUSE) == 0) {
- memset(tcp, 0, sizeof(*tcp));
tcp->pid = pid;
+ tcp->parent = NULL;
+ tcp->nchildren = 0;
+ tcp->nzombies = 0;
+#ifdef TCB_CLONE_THREAD
+ tcp->nclone_threads = tcp->nclone_detached = 0;
+ tcp->nclone_waiting = 0;
+#endif
tcp->flags = TCB_INUSE | TCB_STARTUP;
tcp->outf = outf; /* Initialise to current out file */
+ tcp->stime.tv_sec = 0;
+ tcp->stime.tv_usec = 0;
tcp->pfd = -1;
nprocs++;
if (command_options_parsed)
@@ -1608,7 +1609,7 @@ int sig;
break;
}
error = ptrace_restart(PTRACE_CONT, tcp,
- WSTOPSIG(status) == ptrace_stop_sig ? 0
+ WSTOPSIG(status) == SIGTRAP ? 0
: WSTOPSIG(status));
if (error < 0)
break;
@@ -2249,88 +2250,60 @@ handle_group_exit(struct tcb *tcp, int sig)
}
#endif
-static struct tcb *
-collect_stopped_tcbs(void)
+static int
+trace()
{
-#ifdef LINUX
- static int remembered_pid;
- static int remembered_status;
-#endif
int pid;
int wait_errno;
int status;
struct tcb *tcp;
- struct tcb *found_tcps;
#ifdef LINUX
- struct tcb **nextp;
struct rusage ru;
- struct rusage* ru_ptr = cflag ? &ru : NULL;
- int wnohang = 0;
#ifdef __WALL
- int wait4_options = __WALL;
+ static int wait4_options = __WALL;
#endif
-
- if (remembered_pid > 0) {
- pid = remembered_pid;
- remembered_pid = 0;
- if (debug)
- fprintf(stderr, " [remembered wait(%#x) = %u]\n",
- remembered_status, pid);
- tcp = pid2tcb(pid); /* can't be NULL */
- tcp->wait_status = remembered_status;
- tcp->next_need_service = NULL;
- return tcp;
- }
- nextp = &found_tcps;
#endif /* LINUX */
- /* Make it possible to ^C strace while we wait */
- if (interactive)
- sigprocmask(SIG_SETMASK, &empty_set, NULL);
-
- found_tcps = NULL;
- while (1) {
+ while (nprocs != 0) {
if (interrupted)
- break;
+ return 0;
+ if (interactive)
+ sigprocmask(SIG_SETMASK, &empty_set, NULL);
#ifdef LINUX
#ifdef __WALL
- pid = wait4(-1, &status, wait4_options | wnohang, ru_ptr);
+ pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
/* this kernel does not support __WALL */
wait4_options &= ~__WALL;
errno = 0;
- pid = wait4(-1, &status, wait4_options | wnohang, ru_ptr);
+ pid = wait4(-1, &status, wait4_options,
+ cflag ? &ru : NULL);
}
if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
/* most likely a "cloned" process */
- pid = wait4(-1, &status, __WCLONE | wnohang, ru_ptr);
- if (pid < 0 && errno != ECHILD) {
- fprintf(stderr, "strace: wait4(WCLONE) "
+ pid = wait4(-1, &status, __WCLONE,
+ cflag ? &ru : NULL);
+ if (pid == -1) {
+ fprintf(stderr, "strace: clone wait4 "
"failed: %s\n", strerror(errno));
}
}
-#else /* !__WALL */
- pid = wait4(-1, &status, wnohang, ru_ptr);
-#endif
+#else
+ pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
+#endif /* __WALL */
#endif /* LINUX */
#ifdef SUNOS4
pid = wait(&status);
#endif /* SUNOS4 */
wait_errno = errno;
+ if (interactive)
+ sigprocmask(SIG_BLOCK, &blocked_set, NULL);
- if (pid == 0 && wnohang) {
- /* We had at least one successful
- * wait() before. We waited
- * with WNOHANG second time.
- * Stop collecting more tracees,
- * process what we already have.
- */
- break;
- }
if (pid == -1) {
- if (wait_errno == EINTR)
+ switch (wait_errno) {
+ case EINTR:
continue;
- if (wait_errno == ECHILD) {
+ case ECHILD:
/*
* We would like to verify this case
* but sometimes a race in Solbourne's
@@ -2338,16 +2311,17 @@ collect_stopped_tcbs(void)
* ECHILD before sending us SIGCHILD.
*/
#if 0
- if (nprocs != 0) {
- fprintf(stderr, "strace: proc miscount\n");
- exit(1);
- }
+ if (nprocs == 0)
+ return 0;
+ fprintf(stderr, "strace: proc miscount\n");
+ exit(1);
#endif
- break;
+ return 0;
+ default:
+ errno = wait_errno;
+ perror("strace: wait");
+ return -1;
}
- errno = wait_errno;
- perror("strace: wait");
- exit(1);
}
if (pid == popen_pid) {
if (WIFEXITED(status) || WIFSIGNALED(status))
@@ -2357,14 +2331,6 @@ collect_stopped_tcbs(void)
if (debug)
fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
- /* RHEL5 bug workaround.
- * It can re-report stopped tasks. Happens on SIGSTOPs here.
- * Second (bogus) report has signal# set to 0.
- * Stop collecting and process what we have.
- */
- if (WIFSTOPPED(status) && WSTOPSIG(status) == 0)
- break;
-
/* Look up `pid' in our table. */
if ((tcp = pid2tcb(pid)) == NULL) {
#ifdef LINUX
@@ -2388,7 +2354,7 @@ Process %d attached (waiting for parent)\n",
else
/* This can happen if a clone call used
CLONE_PTRACE itself. */
-#endif /* LINUX */
+#endif
{
fprintf(stderr, "unknown pid: %u\n", pid);
if (WIFSTOPPED(status))
@@ -2396,13 +2362,15 @@ Process %d attached (waiting for parent)\n",
exit(1);
}
}
-
-#ifdef LINUX
+ /* set current output file */
+ outf = tcp->outf;
if (cflag) {
+#ifdef LINUX
tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
tcp->stime = ru.ru_stime;
+#endif /* !LINUX */
}
-#endif
+
if (tcp->flags & TCB_SUSPENDED) {
/*
* Apparently, doing any ptrace() call on a stopped
@@ -2411,76 +2379,9 @@ Process %d attached (waiting for parent)\n",
* process has not been actually restarted.
* Since we have inspected the arguments of suspended
* processes we end up here testing for this case.
- *
- * We also end up here when we catch new pid of
- * CLONE_PTRACEd process. Do not process/restart it
- * until we see corresponding clone() syscall exit
- * in its parent.
*/
continue;
}
-
-#ifdef LINUX
- /* So far observed only on RHEL5 ia64, but I imagine this
- * can legitimately happen elsewhere.
- * If we waited and got a stopped task notification,
- * subsequent wait may return the same pid again, for example,
- * with SIGKILL notification. SIGKILL kills even stopped tasks.
- * We must not add it to the list
- * (one task can't be inserted twice in the list).
- */
- {
- struct tcb *f = found_tcps;
- while (f) {
- if (f == tcp) {
- remembered_pid = pid;
- remembered_status = status;
- goto ret;
- }
- f = f->next_need_service;
- }
- }
- /* It is important to not invert the order of tasks
- * to process. For one, alloc_tcb() above picks newly forked
- * threads in some order, processing of them and their parent
- * should be in the same order, otherwise bad things happen
- * (misinterpreted SIGSTOPs and such).
- */
- tcp->wait_status = status;
- *nextp = tcp;
- nextp = &tcp->next_need_service;
- *nextp = NULL;
- wnohang = WNOHANG;
-#endif
-#ifdef SUNOS4
- /* Probably need to replace wait with waitpid
- * and loop on Sun too, but I can't test it. Volunteers?
- */
- tcp->wait_status = status;
- tcp->next_need_service = NULL;
- found_tcps = tcp;
- break;
-#endif
- } /* while (1) - collecting all stopped/exited tracees */
- ret:
- /* Disable ^C etc */
- if (interactive)
- sigprocmask(SIG_BLOCK, &blocked_set, NULL);
-
- return found_tcps;
-}
-
-static int
-handle_stopped_tcbs(struct tcb *tcp)
-{
- for (; tcp; tcp = tcp->next_need_service) {
- int pid;
- int status;
-
- outf = tcp->outf;
- status = tcp->wait_status;
- pid = tcp->pid;
-
if (WIFSIGNALED(status)) {
if (pid == strace_child)
exit_code = 0x100 | WTERMSIG(status);
@@ -2542,7 +2443,7 @@ handle_stopped_tcbs(struct tcb *tcp)
/*
* Interestingly, the process may stop
* with STOPSIG equal to some other signal
- * than SIGSTOP if we happen to attach
+ * than SIGSTOP if we happend to attach
* just before the process takes a signal.
*/
if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
@@ -2563,100 +2464,10 @@ handle_stopped_tcbs(struct tcb *tcp)
return -1;
}
}
-/* Add more OSes after you verified it works for them. */
-/* PTRACE_SETOPTIONS may be an enum, not a #define.
- * But sometimes we can test for it by checking PT_SETOPTIONS.
- */
-#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
-# ifndef PTRACE_O_TRACESYSGOOD
-# define PTRACE_O_TRACESYSGOOD 0x00000001
-# endif
-# ifndef PTRACE_O_TRACEEXEC
-# define PTRACE_O_TRACEEXEC 0x00000010
-# endif
-# ifndef PTRACE_EVENT_EXEC
-# define PTRACE_EVENT_EXEC 4
-# endif
- /*
- * Ask kernel to set signo to SIGTRAP | 0x80
- * on ptrace-generated SIGTRAPs, and mark
- * execve's SIGTRAP with PTRACE_EVENT_EXEC.
- */
- if (!ptrace_opts_set) {
- char *p;
- ptrace_opts_set = 1;
-
- /* RHEL 2.6.18 definitely has crippling bugs */
- /* Vanilla and Fedora 2.6.29 seems to work */
- p = utsname_buf.release;
- if (strtoul(p, &p, 10) < 2 || *p != '.')
- goto tracing;
- if (strtoul(++p, &p, 10) < 6 || *p != '.')
- goto tracing;
- if (strtoul(++p, &p, 10) < 29)
- goto tracing;
- /*
- * NB: even if this "succeeds", we can
- * revert back to SIGTRAP if we later see
- * that it didnt really work.
- * Old kernels are known to lie here.
- */
- if (ptrace(PTRACE_SETOPTIONS, pid, (char *) 0,
- (long) (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC)) == 0)
- ptrace_stop_sig = SIGTRAP | 0x80;
- }
-#endif
goto tracing;
}
-#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
- if (ptrace_stop_sig != SIGTRAP && WSTOPSIG(status) == SIGTRAP) {
- /*
- * We told ptrace to report SIGTRAP | 0x80 on this process
- * but got bare SIGTRAP. This can be a genuine SIGTRAP:
- * kill(pid, SIGTRAP), trap insn, etc;
- * but be paranoid about it.
- */
- if (((unsigned)status >> 16) == PTRACE_EVENT_EXEC) {
- /* It's post-exec ptrace stop. Ignore it,
- * we will get syscall exit ptrace stop later.
- */
-#ifdef TCB_WAITEXECVE
- tcp->flags &= ~TCB_WAITEXECVE;
-#endif
- goto tracing;
- } else {
- /* Take a better look... */
- siginfo_t si;
- si.si_signo = 0;
- ptrace(PTRACE_GETSIGINFO, pid, (void*) 0, (long) &si);
- /*
- * Check some fields to make sure we see
- * real SIGTRAP.
- * Otherwise interpret it as ptrace stop.
- * Real SIGTRAPs (int3 insn on x86, kill() etc)
- * have these values:
- * int3: kill -TRAP $pid:
- * si_signo:5 (SIGTRAP) si_signo:5 (SIGTRAP)
- * si_errno:0 si_errno:(?)
- * si_code:128 (SI_KERNEL) si_code:0 (SI_USER)
- * si_pid:0 si_pid:(>0?)
- * si_band:0 si_band:(?)
- * Ptrace stops have garbage there instead.
- */
- if (si.si_signo != SIGTRAP
- || (si.si_code != SI_KERNEL && si.si_code != SI_USER)
- ) {
- fprintf(stderr, "bogus SIGTRAP (si_code:%x), assuming old kernel\n", si.si_code);
- ptrace_stop_sig = SIGTRAP;
- }
- }
- }
-#endif
-
- if (WSTOPSIG(status) != ptrace_stop_sig) {
- /* This isn't a ptrace stop. */
-
+ if (WSTOPSIG(status) != SIGTRAP) {
if (WSTOPSIG(status) == SIGSTOP &&
(tcp->flags & TCB_SIGTRAPPED)) {
/*
@@ -2721,28 +2532,27 @@ 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) {
- /* 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.
+ 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().
*/
- 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);
- /* [why SIGTERM? why not also kill(SIGKILL)?] */
+ ptrace(PTRACE_KILL,
+ tcp->pid, (char *) 1, SIGTERM);
droptcb(tcp);
}
continue;
@@ -2773,34 +2583,6 @@ handle_stopped_tcbs(struct tcb *tcp)
cleanup();
return -1;
}
- } /* for each tcp */
-
- return 0;
-}
-
-static int
-trace()
-{
- int rc;
- struct tcb *tcbs;
-
- while (nprocs != 0) {
- /* The loop of "wait for one tracee, serve it, repeat"
- * may leave some tracees never served.
- * Kernel provides no guarantees of fairness when you have
- * many waitable tasks.
- * Try strace -f with test/many_looping_threads.c example.
- * To fix it, we collect *all* waitable tasks, then handle
- * them all, then repeat.
- */
- if (interrupted)
- return 0;
- tcbs = collect_stopped_tcbs();
- if (!tcbs)
- break;
- rc = handle_stopped_tcbs(tcbs);
- if (rc)
- return rc;
}
return 0;
}
@@ -2842,32 +2624,20 @@ va_dcl
}
void
-printleader(struct tcb *tcp)
+printleader(tcp)
+struct tcb *tcp;
{
if (tcp_last) {
- int err = tcp_last->ptrace_errno;
- if (err) {
- tcp_last->ptrace_errno = 0;
+ if (tcp_last->ptrace_errno) {
if (tcp_last->flags & TCB_INSYSCALL) {
- if (err == ESRCH)
- tprintf(" <unavailable ...>\n");
- else
- tprintf(" <ptrace error %d (%s) ...>\n", err, strerror(err));
- tcp_last->flags |= TCB_REPRINT;
- } else {
- /* 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));
+ tprintf(" <unavailable>)");
+ tabto(acolumn);
}
+ tprintf("= ? <unavailable>\n");
+ tcp_last->ptrace_errno = 0;
} else if (!outfname || followfork < 2 || tcp_last == tcp) {
- tprintf(" <unfinished ...>\n");
tcp_last->flags |= TCB_REPRINT;
+ tprintf(" <unfinished ...>\n");
}
}
curcol = 0;
diff --git a/svr4/syscallent.h b/svr4/syscallent.h
index d8e5a12..239d6b0 100644
--- a/svr4/syscallent.h
+++ b/svr4/syscallent.h
@@ -823,5 +823,5 @@
{ -1, TF, sys_aioaread64, "aioaread64" }, /* 417 */
{ -1, TF, sys_aioawrite64, "aioawrite64" }, /* 418 */
{ -1, TF, sys_aiocancel64, "aiocancel64" }, /* 419 */
- { -1, TF, sys_aiofsync, "aiofsync" }, /* 420 */
+ { -1, TF, sys_aiofsync, "aiofsync" }, /* 420 */
#endif
diff --git a/syscall.c b/syscall.c
index 10b6627..2605f91 100644
--- a/syscall.c
+++ b/syscall.c
@@ -38,39 +38,38 @@
#include <signal.h>
#include <time.h>
#include <errno.h>
-#include <sched.h>
#include <sys/user.h>
#include <sys/syscall.h>
#include <sys/param.h>
#if HAVE_ASM_REG_H
-# if defined (SPARC) || defined (SPARC64)
+#if defined (SPARC) || defined (SPARC64)
# define fpq kernel_fpq
# define fq kernel_fq
# define fpu kernel_fpu
-# endif
-# include <asm/reg.h>
-# if defined (SPARC) || defined (SPARC64)
+#endif
+#include <asm/reg.h>
+#if defined (SPARC) || defined (SPARC64)
# undef fpq
# undef fq
# undef fpu
-# endif
+#endif
#endif
#ifdef HAVE_SYS_REG_H
-# include <sys/reg.h>
-# ifndef PTRACE_PEEKUSR
-# define PTRACE_PEEKUSR PTRACE_PEEKUSER
-# endif
+#include <sys/reg.h>
+#ifndef PTRACE_PEEKUSR
+# define PTRACE_PEEKUSR PTRACE_PEEKUSER
+#endif
#elif defined(HAVE_LINUX_PTRACE_H)
-# undef PTRACE_SYSCALL
+#undef PTRACE_SYSCALL
# ifdef HAVE_STRUCT_IA64_FPREG
# define ia64_fpreg XXX_ia64_fpreg
# endif
# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
# define pt_all_user_regs XXX_pt_all_user_regs
# endif
-# include <linux/ptrace.h>
+#include <linux/ptrace.h>
# undef ia64_fpreg
# undef pt_all_user_regs
#endif
@@ -997,47 +996,26 @@ get_scno(struct tcb *tcp)
}
# elif defined(IA64)
# define IA64_PSR_IS ((long)1 << 34)
- if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
+ if (upeek (tcp, PT_CR_IPSR, &psr) >= 0)
ia32 = (psr & IA64_PSR_IS) != 0;
if (!(tcp->flags & TCB_INSYSCALL)) {
if (ia32) {
if (upeek(tcp, PT_R1, &scno) < 0) /* orig eax */
return -1;
} else {
- if (upeek(tcp, PT_R15, &scno) < 0)
+ if (upeek (tcp, PT_R15, &scno) < 0)
return -1;
}
/* Check if we return from execve. */
if (tcp->flags & TCB_WAITEXECVE) {
-# if defined PTRACE_GETSIGINFO
- siginfo_t si;
-
- tcp->flags &= ~TCB_WAITEXECVE;
- /* If SIGTRAP is masked, execve's magic SIGTRAP
- * is not delivered. We end up here on a subsequent
- * ptrace stop instead. Luckily, we can check
- * for the type of this SIGTRAP. execve's magic one
- * has 0 (SI_USER) in si.si_code, ptrace stop has 5.
- * (I don't know why 5).
- */
- si.si_code = SI_USER;
- /* If PTRACE_GETSIGINFO fails, we assume it's
- * magic SIGTRAP. Moot anyway, PTRACE_GETSIGINFO
- * doesn't fail.
- */
- ptrace(PTRACE_GETSIGINFO, tcp->pid, (void*) 0, (void*) &si);
- if (si.si_code == SI_USER)
- return 0;
-# else
tcp->flags &= ~TCB_WAITEXECVE;
return 0;
-# endif
}
} else {
/* syscall in progress */
- if (upeek(tcp, PT_R8, &r8) < 0)
+ if (upeek (tcp, PT_R8, &r8) < 0)
return -1;
- if (upeek(tcp, PT_R10, &r10) < 0)
+ if (upeek (tcp, PT_R10, &r10) < 0)
return -1;
}
# elif defined (ARM)
@@ -1126,7 +1104,7 @@ get_scno(struct tcb *tcp)
# elif defined (LINUX_MIPSN32)
unsigned long long regs[38];
- if (do_ptrace(PTRACE_GETREGS, tcp, NULL, (long) &regs) < 0)
+ if (ptrace (PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
return -1;
a3 = regs[REG_A3];
r2 = regs[REG_V0];
@@ -1379,11 +1357,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
@@ -1938,11 +1916,10 @@ force_result(tcp, error, rval)
#endif /* LINUX */
#ifdef SUNOS4
- 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
- ) {
+ if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_error),
+ error << 24) < 0 ||
+ ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_rval1), rval) < 0)
return -1;
- }
#endif /* SUNOS4 */
#ifdef SVR4
@@ -2074,10 +2051,10 @@ syscall_enter(struct tcb *tcp)
else
nargs = tcp->u_nargs = MAX_ARGS;
- if (do_ptrace(PTRACE_GETREGS, tcp, NULL, (long) &regs) < 0)
+ if (ptrace (PTRACE_GETREGS, pid, NULL, (long) &regs) < 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];
@@ -2092,20 +2069,20 @@ syscall_enter(struct tcb *tcp)
if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
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)
- return -1;
- for (i = 0; i < 4; i++) {
- if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i])<0)
- return -1;
+ nargs = tcp->u_nargs = MAX_ARGS;
+ if(nargs > 4) {
+ if(upeek(tcp, REG_SP, &sp) < 0)
+ return -1;
+ 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++) {
- if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
- return -1;
+ for(i = 0; i < nargs; i++) {
+ if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
+ return -1;
}
}
}
@@ -2377,12 +2354,7 @@ trace_syscall(struct tcb *tcp)
if (dtime)
gettimeofday(&tv, NULL);
- /* 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
+ /* BTW, why we don't just memorize syscall no. on entry
* in tcp->something?
*/
scno_good = res = get_scno(tcp);
@@ -2407,15 +2379,14 @@ trace_syscall(struct tcb *tcp)
if (tcp->flags & TCB_REPRINT) {
printleader(tcp);
- 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?...] */
+ 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 (cflag)
@@ -2424,8 +2395,8 @@ trace_syscall(struct tcb *tcp)
if (res != 1) {
tprintf(") ");
tabto(acolumn);
- tprintf("= ?");
- /* line will be finished by error handling code */
+ tprintf("= ? <unavailable>");
+ printtrailer();
tcp->flags &= ~TCB_INSYSCALL;
return res;
}
@@ -2548,15 +2519,18 @@ trace_syscall(struct tcb *tcp)
if (res != 1) {
printleader(tcp);
- tcp->flags &= ~TCB_REPRINT; /* why? */
+ tcp->flags &= ~TCB_REPRINT;
tcp_last = tcp;
if (scno_good != 1)
- tprintf("syscall_??" /* anti-trigraph gap */ "(");
+ tprintf("????" /* anti-trigraph gap */ "(");
else if (tcp->scno >= nsyscalls || tcp->scno < 0)
tprintf("syscall_%lu(", tcp->scno);
else
tprintf("%s(", sysent[tcp->scno].sys_name);
- /* Line will be finished by error handling code. */
+ /*
+ * " <unavailable>" will be added later by the code which
+ * detects ptrace errors.
+ */
tcp->flags |= TCB_INSYSCALL;
return res;
}
@@ -2710,7 +2684,7 @@ struct tcb *tcp;
#ifdef LINUX
#if defined (SPARC) || defined (SPARC64)
struct regs regs;
- if (do_ptrace(PTRACE_GETREGS, tcp, (char *)&regs, 0) < 0)
+ if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
return -1;
val = regs.r_o1;
#elif defined(SH)
diff --git a/test/childthread.c b/test/childthread.c
index e89fb14..c580db2 100644
--- a/test/childthread.c
+++ b/test/childthread.c
@@ -1,7 +1,7 @@
/* Test exit of a child of a TCB_EXITING child where the toplevel process starts
* waiting on it. The middle one gets detached and strace must update the
* toplevel process'es number of attached children to 0.
- *
+ *
* gcc -o test/childthread test/childthread.c -Wall -ggdb2 -pthread;./strace -f ./test/childthread
* It must print: write(1, "OK\n", ...
*/
diff --git a/test/leaderkill.c b/test/leaderkill.c
index ebb6ad1..67d5de1 100644
--- a/test/leaderkill.c
+++ b/test/leaderkill.c
@@ -1,7 +1,7 @@
/* Test handle_group_exit () handling of a thread leader still alive with its
* thread child calling exit_group () and proper passing of the process exit
* code to the process parent of this whole thread group.
- *
+ *
* gcc -o test/leaderkill test/leaderkill.c -Wall -ggdb2 -pthread;./test/leaderkill & pid=$!;sleep 1;strace -o x -q ./strace -f -p $pid
* It must print: write(1, "OK\n", ...
*/
diff --git a/test/many_looping_threads.c b/test/many_looping_threads.c
deleted file mode 100644
index 1f1fe05..0000000
--- a/test/many_looping_threads.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* This test is not yet added to Makefile */
-
-#include <stdio.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <signal.h>
-#include <stdlib.h>
-
-static int thd_no;
-
-static void *sub_thd(void *c)
-{
- fprintf(stderr, "sub-thread %d created\n", ++thd_no);
- for (;;)
- getuid();
- return NULL;
-}
-
-int main(int argc, char *argv[])
-{
- int i;
- pthread_t *thd;
- int num_threads = 1;
-
- if (argv[1])
- num_threads = atoi(argv[1]);
-
- thd = malloc(num_threads * sizeof(thd[0]));
- fprintf(stderr, "test start, num_threads:%d...\n", num_threads);
-
- for (i = 0; i < num_threads; i++) {
- pthread_create(&thd[i], NULL, sub_thd, NULL);
- fprintf(stderr, "after pthread_create\n");
- }
-
- /* Exit. This kills all threads */
- return 0;
-}
diff --git a/util.c b/util.c
index d9de354..f41b0c3 100644
--- a/util.c
+++ b/util.c
@@ -241,103 +241,30 @@ xlookup(const struct xlat *xlat, int val)
}
/*
- * 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;
- }
- 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;
- }
- }
+ /* Non-ESRCH errors might be our invalid reg/mem accesses,
+ * we do not record them. */
+ if (errno == ESRCH)
+ tcp->ptrace_errno = ESRCH;
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.
@@ -346,21 +273,25 @@ do_ptrace5(int request, struct tcb *tcp, void *addr, long data, char *data2)
* 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, (void *) (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;
}
@@ -857,6 +788,7 @@ int
umoven(struct tcb *tcp, long addr, int len, char *laddr)
{
#ifdef LINUX
+ int pid = tcp->pid;
int n, m;
int started = 0;
union {
@@ -868,17 +800,34 @@ 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 */
- 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;
@@ -898,16 +847,24 @@ 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 */
- u.val = do_ptrace(PTRACE_PEEKDATA, tcp, (char *) addr, 0);
- if (errno)
+ errno = 0;
+ u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
+ if (errno) {
+ if (errno != ESRCH)
+ perror("umoven");
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)
+ errno = 0;
+ u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
+ if (errno) {
+ if (errno != ESRCH)
+ perror("umoven");
return -1;
+ }
memcpy(laddr, u.x, m = MIN(sizeof(long), len));
addr += sizeof(long), laddr += m, len -= m;
}
@@ -917,7 +874,12 @@ umoven(struct tcb *tcp, long addr, int len, char *laddr)
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;
@@ -979,6 +941,7 @@ 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;
@@ -989,9 +952,17 @@ 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 */
- 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))
@@ -1000,9 +971,17 @@ umovestr(struct tcb *tcp, long addr, int len, char *laddr)
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++)
@@ -1025,7 +1004,12 @@ umovestr(struct tcb *tcp, long addr, int len, char *laddr)
#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;
@@ -1033,7 +1017,8 @@ uload(int cmd, struct tcb *tcp, long addr, int len, char *laddr)
while (len) {
n = MIN(len, PAGSIZ);
n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
- if (do_ptrace5(cmd, tcp, (char *)addr, n, laddr) < 0) {
+ if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
+ perror("uload: ptrace(PTRACE_WRITE, ...)");
return -1;
}
len -= n;
@@ -1060,39 +1045,50 @@ uload(int cmd, 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);
- 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, pid, addr, len, laddr);
+}
+
+int
+dload(pid, addr, len, laddr)
+int pid;
+int addr;
+int len;
+char *laddr;
{
- return uload(PTRACE_WRITETEXT, tcp, addr, len, laddr);
+ return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
}
#endif /* SUNOS4 */
@@ -1100,7 +1096,10 @@ tload(struct tcb *tcp, int addr, int len, char *laddr)
#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;
@@ -1127,9 +1126,16 @@ upeek(struct tcb *tcp, long off, long *res)
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;
}
@@ -1175,17 +1181,17 @@ getpc(struct tcb *tcp)
return -1;
# elif defined(SPARC) || defined(SPARC64)
struct regs regs;
- if (do_ptrace(PTRACE_GETREGS, tcp, (char *) &regs, 0) < 0)
+ if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,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)
@@ -1201,8 +1207,10 @@ getpc(struct tcb *tcp)
*/
struct regs regs;
- if (do_ptrace(PTRACE_GETREGS, tcp, (char *) &regs, 0) < 0)
+ if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
+ perror("getpc: ptrace(PTRACE_GETREGS, ...)");
return -1;
+ }
return regs.r_pc;
#endif /* SUNOS4 */
@@ -1238,7 +1246,7 @@ 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;
}
@@ -1290,7 +1298,7 @@ printcall(struct tcb *tcp)
tprintf("[%08lx] ", pc);
# elif defined(SPARC) || defined(SPARC64)
struct regs regs;
- if (do_ptrace(PTRACE_GETREGS, tcp, (char *) &regs, 0) < 0) {
+ if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
PRINTBADPC;
return;
}
@@ -1298,7 +1306,7 @@ printcall(struct tcb *tcp)
# elif defined(HPPA)
long pc;
- if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
+ if(upeek(tcp,PT_IAOQ0,&pc) < 0) {
tprintf ("[????????] ");
return;
}
@@ -1373,7 +1381,8 @@ printcall(struct tcb *tcp)
#ifdef SUNOS4
struct regs regs;
- if (do_ptrace(PTRACE_GETREGS, tcp, (char *) &regs, 0) < 0) {
+ if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
+ perror("printcall: ptrace(PTRACE_GETREGS, ...)");
PRINTBADPC;
return;
}
@@ -1494,9 +1503,9 @@ set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
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
@@ -1510,9 +1519,9 @@ set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
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)
@@ -1526,9 +1535,9 @@ set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
typedef struct 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)
@@ -1598,15 +1607,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 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 */
@@ -1736,13 +1745,17 @@ struct tcb *tcp;
fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
return -1;
}
- if (do_ptrace(PTRACE_GETREGS, tcp, (char *)&regs, 0) < 0) {
+ if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
+ perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
return -1;
}
tcp->baddr = regs.r_o7 + 8;
- tcp->inst[0] = do_ptrace(PTRACE_PEEKTEXT, tcp, (char *)tcp->baddr, 0);
- if (errno)
+ errno = 0;
+ tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
+ if(errno) {
+ perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
return -1;
+ }
/*
* XXX - BRUTAL MODE ON
@@ -1760,8 +1773,11 @@ struct tcb *tcp;
inst <<= 32;
inst |= (tcp->inst[0] & 0xffffffffUL);
# endif
- if (do_ptrace(PTRACE_POKETEXT, tcp, (char *) tcp->baddr, inst) < 0)
+ ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
+ if(errno) {
+ perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
return -1;
+ }
tcp->flags |= TCB_BPTSET;
# else /* !SPARC && !SPARC64 */
@@ -1778,11 +1794,17 @@ struct tcb *tcp;
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)
+ tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
+ (char *) tcp->baddr, 0);
+ if (errno) {
+ perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
return -1;
- if (do_ptrace(PTRACE_POKETEXT, tcp, (char *) tcp->baddr, LOOP) < 0)
+ }
+ ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
+ if (errno) {
+ perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
return -1;
+ }
tcp->flags |= TCB_BPTSET;
} else {
/*
@@ -1808,15 +1830,21 @@ struct tcb *tcp;
/* 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)
+ 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, ...)");
return -1;
+ }
- if (do_ptrace(PTRACE_POKETEXT, tcp, (char *) addr + 0, LOOP0) < 0
- || do_ptrace(PTRACE_POKETEXT, tcp, (char *) addr + 8, LOOP1) < 0
- ) {
+ 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, ...)");
return -1;
}
tcp->flags |= TCB_BPTSET;
@@ -1888,10 +1916,14 @@ struct tcb *tcp;
# 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)
+ tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
+ if (errno) {
+ perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
return -1;
- if (do_ptrace(PTRACE_POKETEXT, tcp, (char *) tcp->baddr, LOOP) < 0) {
+ }
+ ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
+ if (errno) {
+ perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
return -1;
}
tcp->flags |= TCB_BPTSET;
@@ -1918,12 +1950,14 @@ struct tcb *tcp;
fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
return -1;
}
- if (do_ptrace(PTRACE_GETREGS, tcp, (char *)&regs, 0) < 0) {
+ if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 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;
}
@@ -1937,8 +1971,9 @@ struct tcb *tcp;
* 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;
@@ -1976,7 +2011,10 @@ struct tcb *tcp;
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) {
+ errno = 0;
+ ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
+ if(errno) {
+ perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
return -1;
}
tcp->flags &= ~TCB_BPTSET;
@@ -1990,7 +2028,10 @@ struct tcb *tcp;
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) {
+ errno = 0;
+ ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
+ if (errno) {
+ perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
return -1;
}
tcp->flags &= ~TCB_BPTSET;
@@ -2017,15 +2058,20 @@ struct tcb *tcp;
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
- ) {
+ 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, ...)");
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) {
+ errno = 0;
+ ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
+ if (errno) {
+ perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
return -1;
}
@@ -2047,7 +2093,10 @@ struct tcb *tcp;
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) {
+ errno = 0;
+ ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
+ if (errno) {
+ perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
return -1;
}
tcp->flags &= ~TCB_BPTSET;
@@ -2120,11 +2169,8 @@ struct tcb *tcp;
* 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;
- }
+ ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
+ ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
# elif defined(SH)
if (upeek(tcp, 4*REG_PC, &pc) < 0)
return -1;
@@ -2151,8 +2197,9 @@ struct tcb *tcp;
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;
@@ -2162,10 +2209,12 @@ 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 (do_ptrace(PTRACE_GETREGS, tcp, (char *)&regs, 0) < 0) {
+ if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 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,
@@ -2179,7 +2228,8 @@ struct tcb *tcp;
regs.r_pc, tcp->baddr);
regs.r_pc = tcp->baddr;
- if (do_ptrace(PTRACE_SETREGS, tcp, (char *)&regs, 0) < 0) {
+ if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
+ perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
return -1;
}
# endif /* LOOPA */
@@ -2250,7 +2300,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;
@@ -2275,7 +2325,7 @@ struct tcb *tcp;
* 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;