From: Nicholas Nethercote Date: Wed, 24 Nov 2004 18:14:41 +0000 (+0000) Subject: Cleanups: X-Git-Tag: svn/VALGRIND_3_0_0~1221 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9680327dd9cda2dcad5bd96ad5c51fa53d381733;p=thirdparty%2Fvalgrind.git Cleanups: - move things around so that each arch doesn't duplicate stuff to do with VG_(do_thread_syscall)(). - enum PXState doesn't need to be visible outside vg_proxylwp.c git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3097 --- diff --git a/coregrind/core.h b/coregrind/core.h index 84454620e0..eae7980010 100644 --- a/coregrind/core.h +++ b/coregrind/core.h @@ -1318,18 +1318,6 @@ extern REGPARM(2) Exports of vg_proxylwp.c ------------------------------------------------------------------ */ -enum PXState -{ - PXS_BAD = -1, - PXS_WaitReq, /* waiting for a request */ - PXS_RunSyscall, /* running a syscall */ - PXS_IntReply, /* request interrupted - need to send reply */ - PXS_SysDone, /* small window between syscall - complete and results written out */ - PXS_SigACK, /* waiting for a signal ACK */ -}; - - /* Issue a syscall for thread tid */ extern Int VG_(sys_issue)(int tid); @@ -1872,14 +1860,53 @@ extern const struct SyscallTableEntry VGA_(syscall_table)[]; extern const UInt VGA_(syscall_table_size); - -extern const Addr vga_sys_before, vga_sys_restarted, - vga_sys_after, vga_sys_done; - extern void VGA_(restart_syscall)(ThreadArchState* arch); -extern void VGA_(thread_syscall)(Int syscallno, ThreadArchState* arch, - enum PXState* state, enum PXState poststate); +/* We need our own copy of VG_(do_syscall)() to handle a special + race-condition. If we've got signals unblocked, and we take a + signal in the gap either just before or after the syscall, we may + end up not running the syscall at all, or running it more than + once. + + The solution is to make the signal handler derive the proxy's + precise state by looking to see which eip it is executing at + exception time. + + Ranges: + + VGA_(sys_before) ... VGA_(sys_restarted): + Setting up register arguments and running state. If + interrupted, then the syscall should be considered to return + ERESTARTSYS. + + VGA_(sys_restarted): + If interrupted and eip==VGA_(sys_restarted), then either the syscall + was about to start running, or it has run, was interrupted and + the kernel wants to restart it. eax still contains the + syscall number. If interrupted, then the syscall return value + should be ERESTARTSYS. + + VGA_(sys_after): + If interrupted and eip==VGA_(sys_after), the syscall either just + finished, or it was interrupted and the kernel doesn't want to + restart it. Either way, eax equals the correct return value + (either the actual return value, or EINTR). + + VGA_(sys_after) ... VGA_(sys_done): + System call is complete, but the state hasn't been updated, + nor has the result been written back. eax contains the return + value. + + Freakin' horrible... +*/ +extern const Addr VGA_(sys_before), VGA_(sys_restarted), + VGA_(sys_after), VGA_(sys_done); + +extern void VGA_(do_thread_syscall)(UWord sys, + UWord arg1, UWord arg2, UWord arg3, + UWord arg4, UWord arg5, UWord arg6, + UWord *result, /*enum PXState*/Int *statep, + /*enum PXState*/Int poststate); /* --------------------------------------------------------------------- Finally - autoconf-generated settings diff --git a/coregrind/vg_proxylwp.c b/coregrind/vg_proxylwp.c index ae3d1f363b..83ee91da7f 100644 --- a/coregrind/vg_proxylwp.c +++ b/coregrind/vg_proxylwp.c @@ -31,6 +31,18 @@ #include "core.h" +enum PXState +{ + PXS_BAD = -1, + PXS_WaitReq, /* waiting for a request */ + PXS_RunSyscall, /* running a syscall */ + PXS_IntReply, /* request interrupted - need to send reply */ + PXS_SysDone, /* small window between syscall + complete and results written out */ + PXS_SigACK, /* waiting for a signal ACK */ +}; + + enum RequestType { PX_BAD = -1, PX_SetSigmask, /* sched->proxy; proxy->sched */ @@ -300,7 +312,7 @@ void VG_(proxy_handlesig)(const vki_siginfo_t *siginfo, Addr ip, Int sysnum) /* First look to see if the EIP is within our interesting ranges near a syscall to work out what should happen. */ - if (vga_sys_before <= ip && ip <= vga_sys_restarted) { + if (VGA_(sys_before) <= ip && ip <= VGA_(sys_restarted)) { /* We are before the syscall actually ran, or it did run and wants to be restarted. Either way, set the return code to indicate a restart. This is not really any different from @@ -308,7 +320,7 @@ void VG_(proxy_handlesig)(const vki_siginfo_t *siginfo, Addr ip, Int sysnum) the proxy and machine state here. */ vg_assert(px->state == PXS_RunSyscall); vg_assert(SYSCALL_RET(px->tst->arch) == -VKI_ERESTARTSYS); - } else if (vga_sys_after <= ip && ip <= vga_sys_done) { + } else if (VGA_(sys_after) <= ip && ip <= VGA_(sys_done)) { /* We're after the syscall. Either it was interrupted by the signal, or the syscall completed normally. In either case the usual register contains the correct syscall return value, and @@ -337,6 +349,30 @@ static Bool recv_reply(struct PX_Reply *reply) return VG_(read)(result_recv, reply, size) == size; } +/* Run a syscall for a particular thread, getting the arguments from + the thread's registers, and returning the result in the thread's + eax. + + Assumes that the only thread state which matters is the contents of + %eax-%ebp and the return value in %eax. + */ +static void thread_syscall(Int syscallno, ThreadArchState *arch, + enum PXState *state , enum PXState poststate) +{ + VGA_(do_thread_syscall)(syscallno, // syscall no. + arch->vex.guest_EBX, // arg 1 + arch->vex.guest_ECX, // arg 2 + arch->vex.guest_EDX, // arg 3 + arch->vex.guest_ESI, // arg 4 + arch->vex.guest_EDI, // arg 5 + arch->vex.guest_EBP, // arg 6 + (UWord*)&arch->vex.guest_EAX, // result + state, // state to update + poststate); // state when syscall has finished +} + + + /* Proxy LWP thread. This is run as a separate cloned() thread, so it MUST NOT touch any core Valgrind data structures directly: the only exception is while we're running a PX_RunSyscall command, we may @@ -620,8 +656,7 @@ static Int proxylwp(void *v) /* ST:4 */ - VGA_(thread_syscall)(syscallno, &tst->arch, - &px->state, PXS_SysDone); + thread_syscall(syscallno, &tst->arch, &px->state, PXS_SysDone); /* ST:5 */ diff --git a/coregrind/x86-linux/syscalls.c b/coregrind/x86-linux/syscalls.c index 97aede5211..e5cedbe8da 100644 --- a/coregrind/x86-linux/syscalls.c +++ b/coregrind/x86-linux/syscalls.c @@ -30,57 +30,20 @@ #include "core.h" -/* We need our own copy of VG_(do_syscall)() to handle a special - race-condition. If we've got signals unblocked, and we take a - signal in the gap either just before or after the syscall, we may - end up not running the syscall at all, or running it more than - once. - - The solution is to make the signal handler derive the proxy's - precise state by looking to see which eip it is executing at - exception time. - - Ranges: - - vga_sys_before ... vga_sys_restarted: - Setting up register arguments and running state. If - interrupted, then the syscall should be considered to return - ERESTARTSYS. - - vga_sys_restarted: - If interrupted and eip==vga_sys_restarted, then either the syscall - was about to start running, or it has run, was interrupted and - the kernel wants to restart it. eax still contains the - syscall number. If interrupted, then the syscall return value - should be ERESTARTSYS. - - vga_sys_after: - If interrupted and eip==vga_sys_after, the syscall either just - finished, or it was interrupted and the kernel doesn't want to - restart it. Either way, eax equals the correct return value - (either the actual return value, or EINTR). - - vga_sys_after ... vga_sys_done: - System call is complete, but the state hasn't been updated, - nor has the result been written back. eax contains the return - value. -*/ -extern void do_thread_syscall(Int sys, - Int arg1, Int arg2, Int arg3, Int arg4, - Int arg5, Int arg6, - Int *result, enum PXState *statep, - enum PXState poststate); +// See the comment accompanying the declaration of VGA_(thread_syscall)() in +// coregrind/core.h for an explanation of what this does, and why. asm( ".text\n" -" .type do_thread_syscall,@function\n" +" .type vgArch_do_thread_syscall,@function\n" -"do_thread_syscall:\n" +".globl vgArch_do_thread_syscall\n" +"vgArch_do_thread_syscall:\n" " push %esi\n" " push %edi\n" " push %ebx\n" " push %ebp\n" -".vga_sys_before:\n" +".vgArch_sys_before:\n" " movl 16+ 4(%esp),%eax\n" /* syscall */ " movl 16+ 8(%esp),%ebx\n" /* arg1 */ " movl 16+12(%esp),%ecx\n" /* arg2 */ @@ -88,9 +51,9 @@ asm( " movl 16+20(%esp),%esi\n" /* arg4 */ " movl 16+24(%esp),%edi\n" /* arg5 */ " movl 16+28(%esp),%ebp\n" /* arg6 */ -".vga_sys_restarted:\n" +".vgArch_sys_restarted:\n" " int $0x80\n" -".vga_sys_after:\n" +".vgArch_sys_after:\n" " movl 16+32(%esp),%ebx\n" /* ebx = Int *res */ " movl %eax, (%ebx)\n" /* write the syscall retval */ @@ -101,51 +64,27 @@ asm( " movl 16+40(%esp),%ecx\n" /* write the post state (must be after retval write) */ " movl %ecx,(%ebx)\n" -".vga_sys_done:\n" /* OK, all clear from here */ +".vgArch_sys_done:\n" /* OK, all clear from here */ "1: popl %ebp\n" " popl %ebx\n" " popl %edi\n" " popl %esi\n" " ret\n" -" .size do_thread_syscall,.-do_thread_syscall\n" +" .size vgArch_do_thread_syscall,.-vgArch_do_thread_syscall\n" ".previous\n" ".section .rodata\n" -" .globl vga_sys_before\n" -"vga_sys_before: .long .vga_sys_before\n" -" .globl vga_sys_restarted\n" -"vga_sys_restarted: .long .vga_sys_restarted\n" -" .globl vga_sys_after\n" -"vga_sys_after: .long .vga_sys_after\n" -" .globl vga_sys_done\n" -"vga_sys_done: .long .vga_sys_done\n" +" .globl vgArch_sys_before\n" +"vgArch_sys_before: .long .vgArch_sys_before\n" +" .globl vgArch_sys_restarted\n" +"vgArch_sys_restarted: .long .vgArch_sys_restarted\n" +" .globl vgArch_sys_after\n" +"vgArch_sys_after: .long .vgArch_sys_after\n" +" .globl vgArch_sys_done\n" +"vgArch_sys_done: .long .vgArch_sys_done\n" ".previous\n" ); -/* Run a syscall for a particular thread, getting the arguments from - the thread's registers, and returning the result in the thread's - eax. - - Assumes that the only thread state which matters is the contents of - %eax-%ebp and the return value in %eax. - */ -void VGA_(thread_syscall)(Int syscallno, ThreadArchState *arch, - enum PXState *state , enum PXState poststate) -{ - do_thread_syscall(syscallno, // syscall no. - arch->vex.guest_EBX, // arg 1 - arch->vex.guest_ECX, // arg 2 - arch->vex.guest_EDX, // arg 3 - arch->vex.guest_ESI, // arg 4 - arch->vex.guest_EDI, // arg 5 - arch->vex.guest_EBP, // arg 6 - &arch->vex.guest_EAX, // result - state, // state to update - poststate); // state when syscall has finished -} - - - // Back up to restart a system call. void VGA_(restart_syscall)(ThreadArchState *arch) {