]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
When handling syscalls, don't try to figure out if the pre-handler set
authorJulian Seward <jseward@acm.org>
Mon, 28 Feb 2005 17:27:04 +0000 (17:27 +0000)
committerJulian Seward <jseward@acm.org>
Mon, 28 Feb 2005 17:27:04 +0000 (17:27 +0000)
the syscall result by inspecting RES after the pre-handler has run.
Instead, give each thread a syscall_result_set Bool, and make
SET_RESULT set it.  Inspect that Bool.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3254

coregrind/core.h
coregrind/vg_syscalls.c

index f145a3abc81c93ac5c0848c060bc94ba3870e275..ac62debf5dbcf6ffdb36ae2c1c1f3e2e17999db4 100644 (file)
@@ -863,6 +863,11 @@ typedef struct ProxyLWP ProxyLWP;
 
    /* Architecture-specific thread state */
    ThreadArchState arch;
+
+   /* Used in the syscall handlers.  Set to True to indicate that the
+      PRE routine for a syscall has set the syscall result already and
+      so the syscall does not need to be handed to the kernel. */
+   Bool syscall_result_set;
 };
 //ThreadState;
 
@@ -1424,7 +1429,10 @@ void VG_(record_fd_open)(ThreadId tid, Int fd, char *pathname);
 #define ARG5    SYSCALL_ARG5(tst->arch)
 #define ARG6    SYSCALL_ARG6(tst->arch)
 
-#define SET_RESULT(val) PLATFORM_SET_SYSCALL_RESULT(tst->arch, (val))
+#define SET_RESULT(val)                                \
+   do { PLATFORM_SET_SYSCALL_RESULT(tst->arch, (val)); \
+        tst->syscall_result_set = True;                \
+   } while (0)
 
 #define PRINT(format, args...)  \
    if (VG_(clo_trace_syscalls))        \
index b18e402a60cb4e1b2d9fb6af58ff3ab421aea367..4983e52760088c4d00616ef695e19abcf70ab11e 100644 (file)
@@ -3694,6 +3694,7 @@ PRE(old_mmap, Special)
 
    if (RES != -VKI_ENOMEM) {
       PLATFORM_DO_MMAP(RES, a1, a2, a3, a4, a5, a6);
+      SET_RESULT(RES);
 
       if (!VG_(is_kerror)(RES)) {
          vg_assert(VG_(valid_client_addr)(RES, a2, tid, "old_mmap"));
@@ -4901,6 +4902,7 @@ PRE(sys_rt_sigaction, Special)
    // sys_rt_sigaction... perhaps this function should be renamed
    // VG_(do_sys_rt_sigaction)()  --njn
    VG_(do_sys_sigaction)(tid);
+   SET_RESULT( 0/*success*/ );
 }
 
 POST(sys_rt_sigaction)
@@ -4968,11 +4970,13 @@ PRE(sys_rt_sigprocmask, Special)
    // Like the kernel, we fail if the sigsetsize is not exactly what we expect.
    if (sizeof(vki_sigset_t) != ARG4)
       SET_RESULT( -VKI_EMFILE );
-   else
+   else {
       VG_(do_sys_sigprocmask) ( tid, 
                                ARG1 /*how*/, 
                                (vki_sigset_t*) ARG2,
                                (vki_sigset_t*) ARG3 );
+      SET_RESULT( 0/*success*/ );
+   }
 }
 
 POST(sys_rt_sigprocmask)
@@ -5319,6 +5323,7 @@ Bool VG_(pre_syscall) ( ThreadId tid )
       VGP_PUSHCC(VgpToolSysWrap);
       TL_(pre_syscall)(tid, syscallno);
       VGP_POPCC(VgpToolSysWrap);
+      /* This may result in tst->syscall_result_set becoming True. */
    }
 
    PRINT("SYSCALL[%d,%d](%3d)%s%s:", 
@@ -5334,22 +5339,22 @@ Bool VG_(pre_syscall) ( ThreadId tid )
         sets the result.  Special syscalls cannot block. */
       vg_assert(!mayBlock && !runInLWP);
 
+      tst->syscall_result_set = False;
       (sys->before)(tst->tid, tst);
 
       vg_assert(tst->sys_flags == flags);
+      vg_assert(tst->syscall_result_set == True);
 
       PRINT(" --> %lld (0x%llx)\n", (Long)(Word)RES, (ULong)RES);
       syscall_done = True;
    } else {
+      tst->syscall_result_set = False;
       (sys->before)(tst->tid, tst);
 
-      /* JRS 2005 Feb 10: checking RES <= 0 causes sys_read to appear
-         to fail on amd64, because RES and the syscall number (0) live
-         in the same guest register -- %RAX.  Bad. */
-      if ((Word)RES < 0) {
-        /* "before" decided the syscall wasn't viable, so don't do
-           anything - just pretend the syscall happened. */
-         PRINT(" ==> %lld (0x%llx)\n", (Long)(Word)RES, (ULong)RES);
+      if (tst->syscall_result_set) {
+        /* "before" decided to provide a syscall result itself, so
+           don't do anything - just pretend the syscall happened. */
+         PRINT(" ==> %lld (0x%llx)\n", (Long)RES, (ULong)RES);
         syscall_done = True;
       } else if (runInLWP) {
         /* Issue to worker.  If we're waiting on the syscall because