[PATCH 4/5] On x86, EAX read on syscall entry is not necessary

Denys Vlasenko dvlasenk at redhat.com
Mon Aug 22 10:28:59 UTC 2011


On Mon, 2011-08-22 at 12:21 +0200, Denys Vlasenko wrote:
> 4. Another speedup: on x86, EAX read on syscall entry is also not
> necessary if we know that post-execve SIGTRAP is disabled by
> PTRACE_O_TRACEEXEC ptrace option. This patch (a) moves EAX retrieval
> from syscall_fixup to get_scno_on_sysexit, and (b) perform EAX retrieval
> in syscall_fixup only if we are in syscall entry and PTRACE_O_TRACEEXEC
> option is not on.

diff -d -urpN strace.3/syscall.c strace.4/syscall.c
--- strace.3/syscall.c	2011-08-22 03:37:40.306072274 +0200
+++ strace.4/syscall.c	2011-08-22 04:01:28.851814943 +0200
@@ -1309,7 +1309,11 @@ get_scno_on_sysexit(struct tcb *tcp)
 		return -1;
 # elif defined(BFIN)
 # elif defined (I386)
+	if (upeek(tcp, 4*EAX, &eax) < 0)
+		return -1;
 # elif defined (X86_64)
+	if (upeek(tcp, 8*RAX, &rax) < 0)
+		return -1;
 # elif defined(IA64)
 #	define IA64_PSR_IS	((long)1 << 34)
 	if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
@@ -1470,22 +1474,30 @@ syscall_fixup(struct tcb *tcp)
 #ifdef LINUX
 	/* A common case of "not a syscall entry" is post-execve SIGTRAP */
 #if defined (I386)
-	if (upeek(tcp, 4*EAX, &eax) < 0)
-		return -1;
-	if (eax != -ENOSYS && entering(tcp)) {
-		if (debug)
-			fprintf(stderr, "not a syscall entry (eax = %ld)\n", eax);
-		return 0;
+	/* With PTRACE_O_TRACEEXEC, post-execve SIGTRAP is disabled.
+	 * Every extra ptrace call is expensive, so check EAX
+	 * on syscall entry only if PTRACE_O_TRACEEXEC is not enabled:
+	 */
+	if (entering(tcp) && !(ptrace_setoptions & PTRACE_O_TRACEEXEC)) {
+		if (upeek(tcp, 4*EAX, &eax) < 0)
+			return -1;
+		if (eax != -ENOSYS) {
+			if (debug)
+				fprintf(stderr, "not a syscall entry (eax = %ld)\n", eax);
+			return 0;
+		}
 	}
 #elif defined (X86_64)
-	if (upeek(tcp, 8*RAX, &rax) < 0)
-		return -1;
-	if (current_personality == 1)
-		rax = (long int)(int)rax; /* sign extend from 32 bits */
-	if (rax != -ENOSYS && entering(tcp)) {
-		if (debug)
-			fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
-		return 0;
+	if (entering(tcp) && !(ptrace_setoptions & PTRACE_O_TRACEEXEC)) {
+		if (upeek(tcp, 8*RAX, &rax) < 0)
+			return -1;
+		if (current_personality == 1)
+			rax = (long int)(int)rax; /* sign extend from 32 bits */
+		if (rax != -ENOSYS && entering(tcp)) {
+			if (debug)
+				fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
+			return 0;
+		}
 	}
 #elif defined (S390) || defined (S390X)
 	if (upeek(tcp, PT_GPR2, &gpr2) < 0)






More information about the Strace-devel mailing list