]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Clean up after m_syscalls changes: unbreak amd64-linux.
authorJulian Seward <jseward@acm.org>
Thu, 9 Jun 2005 12:43:42 +0000 (12:43 +0000)
committerJulian Seward <jseward@acm.org>
Thu, 9 Jun 2005 12:43:42 +0000 (12:43 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3856

14 files changed:
NOTES.txt
coregrind/amd64/state.c
coregrind/m_debuginfo/symtab.c
coregrind/m_libcbase.c
coregrind/m_signals.c
coregrind/m_syscalls/priv_syscalls-amd64-linux.h
coregrind/m_syscalls/priv_syscalls-generic.h
coregrind/m_syscalls/syscall-amd64-linux.S
coregrind/m_syscalls/syscall-x86-linux.S
coregrind/m_syscalls/syscalls-amd64-linux.c
coregrind/m_syscalls/syscalls-generic.c
coregrind/m_syscalls/syscalls-main.c
coregrind/m_syscalls/syscalls-x86-linux.c
coregrind/pub_core_libcbase.h

index 5401238bfd6f862be84d24e65bd20f24ba48bc2e..d9887ba07a297c8c48a0c5edd5ae7744ab5ce299 100644 (file)
--- a/NOTES.txt
+++ b/NOTES.txt
@@ -5,7 +5,7 @@ ToDo: vex-amd64: check above/below the line for reg-alloc
 9 June 05 (after major syscalls overhaul)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 corecheck/m_syscalls/syscalls-x86-linux.h is now empty.  Should it be
-deleted?
+deleted?  Ditto corecheck/m_syscalls/syscalls-amd64-linux.h.
 
 23 Apr 05 (memcheck-on-amd64 notes)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
index b119873174c2bd506166a73be0b17ab030152782..4159c9b208aaed3a9a5787c278d2b09a7a3dbced 100644 (file)
@@ -76,11 +76,12 @@ void VGA_(init_thread1state) ( Addr client_rip,
    VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State));
 
    /* Put essential stuff into the new state. */
-   if (0) 
-      VG_(printf)("startup rsp 0x%llx  rip 0x%llx\n", 
-                  rsp_at_startup, client_rip);
+
    arch->vex.guest_RSP = rsp_at_startup;
    arch->vex.guest_RIP = client_rip;
+
+   VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
+             sizeof(VexGuestArchState));
 }
 
 
index c0787ae65d5469bb91767bea6a4dcfeeed13c601..1d20ad4194adb38a7341b50bb1b2f4d67d1cd108 100644 (file)
@@ -1718,12 +1718,16 @@ Bool read_lib_symbols ( SegInfo* si )
          VG_(read_callframe_info_dwarf2) ( si, ehframe, ehframe_sz, ehframe_addr );
       }
 
-      /* Read the stabs and/or dwarf2 debug information, if any. */
+      /* Read the stabs and/or dwarf2 debug information, if any.  It
+         appears reading stabs stuff on amd64-linux doesn't work, so
+         we ignore it. */
+#     if !defined(VGP_amd64_linux)
       if (stab != NULL && stabstr != NULL) {
          has_debuginfo = True;
          VG_(read_debuginfo_stabs) ( si, stab, stab_sz, 
                                          stabstr, stabstr_sz );
       }
+#     endif
       if (debug_line) {
          has_debuginfo = True;
          VG_(read_debuginfo_dwarf2) ( si, debug_line, debug_line_sz );
index 2ed7f821679b765beb9c8a8453f83e3d402b41a3..1f1a53b2931b6dd053a2d98639cfacc46f46693d 100644 (file)
@@ -504,6 +504,44 @@ asm(
 #endif
 
 
+#if defined(VGP_amd64_linux)
+/* Perform a Linux syscall with the "syscall" instruction.
+       
+   Incoming args (syscall number + up to 6 args) come in %rdi, %rsi,
+   %rdx, %rcx, %r8, %r9, and the last one on the stack (ie. the C
+   calling convention).
+
+   They are passed to the syscall in the regs %rdi, %rsi, %rdx, %r10,
+   %r8, %r9 (yes, really %r10, not %rcx), ie. the kernel's syscall
+   calling convention.
+
+   %rax holds the syscall number and gets the return value.  %rcx and
+   %r11 are clobbered by the syscall; no matter, they are caller-save
+   (the syscall clobbers no callee-save regs, so we don't have to do
+   any register saving/restoring).
+*/
+extern ULong do_syscall_amd64_linux_WRK (
+          ULong syscall_no, 
+          ULong a1, ULong a2, ULong a3,
+          ULong a4, ULong a5, ULong a6
+       );
+asm(
+"do_syscall_amd64_linux_WRK:\n"
+        /* Convert function calling convention --> syscall calling
+           convention */
+"      movq    %rdi, %rax\n"
+"      movq    %rsi, %rdi\n"
+"      movq    %rdx, %rsi\n"
+"      movq    %rcx, %rdx\n"
+"      movq    %r8,  %r10\n"
+"      movq    %r9,  %r8\n"
+"      movq    8(%rsp), %r9\n"  /* last arg from stack */
+"      syscall\n"
+"      ret\n"
+);
+#endif
+
+
 SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3, 
                                       UWord a4, UWord a5, UWord a6 )
 {
@@ -514,8 +552,14 @@ SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3,
    res = VG_(mk_SysRes_x86_linux)( eax );
 #  else
 
+#  if defined(VGP_amd64_linux)
+   ULong rax = do_syscall_amd64_linux_WRK(sysno,a1,a2,a3,a4,a5,a6);
+   res = VG_(mk_SysRes_amd64_linux)( rax );
+#  else
+
 #    error VG_(do_syscall): unimplemented on this platform
 
+#  endif
 #  endif
 
    return res;
index 5f3adc5b4d290a24a1eb2ec238eeb87157e524d5..45abd4506c7325a4e6702ff59d2a803d576ef8b0 100644 (file)
@@ -127,18 +127,23 @@ typedef struct SigQueue {
 #  define VGP_UCONTEXT_SYSCALL_SYSRES(uc)                       \
       /* Convert the value in uc_mcontext.eax into a SysRes. */ \
       VG_(mk_SysRes_x86_linux)( (uc)->uc_mcontext.eax )
+
 #elif defined(VGP_amd64_linux)
 #  define VGP_UCONTEXT_INSTR_PTR(uc)      ((uc)->uc_mcontext.rip)
 #  define VGP_UCONTEXT_STACK_PTR(uc)      ((uc)->uc_mcontext.rsp)
 #  define VGP_UCONTEXT_FRAME_PTR(uc)      ((uc)->uc_mcontext.rbp)
 #  define VGP_UCONTEXT_SYSCALL_NUM(uc)    ((uc)->uc_mcontext.rax)
-#  define VGP_UCONTEXT_SYSCALL_RET(uc)    ((uc)->uc_mcontext.rax)
+#  define VGP_UCONTEXT_SYSCALL_SYSRES(uc)                       \
+      /* Convert the value in uc_mcontext.rax into a SysRes. */ \
+      VG_(mk_SysRes_amd64_linux)( (uc)->uc_mcontext.rax )
+
 #elif defined(VGP_arm_linux)
 #  define VGP_UCONTEXT_INSTR_PTR(uc)     ((uc)->uc_mcontext.arm_pc)
 #  define VGP_UCONTEXT_STACK_PTR(uc)     ((uc)->uc_mcontext.arm_sp)
 #  define VGP_UCONTEXT_FRAME_PTR(uc)     ((uc)->uc_mcontext.arm_fp)
 #  define VGP_UCONTEXT_SYSCALL_NUM(uc)   ((uc)->uc_mcontext.arm_r0)
 #  error VGP_UCONTEXT_SYSCALL_RET undefined for ARM/Linux
+
 #else
 #  error Unknown platform
 #endif
index ff7d2eb509463423f7e82dd598bcbc78b1461ef7..0f7bdd8dddb4a444dde50e28fb151b7b3c566440 100644 (file)
 #ifndef __PRIV_SYSCALLS_AMD64_LINUX_H
 #define __PRIV_SYSCALLS_AMD64_LINUX_H
 
-// Accessors for the ThreadArchState
-#define VGP_SYSCALL_NUM       guest_RAX
-#define VGP_SYSCALL_ARG1      guest_RDI
-#define VGP_SYSCALL_ARG2      guest_RSI
-#define VGP_SYSCALL_ARG3      guest_RDX
-#define VGP_SYSCALL_ARG4      guest_R10
-#define VGP_SYSCALL_ARG5      guest_R8
-#define VGP_SYSCALL_ARG6      guest_R9
-#define VGP_SYSCALL_RET       guest_RAX
-
-// Setting a syscall result
-#define VGP_SET_SYSCALL_RESULT(regs, val)    ((regs).vex.guest_RAX = (val))
-
-// For informing tools that a syscall result has been set.
-#define VGP_TRACK_SYSCALL_RETVAL(zztid) \
-   VG_TRACK( post_reg_write, Vg_CoreSysCall, zztid, O_SYSCALL_RET, sizeof(UWord) );
-
 #endif   // __PRIV_SYSCALLS_AMD64_LINUX_H
 
 /*--------------------------------------------------------------------*/
index 9562dffe9cc50c6ce1c7f9fd7b95d9516546921d..a3bd8ac3befd2f417dd9d6da3f8a4474839feb9f 100644 (file)
@@ -319,4 +319,3 @@ extern void   VG_(generic_POST_sys_shmctl)      ( TId, UW, UW, UW, UW );
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
 /*--------------------------------------------------------------------*/
-
index 8ca293f048ee31ee5378c72bb90f355553a66192..419772a9f0074eb034450231af1ed10d27dfd9f8 100644 (file)
 #include "vki_unistd.h"
 #include "libvex_guest_offsets.h"
 
-/*
-       Perform a Linux syscall with the "syscall" instruction.
-       
-       Incoming args (syscall number + up to 6 args) come in 
-       %rdi, %rsi, %rdx, %rcx, %r8, %r9, and the last one on the stack
-       (ie. the C calling convention).
-
-       They are passed to the syscall in the regs
-       %rdi, %rsi, %rdx, %r10, %r8, %r9 (yes, really %r10, not %rcx), ie. the
-       kernel's syscall calling convention.
-
-       %rax holds the syscall number and gets the return value.
-       %rcx and %r11 are clobbered by the syscall;  no matter, they
-       are caller-save (the syscall clobbers no callee-save regs, so
-       we don't have to do any register saving/restoring).
-
-       This has no effect on the virtual machine; the expectation is
-       that the syscall mechanism makes no useful changes to any
-       register except %rax, which is returned.
-*/
-.globl VG_(do_syscall)
-VG_(do_syscall):
-       # Convert function calling convention --> syscall calling convention
-       movq    %rdi, %rax
-       movq    %rsi, %rdi
-       movq    %rdx, %rsi
-       movq    %rcx, %rdx
-       movq    %r8,  %r10
-       movq    %r9,  %r8
-       movq    8(%rsp), %r9            # last arg from stack
-       syscall
-       ret
-
-
-/*
-        Perform a clone system call.  clone is strange because it has
-        fork()-like return-twice semantics, so it needs special
-        handling here.
-
-       Upon entry, we have:
-
-           int (*fn)(void*)    in %rdi
-           void*  child_stack  in %rsi
-           int    flags        in %rdx
-           void*  arg          in %rcx
-           pid_t* child_tid    in %r8
-           pid_t* parent_tid   in %r9
-           void*  tls_ptr      at 8(%rsp)
-
-       System call requires:
-
-           int    $__NR_clone  in %rax
-           int    flags        in %rdi
-           void*  child_stack  in %rsi
-           pid_t* parent_tid   in %rdx
-           pid_t* child_tid    in %r10
-           void*  tls_ptr      in %r8
- */
-.globl VG_(clone)
-VG_(clone):
-        // set up child stack, temporarily preserving fn and arg
-        subq    $16, %rsi               // make space on stack
-        movq    %rcx, 8(%rsi)           // save arg
-        movq    %rdi, 0(%rsi)           // save fn 
-        
-        // setup syscall
-        movq    $__NR_clone, %rax       // syscall number
-        movq    %rdx,     %rdi          // syscall arg1: flags
-        // %rsi already setup           // syscall arg2: child_stack
-        movq    %r9,      %rdx          // syscall arg3: parent_tid
-        movq    %r8,      %r10          // syscall arg4: child_tid
-        movq    8(%rsp),  %r8           // syscall arg5: tls_ptr
-
-        syscall                         // clone()
-
-        testq   %rax, %rax              // child if retval == 0
-        jnz     1f
-
-        // CHILD - call thread function
-        pop     %rax                    // pop fn
-        pop     %rdi                    // pop fn arg1: arg
-        call    *%rax                   // call fn
-
-        // exit with result
-        movq    %rax, %rdi              // arg1: return value from fn
-        movq    $__NR_exit, %rax
-
-        syscall
-
-        // Exit returned?!
-        ud2
-
-1:      // PARENT or ERROR
-        ret
 
+/*----------------------------------------------------------------*/
 .globl VG_(sigreturn)
 VG_(sigreturn):
         movq    $__NR_rt_sigreturn, %rax
@@ -159,7 +66,8 @@ VG_(sigreturn):
        
        Prototype:
 
-       Int VGA_(_client_syscall)(Int syscallno,                // rdi
+       Int VGA_(do_syscall_for_client_WRK(
+                                 Int syscallno,                // rdi
                                  void* guest_state,            // rsi
                                  const vki_sigset_t *sysmask,  // rdx
                                  const vki_sigset_t *postmask, // rcx
@@ -170,8 +78,8 @@ VG_(sigreturn):
 /* from vki_arch.h */  
 #define VKI_SIG_SETMASK        2
        
-.globl VGA_(_client_syscall)
-VGA_(_client_syscall):
+.globl VGA_(do_syscall_for_client_WRK)
+VGA_(do_syscall_for_client_WRK):
        /* save callee-saved regs */
        pushq   %rbx
        pushq   %rbp
index 5e403b0a359e8d374e7cb374ffd17c907c7da77d..81fb6abc137d53862bc2210c0995890aa2f3bdb6 100644 (file)
 #include "libvex_guest_offsets.h"
                
        
+/*----------------------------------------------------------------*/
 .globl VG_(sigreturn)
 VG_(sigreturn):
        movl    $__NR_rt_sigreturn, %eax
        int     $0x80
 
-
+/*----------------------------------------------------------------*/
 /*
        Perform a syscall for the client.  This will run a syscall
        with the client's specific per-thread signal mask.
index 62b15dcdddb080496d24e93b7160301824c57bf4..4efbdb37d9cf73965284c873965ec7786498f7a4 100644 (file)
 #include "ume.h"                /* for jmp_with_stack */
 #include "pub_core_debuglog.h"
 #include "pub_core_aspacemgr.h"
+#include "pub_core_options.h"
+#include "pub_core_libcbase.h"
 #include "pub_core_libcassert.h"
 #include "pub_core_libcprint.h"
 #include "pub_core_sigframe.h"
 #include "pub_core_syscalls.h"
 #include "pub_core_tooliface.h"
-#include "priv_syscalls.h"
+#include "pub_core_signals.h"
 
+#include "priv_types_n_macros.h"
+#include "priv_syscalls-generic.h"   /* for decls of generic wrappers */
+#include "priv_syscalls-linux.h"     /* for decls of linux-ish wrappers */
+#include "priv_syscalls-main.h"
+
+#include "vki_unistd.h"              /* for the __NR_* constants */
 
 /* COPIED FROM /usr/include/asm-i386/prctl.h (amd64-linux) */
 #define ARCH_SET_GS 0x1001
    Note.  Why is this stuff here?
    ------------------------------------------------------------------ */
 
-/* These are addresses within VGA_(client_syscall).  See syscall.S for details. */
-extern const Addr VGA_(blksys_setup);
-extern const Addr VGA_(blksys_restart);
-extern const Addr VGA_(blksys_complete);
-extern const Addr VGA_(blksys_committed);
-extern const Addr VGA_(blksys_finished);
-
-// Back up to restart a system call.
-static void restart_syscall(ThreadArchState *arch)
-{
-   arch->vex.guest_RIP -= 2;             // sizeof(syscall)
-
-   /* Make sure our caller is actually sane, and we're really backing
-      back over a syscall.
-
-      syscall == 0F 05 
-   */
-   {
-      UChar *p = (UChar *)arch->vex.guest_RIP;
-      
-      if (p[0] != 0x0F || p[1] != 0x05)
-         VG_(message)(Vg_DebugMsg,
-                      "?! restarting over syscall at %p %02x %02x\n",
-                      arch->vex.guest_RIP, p[0], p[1]); 
-
-      vg_assert(p[0] == 0x0F && p[1] == 0x05);
-   }
-}
-
-/* 
-   Fix up the VCPU state when a syscall is interrupted by a signal.
-
-   To do this, we determine the precise state of the syscall by
-   looking at the (real) rip at the time the signal happened.  The
-   syscall sequence looks like:
-
-     1. unblock signals
-     2. perform syscall
-     3. save result to RAX
-     4. re-block signals
-
-   If a signal
-   happens at      Then     Why?
-   [1-2)           restart  nothing has happened (restart syscall)
-   [2]             restart  syscall hasn't started, or kernel wants to restart
-   [2-3)           save     syscall complete, but results not saved
-   [3-4)           syscall complete, results saved
-
-   Sometimes we never want to restart an interrupted syscall (because
-   sigaction says not to), so we only restart if "restart" is True.
-
-   This will also call VG_(post_syscall)() if the syscall has actually
-   completed (either because it was interrupted, or because it
-   actually finished).  It will not call VG_(post_syscall)() if the
-   syscall is set up for restart, which means that the pre-wrapper may
-   get called multiple times.
- */
-/* NB: this is identical to the x86 version */
-void VGP_(interrupted_syscall)(ThreadId tid, 
-                               Word ip, UWord sysnum, UWord sysret,
-                              Bool restart)
-{
-   static const Bool debug = 0;
-
-   ThreadState *tst = VG_(get_ThreadState)(tid);
-   ThreadArchState *th_regs = &tst->arch;
-
-   if (debug)
-      VG_(printf)("interrupted_syscall: ip=%p; restart=%d eax=%d\n", 
-                 ip, restart, sysnum);
-
-   if (ip < VGA_(blksys_setup) || ip >= VGA_(blksys_finished)) {
-      VG_(printf)("  not in syscall (%p - %p)\n", VGA_(blksys_setup), VGA_(blksys_finished));
-      vg_assert(tst->syscallno == -1);
-      return;
-   }
-
-   vg_assert(tst->syscallno != -1);
-
-   if (ip >= VGA_(blksys_setup) && ip < VGA_(blksys_restart)) {
-      /* syscall hasn't even started; go around again */
-      if (debug)
-        VG_(printf)("  not started: restart\n");
-      restart_syscall(th_regs);
-   } else if (ip == VGA_(blksys_restart)) {
-      /* We're either about to run the syscall, or it was interrupted
-        and the kernel restarted it.  Restart if asked, otherwise
-        EINTR it. */
-      if (restart)
-        restart_syscall(th_regs);
-      else {
-        th_regs->vex.VGP_SYSCALL_RET = -VKI_EINTR;
-        VG_(post_syscall)(tid);
-      }
-   } else if (ip >= VGA_(blksys_complete) && ip < VGA_(blksys_committed)) {
-      /* Syscall complete, but result hasn't been written back yet.
-        The saved real CPU %rax has the result, which we need to move
-        to RAX. */
-      if (debug)
-        VG_(printf)("  completed: ret=%d\n", sysret);
-      th_regs->vex.VGP_SYSCALL_RET = sysret;
-      VG_(post_syscall)(tid);
-   } else if (ip >= VGA_(blksys_committed) && ip < VGA_(blksys_finished)) {
-      /* Result committed, but the signal mask has not been restored;
-        we expect our caller (the signal handler) will have fixed
-        this up. */
-      if (debug)
-        VG_(printf)("  all done\n");
-      VG_(post_syscall)(tid);
-   } else
-      VG_(core_panic)("?? strange syscall interrupt state?");
-   
-   tst->syscallno = -1;
-}
-
-extern void VGA_(_client_syscall)(Int syscallno, 
-                                  void* guest_state,
-                                 const vki_sigset_t *syscall_mask,
-                                 const vki_sigset_t *restore_mask,
-                                 Int nsigwords);
-
-void VGA_(client_syscall)(Int syscallno, ThreadState *tst,
-                         const vki_sigset_t *syscall_mask)
-{
-   vki_sigset_t saved;
-   VGA_(_client_syscall)(syscallno, &tst->arch.vex, 
-                         syscall_mask, &saved, _VKI_NSIG_WORDS * sizeof(UWord));
-}
-
-
 /* 
    Allocate a stack for this thread.
 
@@ -256,7 +134,7 @@ static void run_a_thread_NORETURN ( Word tidW )
 {
    ThreadId tid = (ThreadId)tidW;
 
-   VG_(debugLog)(1, "syscalls-x86-linux", 
+   VG_(debugLog)(1, "syscalls-amd64-linux", 
                     "run_a_thread_NORETURN(tid=%lld): "
                        "VGO_(thread_wrapper) called\n",
                        (ULong)tidW);
@@ -264,7 +142,7 @@ static void run_a_thread_NORETURN ( Word tidW )
    /* Run the thread all the way through. */
    VgSchedReturnCode src = VGO_(thread_wrapper)(tid);  
 
-   VG_(debugLog)(1, "syscalls-x86-linux", 
+   VG_(debugLog)(1, "syscalls-amd64-linux", 
                     "run_a_thread_NORETURN(tid=%lld): "
                        "VGO_(thread_wrapper) done\n",
                        (ULong)tidW);
@@ -274,7 +152,7 @@ static void run_a_thread_NORETURN ( Word tidW )
 
    if (c == 1) {
 
-      VG_(debugLog)(1, "syscalls-x86-linux", 
+      VG_(debugLog)(1, "syscalls-amd64-linux", 
                        "run_a_thread_NORETURN(tid=%lld): "
                           "last one standing\n",
                           (ULong)tidW);
@@ -285,7 +163,7 @@ static void run_a_thread_NORETURN ( Word tidW )
 
    } else {
 
-      VG_(debugLog)(1, "syscalls-x86-linux", 
+      VG_(debugLog)(1, "syscalls-amd64-linux", 
                        "run_a_thread_NORETURN(tid=%lld): "
                           "not last one standing\n",
                           (ULong)tidW);
@@ -347,7 +225,7 @@ void VGP_(main_thread_wrapper_NORETURN)(ThreadId tid)
 }
 
 
-static Int start_thread_NORETURN ( void* arg )
+static Long start_thread_NORETURN ( void* arg )
 {
    ThreadState* tst = (ThreadState*)arg;
    ThreadId     tid = tst->tid;
@@ -362,6 +240,90 @@ static Int start_thread_NORETURN ( void* arg )
    clone() handling
    ------------------------------------------------------------------ */
 
+/*
+        Perform a clone system call.  clone is strange because it has
+        fork()-like return-twice semantics, so it needs special
+        handling here.
+
+       Upon entry, we have:
+
+           int (*fn)(void*)    in %rdi
+           void*  child_stack  in %rsi
+           int    flags        in %rdx
+           void*  arg          in %rcx
+           pid_t* child_tid    in %r8
+           pid_t* parent_tid   in %r9
+           void*  tls_ptr      at 8(%rsp)
+
+       System call requires:
+
+           int    $__NR_clone  in %rax
+           int    flags        in %rdi
+           void*  child_stack  in %rsi
+           pid_t* parent_tid   in %rdx
+           pid_t* child_tid    in %r10
+           void*  tls_ptr      in %r8
+
+       Returns a Long encoded in the linux-amd64 way, not a SysRes.
+ */
+#define STRINGIFZ(__str) #__str
+#define STRINGIFY(__str)  STRINGIFZ(__str)
+#define __NR_CLONE        STRINGIFY(__NR_clone)
+#define __NR_EXIT         STRINGIFY(__NR_exit)
+
+extern
+Long do_syscall_clone_amd64_linux ( Long (*fn)(void *), 
+                                    void* stack, 
+                                    Long  flags, 
+                                    void* arg,
+                                    Long* child_tid, 
+                                    Long* parent_tid, 
+                                    vki_modify_ldt_t * );
+asm(
+"\n"
+"do_syscall_clone_amd64_linux:\n"
+        // set up child stack, temporarily preserving fn and arg
+"       subq    $16, %rsi\n"            // make space on stack
+"       movq    %rcx, 8(%rsi)\n"        // save arg
+"       movq    %rdi, 0(%rsi)\n"        // save fn 
+        
+        // setup syscall
+"       movq    $"__NR_CLONE", %rax\n"  // syscall number
+"       movq    %rdx,     %rdi\n"       // syscall arg1: flags
+        // %rsi already setup           // syscall arg2: child_stack
+"       movq    %r9,      %rdx\n"       // syscall arg3: parent_tid
+"       movq    %r8,      %r10\n"       // syscall arg4: child_tid
+"       movq    8(%rsp),  %r8\n"        // syscall arg5: tls_ptr
+
+"       syscall\n"                      // clone()
+
+"       testq   %rax, %rax\n"           // child if retval == 0
+"       jnz     1f\n"
+
+        // CHILD - call thread function
+"       pop     %rax\n"                 // pop fn
+"       pop     %rdi\n"                 // pop fn arg1: arg
+"       call    *%rax\n"                // call fn
+
+        // exit with result
+"       movq    %rax, %rdi\n"           // arg1: return value from fn
+"       movq    $"__NR_EXIT", %rax\n"
+
+"       syscall\n"
+
+        // Exit returned?!
+"       ud2\n"
+
+"1:\n"  // PARENT or ERROR
+"       ret\n"
+);
+
+#undef __NR_CLONE
+#undef __NR_EXIT
+#undef STRINGIFY
+#undef STRINGIFZ
+
+
 // forward declaration
 static void setup_child ( ThreadArchState*, ThreadArchState* );
 
@@ -375,20 +337,21 @@ static void setup_child ( ThreadArchState*, ThreadArchState* );
    but using the scheduler entrypoint for EIP, and a separate stack
    for ESP.
  */
-static Int do_clone(ThreadId ptid, 
-                   UInt flags, Addr rsp, 
-                   Int *parent_tidptr, 
-                   Int *child_tidptr, 
-                   Addr tlsaddr)
+static SysRes do_clone ( ThreadId ptid, 
+                         ULong flags, Addr rsp, 
+                         Long* parent_tidptr, 
+                         Long* child_tidptr, 
+                         Addr tlsaddr )
 {
    static const Bool debug = False;
 
-   ThreadId ctid = VG_(alloc_ThreadState)();
-   ThreadState *ptst = VG_(get_ThreadState)(ptid);
-   ThreadState *ctst = VG_(get_ThreadState)(ctid);
-   UWord *stack;
-   Segment *seg;
-   Int ret;
+   ThreadId     ctid = VG_(alloc_ThreadState)();
+   ThreadState* ptst = VG_(get_ThreadState)(ptid);
+   ThreadState* ctst = VG_(get_ThreadState)(ctid);
+   UWord*       stack;
+   Segment*     seg;
+   SysRes       res;
+   Long         rax;
    vki_sigset_t blockall, savedmask;
 
    VG_(sigfillset)(&blockall);
@@ -412,7 +375,10 @@ static Int do_clone(ThreadId ptid,
    */
    setup_child( &ctst->arch, &ptst->arch );
 
-   VGP_SET_SYSCALL_RESULT(ctst->arch, 0);
+   /* Make sys_clone appear to have returned Success(0) in the
+      child. */
+   ctst->arch.vex.guest_RAX = 0;
+
    if (rsp != 0)
       ctst->arch.vex.guest_RSP = rsp;
 
@@ -453,29 +419,37 @@ static Int do_clone(ThreadId ptid,
    VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
 
    /* Create the new thread */
-   ret = VG_(clone)(start_thread_NORETURN, stack, flags, &VG_(threads)[ctid],
-                   child_tidptr, parent_tidptr, NULL);
+   rax = do_syscall_clone_amd64_linux(
+            start_thread_NORETURN, stack, flags, &VG_(threads)[ctid],
+            child_tidptr, parent_tidptr, NULL
+         );
+   res = VG_(mk_SysRes_amd64_linux)( rax );
 
    VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
 
-   if (ret < 0) {
+   if (res.isError) {
       /* clone failed */
       VGP_(cleanup_thread)(&ctst->arch);
       ctst->status = VgTs_Empty;
    }
 
-   return ret;
+   return res;
 }
 
+
 /* Do a clone which is really a fork() */
-static Int do_fork_clone(ThreadId tid, UInt flags, Addr rsp, Int *parent_tidptr, Int *child_tidptr)
+static SysRes do_fork_clone ( ThreadId tid, 
+                              ULong flags, Addr rsp, 
+                              Long* parent_tidptr, 
+                              Long* child_tidptr )
 {
    vki_sigset_t fork_saved_mask;
    vki_sigset_t mask;
-   Int ret;
+   SysRes       res;
 
-   if (flags & (VKI_CLONE_SETTLS | VKI_CLONE_FS | VKI_CLONE_VM | VKI_CLONE_FILES | VKI_CLONE_VFORK))
-      return -VKI_EINVAL;
+   if (flags & (VKI_CLONE_SETTLS | VKI_CLONE_FS | VKI_CLONE_VM 
+                | VKI_CLONE_FILES | VKI_CLONE_VFORK))
+      return VG_(mk_SysRes_Error)( VKI_EINVAL );
 
    /* Block all signals during fork, so that we can fix things up in
       the child without being interrupted. */
@@ -486,19 +460,23 @@ static Int do_fork_clone(ThreadId tid, UInt flags, Addr rsp, Int *parent_tidptr,
 
    /* Since this is the fork() form of clone, we don't need all that
       VG_(clone) stuff */
-   ret = VG_(do_syscall5)(__NR_clone, flags, (UWord)NULL, (UWord)parent_tidptr, 
-                                             (UWord)NULL, (UWord)child_tidptr);
+   res = VG_(do_syscall5)( __NR_clone, flags, 
+                           (UWord)NULL, (UWord)parent_tidptr, 
+                           (UWord)NULL, (UWord)child_tidptr );
 
-   if (ret == 0) {
+   if (!res.isError && res.val == 0) {
       /* child */
       VG_(do_atfork_child)(tid);
 
       /* restore signal mask */
       VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
-   } else if (ret > 0) {
+   } 
+   else 
+   if (!res.isError && res.val > 0) {
       /* parent */
       if (VG_(clo_trace_syscalls))
-         VG_(printf)("   clone(fork): process %d created child %d\n", VG_(getpid)(), ret);
+         VG_(printf)("   clone(fork): process %d created child %d\n", 
+                      VG_(getpid)(), res.val);
 
       VG_(do_atfork_parent)(tid);
 
@@ -506,7 +484,7 @@ static Int do_fork_clone(ThreadId tid, UInt flags, Addr rsp, Int *parent_tidptr,
       VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
    }
 
-   return ret;
+   return res;
 }
 
 /* ---------------------------------------------------------------------
@@ -525,19 +503,55 @@ void setup_child ( /*OUT*/ ThreadArchState *child,
    child->vex_shadow = parent->vex_shadow;
 }  
 
+
 /* ---------------------------------------------------------------------
    PRE/POST wrappers for AMD64/Linux-specific syscalls
    ------------------------------------------------------------------ */
 
-// Nb: See the comment above the generic PRE/POST wrappers in
-// coregrind/vg_syscalls.c for notes about how they work.
-
-#define PRE(name, f)     PRE_TEMPLATE(static, amd64_linux, name, f)
-#define POST(name)      POST_TEMPLATE(static, amd64_linux, name)
-
-PRE(sys_clone, Special)
+#define PRE(name)       DEFN_PRE_TEMPLATE(amd64_linux, name)
+#define POST(name)      DEFN_POST_TEMPLATE(amd64_linux, name)
+
+/* Add prototypes for the wrappers declared here, so that gcc doesn't
+   harass us for not having prototypes.  Really this is a kludge --
+   the right thing to do is to make these wrappers 'static' since they
+   aren't visible outside this file, but that requires even more macro
+   magic. */
+DECL_TEMPLATE(amd64_linux, sys_clone);
+DECL_TEMPLATE(amd64_linux, sys_rt_sigreturn);
+DECL_TEMPLATE(amd64_linux, sys_socket);
+DECL_TEMPLATE(amd64_linux, sys_setsockopt);
+DECL_TEMPLATE(amd64_linux, sys_getsockopt);
+DECL_TEMPLATE(amd64_linux, sys_connect);
+DECL_TEMPLATE(amd64_linux, sys_accept);
+DECL_TEMPLATE(amd64_linux, sys_sendto);
+DECL_TEMPLATE(amd64_linux, sys_recvfrom);
+DECL_TEMPLATE(amd64_linux, sys_sendmsg);
+DECL_TEMPLATE(amd64_linux, sys_recvmsg);
+DECL_TEMPLATE(amd64_linux, sys_shutdown);
+DECL_TEMPLATE(amd64_linux, sys_bind);
+DECL_TEMPLATE(amd64_linux, sys_listen);
+DECL_TEMPLATE(amd64_linux, sys_getsockname);
+DECL_TEMPLATE(amd64_linux, sys_getpeername);
+DECL_TEMPLATE(amd64_linux, sys_socketpair);
+DECL_TEMPLATE(amd64_linux, sys_semget);
+DECL_TEMPLATE(amd64_linux, sys_semop);
+DECL_TEMPLATE(amd64_linux, sys_semtimedop);
+DECL_TEMPLATE(amd64_linux, sys_semctl);
+DECL_TEMPLATE(amd64_linux, sys_msgget);
+DECL_TEMPLATE(amd64_linux, sys_msgrcv);
+DECL_TEMPLATE(amd64_linux, sys_msgsnd);
+DECL_TEMPLATE(amd64_linux, sys_msgctl);
+DECL_TEMPLATE(amd64_linux, sys_shmget);
+DECL_TEMPLATE(amd64_linux, wrap_sys_shmat);
+DECL_TEMPLATE(amd64_linux, sys_shmdt);
+DECL_TEMPLATE(amd64_linux, sys_shmdt);
+DECL_TEMPLATE(amd64_linux, sys_shmctl);
+DECL_TEMPLATE(amd64_linux, sys_arch_prctl);
+
+
+PRE(sys_clone)
 {
-   UInt cloneflags;
+   ULong cloneflags;
 
    PRINT("sys_clone ( %x, %p, %p, %p, %p )",ARG1,ARG2,ARG3,ARG4,ARG5);
    PRE_REG_READ5(int, "clone",
@@ -550,14 +564,14 @@ PRE(sys_clone, Special)
    if (ARG1 & VKI_CLONE_PARENT_SETTID) {
       PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
       if (!VG_(is_addressable)(ARG3, sizeof(Int), VKI_PROT_WRITE)) {
-         SET_RESULT( -VKI_EFAULT );
+         SET_STATUS_Failure( VKI_EFAULT );
          return;
       }
    }
    if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
       PRE_MEM_WRITE("clone(child_tidptr)", ARG4, sizeof(Int));
       if (!VG_(is_addressable)(ARG4, sizeof(Int), VKI_PROT_WRITE)) {
-         SET_RESULT( -VKI_EFAULT );
+         SET_STATUS_Failure( VKI_EFAULT );
          return;
       }
    }
@@ -565,20 +579,22 @@ PRE(sys_clone, Special)
    cloneflags = ARG1;
 
    if (!VG_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
-      SET_RESULT( -VKI_EINVAL );
+      SET_STATUS_Failure( VKI_EINVAL );
       return;
    }
 
    /* Only look at the flags we really care about */
-   switch(cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
+   switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS 
+                         | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
    case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
       /* thread creation */
-      SET_RESULT(do_clone(tid,
-                          ARG1,         /* flags */
-                          (Addr)ARG2,   /* child ESP */
-                          (Int *)ARG3,  /* parent_tidptr */
-                          (Int *)ARG4,  /* child_tidptr */
-                          (Addr)ARG5)); /* set_tls */
+      SET_STATUS_from_SysRes(
+         do_clone(tid,
+                  ARG1,          /* flags */
+                  (Addr)ARG2,    /* child ESP */
+                  (Long *)ARG3,  /* parent_tidptr */
+                  (Long *)ARG4,  /* child_tidptr */
+                  (Addr)ARG5));  /* set_tls */
       break;
 
    case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
@@ -586,22 +602,26 @@ PRE(sys_clone, Special)
       cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
 
    case 0: /* plain fork */
-      SET_RESULT(do_fork_clone(tid,
-                               cloneflags,              /* flags */
-                               (Addr)ARG2,      /* child ESP */
-                               (Int *)ARG3,     /* parent_tidptr */
-                               (Int *)ARG4));   /* child_tidptr */
+      SET_STATUS_from_SysRes(
+         do_fork_clone(tid,
+                       cloneflags,      /* flags */
+                       (Addr)ARG2,      /* child ESP */
+                       (Long *)ARG3,    /* parent_tidptr */
+                       (Long *)ARG4));  /* child_tidptr */
       break;
 
    default:
       /* should we just ENOSYS? */
-      VG_(message)(Vg_UserMsg, "Unsupported clone() flags: %x", ARG1);
+      VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%x", ARG1);
+      VG_(message)(Vg_UserMsg, "");
+      VG_(message)(Vg_UserMsg, "The only supported clone() uses are:");
+      VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)");
+      VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork");
       VG_(unimplemented)
-         ("Valgrind does not support general clone().  The only supported uses "
-          "are via a threads library, fork, or vfork.");
+         ("Valgrind does not support general clone().");
    }
 
-   if (!VG_(is_kerror)(RES)) {
+   if (SUCCESS) {
       if (ARG1 & VKI_CLONE_PARENT_SETTID)
          POST_MEM_WRITE(ARG3, sizeof(Int));
       if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
@@ -609,35 +629,52 @@ PRE(sys_clone, Special)
 
       /* Thread creation was successful; let the child have the chance
          to run */
-      XXX FIXME VG_(vg_yield)();
+      *flags |= SfYieldAfter;
    }
 }
 
-PRE(sys_rt_sigreturn, Special)
+PRE(sys_rt_sigreturn)
 {
+   ThreadState* tst;
    PRINT("rt_sigreturn ( )");
 
+   vg_assert(VG_(is_valid_tid)(tid));
+   vg_assert(tid >= 1 && tid < VG_N_THREADS);
+   vg_assert(VG_(is_running_thread)(tid));
+
    /* Adjust esp to point to start of frame; skip back up over handler
       ret addr */
+   tst = VG_(get_ThreadState)(tid);
    tst->arch.vex.guest_RSP -= sizeof(Addr);
 
    /* This is only so that the RIP is (might be) useful to report if
       something goes wrong in the sigreturn */
-   restart_syscall(&tst->arch);
+   VG_(fixup_guest_state_to_restart_syscall)(&tst->arch);
 
    VG_(sigframe_destroy)(tid, True);
 
-   /* Keep looking for signals until there are none */
-   XXX FIXME VG_(poll_signals)(tid);
+   /* For unclear reasons, it appears we need the syscall to return
+      without changing %RAX.  Since %RAX is the return value, and can
+      denote either success or failure, we must set up so that the
+      driver logic copies it back unchanged.  Also, note %RAX is of
+      the guest registers written by VG_(sigframe_destroy). */
+   SET_STATUS_from_SysRes(
+      VG_(mk_SysRes_amd64_linux)( tst->arch.vex.guest_RAX ) 
+   );
 
-   /* placate return-must-be-set assertion */
-   SET_RESULT(RES);
+   /* Check to see if some any signals arose as a result of this. */
+   *flags |= SfPollAfter;
 }
 
-PRE(sys_arch_prctl, 0)
+PRE(sys_arch_prctl)
 {
+   ThreadState* tst;
    PRINT( "arch_prctl ( %d, %llx )", ARG1, ARG2 );
 
+   vg_assert(VG_(is_valid_tid)(tid));
+   vg_assert(tid >= 1 && tid < VG_N_THREADS);
+   vg_assert(VG_(is_running_thread)(tid));
+
    // Nb: can't use "ARG2".."ARG5" here because that's our own macro...
    PRE_REG_READ2(long, "arch_prctl",
                  int, option, unsigned long, arg2);
@@ -646,23 +683,29 @@ PRE(sys_arch_prctl, 0)
 
    /* "do" the syscall ourselves; the kernel never sees it */
    vg_assert(ARG1 == ARCH_SET_FS);
+   tst = VG_(get_ThreadState)(tid);
    tst->arch.vex.guest_FS_ZERO = ARG2;
-   SET_RESULT( 0 );
+
+   /* Note; the Status writeback to guest state that happens after
+      this wrapper returns does not change guest_FS_ZERO; hence that
+      direct assignment to the guest state is safe here. */
+   SET_STATUS_Success( 0 );
 }
 
-PRE(sys_socket, 0)
+PRE(sys_socket)
 {
    PRINT("sys_socket ( %d, %d, %d )",ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "socket", int, domain, int, type, int, protocol);
 }
-
 POST(sys_socket)
 {
-   UWord r = VG_(generic_POST_sys_socket)(tid, RES);
-   SET_RESULT(r);
+   SysRes r;
+   vg_assert(SUCCESS);
+   r = VG_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES));
+   SET_STATUS_from_SysRes(r);
 }
 
-PRE(sys_setsockopt, 0)
+PRE(sys_setsockopt)
 {
    PRINT("sys_setsockopt ( %d, %d, %d, %p, %d )",ARG1,ARG2,ARG3,ARG4,ARG5);
    PRE_REG_READ5(long, "setsockopt",
@@ -671,7 +714,7 @@ PRE(sys_setsockopt, 0)
    VG_(generic_PRE_sys_setsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5);
 }
 
-PRE(sys_getsockopt, 0)
+PRE(sys_getsockopt)
 {
    PRINT("sys_getsockopt ( %d, %d, %d, %p, %p )",ARG1,ARG2,ARG3,ARG4,ARG5);
    PRE_REG_READ5(long, "getsockopt",
@@ -679,36 +722,42 @@ PRE(sys_getsockopt, 0)
                  void *, optval, int, *optlen);
    VG_(generic_PRE_sys_getsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5);
 }
-
 POST(sys_getsockopt)
 {
-   VG_(generic_POST_sys_getsockopt)(tid, RES,ARG1,ARG2,ARG3,ARG4,ARG5);
+   vg_assert(SUCCESS);
+   VG_(generic_POST_sys_getsockopt)(tid, VG_(mk_SysRes_Success)(RES),
+                                         ARG1,ARG2,ARG3,ARG4,ARG5);
 }
 
-PRE(sys_connect, MayBlock)
+PRE(sys_connect)
 {
+   *flags |= SfMayBlock;
    PRINT("sys_connect ( %d, %p, %d )",ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "connect",
                  int, sockfd, struct sockaddr *, serv_addr, int, addrlen);
    VG_(generic_PRE_sys_connect)(tid, ARG1,ARG2,ARG3);
 }
 
-PRE(sys_accept, MayBlock)
+PRE(sys_accept)
 {
+   *flags |= SfMayBlock;
    PRINT("sys_accept ( %d, %p, %d )",ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "accept",
                  int, s, struct sockaddr *, addr, int, *addrlen);
    VG_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3);
 }
-
 POST(sys_accept)
 {
-   UWord r = VG_(generic_POST_sys_accept)(tid, RES,ARG1,ARG2,ARG3);
-   SET_RESULT(r);
+   SysRes r;
+   vg_assert(SUCCESS);
+   r = VG_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES),
+                                         ARG1,ARG2,ARG3);
+   SET_STATUS_from_SysRes(r);
 }
 
-PRE(sys_sendto, MayBlock)
+PRE(sys_sendto)
 {
+   *flags |= SfMayBlock;
    PRINT("sys_sendto ( %d, %s, %d, %u, %p, %d )",ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
    PRE_REG_READ6(long, "sendto",
                  int, s, const void *, msg, int, len, 
@@ -717,8 +766,9 @@ PRE(sys_sendto, MayBlock)
    VG_(generic_PRE_sys_sendto)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
 }
 
-PRE(sys_recvfrom, MayBlock)
+PRE(sys_recvfrom)
 {
+   *flags |= SfMayBlock;
    PRINT("sys_recvfrom ( %d, %p, %d, %u, %p, %p )",ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
    PRE_REG_READ6(long, "recvfrom",
                  int, s, void *, buf, int, len, unsigned int, flags,
@@ -727,35 +777,40 @@ PRE(sys_recvfrom, MayBlock)
 }
 POST(sys_recvfrom)
 {
-   VG_(generic_POST_sys_recvfrom)(tid, RES,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
+   vg_assert(SUCCESS);
+   VG_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES),
+                                       ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
 }
 
-PRE(sys_sendmsg, MayBlock)
+PRE(sys_sendmsg)
 {
+   *flags |= SfMayBlock;
    PRINT("sys_sendmsg ( %d, %p, %d )",ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "sendmsg",
                  int, s, const struct msghdr *, msg, int, flags);
    VG_(generic_PRE_sys_sendmsg)(tid, ARG1,ARG2);
 }
 
-PRE(sys_recvmsg, MayBlock)
+PRE(sys_recvmsg)
 {
+   *flags |= SfMayBlock;
    PRINT("sys_recvmsg ( %d, %p, %d )",ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
    VG_(generic_PRE_sys_recvmsg)(tid, ARG1,ARG2);
 }
 POST(sys_recvmsg)
 {
-   VG_(generic_POST_sys_recvmsg)(tid, RES,ARG1,ARG2);
+   VG_(generic_POST_sys_recvmsg)(tid, ARG1,ARG2);
 }
 
-PRE(sys_shutdown, MayBlock)
+PRE(sys_shutdown)
 {
+   *flags |= SfMayBlock;
    PRINT("sys_shutdown ( %d, %d )",ARG1,ARG2);
    PRE_REG_READ2(int, "shutdown", int, s, int, how);
 }
 
-PRE(sys_bind, 0)
+PRE(sys_bind)
 {
    PRINT("sys_bind ( %d, %p, %d )",ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "bind",
@@ -763,13 +818,13 @@ PRE(sys_bind, 0)
    VG_(generic_PRE_sys_bind)(tid, ARG1,ARG2,ARG3);
 }
 
-PRE(sys_listen, 0)
+PRE(sys_listen)
 {
    PRINT("sys_listen ( %d, %d )",ARG1,ARG2);
    PRE_REG_READ2(long, "listen", int, s, int, backlog);
 }
 
-PRE(sys_getsockname, 0)
+PRE(sys_getsockname)
 {
    PRINT("sys_getsockname ( %d, %p, %p )",ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "getsockname",
@@ -778,10 +833,12 @@ PRE(sys_getsockname, 0)
 }
 POST(sys_getsockname)
 {
-   VG_(generic_POST_sys_getsockname)(tid, RES,ARG1,ARG2,ARG3);
+   vg_assert(SUCCESS);
+   VG_(generic_POST_sys_getsockname)(tid, VG_(mk_SysRes_Success)(RES),
+                                          ARG1,ARG2,ARG3);
 }
 
-PRE(sys_getpeername, 0)
+PRE(sys_getpeername)
 {
    PRINT("sys_getpeername ( %d, %p, %p )",ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "getpeername",
@@ -790,10 +847,12 @@ PRE(sys_getpeername, 0)
 }
 POST(sys_getpeername)
 {
-   VG_(generic_POST_sys_getpeername)(tid, RES,ARG1,ARG2,ARG3);
+   vg_assert(SUCCESS);
+   VG_(generic_POST_sys_getpeername)(tid, VG_(mk_SysRes_Success)(RES),
+                                          ARG1,ARG2,ARG3);
 }
 
-PRE(sys_socketpair, 0)
+PRE(sys_socketpair)
 {
    PRINT("sys_socketpair ( %d, %d, %d, %p )",ARG1,ARG2,ARG3,ARG4);
    PRE_REG_READ4(long, "socketpair",
@@ -802,25 +861,29 @@ PRE(sys_socketpair, 0)
 }
 POST(sys_socketpair)
 {
-   VG_(generic_POST_sys_socketpair)(tid, RES,ARG1,ARG2,ARG3,ARG4);
+   vg_assert(SUCCESS);
+   VG_(generic_POST_sys_socketpair)(tid, VG_(mk_SysRes_Success)(RES),
+                                         ARG1,ARG2,ARG3,ARG4);
 }
 
-PRE(sys_semget, 0)
+PRE(sys_semget)
 {
    PRINT("sys_semget ( %d, %d, %d )",ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "semget", key_t, key, int, nsems, int, semflg);
 }
 
-PRE(sys_semop, MayBlock)
+PRE(sys_semop)
 {
+   *flags |= SfMayBlock;
    PRINT("sys_semop ( %d, %p, %u )",ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "semop",
                  int, semid, struct sembuf *, sops, unsigned, nsoops);
    VG_(generic_PRE_sys_semop)(tid, ARG1,ARG2,ARG3);
 }
 
-PRE(sys_semtimedop, MayBlock)
+PRE(sys_semtimedop)
 {
+   *flags |= SfMayBlock;
    PRINT("sys_semtimedop ( %d, %p, %u, %p )",ARG1,ARG2,ARG3,ARG4);
    PRE_REG_READ4(long, "semtimedop",
                  int, semid, struct sembuf *, sops, unsigned, nsoops,
@@ -828,7 +891,7 @@ PRE(sys_semtimedop, MayBlock)
    VG_(generic_PRE_sys_semtimedop)(tid, ARG1,ARG2,ARG3,ARG4);
 }
 
-PRE(sys_semctl, 0)
+PRE(sys_semctl)
 {
    switch (ARG3 & ~VKI_IPC_64) {
    case VKI_IPC_INFO:
@@ -858,101 +921,93 @@ PRE(sys_semctl, 0)
    }
    VG_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4);
 }
-
 POST(sys_semctl)
 {
    VG_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4);
 }
 
-PRE(sys_msgget, 0)
+PRE(sys_msgget)
 {
    PRINT("sys_msgget ( %d, %d )",ARG1,ARG2);
    PRE_REG_READ2(long, "msgget", key_t, key, int, msgflg);
 }
 
-PRE(sys_msgsnd, 0)
+PRE(sys_msgsnd)
 {
    PRINT("sys_msgsnd ( %d, %p, %d, %d )",ARG1,ARG2,ARG3,ARG4);
    PRE_REG_READ4(long, "msgsnd",
                  int, msqid, struct msgbuf *, msgp, size_t, msgsz, int, msgflg);
    VG_(generic_PRE_sys_msgsnd)(tid, ARG1,ARG2,ARG3,ARG4);
-      /* if ((ARG4 & VKI_IPC_NOWAIT) == 0)
-            tst->sys_flags |= MayBlock;
-      */
+   if ((ARG4 & VKI_IPC_NOWAIT) == 0)
+      *flags |= SfMayBlock;
 }
 
-PRE(sys_msgrcv, 0)
+PRE(sys_msgrcv)
 {
    PRINT("sys_msgrcv ( %d, %p, %d, %d, %d )",ARG1,ARG2,ARG3,ARG4,ARG5);
    PRE_REG_READ5(long, "msgrcv",
                  int, msqid, struct msgbuf *, msgp, size_t, msgsz,
                  long, msgytp, int, msgflg);
    VG_(generic_PRE_sys_msgrcv)(tid, ARG1,ARG2,ARG3,ARG4,ARG5);
-      /* if ((ARG4 & VKI_IPC_NOWAIT) == 0)
-            tst->sys_flags |= MayBlock;
-      */
+   if ((ARG4 & VKI_IPC_NOWAIT) == 0)
+      *flags |= SfMayBlock;
 }
-
 POST(sys_msgrcv)
 {
    VG_(generic_POST_sys_msgrcv)(tid, RES,ARG1,ARG2,ARG3,ARG4,ARG5);
 }
 
-PRE(sys_msgctl, 0)
+PRE(sys_msgctl)
 {
    PRINT("sys_msgctl ( %d, %d, %p )",ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "msgctl",
                  int, msqid, int, cmd, struct msqid_ds *, buf);
    VG_(generic_PRE_sys_msgctl)(tid, ARG1,ARG2,ARG3);
 }
-
 POST(sys_msgctl)
 {
    VG_(generic_POST_sys_msgctl)(tid, RES,ARG1,ARG2,ARG3);
 }
 
-PRE(sys_shmget, 0)
+PRE(sys_shmget)
 {
    PRINT("sys_shmget ( %d, %d, %d )",ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "shmget", key_t, key, size_t, size, int, shmflg);
 }
 
-PRE(wrap_sys_shmat, 0)
+PRE(wrap_sys_shmat)
 {
    PRINT("wrap_sys_shmat ( %d, %p, %d )",ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "shmat",
                  int, shmid, const void *, shmaddr, int, shmflg);
    ARG2 = VG_(generic_PRE_sys_shmat)(tid, ARG1,ARG2,ARG3);
    if (ARG2 == 0)
-      SET_RESULT( -VKI_EINVAL );
+      SET_STATUS_Failure( VKI_EINVAL );
 }
-
 POST(wrap_sys_shmat)
 {
    VG_(generic_POST_sys_shmat)(tid, RES,ARG1,ARG2,ARG3);
 }
 
-PRE(sys_shmdt, 0)
+PRE(sys_shmdt)
 {
    PRINT("sys_shmdt ( %p )",ARG1);
    PRE_REG_READ1(long, "shmdt", const void *, shmaddr);
    if (!VG_(generic_PRE_sys_shmdt)(tid, ARG1))
-      SET_RESULT( -VKI_EINVAL );
+      SET_STATUS_Failure( VKI_EINVAL );
 }
-
 POST(sys_shmdt)
 {
    VG_(generic_POST_sys_shmdt)(tid, RES,ARG1);
 }
 
-PRE(sys_shmctl, 0)
+PRE(sys_shmctl)
 {
    PRINT("sys_shmctl ( %d, %d, %p )",ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "shmctl",
                  int, shmid, int, cmd, struct shmid_ds *, buf);
    VG_(generic_PRE_sys_shmctl)(tid, ARG1,ARG2,ARG3);
 }
-
 POST(sys_shmctl)
 {
    VG_(generic_POST_sys_shmctl)(tid, RES,ARG1,ARG2,ARG3);
@@ -966,9 +1021,9 @@ POST(sys_shmctl)
    The AMD64/Linux syscall table
    ------------------------------------------------------------------ */
 
-// Macros for adding AMD64/Linux-specific wrappers to the syscall table.
-#define PLAX_(const, name)    SYS_WRAPPER_ENTRY_X_(amd64_linux, const, name) 
-#define PLAXY(const, name)    SYS_WRAPPER_ENTRY_XY(amd64_linux, const, name) 
+/* Add an amd64-linux specific wrapper to a syscall table. */
+#define PLAX_(const, name)    WRAPPER_ENTRY_X_(amd64_linux, const, name) 
+#define PLAXY(const, name)    WRAPPER_ENTRY_XY(amd64_linux, const, name) 
 
 // This table maps from __NR_xxx syscall numbers (from
 // linux/include/asm-x86_64/unistd.h) to the appropriate PRE/POST sys_foo()
@@ -978,7 +1033,7 @@ POST(sys_shmctl)
 // When implementing these wrappers, you need to work out if the wrapper is
 // generic, Linux-only (but arch-independent), or AMD64/Linux only.
 
-const struct SyscallTableEntry VGA_(syscall_table)[] = {
+const SyscallTableEntry VGP_(syscall_table)[] = {
    GENXY(__NR_read,              sys_read),           // 0 
    GENX_(__NR_write,             sys_write),          // 1 
    GENXY(__NR_open,              sys_open),           // 2 
@@ -1089,8 +1144,8 @@ const struct SyscallTableEntry VGA_(syscall_table)[] = {
 
    GENX_(__NR_chmod,             sys_chmod),          // 90 
    GENX_(__NR_fchmod,            sys_fchmod),         // 91 
-   GENX_(__NR_chown,             sys_chown),          // 92 
-   GENX_(__NR_fchown,            sys_fchown),         // 93 
+//zz    GENX_(__NR_chown,             sys_chown),          // 92 
+//zz    GENX_(__NR_fchown,            sys_fchown),         // 93 
    //   (__NR_lchown,            sys_lchown),         // 94 
 
    GENX_(__NR_umask,             sys_umask),          // 95 
@@ -1105,8 +1160,8 @@ const struct SyscallTableEntry VGA_(syscall_table)[] = {
    //   (__NR_syslog,            sys_syslog),         // 103 
    GENX_(__NR_getgid,            sys_getgid),         // 104 
 
-   GENX_(__NR_setuid,            sys_setuid),         // 105 
-   GENX_(__NR_setgid,            sys_setgid),         // 106 
+//zz    GENX_(__NR_setuid,            sys_setuid),         // 105 
+//zz    GENX_(__NR_setgid,            sys_setgid),         // 106 
    GENX_(__NR_geteuid,           sys_geteuid),        // 107 
    GENX_(__NR_getegid,           sys_getegid),        // 108 
    GENX_(__NR_setpgid,           sys_setpgid),        // 109 
@@ -1118,10 +1173,10 @@ const struct SyscallTableEntry VGA_(syscall_table)[] = {
    //   (__NR_setregid,          sys_setregid),       // 114 
 
    GENXY(__NR_getgroups,         sys_getgroups),      // 115 
-   GENX_(__NR_setgroups,         sys_setgroups),      // 116 
-   LINX_(__NR_setresuid,         sys_setresuid),      // 117 
+//zz    GENX_(__NR_setgroups,         sys_setgroups),      // 116 
+//zz    LINX_(__NR_setresuid,         sys_setresuid),      // 117 
    LINXY(__NR_getresuid,         sys_getresuid),      // 118 
-   LINX_(__NR_setresgid,         sys_setresgid),      // 119 
+//zz    LINX_(__NR_setresgid,         sys_setresgid),      // 119 
 
    LINXY(__NR_getresgid,         sys_getresgid),      // 120 
    GENX_(__NR_getpgid,           sys_getpgid),        // 121 
@@ -1131,9 +1186,9 @@ const struct SyscallTableEntry VGA_(syscall_table)[] = {
 
    //   (__NR_capget,            sys_capget),         // 125 
    //   (__NR_capset,            sys_capset),         // 126 
-   GENXY(__NR_rt_sigpending,     sys_rt_sigpending),  // 127 
+//zz    GENXY(__NR_rt_sigpending,     sys_rt_sigpending),  // 127 
    GENXY(__NR_rt_sigtimedwait,   sys_rt_sigtimedwait),// 128 
-   GENXY(__NR_rt_sigqueueinfo,   sys_rt_sigqueueinfo),// 129 
+//zz    GENXY(__NR_rt_sigqueueinfo,   sys_rt_sigqueueinfo),// 129 
 
    GENX_(__NR_rt_sigsuspend,     sys_rt_sigsuspend),  // 130 
    GENXY(__NR_sigaltstack,       sys_sigaltstack),    // 131 
@@ -1149,7 +1204,7 @@ const struct SyscallTableEntry VGA_(syscall_table)[] = {
 
    //   (__NR_getpriority,             sys_getpriority),             // 140 
    //   (__NR_setpriority,             sys_setpriority),             // 141 
-   GENXY(__NR_sched_setparam,          sys_sched_setparam),          // 142 
+//zz    GENXY(__NR_sched_setparam,          sys_sched_setparam),          // 142 
    GENXY(__NR_sched_getparam,          sys_sched_getparam),          // 143 
    GENX_(__NR_sched_setscheduler,      sys_sched_setscheduler),      // 144 
 
@@ -1226,25 +1281,25 @@ const struct SyscallTableEntry VGA_(syscall_table)[] = {
    //   (__NR_sched_getaffinity, sys_sched_getaffinity), // 204 
 
    //   (__NR_set_thread_area,   sys_ni_syscall),     // 205 
-   LINX_(__NR_io_setup,          sys_io_setup),       // 206 
-   LINX_(__NR_io_destroy,        sys_io_destroy),     // 207 
-   LINXY(__NR_io_getevents,      sys_io_getevents),   // 208 
-   LINX_(__NR_io_submit,         sys_io_submit),      // 209 
+//zz    LINX_(__NR_io_setup,          sys_io_setup),       // 206 
+//zz    LINX_(__NR_io_destroy,        sys_io_destroy),     // 207 
+//zz    LINXY(__NR_io_getevents,      sys_io_getevents),   // 208 
+//zz    LINX_(__NR_io_submit,         sys_io_submit),      // 209 
 
-   LINXY(__NR_io_cancel,         sys_io_cancel),      // 210 
+//zz    LINXY(__NR_io_cancel,         sys_io_cancel),      // 210 
    //   (__NR_get_thread_area,   sys_ni_syscall),     // 211 
    //   (__NR_lookup_dcookie,    sys_lookup_dcookie), // 212 
-   LINXY(__NR_epoll_create,      sys_epoll_create),   // 213 
+//zz    LINXY(__NR_epoll_create,      sys_epoll_create),   // 213 
    //   (__NR_epoll_ctl_old,     sys_ni_syscall),     // 214 
 
    //   (__NR_epoll_wait_old,    sys_ni_syscall),     // 215 
    //   (__NR_remap_file_pages,  sys_remap_file_pages)// 216 
    GENXY(__NR_getdents64,        sys_getdents64),     // 217 
-   GENX_(__NR_set_tid_address,   sys_set_tid_address),// 218 
+   LINX_(__NR_set_tid_address,   sys_set_tid_address),// 218 
    //   (__NR_restart_syscall,   sys_restart_syscall),// 219 
 
    PLAX_(__NR_semtimedop,        sys_semtimedop),     // 220 
-   LINX_(__NR_fadvise64,         sys_fadvise64),      // 221 
+//zz    LINX_(__NR_fadvise64,         sys_fadvise64),      // 221 
    //   (__NR_timer_create,      sys_timer_create),   // 222 
    //   (__NR_timer_settime,     sys_timer_settime),  // 223 
    //   (__NR_timer_gettime,     sys_timer_gettime),  // 224 
@@ -1257,8 +1312,8 @@ const struct SyscallTableEntry VGA_(syscall_table)[] = {
 
    //   (__NR_clock_nanosleep,   sys_clock_nanosleep),// 230 
    LINX_(__NR_exit_group,        sys_exit_group),     // 231 
-   LINXY(__NR_epoll_wait,        sys_epoll_wait),     // 232 
-   LINX_(__NR_epoll_ctl,         sys_epoll_ctl),      // 233 
+//zz    LINXY(__NR_epoll_wait,        sys_epoll_wait),     // 232 
+//zz    LINX_(__NR_epoll_ctl,         sys_epoll_ctl),      // 233 
    LINXY(__NR_tgkill,            sys_tgkill),         // 234 
 
    //   (__NR_utimes,            sys_utimes),         // 235 
@@ -1279,12 +1334,8 @@ const struct SyscallTableEntry VGA_(syscall_table)[] = {
    //   (__NR_waitid,            sys_waitid),         // 247 
 };
 
-const UInt VGA_(syscall_table_size) = 
-            sizeof(VGA_(syscall_table)) / sizeof(VGA_(syscall_table)[0]);
-
-//void        VG_(clear_TLS_for_thread)      ( VgLdtEntry* tls )
-//{
-//}
+const UInt VGP_(syscall_table_size) = 
+            sizeof(VGP_(syscall_table)) / sizeof(VGP_(syscall_table)[0]);
 
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
index 25658d8bc753d9dbeca406102a0022f87352fed7..17b430d0d2bc9225dc6b35aa1e7a4f21737f109f 100644 (file)
@@ -1648,9 +1648,9 @@ VG_(generic_POST_sys_shmctl) ( ThreadId tid,
 #define PRE(name)      DEFN_PRE_TEMPLATE(generic, name)
 #define POST(name)     DEFN_POST_TEMPLATE(generic, name)
 
-//zz // Combine two 32-bit values into a 64-bit value
-//zz #define LOHI64(lo,hi)   ( (lo) | ((ULong)(hi) << 32) )
-//zz 
+// Combine two 32-bit values into a 64-bit value
+#define LOHI64(lo,hi)   ( (lo) | ((ULong)(hi) << 32) )
+
 //zz //PRE(sys_exit_group, Special)
 //zz //{
 //zz //   VG_(core_panic)("syscall exit_group() not caught by the scheduler?!");
@@ -2147,23 +2147,26 @@ PRE(sys_getsid)
    PRE_REG_READ1(long, "getsid", vki_pid_t, pid);
 }
 
-//zz // XXX: only for 32-bit archs
-//zz PRE(sys_pread64, SfMayBlock)
-//zz {
-//zz    PRINT("sys_pread64 ( %d, %p, %llu, %lld )",
-//zz          ARG1, ARG2, (ULong)ARG3, LOHI64(ARG4,ARG5));
-//zz    PRE_REG_READ5(ssize_t, "pread64",
-//zz                  unsigned int, fd, char *, buf, vki_size_t, count,
-//zz                  vki_u32, offset_low32, vki_u32, offset_high32);
-//zz    PRE_MEM_WRITE( "pread64(buf)", ARG2, ARG3 );
-//zz }
-//zz 
-//zz POST(sys_pread64)
-//zz {
-//zz    if (RES > 0) {
-//zz       POST_MEM_WRITE( ARG2, RES );
-//zz    }
-//zz }
+// XXX: only for 32-bit archs
+// XXX even more: this in fact gets used by amd64-linux.  Someone
+// should look into this properly.
+PRE(sys_pread64)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_pread64 ( %d, %p, %llu, %lld )",
+         ARG1, ARG2, (ULong)ARG3, LOHI64(ARG4,ARG5));
+   PRE_REG_READ5(ssize_t, "pread64",
+                 unsigned int, fd, char *, buf, vki_size_t, count,
+                 vki_u32, offset_low32, vki_u32, offset_high32);
+   PRE_MEM_WRITE( "pread64(buf)", ARG2, ARG3 );
+}
+POST(sys_pread64)
+{
+   vg_assert(SUCCESS);
+   if (RES > 0) {
+      POST_MEM_WRITE( ARG2, RES );
+   }
+}
 
 PRE(sys_mknod)
 {
@@ -2579,7 +2582,7 @@ PRE(sys_fcntl)
    case VKI_F_GETLK:
    case VKI_F_SETLK:
    case VKI_F_SETLKW:
-#  if defined(VGP_amd64_linux)
+#  if defined(VGP_x86_linux)
    case VKI_F_GETLK64:
    case VKI_F_SETLK64:
    case VKI_F_SETLKW64:
@@ -2641,7 +2644,7 @@ PRE(sys_fcntl64)
    case VKI_F_GETLK:
    case VKI_F_SETLK:
    case VKI_F_SETLKW:
-#  if defined(VGP_amd64_linux)
+#  if defined(VGP_x86_linux)
    case VKI_F_GETLK64:
    case VKI_F_SETLK64:
    case VKI_F_SETLKW64:
@@ -2653,12 +2656,12 @@ PRE(sys_fcntl64)
       break;
    }
    
-#  if defined(VGP_amd64_linux)
-   //if (ARG2 == VKI_F_SETLKW || ARG2 == VKI_F_SETLKW64)
-   //   tst->sys_flags |= SfMayBlock;
+#  if defined(VGP_x86_linux)
+   if (ARG2 == VKI_F_SETLKW || ARG2 == VKI_F_SETLKW64)
+      *flags |= SfMayBlock;
 #  else
-   //if (ARG2 == VKI_F_SETLKW)
-   //   tst->sys_flags |= SfMayBlock;
+   if (ARG2 == VKI_F_SETLKW)
+      *flags |= SfMayBlock;
 #  endif
 }
 
index f2fbb0890b8a293054e0ec2bd6872111889f1e59..ffb64f5db2df305f4fca09f10b3676e07d90631a 100644 (file)
 #include "priv_syscalls-main.h"
 
 
+/* Useful info which needs to be recorded somewhere:
+   Use of registers in syscalls (on linux) is:
+
+          NUM  ARG1  ARG2  ARG3  ARG4  ARG5  ARG6  RESULT
+   x86    eax  ebx   ecx   edx   esi   edi   ebp   eax       (== NUM)
+   amd64  rax  rdi   rsi   rdx   r10   r8    r9    rax       (== NUM)
+   ppc32  r0   r3    r4    r5    r6    r7    r8    r3+CR0.SO (== ARG1)
+*/
+
 /* This is the top level of the system-call handler module.  All
    system calls are channelled through here, doing two things:
 
@@ -262,8 +271,19 @@ void getSyscallArgsFromGuestState ( /*OUT*/SyscallArgs*       canonical,
    canonical->arg5  = gst->guest_EDI;
    canonical->arg6  = gst->guest_EBP;
 #  else
+#  if defined(VGP_amd64_linux)
+   VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
+   canonical->sysno = gst->guest_RAX;
+   canonical->arg1  = gst->guest_RDI;
+   canonical->arg2  = gst->guest_RSI;
+   canonical->arg3  = gst->guest_RDX;
+   canonical->arg4  = gst->guest_R10;
+   canonical->arg5  = gst->guest_R8;
+   canonical->arg6  = gst->guest_R9;
+#  else
 #    error "getSyscallArgsFromGuestState: unknown arch"
 #  endif
+#  endif
 }
 
 static 
@@ -280,8 +300,19 @@ void putSyscallArgsIntoGuestState ( /*IN*/ SyscallArgs*       canonical,
    gst->guest_EDI = canonical->arg5;
    gst->guest_EBP = canonical->arg6;
 #  else
+#  if defined(VGP_amd64_linux)
+   VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
+   gst->guest_RAX = canonical->sysno;
+   gst->guest_RDI = canonical->arg1;
+   gst->guest_RSI = canonical->arg2;
+   gst->guest_RDX = canonical->arg3;
+   gst->guest_R10 = canonical->arg4;
+   gst->guest_R8  = canonical->arg5;
+   gst->guest_R9  = canonical->arg6;
+#  else
 #    error "putSyscallArgsIntoGuestState: unknown arch"
 #  endif
+#  endif
 }
 
 static
@@ -294,8 +325,15 @@ void getSyscallStatusFromGuestState ( /*OUT*/SyscallStatus*     canonical,
    canonical->what = i >= -4095 && i <= -1  ? SsFailure  : SsSuccess;
    canonical->val  = (UWord)(canonical->what==SsFailure ? -i : i);
 #  else
+#  if defined(VGP_amd64_linux)
+   VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
+   Long              i   = (Int)gst->guest_RAX;
+   canonical->what = i >= -4095 && i <= -1  ? SsFailure  : SsSuccess;
+   canonical->val  = (UWord)(canonical->what==SsFailure ? -i : i);
+#  else
 #    error "getSyscallStatusFromGuestState: unknown arch"
 #  endif
+#  endif
 }
 
 static 
@@ -315,8 +353,20 @@ void putSyscallStatusIntoGuestState ( /*IN*/ SyscallStatus*     canonical,
       gst->guest_EAX = canonical->val;
    }
 #  else
+#  if defined(VGP_amd64_linux)
+   VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
+   if (canonical->what == SsFailure) {
+      /* This isn't exactly right, in that really a Failure with res
+         not in the range 1 .. 4095 is unrepresentable in the
+         Linux-x86 scheme.  Oh well. */
+      gst->guest_RAX = - (Long)canonical->val;
+   } else {
+      gst->guest_RAX = canonical->val;
+   }
+#  else
 #    error "putSyscallStatusIntoGuestState: unknown arch"
 #  endif
+#  endif
 }
 
 
@@ -337,8 +387,19 @@ void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout )
    layout->o_arg6   = OFFSET_x86_EBP;
    layout->o_retval = OFFSET_x86_EAX;
 #  else
+#  if defined(VGP_amd64_linux)
+   layout->o_sysno  = OFFSET_amd64_RAX;
+   layout->o_arg1   = OFFSET_amd64_RDI;
+   layout->o_arg2   = OFFSET_amd64_RSI;
+   layout->o_arg3   = OFFSET_amd64_RDX;
+   layout->o_arg4   = OFFSET_amd64_R10;
+   layout->o_arg5   = OFFSET_amd64_R8;
+   layout->o_arg6   = OFFSET_amd64_R9;
+   layout->o_retval = OFFSET_amd64_RAX;
+#  else
 #    error "getSyscallLayout: unknown arch"
 #  endif
+#  endif
 }
 
 
@@ -819,8 +880,29 @@ void VG_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch )
    }
 #  else
 
+#  if defined(VGP_amd64_linux)
+   arch->vex.guest_RIP -= 2;             // sizeof(syscall)
+
+   /* Make sure our caller is actually sane, and we're really backing
+      back over a syscall.
+
+      syscall == 0F 05 
+   */
+   {
+      UChar *p = (UChar *)arch->vex.guest_RIP;
+      
+      if (p[0] != 0x0F || p[1] != 0x05)
+         VG_(message)(Vg_DebugMsg,
+                      "?! restarting over syscall at %p %02x %02x\n",
+                      arch->vex.guest_RIP, p[0], p[1]); 
+
+      vg_assert(p[0] == 0x0F && p[1] == 0x05);
+   }
+#  else
+
 #    error "VG_(fixup_guest_state_to_restart_syscall): unknown plat"
 #  endif
+#  endif
 }
 
 /* 
index 53395beb1dd5469877202258e74e3ee53d50048d..a8f65d39d8304fdadbdf7e8d25cf9ae0bbf647fb 100644 (file)
@@ -315,7 +315,7 @@ asm(
          /* Hm, exit returned */
 "        ud2\n"
 
-"1:      /* PARENT or ERROR */\n"
+"1:\n"   /* PARENT or ERROR */
 "        pop     %edi\n"
 "        pop     %ebx\n"
 "        ret\n"
@@ -327,6 +327,7 @@ asm(
 #undef STRINGIFY
 #undef STRINGIFZ
 
+
 // forward declarations
 static void setup_child ( ThreadArchState*, ThreadArchState*, Bool );
 static SysRes sys_set_thread_area ( ThreadId, vki_modify_ldt_t* );
@@ -343,8 +344,8 @@ static SysRes sys_set_thread_area ( ThreadId, vki_modify_ldt_t* );
  */
 static SysRes do_clone ( ThreadId ptid, 
                          UInt flags, Addr esp, 
-                         Int *parent_tidptr, 
-                         Int *child_tidptr, 
+                         Intparent_tidptr, 
+                         Intchild_tidptr, 
                          vki_modify_ldt_t *tlsinfo)
 {
    static const Bool debug = False;
@@ -383,7 +384,8 @@ static SysRes do_clone ( ThreadId ptid,
       is passed as an arg to setup_child. */
    setup_child( &ctst->arch, &ptst->arch, True /*VG_(clo_support_elan3)*/ );
 
-   /* Make sys_clone appear to have returned zero in the child. */
+   /* Make sys_clone appear to have returned Success(0) in the
+      child. */
    ctst->arch.vex.guest_EAX = 0;
 
    if (esp != 0)
@@ -438,6 +440,7 @@ static SysRes do_clone ( ThreadId ptid,
             child_tidptr, parent_tidptr, NULL
          );
    res = VG_(mk_SysRes_x86_linux)( eax );
+
    VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
 
   out:
@@ -474,8 +477,9 @@ static SysRes do_fork_clone ( ThreadId tid,
 
    /* Since this is the fork() form of clone, we don't need all that
       VG_(clone) stuff */
-   res = VG_(do_syscall5)(__NR_clone, flags, (UWord)NULL, (UWord)parent_tidptr, 
-                                             (UWord)NULL, (UWord)child_tidptr);
+   res = VG_(do_syscall5)( __NR_clone, flags, 
+                           (UWord)NULL, (UWord)parent_tidptr, 
+                           (UWord)NULL, (UWord)child_tidptr );
 
    if (!res.isError && res.val == 0) {
       /* child */
@@ -1070,7 +1074,7 @@ PRE(sys_clone)
    case 0: /* plain fork */
       SET_STATUS_from_SysRes(
          do_fork_clone(tid,
-                       cloneflags,              /* flags */
+                       cloneflags,      /* flags */
                        (Addr)ARG2,      /* child ESP */
                        (Int *)ARG3,     /* parent_tidptr */
                        (Int *)ARG5));   /* child_tidptr */
@@ -1890,8 +1894,7 @@ POST(sys_sigaction)
    The x86/Linux syscall table
    ------------------------------------------------------------------ */
 
-/* Add a Linux-specific, arch-independent wrapper to a syscall
-   table. */
+/* Add an x86-linux specific wrapper to a syscall table. */
 #define PLAX_(sysno, name)    WRAPPER_ENTRY_X_(x86_linux, sysno, name) 
 #define PLAXY(sysno, name)    WRAPPER_ENTRY_XY(x86_linux, sysno, name)
 
index e65c6653cfc794496ec3560159a0c08661e742f4..cdc4838ddc99d8f19cae89ff4f421ab0e61d744e 100644 (file)
@@ -106,6 +106,15 @@ static inline SysRes VG_(mk_SysRes_x86_linux) ( Int eax ) {
    return res;
 }
 
+/* Similarly .. */
+static inline SysRes VG_(mk_SysRes_amd64_linux) ( Long rax ) {
+   SysRes res;
+   res.isError = rax >= -4095 && rax <= -1;
+   res.val     = res.isError ? -rax : rax;
+   return res;
+}
+
+
 
 #endif   // __PUB_CORE_LIBCBASE_H