]> granicus.if.org Git - strace/commitdiff
Revert unapproved commits.
authorRoland McGrath <roland@redhat.com>
Tue, 2 Jun 2009 23:49:22 +0000 (16:49 -0700)
committerRoland McGrath <roland@redhat.com>
Tue, 2 Jun 2009 23:49:22 +0000 (16:49 -0700)
12 files changed:
ChangeLog
defs.h
desc.c
process.c
signal.c
strace.c
svr4/syscallent.h
syscall.c
test/childthread.c
test/leaderkill.c
test/many_looping_threads.c [deleted file]
util.c

index cea9670ede851b6ccb14f7b1066c9503b8b39f17..29e42db5248a9f3a29477841f3b8a4b10be5eda9 100644 (file)
--- 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.
        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.
        * 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.
        (force_result): While at it, fix cpp directives indentation.
        * util.c (printcall): Add support for cris.
 
-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
        [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.
        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.
        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
        (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.
        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.
        * 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
        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.
        * 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 2f5683be4352fb30f83f108e540fd3043d57d270..769ed225d5f5008ade299a24635be00134d9528a 100644 (file)
--- 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 383107e30d7056f71de7f9bb7ebeb8b3f0baf8fd..e01b9acc25147b9af05d3541052ca28f6543f326 100644 (file)
--- 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("{...}");
                }
index 5119ede5b047b5b38b36778a343937bf6ac1aa8c..afd36bb8fb098443e0e45e62aeae265b7b2aa11d 100644 (file)
--- 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",      },
index 3203657602d09e49a1457f0efe631be4fca076af..76504f603b17b2cd25452422a720dec320af7709 100644 (file)
--- 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;
                }
index d351dc5e742646fb6d3ff7f4ec276fdccb990683..da8cc4a559c85df4906bc51605125dfbc628f8f3 100644 (file)
--- 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;
index d8e5a125e90372b8198ccc76c10b5f3f40d69d2b..239d6b0b1b39647418af3252a8a9fa460f062c28 100644 (file)
        { -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
index 10b6627a9468dc31472a692171eb84bb60111208..2605f91ad34f0a2e79cc89b88c085ea4c1f46a0b 100644 (file)
--- a/syscall.c
+++ b/syscall.c
 #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)
index e89fb1454011ee69a963a31f3b1584f9773a1789..c580db295621656d657773269ab0c3cd3431b854 100644 (file)
@@ -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", ...
  */
index ebb6ad1cf4eb621e006c08cf7f1ee0489ca69b64..67d5de1579837f1e6565431e48425a702405fdd9 100644 (file)
@@ -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 (file)
index 1f1fe05..0000000
+++ /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 d9de3543d8bb0c0aba0bfce86762e1d6ac3a2c5e..f41b0c39c93caa38832eaa7e883f47692f314149 100644 (file)
--- 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;