Fixes from Supriya Kannery <supriyak@in.ibm.com>
* wait_for_something.c, process_event.c: Tracing across exec.
* sysdeps/linux-gnu/trace.c, ltrace.h: New interface was_exec.
* testsuite/ltrace.minor/trace-exec.c,
testsuite/ltrace.minor/trace-exec.exp,
testsuite/ltrace.minor/trace-exec1.c: Testcase for same.
diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c
index 0ea9b02..466c0c2 100644
--- a/sysdeps/linux-gnu/trace.c
+++ b/sysdeps/linux-gnu/trace.c
@@ -11,6 +11,34 @@
#include "ltrace.h"
#include "options.h"
#include "sysdep.h"
+#include "debug.h"
+
+/* If the system headers did not provide the constants, hard-code the normal
+ values. */
+#ifndef PTRACE_EVENT_FORK
+
+#define PTRACE_OLDSETOPTIONS 21
+#define PTRACE_SETOPTIONS 0x4200
+#define PTRACE_GETEVENTMSG 0x4201
+
+/* options set using PTRACE_SETOPTIONS */
+#define PTRACE_O_TRACESYSGOOD 0x00000001
+#define PTRACE_O_TRACEFORK 0x00000002
+#define PTRACE_O_TRACEVFORK 0x00000004
+#define PTRACE_O_TRACECLONE 0x00000008
+#define PTRACE_O_TRACEEXEC 0x00000010
+#define PTRACE_O_TRACEVFORKDONE 0x00000020
+#define PTRACE_O_TRACEEXIT 0x00000040
+
+/* Wait extended result codes for the above trace options. */
+#define PTRACE_EVENT_FORK 1
+#define PTRACE_EVENT_VFORK 2
+#define PTRACE_EVENT_CLONE 3
+#define PTRACE_EVENT_EXEC 4
+#define PTRACE_EVENT_VFORK_DONE 5
+#define PTRACE_EVENT_EXIT 6
+
+#endif /* PTRACE_EVENT_FORK */
static int fork_exec_syscalls[][5] = {
{
@@ -75,6 +103,39 @@
return 0;
}
+/* Check that we just hit an exec.
+ */
+int was_exec(struct process *proc, int status)
+{
+ if (!WIFSTOPPED (status))
+ return 0;
+
+ if (WSTOPSIG (status) == SIGTRAP
+ && (status >> 16) == PTRACE_EVENT_EXEC) {
+ debug (1, "detected exec (PTRACE_EVENT_EXEC)");
+ return 1;
+ }
+
+ if (WSTOPSIG (status) == SIGTRAP
+ && proc->callstack_depth > 0) {
+ /* Check whether this SIGTRAP is received just after
+ execve is called for this process. Ideally we'd
+ like to check that the exec succeeded, but e.g. on
+ s390 we have no way of knowing, because return
+ value is not set to -1 (as it should). Never mind,
+ reseting breakpoints for current process doesn't
+ hurt. */
+ struct callstack_element *elem;
+ elem = &proc->callstack[proc->callstack_depth - 1];
+ if (elem && elem->is_syscall && exec_p(proc, elem->c_un.syscall)) {
+ debug (1, "detected exec (callstack)");
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
void trace_me(void)
{
if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
@@ -103,19 +164,12 @@
void trace_set_options(struct process *proc, pid_t pid)
{
-#ifndef PTRACE_SETOPTIONS
-#define PTRACE_SETOPTIONS 0x4200
-#endif
-#ifndef PTRACE_OLDSETOPTIONS
-#define PTRACE_OLDSETOPTIONS 21
-#endif
-#ifndef PTRACE_O_TRACESYSGOOD
-#define PTRACE_O_TRACESYSGOOD 0x00000001
-#endif
if (proc->tracesysgood & 0x80)
return;
- if (ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0 &&
- ptrace(PTRACE_OLDSETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0) {
+
+ long options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
+ if (ptrace(PTRACE_SETOPTIONS, pid, 0, options) < 0 &&
+ ptrace(PTRACE_OLDSETOPTIONS, pid, 0, options) < 0) {
perror("PTRACE_SETOPTIONS");
return;
}