]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Arch-abstraction:
authorNicholas Nethercote <n.nethercote@gmail.com>
Mon, 18 Oct 2004 17:36:40 +0000 (17:36 +0000)
committerNicholas Nethercote <n.nethercote@gmail.com>
Mon, 18 Oct 2004 17:36:40 +0000 (17:36 +0000)
- factor out the horrid thread_syscall() function, which is written in assembly
  code.

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

coregrind/core.h
coregrind/vg_proxylwp.c
coregrind/x86-linux/ldt.c
coregrind/x86-linux/syscalls.c

index 4a972b1125a47172159596dd8ae968780b3f7292..fcbd760c5f3157cc34c6411f7ed0bd5a2ca5283b 100644 (file)
@@ -1339,6 +1339,18 @@ extern REGPARM(1)
    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);
 
@@ -1524,7 +1536,13 @@ extern Int  VGA_(pop_signal_frame)  ( ThreadId tid );
 // Platform-specific things defined in eg. x86/*.c
 // ---------------------------------------------------------------------
 
-void VGA_(restart_syscall)(arch_thread_t *tst);
+extern const Addr vga_sys_before, vga_sys_restarted,
+                  vga_sys_after, vga_sys_done;
+
+extern void VGA_(restart_syscall)(arch_thread_t* tst);
+
+extern void VGA_(thread_syscall)(Int syscallno, ThreadState* tst, 
+                                 enum PXState* state, enum PXState poststate);
 
 /* ---------------------------------------------------------------------
    Finally - autoconf-generated settings
index de25bc16976046e5151196977939a26e294ebb79..3b0a681a4f40a402936114612c3538fa554273b8 100644 (file)
 
 #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:
-
-   sys_before ... sys_restarted:
-       Setting up register arguments and running state.  If
-       interrupted, then the syscall should be considered to return
-       ERESTARTSYS.
-
-   sys_restarted:
-       If interrupted and eip==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.
-
-   sys_after:
-       If interrupted and eip==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).
-
-   sys_after ... 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.
-*/
-
-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 */
@@ -88,79 +41,6 @@ enum RequestType {
    PX_Exiting,                 /* reply sent by proxy for exit sync */
 };
 
-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);
-
-asm(
-".text\n"
-"      .type do_thread_syscall,@function\n"
-
-"do_thread_syscall:\n"
-"      push    %esi\n"
-"      push    %edi\n"
-"      push    %ebx\n"
-"      push    %ebp\n"
-".sys_before:\n"
-"      movl    16+ 4(%esp),%eax\n" /* syscall */
-"      movl    16+ 8(%esp),%ebx\n" /* arg1 */
-"      movl    16+12(%esp),%ecx\n" /* arg2 */
-"      movl    16+16(%esp),%edx\n" /* arg3 */
-"      movl    16+20(%esp),%esi\n" /* arg4 */
-"      movl    16+24(%esp),%edi\n" /* arg5 */
-"      movl    16+28(%esp),%ebp\n" /* arg6 */
-".sys_restarted:\n"
-"      int     $0x80\n"
-".sys_after:\n"
-"      movl    16+32(%esp),%ebx\n"     /* ebx = Int *res */
-"      movl    %eax, (%ebx)\n"         /* write the syscall retval */
-
-"      movl    16+36(%esp),%ebx\n"     /* ebx = enum PXState * */
-"      testl   %ebx, %ebx\n"
-"      jz      1f\n"
-
-"      movl    16+40(%esp),%ecx\n"     /* write the post state (must be after retval write) */
-"      movl    %ecx,(%ebx)\n"
-
-".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"
-".previous\n"
-
-".section .rodata\n"
-"sys_before:   .long   .sys_before\n"
-"sys_restarted:        .long   .sys_restarted\n"
-"sys_after:    .long   .sys_after\n"
-"sys_done:     .long   .sys_done\n"
-".previous\n"
-);
-extern const Addr sys_before, sys_restarted, sys_after, sys_done;
-
-/* 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, ThreadState *tst, 
-                          enum PXState *state , enum PXState poststate)
-{
-   do_thread_syscall(syscallno,   /* syscall no. */
-                    tst->arch.m_ebx,  /* arg 1 */
-                    tst->arch.m_ecx,  /* arg 2 */
-                    tst->arch.m_edx,  /* arg 3 */
-                    tst->arch.m_esi,  /* arg 4 */
-                    tst->arch.m_edi,  /* arg 5 */
-                    tst->arch.m_ebp,  /* arg 6 */
-                    &tst->arch.m_eax, /* result */
-                    state,       /* state to update */
-                    poststate);  /* state when syscall has finished */
-}
 
 #define VG_PROXY_MAGIC 0xef83b192
 struct ProxyLWP {
@@ -420,7 +300,7 @@ void VG_(proxy_handlesig)(const vki_ksiginfo_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 (sys_before <= ip && ip <= 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
@@ -428,7 +308,7 @@ void VG_(proxy_handlesig)(const vki_ksiginfo_t *siginfo, Addr ip, Int sysnum)
         the proxy and machine state here. */
       vg_assert(px->state == PXS_RunSyscall);
       vg_assert(PLATFORM_SYSCALL_RET(px->tst->arch) == -VKI_ERESTARTSYS);
-   } else if (sys_after <= ip && ip <= 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
@@ -740,7 +620,7 @@ static Int proxylwp(void *v)
 
               /* ST:4 */
               
-              thread_syscall(syscallno, tst, &px->state, PXS_SysDone);
+              VGA_(thread_syscall)(syscallno, tst, &px->state, PXS_SysDone);
 
               /* ST:5 */
 
index 42b976bd541b1757ba8eff452d017ebe10c23e1c..d22c0c5d6f145d75565260094313c24057180345 100644 (file)
@@ -1,6 +1,6 @@
 
 /*--------------------------------------------------------------------*/
-/*--- Simulation of Local Descriptor Tables               vg_ldt.c ---*/
+/*--- Simulation of Local Descriptor Tables        x86-linux/ldt.c ---*/
 /*--------------------------------------------------------------------*/
 
 /*
index d9e234a4436875f65eee7b45e4aac3ca4e84bfa9..6d5f59656515bfa3b285b035db6a57bb71e731f6 100644 (file)
@@ -1,6 +1,6 @@
 
 /*--------------------------------------------------------------------*/
-/*--- x86/Linux-specific syscalls, etc.                 syscalls.c ---*/
+/*--- x86/Linux-specific syscalls, etc.       x86-linux/syscalls.c ---*/
 /*--------------------------------------------------------------------*/
 
 /*
 
 #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);
+
+asm(
+".text\n"
+"      .type do_thread_syscall,@function\n"
+
+"do_thread_syscall:\n"
+"      push    %esi\n"
+"      push    %edi\n"
+"      push    %ebx\n"
+"      push    %ebp\n"
+".vga_sys_before:\n"
+"      movl    16+ 4(%esp),%eax\n" /* syscall */
+"      movl    16+ 8(%esp),%ebx\n" /* arg1 */
+"      movl    16+12(%esp),%ecx\n" /* arg2 */
+"      movl    16+16(%esp),%edx\n" /* arg3 */
+"      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"
+"      int     $0x80\n"
+".vga_sys_after:\n"
+"      movl    16+32(%esp),%ebx\n"     /* ebx = Int *res */
+"      movl    %eax, (%ebx)\n"         /* write the syscall retval */
+
+"      movl    16+36(%esp),%ebx\n"     /* ebx = enum PXState * */
+"      testl   %ebx, %ebx\n"
+"      jz      1f\n"
+
+"      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 */
+"1:    popl    %ebp\n"
+"      popl    %ebx\n"
+"      popl    %edi\n"
+"      popl    %esi\n"
+"      ret\n"
+"      .size do_thread_syscall,.-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"
+".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, ThreadState *tst, 
+                          enum PXState *state , enum PXState poststate)
+{
+   do_thread_syscall(syscallno,   /* syscall no. */
+                    tst->arch.m_ebx,  /* arg 1 */
+                    tst->arch.m_ecx,  /* arg 2 */
+                    tst->arch.m_edx,  /* arg 3 */
+                    tst->arch.m_esi,  /* arg 4 */
+                    tst->arch.m_edi,  /* arg 5 */
+                    tst->arch.m_ebp,  /* arg 6 */
+                    &tst->arch.m_eax, /* result */
+                    state,       /* state to update */
+                    poststate);  /* state when syscall has finished */
+}
+
+
+
 // Back up to restart a system call.
 void VGA_(restart_syscall)(arch_thread_t *tst)
 {