[Ltrace-devel] Patch for tracing fork

supriya kannery supriyak at in.ibm.com
Mon Aug 28 09:55:45 UTC 2006


Hello All,
   On 2.6 kernels, forked process is not traced properly by ltrace with 
-f option.  Ltrace (ltrace_0.4 level)  is not getting signals before the 
child process starts execution. I have observed this in ppc and s390x 
architectures. Ltrace is placing breakpoints on the child process after 
the child has executed some initial statements in its program. The 
reason for ltrace not getting signals prior to child's execution is that 
current ltrace code is not using PTRACE_O_TRACEFORK option while setting 
trace options for the parent process.
   I have prepared a patch for this problem. Introduced the trace option 
"PTRACE_O_TRACEFORK" so that parent program will get the fork events 
before child program starts execution.
   Please find  the patch attached. This is prepared over 
ltrace_0.4.orig.tar.gz level.
Thanks & Rgds, Supriya
IBM Linux Technology Centre
-------------- next part --------------
diff -Naurp ltrace-0.4/ltrace.h ltrace-0.4-Getmsg/ltrace.h
--- ltrace-0.4/ltrace.h	2006-02-20 16:48:07.000000000 -0500
+++ ltrace-0.4-Getmsg/ltrace.h	2006-07-18 02:23:36.000000000 -0400
@@ -12,6 +12,7 @@
 #include "sysdep.h"
 
 #define MAX_LIBRARY	30
+#define TRACE_FORK	1
 
 #if defined HAVE_LIBIBERTY || defined HAVE_LIBSUPC__
 # define USE_DEMANGLE
@@ -170,7 +171,7 @@ extern void show_summary(void);
 
 /* Arch-dependent stuff: */
 extern char *pid2name(pid_t pid);
-extern void trace_set_options(struct process *proc, pid_t pid);
+extern void trace_set_options(struct process *proc, pid_t pid, int option);
 extern void trace_me(void);
 extern int trace_pid(pid_t pid);
 extern void untrace_pid(pid_t pid);
@@ -198,5 +199,5 @@ extern void *plt2addr(struct process *, 
 #if 0				/* not yet */
 extern int umoven(struct process *proc, void *addr, int len, void *laddr);
 #endif
-
+extern ulong get_child_pid(pid_t pid);
 #endif
diff -Naurp ltrace-0.4/proc.c ltrace-0.4-Getmsg/proc.c
--- ltrace-0.4/proc.c	2006-02-20 16:48:07.000000000 -0500
+++ ltrace-0.4-Getmsg/proc.c	2006-07-17 06:00:36.000000000 -0400
@@ -22,10 +22,11 @@ struct process *open_program(char *filen
 	}
 	proc->filename = filename;
 	proc->breakpoints_enabled = -1;
+	proc->pid = 0;
+	breakpoints_init(proc); 
 	if (pid) {
 		proc->pid = pid;
 	}
-	breakpoints_init(proc);
 
 	proc->next = list_of_processes;
 	list_of_processes = proc;
@@ -37,11 +38,13 @@ void open_pid(pid_t pid, int verbose)
 	struct process *proc;
 	char *filename;
 
+#if 0
 	if (trace_pid(pid) < 0) {
 		fprintf(stderr, "Cannot attach to pid %u: %s\n", pid,
 			strerror(errno));
 		return;
 	}
+#endif
 
 	filename = pid2name(pid);
 
@@ -54,7 +57,6 @@ void open_pid(pid_t pid, int verbose)
 		return;
 	}
 #endif
-
 	proc = open_program(filename, pid);
-	proc->breakpoints_enabled = 1;
+	proc->breakpoints_enabled = -1;
 }
diff -Naurp ltrace-0.4/process_event.c ltrace-0.4-Getmsg/process_event.c
--- ltrace-0.4/process_event.c	2006-02-20 16:48:07.000000000 -0500
+++ ltrace-0.4-Getmsg/process_event.c	2006-07-18 03:05:16.000000000 -0400
@@ -223,16 +223,6 @@ static void process_sysret(struct event 
 	if (opt_T || opt_c) {
 		calc_time_spent(event->proc);
 	}
-	if (fork_p(event->proc, event->e_un.sysnum)) {
-		if (opt_f) {
-			pid_t child =
-			    gimme_arg(LT_TOF_SYSCALLR, event->proc, -1);
-			if (child > 0) {
-				open_pid(child, 0);
-			}
-		}
-		enable_all_breakpoints(event->proc);
-	}
 	callstack_pop(event->proc);
 	if (opt_S) {
 		output_right(LT_TOF_SYSCALLR, event->proc,
diff -Naurp ltrace-0.4/sysdeps/linux-gnu/trace.c ltrace-0.4-Getmsg/sysdeps/linux-gnu/trace.c
--- ltrace-0.4/sysdeps/linux-gnu/trace.c	2006-02-20 16:48:07.000000000 -0500
+++ ltrace-0.4-Getmsg/sysdeps/linux-gnu/trace.c	2006-07-18 02:49:35.000000000 -0400
@@ -90,7 +90,7 @@ int trace_pid(pid_t pid)
 	return 0;
 }
 
-void trace_set_options(struct process *proc, pid_t pid)
+void trace_set_options(struct process *proc, pid_t pid, int option)
 {
 #ifndef PTRACE_SETOPTIONS
 #define PTRACE_SETOPTIONS 0x4200
@@ -101,10 +101,21 @@ void trace_set_options(struct process *p
 #ifndef PTRACE_O_TRACESYSGOOD
 #define PTRACE_O_TRACESYSGOOD 0x00000001
 #endif
+#ifndef PTRACE_O_TRACEFORK
+#define PTRACE_O_TRACEFORK 0x00000002
+#endif
+      
+	ulong setoptions = 0;
+
 	if (proc->tracesysgood & 0x80)
 		return;
-	if (ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0 &&
-	    ptrace(PTRACE_OLDSETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0) {
+ 
+	setoptions |= PTRACE_O_TRACESYSGOOD;
+	if (TRACE_FORK == option){
+		setoptions |= PTRACE_O_TRACEFORK;
+	}
+	if (ptrace(PTRACE_SETOPTIONS, pid, 0, setoptions) < 0 &&
+	    ptrace(PTRACE_OLDSETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0){
 		perror("PTRACE_SETOPTIONS");
 		return;
 	}
@@ -175,3 +186,18 @@ int umovestr(struct process *proc, void 
 	*(char *)(laddr + offset) = '\0';
 	return 0;
 }
+
+ulong get_child_pid(pid_t pid)
+{
+#ifndef PTRACE_GETEVENTMSG
+#define PTRACE_GETEVENTMSG 0x4201
+#endif
+        ulong child_pid = 9999;
+                                                                                                                             
+       if( ptrace(PTRACE_GETEVENTMSG, pid, 0, &child_pid) < 0) {
+                perror("PTRACE_GETEVENTMSG");
+                return 0;
+        }
+        return child_pid;
+}
+
diff -Naurp ltrace-0.4/wait_for_something.c ltrace-0.4-Getmsg/wait_for_something.c
--- ltrace-0.4/wait_for_something.c	2006-02-20 16:48:07.000000000 -0500
+++ ltrace-0.4-Getmsg/wait_for_something.c	2006-07-18 02:32:26.000000000 -0400
@@ -14,15 +14,17 @@
 #include "options.h"
 #include "debug.h"
 
+#define FORK_MASK 0x00010000
 static struct event event;
 
 /* This should also update `current_process' */
 
 static struct process *pid2proc(int pid);
+void verify(int sig_status);
 
 struct event *wait_for_something(void)
 {
-	pid_t pid;
+	pid_t pid, child_pid;
 	int status;
 	int tmp;
 
@@ -54,7 +56,11 @@ struct event *wait_for_something(void)
 	if (event.proc->breakpoints_enabled == -1) {
 		enable_all_breakpoints(event.proc);
 		event.thing = LT_EV_NONE;
-		trace_set_options(event.proc, event.proc->pid);
+  		if(opt_f){
+			trace_set_options(event.proc, event.proc->pid, TRACE_FORK);
+		}else{
+			trace_set_options(event.proc, event.proc->pid, 0);
+		}
 		continue_process(event.proc->pid);
 		return &event;
 	}
@@ -92,6 +98,17 @@ struct event *wait_for_something(void)
 		event.e_un.signum = WSTOPSIG(status);
 		return &event;
 	}
+        if((WSTOPSIG(status) == SIGTRAP) && (status & FORK_MASK)) {
+		event.thing = LT_EV_NONE;
+		event.e_un.signum = WSTOPSIG(status);
+		child_pid = (pid_t) get_child_pid(event.proc->pid);
+                if (child_pid){
+			open_pid(child_pid,0);
+                }
+                enable_all_breakpoints(event.proc);
+		continue_after_signal(event.proc->pid, event.e_un.signum);
+		return &event;
+	}
 	event.thing = LT_EV_BREAKPOINT;
 	if (!event.proc->instruction_pointer) {
 		event.proc->instruction_pointer =
@@ -115,3 +132,4 @@ static struct process *pid2proc(pid_t pi
 	}
 	return NULL;
 }
+


More information about the Ltrace-devel mailing list