From: Julian Seward Date: Mon, 28 Feb 2005 17:27:04 +0000 (+0000) Subject: When handling syscalls, don't try to figure out if the pre-handler set X-Git-Tag: svn/VALGRIND_3_0_0~1064 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=006c9e84c35e6fa0141eba4078471e14866f17d1;p=thirdparty%2Fvalgrind.git When handling syscalls, don't try to figure out if the pre-handler set 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 --- diff --git a/coregrind/core.h b/coregrind/core.h index f145a3abc8..ac62debf5d 100644 --- a/coregrind/core.h +++ b/coregrind/core.h @@ -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)) \ diff --git a/coregrind/vg_syscalls.c b/coregrind/vg_syscalls.c index b18e402a60..4983e52760 100644 --- a/coregrind/vg_syscalls.c +++ b/coregrind/vg_syscalls.c @@ -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