* defs.h (use_ptrace_setoptions): Declare.
* strace.c (set_ptrace_options): Define.
(is_ptrace_stop): Define.
(is_post_execve_trap): Define.
(trace): Use them.
* process.c (internal_exec): Don't set TCB_WAITEXECVE if
PTRACE_SETOPTIONS works.
---
 defs.h    |   16 +++++++++++++
 process.c |    5 ++++
 strace.c  |   72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 92 insertions(+), 1 deletions(-)

diff --git a/defs.h b/defs.h
index 4797e96..c0d2dcc 100644
--- a/defs.h
+++ b/defs.h
@@ -246,6 +246,22 @@ extern int ptrace(int, int, char *, int, ...);
 #define PERSONALITY1_WORDSIZE 4
 #endif
 
+#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
+# define USE_PTRACE_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
+extern int use_ptrace_setoptions;
+#else
+# define use_ptrace_setoptions 0
+#endif
+
 #ifdef SVR4
 #ifdef HAVE_MP_PROCFS
 extern int mp_ioctl (int f, int c, void *a, int s);
diff --git a/process.c b/process.c
index c69e45e..eb464e2 100644
--- a/process.c
+++ b/process.c
@@ -1732,6 +1732,11 @@ struct tcb *tcp;
                fixvfork(tcp);
 #endif /* SUNOS4 */
 #if defined LINUX && defined TCB_WAITEXECVE
+#ifdef USE_PTRACE_SETOPTIONS
+       /* Don't set TCB_WAITEXECVE when PTRACE_SETOPTIONS works. */
+       if (use_ptrace_setoptions > 0)
+               return 0;
+#endif
        if (exiting(tcp) && syserror(tcp))
                tcp->flags &= ~TCB_WAITEXECVE;
        else
diff --git a/strace.c b/strace.c
index 2fb75c9..bb29729 100644
--- a/strace.c
+++ b/strace.c
@@ -2253,6 +2253,72 @@ handle_group_exit(struct tcb *tcp, int sig)
 }
 #endif
 
+#ifdef USE_PTRACE_SETOPTIONS
+int use_ptrace_setoptions = -1;
+
+static void
+set_ptrace_options(struct tcb *tcp)
+{
+       /*
+        * Ask kernel to set signo to SIGTRAP | 0x80
+        * on ptrace-generated SIGTRAPs, and mark
+        * execve's SIGTRAP with PTRACE_EVENT_EXEC.
+        */
+       if (use_ptrace_setoptions)
+               if (ptrace(PTRACE_SETOPTIONS, tcp->pid, (char *) 0,
+                          (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC)) < 0)
+                       use_ptrace_setoptions = 0;
+}
+
+static int
+is_ptrace_stop(struct tcb *tcp, int status)
+{
+       if (!use_ptrace_setoptions)
+               return WSTOPSIG(status) == SIGTRAP;
+       if (use_ptrace_setoptions > 0)
+               return (WSTOPSIG(status) == (SIGTRAP | 0x80) ||
+                       ((unsigned)status >> 16) == PTRACE_EVENT_EXEC);
+
+       /* Check whether PTRACE_SETOPTIONS works. */
+       if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
+               /* PTRACE_O_TRACESYSGOOD works. */
+               use_ptrace_setoptions = 1;
+               return 1;
+       }
+       if (WSTOPSIG(status) == SIGTRAP) {
+               siginfo_t si;
+
+               /* Check for post-execve trap.  */
+               if (((unsigned)status >> 16) == PTRACE_EVENT_EXEC) {
+                       /* PTRACE_O_TRACEEXEC works.  */
+                       use_ptrace_setoptions = 1;
+                       return 1;
+               }
+               if (ptrace(PTRACE_GETSIGINFO, tcp->pid, (void *)0,
+                          (long)&si) == 0 &&
+                   (tprintf("[si_signo = %d, si_code = %d]\n",
+                            si.si_signo, si.si_code),
+                   (si.si_signo != SIGTRAP ||
+                    (si.si_code != SI_KERNEL && si.si_code != SI_USER))))
+                       /* PTRACE_O_TRACEEXEC does not work.  */
+                       use_ptrace_setoptions = 0;
+               return 1;
+       }
+       return 0;
+}
+
+static int
+is_post_execve_trap(struct tcb *tcp, int status)
+{
+       return (use_ptrace_setoptions && WSTOPSIG(status) == SIGTRAP &&
+               ((unsigned)status >> 16) == PTRACE_EVENT_EXEC);
+}
+#else
+#define set_ptrace_options(tcp)
+#define is_ptrace_stop(tcp, status) (WSTOPSIG(status) == SIGTRAP)
+#define is_post_execve_trap(tcp, status) 0
+#endif
+
 static int
 trace()
 {
@@ -2465,10 +2531,11 @@ Process %d attached (waiting for parent)\n",
                                        return -1;
                                }
                        }
+                       set_ptrace_options(tcp);
                        goto tracing;
                }
 
-               if (WSTOPSIG(status) != SIGTRAP) {
+               if (!is_ptrace_stop(tcp, status)) {
                        if (WSTOPSIG(status) == SIGSTOP &&
                                        (tcp->flags & TCB_SIGTRAPPED)) {
                                /*
@@ -2530,6 +2597,9 @@ Process %d attached (waiting for parent)\n",
                        tcp->flags &= ~TCB_SUSPENDED;
                        continue;
                }
+               /* Ignore post-execve trap. */
+               if (is_post_execve_trap(tcp, status))
+                       goto tracing;
                /* we handled the STATUS, we are permitted to interrupt now. */
                if (interrupted)
                        return 0;
-- 
1.7.0


-- 
Andreas Schwab, [email protected]
GPG Key fingerprint = D4E8 DBE3 3813 BB5D FA84  5EC7 45C6 250E 6F00 984E
"And now for something completely different."

------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
Strace-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/strace-devel

Reply via email to