]> granicus.if.org Git - strace/commitdiff
Speed up x86 by avoiding EAX read on syscall entry
authorDenys Vlasenko <dvlasenk@redhat.com>
Wed, 24 Aug 2011 14:59:23 +0000 (16:59 +0200)
committerDenys Vlasenko <dvlasenk@redhat.com>
Wed, 24 Aug 2011 14:59:23 +0000 (16:59 +0200)
on x86, EAX read on syscall entry is 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.

* syscall.c (get_scno_on_sysexit): On I386 and X86_64, read eax/rax
which contain syscall return value.
(syscall_fixup): On I386 and X86_64, read eax/rax only on syscall enter
and only if PTRACE_O_TRACEEXEC is not in effect.

Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
syscall.c

index a6f47af42d6fff881e4ac56a64258d165403d945..fc502bf27a8464d255a2a5560ee61380712534a5 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -1307,7 +1307,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)
@@ -1468,22 +1472,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)