[PATCH] allow strace to trace SIGTRAP signals

Heiko Carstens heiko.carstens at de.ibm.com
Thu Jan 20 23:00:01 UTC 2005


Hi Roland,

the patch below is from Ulrich Weigand which incorporates some changes
by me. It allows strace to trace SIGTRAP signals by exploiting the
PTRACE_O_TRACESYSGOOD flag.
Tested on i386 (2.4 kernel) and s390x (2.6 kernel). Tracing SIGTRAP
won't work on most architectures with 2.4 kernels since
PTRACE_(OLD)SETOPTIONS isn't implemented there.
This patch might break some other architectures since the
TCB_WAITEXECVE flag is now mandatory for all architectures (on
LINUX).

Please apply, thanks,
Heiko

diff -urN strace-4.5.8/defs.h strace-4.5.8-trace/defs.h
--- strace-4.5.8/defs.h	Thu Oct  7 00:27:43 2004
+++ strace-4.5.8-trace/defs.h	Thu Jan 20 15:33:23 2005
@@ -293,6 +293,7 @@
 	long baddr;		/* `Breakpoint' address */
 	long inst[2];		/* Instructions on above */
 	int pfd;		/* proc file descriptor */
+	int tracesysgood;	/* signal indicating a PTRACE_SYSCALL trap */
 #ifdef SVR4
 #ifdef HAVE_MP_PROCFS
 	int pfd_stat;
@@ -322,7 +323,7 @@
 #define TCB_FOLLOWFORK	00400	/* Process should have forks followed */
 #define TCB_REPRINT	01000	/* We should reprint this syscall on exit */
 #ifdef LINUX
-# if defined(ALPHA) || defined(SPARC) || defined(SPARC64) || defined(POWERPC) || defined(IA64) || defined(HPPA) || defined(SH) || defined(SH64) || defined(S390) || defined(S390X) || defined(ARM)
+# if defined(ALPHA) || defined(SPARC) || defined(SPARC64) || defined(POWERPC) || defined(IA64) || defined(HPPA) || defined(SH) || defined(SH64) || defined(S390) || defined(S390X) || defined(ARM) || defined(I386)
 #  define TCB_WAITEXECVE 02000	/* ignore SIGTRAP after exceve */
 # endif
 # define TCB_CLONE_DETACHED 04000 /* CLONE_DETACHED set in creating syscall */
@@ -418,6 +419,9 @@
 extern struct tcb *pid2tcb P((int));
 extern void droptcb P((struct tcb *));
 extern int expand_tcbtab P((void));
+#ifdef LINUX
+extern void ptrace_set_options P((struct tcb *, int));
+#endif
 
 extern void set_sortby P((char *));
 extern void set_overhead P((int));
diff -urN strace-4.5.8/process.c strace-4.5.8-trace/process.c
--- strace-4.5.8/process.c	Wed Oct 20 01:33:47 2004
+++ strace-4.5.8-trace/process.c	Thu Jan 20 15:15:37 2005
@@ -840,7 +840,10 @@
 			droptcb(tcpchild);
 			return 0;
 		}
-#endif
+#ifdef LINUX
+		ptrace_set_options(tcb, pid);
+#endif /* LINUX */
+#endif /* CLONE_PTRACE */
 
 		if (bpt)
 			clearbpt(tcp);
@@ -989,6 +992,7 @@
 			droptcb(tcpchild);
 			return 0;
 		}
+		ptrace_set_options(tcb, pid);
 #endif /* LINUX */
 #ifdef SUNOS4
 #ifdef oldway
diff -urN strace-4.5.8/strace.c strace-4.5.8-trace/strace.c
--- strace-4.5.8/strace.c	Wed Oct 20 04:04:15 2004
+++ strace-4.5.8-trace/strace.c	Thu Jan 20 15:47:46 2005
@@ -744,6 +744,7 @@
 			tcp->stime.tv_sec = 0;
 			tcp->stime.tv_usec = 0;
 			tcp->pfd = -1;
+			tcp->tracesysgood = 0;
 			nprocs++;
 			return tcp;
 		}
@@ -751,6 +752,32 @@
 	return NULL;
 }
 
+#ifdef LINUX
+void
+ptrace_set_options(tcp, pid)
+struct tcb *tcp;
+int 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 (tcp->tracesysgood & 0x80)
+		return;
+	if ((ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0) &&
+	    (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0)) {
+		perror("ptrace_set_options: ptrace(PTRACE_SETOPTIONS, ...)");
+		return;
+	}
+	tcp->tracesysgood |= 0x80;
+}
+#endif
+
 #ifdef USE_PROCFS
 int
 proc_open(tcp, attaching)
@@ -1272,7 +1299,7 @@
 				break;
 			}
 			if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
-			    WSTOPSIG(status) == SIGTRAP ?
+			    WSTOPSIG(status) == (SIGTRAP | tcp->tracesysgood) ?
 			    0 : WSTOPSIG(status))) < 0) {
 				if (errno != ESRCH)
 					perror("detach: ptrace(PTRACE_CONT, ...)");
@@ -2096,6 +2123,9 @@
 				exit(1);
 			}
 		}
+#ifdef LINUX
+		ptrace_set_options(tcp, pid);
+#endif /* LINUX */
 		/* set current output file */
 		outf = tcp->outf;
 		if (cflag) {
@@ -2208,7 +2238,8 @@
 			goto tracing;
 		}
 
-		if (WSTOPSIG(status) != SIGTRAP) {
+		if ((WSTOPSIG(status) != (SIGTRAP | tcp->tracesysgood)) &&
+		    ((WSTOPSIG(status) != SIGTRAP) || !(tcp->flags & TCB_WAITEXECVE))) {
 			if (WSTOPSIG(status) == SIGSTOP &&
 					(tcp->flags & TCB_SIGTRAPPED)) {
 				/*
diff -urN strace-4.5.8/syscall.c strace-4.5.8-trace/syscall.c
--- strace-4.5.8/syscall.c	Sat Sep  4 06:20:43 2004
+++ strace-4.5.8-trace/syscall.c	Thu Jan 20 15:40:51 2005
@@ -891,6 +891,13 @@
 #elif defined (I386)
 	if (upeek(pid, 4*ORIG_EAX, &scno) < 0)
 		return -1;
+        if (!(tcp->flags & TCB_INSYSCALL)) { 
+                /* Check if we return from execve. */ 
+                if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) { 
+                        tcp->flags &= ~TCB_WAITEXECVE; 
+                        return 0; 
+                } 
+        } 
 #elif defined (X86_64)
 	if (upeek(pid, 8*ORIG_RAX, &scno) < 0)
 		return -1;




More information about the Strace-devel mailing list