[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