[Ltrace-devel] r77 - in ltrace/trunk: . sysdeps/linux-gnu testsuite/ltrace.minor
pmachata-guest at alioth.debian.org
pmachata-guest at alioth.debian.org
Thu May 17 14:24:15 UTC 2007
Author: pmachata-guest
Date: 2007-05-17 14:24:15 +0000 (Thu, 17 May 2007)
New Revision: 77
Added:
ltrace/trunk/testsuite/ltrace.minor/trace-exec.c
ltrace/trunk/testsuite/ltrace.minor/trace-exec.exp
ltrace/trunk/testsuite/ltrace.minor/trace-exec1.c
Modified:
ltrace/trunk/ChangeLog
ltrace/trunk/breakpoints.c
ltrace/trunk/ltrace.h
ltrace/trunk/process_event.c
ltrace/trunk/sysdeps/linux-gnu/trace.c
ltrace/trunk/wait_for_something.c
Log:
* Based on work of Supriya Kannery <supriyak at 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.
Modified: ltrace/trunk/ChangeLog
===================================================================
--- ltrace/trunk/ChangeLog 2007-05-09 17:21:42 UTC (rev 76)
+++ ltrace/trunk/ChangeLog 2007-05-17 14:24:15 UTC (rev 77)
@@ -1,3 +1,12 @@
+2007-05-10 Petr Machata <pmachata at redhat.com>
+
+ * Based on work of Supriya Kannery <supriyak at 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.
+
2007-05-09 Petr Machata <pmachata at redhat.com>
* wait_for_something.c (wait_for_something): Interpret SIGILL,
Modified: ltrace/trunk/breakpoints.c
===================================================================
--- ltrace/trunk/breakpoints.c 2007-05-09 17:21:42 UTC (rev 76)
+++ ltrace/trunk/breakpoints.c 2007-05-17 14:24:15 UTC (rev 77)
@@ -158,7 +158,6 @@
struct library_symbol *sym;
if (proc->breakpoints) { /* let's remove that struct */
- /* TODO FIXME XXX: free() all "struct breakpoint"s */
dict_apply_to_all(proc->breakpoints, free_bp_cb, NULL);
dict_clear(proc->breakpoints);
proc->breakpoints = NULL;
Modified: ltrace/trunk/ltrace.h
===================================================================
--- ltrace/trunk/ltrace.h 2007-05-09 17:21:42 UTC (rev 76)
+++ ltrace/trunk/ltrace.h 2007-05-17 14:24:15 UTC (rev 77)
@@ -242,6 +242,7 @@
extern void disable_breakpoint(pid_t pid, const struct breakpoint *sbp);
extern int fork_p(struct process *proc, int sysnum);
extern int exec_p(struct process *proc, int sysnum);
+extern int was_exec(struct process *proc, int status);
extern int syscall_p(struct process *proc, int status, int *sysnum);
extern void continue_process(pid_t pid);
extern void continue_after_signal(pid_t pid, int signum);
Modified: ltrace/trunk/process_event.c
===================================================================
--- ltrace/trunk/process_event.c 2007-05-09 17:21:42 UTC (rev 76)
+++ ltrace/trunk/process_event.c 2007-05-17 14:24:15 UTC (rev 77)
@@ -185,10 +185,7 @@
output_left(LT_TOF_SYSCALL, event->proc,
sysname(event->proc, event->e_un.sysnum));
}
- if (fork_p(event->proc, event->e_un.sysnum)
- || exec_p(event->proc, event->e_un.sysnum)) {
- disable_all_breakpoints(event->proc);
- } else if (event->proc->breakpoints_enabled == 0) {
+ if (event->proc->breakpoints_enabled == 0) {
enable_all_breakpoints(event->proc);
}
callstack_push_syscall(event->proc, event->e_un.sysnum);
@@ -241,25 +238,6 @@
output_right(LT_TOF_SYSCALLR, event->proc,
sysname(event->proc, event->e_un.sysnum));
}
- if (exec_p(event->proc, event->e_un.sysnum)) {
- arg_type_info info;
- info.arg_num = -1; /* Return value */
- info.type = ARGTYPE_LONG;
- if (gimme_arg(LT_TOF_SYSCALLR, event->proc, &info) == 0) {
- pid_t saved_pid;
- event->proc->mask_32bit = 0;
- event->proc->personality = 0;
- /* FIXME: Leak, should have arch_dep_free.
- But we are leaking here much more than that. */
- event->proc->arch_ptr = NULL;
- event->proc->filename = pid2name(event->proc->pid);
- saved_pid = event->proc->pid;
- event->proc->pid = 0;
- breakpoints_init(event->proc);
- event->proc->pid = saved_pid;
- } else
- enable_all_breakpoints(event->proc);
- }
continue_process(event->proc->pid);
}
Modified: ltrace/trunk/sysdeps/linux-gnu/trace.c
===================================================================
--- ltrace/trunk/sysdeps/linux-gnu/trace.c 2007-05-09 17:21:42 UTC (rev 76)
+++ ltrace/trunk/sysdeps/linux-gnu/trace.c 2007-05-17 14:24:15 UTC (rev 77)
@@ -11,7 +11,35 @@
#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] = {
{
#ifdef __NR_fork
@@ -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;
}
Added: ltrace/trunk/testsuite/ltrace.minor/trace-exec.c
===================================================================
--- ltrace/trunk/testsuite/ltrace.minor/trace-exec.c (rev 0)
+++ ltrace/trunk/testsuite/ltrace.minor/trace-exec.c 2007-05-17 14:24:15 UTC (rev 77)
@@ -0,0 +1,8 @@
+#include <unistd.h>
+#include <stdlib.h>
+
+int main (int argc, char ** argv)
+{
+ execl (argv[1], argv[1], NULL);
+ abort ();
+}
Added: ltrace/trunk/testsuite/ltrace.minor/trace-exec.exp
===================================================================
--- ltrace/trunk/testsuite/ltrace.minor/trace-exec.exp (rev 0)
+++ ltrace/trunk/testsuite/ltrace.minor/trace-exec.exp 2007-05-17 14:24:15 UTC (rev 77)
@@ -0,0 +1,45 @@
+set testfile "trace-exec"
+set srcfile ${testfile}.c
+set binfile ${testfile}
+
+verbose "compiling first source file now....."
+if { [ ltrace_compile "${srcdir}/${subdir}/${testfile}.c" "${srcdir}/${subdir}/${binfile}" executable {debug} ] != "" } {
+ send_user "Testcase compile failed, so all tests in this file will automatically fail.\n"
+}
+
+verbose "compiling second source file now....."
+if { [ ltrace_compile "${srcdir}/${subdir}/${testfile}1.c" "${srcdir}/${subdir}/${binfile}1" executable {debug} ] != "" } {
+ send_user "Testcase compile failed, so all tests in this file will automatically fail.\n"
+}
+
+global LTRACE
+set exec_output ""
+
+#Run PUT for ltarce.
+spawn $LTRACE -f $srcdir/$subdir/$testfile $srcdir/$subdir/${testfile}1
+set timeout 4
+expect timeout {
+ fail "Time out! Maybe caused by ltrace segment fault or improper timeout value here!"
+ return
+}
+
+catch "exec $LTRACE -f $srcdir/$subdir/$testfile $srcdir/$subdir/${testfile}1" exec_output
+
+#check the output of this program.
+verbose "ltrace runtest output: $exec_output\n"
+if [regexp {ELF from incompatible architecture} $exec_output] {
+ fail "32-bit ltrace can not perform on 64-bit PUTs and rebuild ltrace in 64 bit mode!"
+ return
+} elseif [ regexp {Couldn't get .hash data} $exec_output ] {
+ fail "Couldn't get .hash data!"
+ return
+}
+
+ltrace_saveoutput "${exec_output}" ${srcdir}/${subdir}/${testfile}.ltrace
+
+# execl from first binary
+ltrace_verify_output ${srcdir}/${subdir}/${testfile}.ltrace {"^execl"} 1
+# puts from second binary
+ltrace_verify_output ${srcdir}/${subdir}/${testfile}.ltrace {"^puts"} 1
+# assume glibc and see we really trace both binaries
+ltrace_verify_output ${srcdir}/${subdir}/${testfile}.ltrace {"^__libc_start_main"} 2
Added: ltrace/trunk/testsuite/ltrace.minor/trace-exec1.c
===================================================================
--- ltrace/trunk/testsuite/ltrace.minor/trace-exec1.c (rev 0)
+++ ltrace/trunk/testsuite/ltrace.minor/trace-exec1.c 2007-05-17 14:24:15 UTC (rev 77)
@@ -0,0 +1,6 @@
+#include <stdio.h>
+int main (void)
+{
+ puts("Hello, World.");
+ return 0;
+}
Modified: ltrace/trunk/wait_for_something.c
===================================================================
--- ltrace/trunk/wait_for_something.c 2007-05-09 17:21:42 UTC (rev 76)
+++ ltrace/trunk/wait_for_something.c 2007-05-17 14:24:15 UTC (rev 77)
@@ -114,6 +114,25 @@
event.e_un.signum = stop_signal;
return &event;
}
+
+ if (was_exec(event.proc, status)) {
+ pid_t saved_pid;
+
+ event.thing = LT_EV_NONE;
+ event.e_un.signum = WSTOPSIG(status);
+ debug(1, "Placing breakpoints for the new program");
+ event.proc->mask_32bit = 0;
+ event.proc->personality = 0;
+ event.proc->arch_ptr = NULL;
+ event.proc->filename = pid2name(event.proc->pid);
+ saved_pid = event.proc->pid;
+ event.proc->pid = 0;
+ breakpoints_init(event.proc);
+ event.proc->pid = saved_pid;
+ continue_process(event.proc->pid);
+ return &event;
+ }
+
event.thing = LT_EV_BREAKPOINT;
if (!event.proc->instruction_pointer) {
event.proc->instruction_pointer =
More information about the Ltrace-devel
mailing list