--- coregrind/m_syswrap/syswrap-openbsd.c.orig
+++ coregrind/m_syswrap/syswrap-openbsd.c
@@ -0,0 +1,4504 @@
+
+/*--------------------------------------------------------------------*/
+/*--- FreeBSD-specific syscalls, etc.            syswrap-freebsd.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2000-2008 Nicholas Nethercote
+      njn@valgrind.org
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#if defined(VGO_openbsd)
+
+#include "pub_core_basics.h"
+#include "pub_core_vki.h"
+#include "pub_core_vkiscnums.h"
+#include "pub_core_libcsetjmp.h"   // to keep _threadstate.h happy
+#include "pub_core_threadstate.h"
+#include "pub_core_aspacemgr.h"
+#include "pub_core_debuginfo.h"    // VG_(di_notify_*)
+#include "pub_core_transtab.h"     // VG_(discard_translations)
+#include "pub_core_xarray.h"
+#include "pub_core_clientstate.h"
+#include "pub_core_debuglog.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcfile.h"
+#include "pub_core_libcprint.h"
+#include "pub_core_libcproc.h"
+#include "pub_core_libcsignal.h"
+#include "pub_core_machine.h"
+#include "pub_core_mallocfree.h"
+#include "pub_core_tooliface.h"
+#include "pub_core_options.h"
+#include "pub_core_scheduler.h"
+#include "pub_core_signals.h"
+#include "pub_core_syscall.h"
+#include "pub_core_syswrap.h"
+
+#include "priv_types_n_macros.h"
+#include "priv_syswrap-generic.h"
+#include "priv_syswrap-openbsd.h"
+
+
+// Run a thread from beginning to end and return the thread's
+// scheduler-return-code.
+static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW)
+{
+   VgSchedReturnCode ret;
+   ThreadId     tid = (ThreadId)tidW;
+   ThreadState* tst = VG_(get_ThreadState)(tid);
+
+   VG_(debugLog)(1, "syswrap-openbsd", 
+                    "thread_wrapper(tid=%lld): entry\n", 
+                    (ULong)tidW);
+
+   vg_assert(tst->status == VgTs_Init);
+
+   /* make sure we get the CPU lock before doing anything significant */
+   VG_(acquire_BigLock)(tid, "thread_wrapper(starting new thread)");
+
+   if (0)
+      VG_(printf)("thread tid %d started: stack = %p\n",
+		  tid, &tid);
+
+   /* Make sure error reporting is enabled in the new thread. */
+   tst->err_disablement_level = 0;
+
+   VG_TRACK(pre_thread_first_insn, tid);
+
+   tst->os_state.lwpid = VG_(gettid)();
+   tst->os_state.threadgroup = VG_(getpid)();
+
+   /* Thread created with all signals blocked; scheduler will set the
+      appropriate mask */
+
+   ret = VG_(scheduler)(tid);
+
+   vg_assert(VG_(is_exiting)(tid));
+   
+   vg_assert(tst->status == VgTs_Runnable);
+   vg_assert(VG_(is_running_thread)(tid));
+
+   VG_(debugLog)(1, "syswrap-openbsd", 
+                    "thread_wrapper(tid=%lld): exit\n", 
+                    (ULong)tidW);
+
+   /* Return to caller, still holding the lock. */
+   return ret;
+}
+
+
+/* ---------------------------------------------------------------------
+   clone-related stuff
+   ------------------------------------------------------------------ */
+
+/* Run a thread all the way to the end, then do appropriate exit actions
+   (this is the last-one-out-turn-off-the-lights bit).  */
+static void run_a_thread_NORETURN ( Word tidW )
+{
+   ThreadId          tid = (ThreadId)tidW;
+   VgSchedReturnCode src;
+   Int               c;
+   ThreadState*      tst;
+
+   VG_(debugLog)(1, "syswrap-openbsd", 
+                    "run_a_thread_NORETURN(tid=%lld): pre-thread_wrapper\n",
+                    (ULong)tidW);
+
+   tst = VG_(get_ThreadState)(tid);
+   vg_assert(tst);
+
+   /* Run the thread all the way through. */
+   src = thread_wrapper(tid);  
+
+   VG_(debugLog)(1, "syswrap-openbsd", 
+                    "run_a_thread_NORETURN(tid=%lld): post-thread_wrapper\n",
+                    (ULong)tidW);
+
+   c = VG_(count_living_threads)();
+   vg_assert(c >= 1); /* stay sane */
+
+   // Tell the tool this thread is exiting
+   VG_TRACK( pre_thread_ll_exit, tid );
+
+   /* If the thread is exiting with errors disabled, complain loudly;
+      doing so is bad (does the user know this has happened?)  Also,
+      in all cases, be paranoid and clear the flag anyway so that the
+      thread slot is safe in this respect if later reallocated.  This
+      should be unnecessary since the flag should be cleared when the
+      slot is reallocated, in thread_wrapper(). */
+   if (tst->err_disablement_level > 0) {
+      VG_(umsg)(
+         "WARNING: exiting thread has error reporting disabled.\n"
+         "WARNING: possibly as a result of some mistake in the use\n"
+         "WARNING: of the VALGRIND_DISABLE_ERROR_REPORTING macros.\n"
+      );
+      VG_(debugLog)(
+         1, "syswrap-openbsd", 
+            "run_a_thread_NORETURN(tid=%lld): "
+            "WARNING: exiting thread has err_disablement_level = %u\n",
+            (ULong)tidW, tst->err_disablement_level
+      );
+   }
+   tst->err_disablement_level = 0;
+
+   if (c == 1) {
+
+      VG_(debugLog)(1, "syswrap-openbsd", 
+                       "run_a_thread_NORETURN(tid=%lld): "
+                          "last one standing\n",
+                          (ULong)tidW);
+
+      /* We are the last one standing.  Keep hold of the lock and
+         carry on to show final tool results, then exit the entire system. 
+         Use the continuation pointer set at startup in m_main. */
+      ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src);
+
+   } else {
+
+      VG_(debugLog)(1, "syswrap-openbsd", 
+                       "run_a_thread_NORETURN(tid=%lld): "
+                          "not last one standing\n",
+                          (ULong)tidW);
+
+      /* OK, thread is dead, but others still exist.  Just exit. */
+
+      /* This releases the run lock */
+      VG_(exit_thread)(tid);
+      vg_assert(tst->status == VgTs_Zombie);
+
+      /* We have to use this sequence to terminate the thread to
+         prevent a subtle race.  If VG_(exit_thread)() had left the
+         ThreadState as Empty, then it could have been reallocated,
+         reusing the stack while we're doing these last cleanups.
+         Instead, VG_(exit_thread) leaves it as Zombie to prevent
+         reallocation.  We need to make sure we don't touch the stack
+         between marking it Empty and exiting.  Hence the
+         assembler. */
+/* #if defined(VGP_x86_openbsd)	/\* FreeBSD has args on the stack *\/ */
+      /* asm volatile ( */
+         /* "movl	%1, %0\n"	/\* set tst->status = VgTs_Empty *\/ */
+         /* "movl	%2, %%eax\n"    /\* set %eax = __NR_thr_exit *\/ */
+         /* "movl	%3, %%ebx\n"    /\* set %ebx = tst->os_state.exitcode *\/ */
+	 /* "pushl	%%ebx\n"	/\* arg on stack *\/ */
+	 /* "pushl	%%ebx\n"	/\* fake return address *\/ */
+         /* "int	$0x80\n"	/\* thr_exit(tst->os_state.exitcode) *\/ */
+	 /* "popl	%%ebx\n"	/\* fake return address *\/ */
+	 /* "popl	%%ebx\n"	/\* arg off stack *\/ */
+      /*    : "=m" (tst->status) */
+      /*    : "n" (VgTs_Empty), "n" (__NR_thr_exit), "m" (tst->os_state.exitcode) */
+      /*    : "eax", "ebx" */
+      /* ); */
+#if defined(VGP_amd64_openbsd)
+      asm volatile (
+         "movl	%1, %0\n"	/* set tst->status = VgTs_Empty */
+         "movq	%2, %%rax\n"    /* set %rax = __NR_thr_exit */
+         "movq	%3, %%rdi\n"    /* set %rdi = tst->os_state.exitcode */
+	 "pushq	%%rdi\n"	/* fake return address */
+         "syscall\n"		/* thr_exit(tst->os_state.exitcode) */
+	 "popq	%%rdi\n"	/* fake return address */
+         : "=m" (tst->status)
+         : "n" (VgTs_Empty), "n" (__NR___threxit), "m" (tst->os_state.exitcode)
+         : "rax", "rdi"
+      );
+#else
+# error Unknown platform
+#endif
+
+      VG_(core_panic)("Thread exit failed?\n");
+   }
+
+   /*NOTREACHED*/
+   vg_assert(0);
+}
+
+Word ML_(start_thread_NORETURN) ( void* arg )
+{
+   ThreadState* tst = (ThreadState*)arg;
+   ThreadId     tid = tst->tid;
+
+   run_a_thread_NORETURN ( (Word)tid );
+   /*NOTREACHED*/
+   vg_assert(0);
+}
+
+/* Allocate a stack for this thread, if it doesn't already have one.
+   They're allocated lazily, and never freed.  Returns the initial stack
+   pointer value to use, or 0 if allocation failed. */
+Addr ML_(allocstack)(ThreadId tid)
+{
+   ThreadState* tst = VG_(get_ThreadState)(tid);
+   VgStack*     stack;
+   Addr         initial_SP;
+
+   /* Either the stack_base and stack_init_SP are both zero (in which
+      case a stack hasn't been allocated) or they are both non-zero,
+      in which case it has. */
+
+   if (tst->os_state.valgrind_stack_base == 0)
+      vg_assert(tst->os_state.valgrind_stack_init_SP == 0);
+
+   if (tst->os_state.valgrind_stack_base != 0)
+      vg_assert(tst->os_state.valgrind_stack_init_SP != 0);
+
+   /* If no stack is present, allocate one. */
+
+   if (tst->os_state.valgrind_stack_base == 0) {
+      stack = VG_(am_alloc_VgStack)( &initial_SP );
+      if (stack) {
+         tst->os_state.valgrind_stack_base    = (Addr)stack;
+         tst->os_state.valgrind_stack_init_SP = initial_SP;
+      }
+   }
+
+   if (0)
+      VG_(printf)( "stack for tid %d at %p; init_SP=%p\n",
+                   tid, 
+                   (void*)tst->os_state.valgrind_stack_base, 
+                   (void*)tst->os_state.valgrind_stack_init_SP );
+                  
+   return tst->os_state.valgrind_stack_init_SP;
+}
+
+/* Allocate a stack for the main thread, and run it all the way to the
+   end.  Although we already have a working VgStack
+   (VG_(interim_stack)) it's better to allocate a new one, so that
+   overflow detection works uniformly for all threads.
+*/
+void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
+{
+   Addr sp;
+   VG_(debugLog)(1, "syswrap-openbsd", 
+                    "entering VG_(main_thread_wrapper_NORETURN)\n");
+
+   sp = ML_(allocstack)(tid);
+
+/* QQQ keep for amd64 redzone stuff */
+#if defined(VGP_ppc32_linux)
+   /* make a stack frame */
+   sp -= 16;
+   sp &= ~0xF;
+   *(UWord *)sp = 0;
+#elif defined(VGP_ppc64_linux)
+   /* make a stack frame */
+   sp -= 112;
+   sp &= ~((Addr)0xF);
+   *(UWord *)sp = 0;
+#endif
+
+   /* If we can't even allocate the first thread's stack, we're hosed.
+      Give up. */
+   vg_assert2(sp != 0, "Cannot allocate main thread's stack.");
+
+   /* shouldn't be any other threads around yet */
+   vg_assert( VG_(count_living_threads)() == 1 );
+
+   ML_(call_on_new_stack_0_1)( 
+      (Addr)sp,               /* stack */
+      0,                      /* bogus return address */
+      run_a_thread_NORETURN,  /* fn to call */
+      (Word)tid               /* arg to give it */
+   );
+
+   /*NOTREACHED*/
+   vg_assert(0);
+}
+
+
+/* Do a fork() */
+SysRes ML_(do_fork) ( ThreadId tid )
+{
+   vki_sigset_t fork_saved_mask;
+   vki_sigset_t mask;
+   SysRes       res;
+
+   /* Block all signals during fork, so that we can fix things up in
+      the child without being interrupted. */
+   VG_(sigfillset)(&mask);
+   VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
+
+   VG_(do_atfork_pre)(tid);
+
+   res = VG_(do_syscall0)( __NR_fork );
+   
+   if (!sr_isError(res)) {
+      if (sr_Res(res) == 0) {
+         /* child */
+         VG_(do_atfork_child)(tid);
+
+         /* restore signal mask */
+         VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
+
+      } 
+      else { 
+         /* parent */
+         VG_(do_atfork_parent)(tid);
+
+         if (VG_(clo_trace_syscalls))
+	     VG_(printf)("   clone(fork): process %d created child %ld\n",
+                         VG_(getpid)(), sr_Res(res));
+
+         /* restore signal mask */
+         VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
+      }
+   }
+
+   return res;
+}
+
+
+/* ---------------------------------------------------------------------
+   PRE/POST wrappers for arch-generic, Linux-specific syscalls
+   ------------------------------------------------------------------ */
+
+// Nb: See the comment above the generic PRE/POST wrappers in
+// m_syswrap/syswrap-generic.c for notes about how they work.
+
+#define PRE(name)       DEFN_PRE_TEMPLATE(openbsd, name)
+#define POST(name)      DEFN_POST_TEMPLATE(openbsd, name)
+
+// Combine two 32-bit values into a 64-bit value
+#define LOHI64(lo,hi)   ( (lo) | ((ULong)(hi) << 32) )
+
+PRE(sys_fork)
+{
+   PRINT("sys_fork ()");
+   PRE_REG_READ0(int, "fork");
+
+   SET_STATUS_from_SysRes( ML_(do_fork)(tid) );
+   if (SUCCESS) {
+      /* Thread creation was successful; let the child have the chance
+         to run */
+      *flags |= SfYieldAfter;
+   }
+}
+
+PRE(sys_vfork)
+{
+   PRINT("sys_vfork ()");
+   PRE_REG_READ0(int, "vfork");
+
+   /* Pretend vfork == fork. Not true, but will have to do. */
+   SET_STATUS_from_SysRes( ML_(do_fork)(tid) );
+   if (SUCCESS) {
+      /* Thread creation was successful; let the child have the chance
+         to run */
+      *flags |= SfYieldAfter;
+   }
+}
+
+PRE(sys_msyscall)
+{
+   PRINT("sys_msyscall ( %ld, %ld )",ARG1,ARG2);
+   PRE_REG_READ2(long, "msyscall", void *, addr, vki_size_t, len);
+}
+
+PRE(sys_socket)
+{
+   PRINT("sys_socket ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "socket", int, domain, int, type, int, protocol);
+}
+POST(sys_socket)
+{
+   SysRes r;
+   vg_assert(SUCCESS);
+   r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES));
+   SET_STATUS_from_SysRes(r);
+}
+
+PRE(sys_setsockopt)
+{
+   PRINT("sys_setsockopt ( %ld, %ld, %ld, %#lx, %ld )",ARG1,ARG2,ARG3,ARG4,ARG5);
+   PRE_REG_READ5(long, "setsockopt",
+                 int, s, int, level, int, optname,
+                 const void *, optval, int, optlen);
+   ML_(generic_PRE_sys_setsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5);
+}
+
+PRE(sys_getsockopt)
+{
+   PRINT("sys_getsockopt ( %ld, %ld, %ld, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
+   PRE_REG_READ5(long, "getsockopt",
+                 int, s, int, level, int, optname,
+                 void *, optval, int, *optlen);
+// XXX: ML_(generic_PRE_sys_getsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5);
+}
+POST(sys_getsockopt)
+{
+   vg_assert(SUCCESS);
+//   ML_(generic_POST_sys_getsockopt)(tid, VG_(mk_SysRes_Success)(RES),
+//XXX:                                         ARG1,ARG2,ARG3,ARG4,ARG5);
+}
+
+PRE(sys_connect)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_connect ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "connect",
+                 int, sockfd, struct sockaddr *, serv_addr, int, addrlen);
+   ML_(generic_PRE_sys_connect)(tid, ARG1,ARG2,ARG3);
+}
+
+PRE(sys_accept)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_accept ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "accept",
+                 int, s, struct sockaddr *, addr, int, *addrlen);
+   ML_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3);
+}
+POST(sys_accept)
+{
+   SysRes r;
+   vg_assert(SUCCESS);
+   r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES),
+                                         ARG1,ARG2,ARG3);
+   SET_STATUS_from_SysRes(r);
+}
+
+/* XXX copied from syswrap-linux.c */
+PRE(sys_accept4)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_accept4 ( %ld, %#lx, %ld, %ld )",ARG1,ARG2,ARG3,ARG4);
+   PRE_REG_READ4(long, "accept4",
+                 int, s, struct sockaddr *, addr, int, *addrlen, int, flags);
+   ML_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3);
+}
+POST(sys_accept4)
+{
+   SysRes r;
+   vg_assert(SUCCESS);
+   r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES),
+                                         ARG1,ARG2,ARG3);
+   SET_STATUS_from_SysRes(r);
+}
+
+PRE(sys_sendto)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_sendto ( %ld, %#lx, %ld, %lu, %#lx, %ld )",ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
+   PRE_REG_READ6(long, "sendto",
+                 int, s, const void *, msg, int, len, 
+                 unsigned int, flags, 
+                 const struct sockaddr *, to, int, tolen);
+   ML_(generic_PRE_sys_sendto)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
+}
+
+PRE(sys_recvfrom)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_recvfrom ( %ld, %#lx, %ld, %lu, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
+   PRE_REG_READ6(long, "recvfrom",
+                 int, s, void *, buf, int, len, unsigned int, flags,
+                 struct sockaddr *, from, int *, fromlen);
+   ML_(generic_PRE_sys_recvfrom)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
+}
+POST(sys_recvfrom)
+{
+   vg_assert(SUCCESS);
+   ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES),
+                                       ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
+}
+
+PRE(sys_sendmsg)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_sendmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "sendmsg",
+                 int, s, const struct msghdr *, msg, int, flags);
+   ML_(generic_PRE_sys_sendmsg)(tid, "sendmsg", (struct vki_msghdr *)ARG2);
+}
+
+PRE(sys_recvmsg)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_recvmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
+   ML_(generic_PRE_sys_recvmsg)(tid, "recvmsg", (struct vki_msghdr *)ARG2);
+}
+POST(sys_recvmsg)
+{
+
+   ML_(generic_POST_sys_recvmsg)(tid, "recvmsg", (struct vki_msghdr *)ARG2, RES);
+}
+
+PRE(sys_shutdown)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_shutdown ( %ld, %ld )",ARG1,ARG2);
+   PRE_REG_READ2(int, "shutdown", int, s, int, how);
+}
+
+PRE(sys_bind)
+{
+   PRINT("sys_bind ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "bind",
+                 int, sockfd, struct sockaddr *, my_addr, int, addrlen);
+   ML_(generic_PRE_sys_bind)(tid, ARG1,ARG2,ARG3);
+}
+
+PRE(sys_listen)
+{
+   PRINT("sys_listen ( %ld, %ld )",ARG1,ARG2);
+   PRE_REG_READ2(long, "listen", int, s, int, backlog);
+}
+
+PRE(sys_pledge)
+{
+   /* Force success to prevent client from actually calling pledge(2). */
+   SET_STATUS_Success(0);
+}
+
+PRE(sys_ppoll)
+{
+// XXXTBD
+}
+
+PRE(sys_pselect)
+{
+// XXXTBD
+}
+
+PRE(sys_unveil)
+{
+   PRINT("sys_unveil ( %#lx(%s), %#lx(%s) )",
+         ARG1,(char *)ARG1,ARG2,(char*)ARG2);
+   PRE_REG_READ2(long, "unveil", const char *, path, const char *, permissions);
+   if (ARG1 != (UWord)NULL)
+     PRE_MEM_RASCIIZ( "unveil(path)", ARG1 );
+   if (ARG2 != (UWord)NULL)
+     PRE_MEM_RASCIIZ( "unveil(permissions)", ARG2 );
+}
+
+PRE(sys___realpath)
+{
+   PRINT("sys___realpath ( %#lx(%s), %#lx )",
+         ARG1,(char *)ARG1,ARG2);
+   PRE_REG_READ2(long, "__realpath",
+		 const char *, pathname, char *, resolved);
+   if (ARG1 != NULL)
+     PRE_MEM_RASCIIZ( "__realpath(path)", ARG1 );
+}
+POST(sys___realpath)
+{
+   if (ARG2 != NULL) {
+      POST_MEM_WRITE( ARG2, MAXPATHLEN );
+   }
+}
+
+PRE(sys_recvmmsg)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_recvmmsg ( %ld, %#lx, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
+   PRE_REG_READ5(long, "recvmmsg", int, s, struct mmsghdr *, mmsg,
+		 unsigned int, vlen, int, flags, struct timespec *, timeout);
+}
+POST(sys_recvmmsg)
+{
+   ML_(generic_POST_sys_recvmsg)(tid, "recvmmsg",
+				 &((struct vki_mmsghdr *)ARG2)->msg_hdr,
+				 ((struct vki_mmsghdr *)ARG2)->msg_len);
+}
+
+PRE(sys_sendmmsg)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_sendmmsg ( %ld, %#lx, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
+   PRE_REG_READ4(long, "sendmmsg",
+                 int, s, const struct mmsghdr *, mmsg, unsigned int, vlen,
+		 int, flags);
+   ML_(generic_PRE_sys_sendmsg)(tid, "sendmmsg",
+				 &((struct vki_mmsghdr *)ARG2)->msg_hdr);
+}
+
+PRE(sys_getsockname)
+{
+   PRINT("sys_getsockname ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "getsockname",
+                 int, s, struct sockaddr *, name, int *, namelen);
+   ML_(generic_PRE_sys_getsockname)(tid, ARG1,ARG2,ARG3);
+}
+POST(sys_getsockname)
+{
+   vg_assert(SUCCESS);
+   ML_(generic_POST_sys_getsockname)(tid, VG_(mk_SysRes_Success)(RES),
+                                          ARG1,ARG2,ARG3);
+}
+
+PRE(sys_getpeername)
+{
+   PRINT("sys_getpeername ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "getpeername",
+                 int, s, struct sockaddr *, name, int *, namelen);
+   ML_(generic_PRE_sys_getpeername)(tid, ARG1,ARG2,ARG3);
+}
+POST(sys_getpeername)
+{
+   vg_assert(SUCCESS);
+   ML_(generic_POST_sys_getpeername)(tid, VG_(mk_SysRes_Success)(RES),
+                                          ARG1,ARG2,ARG3);
+}
+
+PRE(sys_socketpair)
+{
+   PRINT("sys_socketpair ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
+   PRE_REG_READ4(long, "socketpair",
+                 int, d, int, type, int, protocol, int *, sv);
+   ML_(generic_PRE_sys_socketpair)(tid, ARG1,ARG2,ARG3,ARG4);
+}
+POST(sys_socketpair)
+{
+   vg_assert(SUCCESS);
+   ML_(generic_POST_sys_socketpair)(tid, VG_(mk_SysRes_Success)(RES),
+                                         ARG1,ARG2,ARG3,ARG4);
+}
+
+/* ---------------------------------------------------------------------
+   *mount wrappers
+   ------------------------------------------------------------------ */
+
+PRE(sys_mount)
+{
+   // Nb: depending on 'flags', the 'type' and 'data' args may be ignored.
+   // We are conservative and check everything, except the memory pointed to
+   // by 'data'.
+   *flags |= SfMayBlock;
+   PRINT( "sys_mount( %#lx, %#lx, %ld, %#lx )" ,ARG1,ARG2,ARG3,ARG4);
+   PRE_REG_READ4(long, "mount",
+                 char *, type, char *, path, int, flags,
+                 void *, data);
+   PRE_MEM_RASCIIZ( "mount(type)", ARG1);
+   PRE_MEM_RASCIIZ( "mount(path)", ARG2);
+}
+
+PRE(sys_unmount)
+{
+   PRINT("sys_umount( %#lx, %ld )", ARG1, ARG2);
+   PRE_REG_READ2(long, "unmount", char *, path, int, flags);
+   PRE_MEM_RASCIIZ( "unmount(path)", ARG1);
+}
+
+/* ---------------------------------------------------------------------
+   16- and 32-bit uid/gid wrappers
+   ------------------------------------------------------------------ */
+
+#if 0
+PRE(sys_setfsuid)
+{
+   PRINT("sys_setfsuid ( %ld )", ARG1);
+   PRE_REG_READ1(long, "setfsuid", vki_uid_t, uid);
+}
+
+PRE(sys_setfsgid)
+{
+   PRINT("sys_setfsgid ( %ld )", ARG1);
+   PRE_REG_READ1(long, "setfsgid", vki_gid_t, gid);
+}
+#endif
+
+PRE(sys_setresuid)
+{
+   PRINT("sys_setresuid ( %ld, %ld, %ld )", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "setresuid",
+                 vki_uid_t, ruid, vki_uid_t, euid, vki_uid_t, suid);
+}
+
+PRE(sys_getresuid)
+{
+   PRINT("sys_getresuid ( %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "getresuid", 
+                 vki_uid_t *, ruid, vki_uid_t *, euid, vki_uid_t *, suid);
+   PRE_MEM_WRITE( "getresuid(ruid)", ARG1, sizeof(vki_uid_t) );
+   PRE_MEM_WRITE( "getresuid(euid)", ARG2, sizeof(vki_uid_t) );
+   PRE_MEM_WRITE( "getresuid(suid)", ARG3, sizeof(vki_uid_t) );
+}
+
+POST(sys_getresuid)
+{
+   vg_assert(SUCCESS);
+   if (RES == 0) {
+      POST_MEM_WRITE( ARG1, sizeof(vki_uid_t) );
+      POST_MEM_WRITE( ARG2, sizeof(vki_uid_t) );
+      POST_MEM_WRITE( ARG3, sizeof(vki_uid_t) );
+   }
+}
+
+PRE(sys_setresgid)
+{
+   PRINT("sys_setresgid ( %ld, %ld, %ld )", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "setresgid",
+                 vki_gid_t, rgid, vki_gid_t, egid, vki_gid_t, sgid);
+}
+
+PRE(sys_getresgid)
+{
+   PRINT("sys_getresgid ( %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "getresgid", 
+                 vki_gid_t *, rgid, vki_gid_t *, egid, vki_gid_t *, sgid);
+   PRE_MEM_WRITE( "getresgid(rgid)", ARG1, sizeof(vki_gid_t) );
+   PRE_MEM_WRITE( "getresgid(egid)", ARG2, sizeof(vki_gid_t) );
+   PRE_MEM_WRITE( "getresgid(sgid)", ARG3, sizeof(vki_gid_t) );
+}
+
+POST(sys_getresgid)
+{
+   vg_assert(SUCCESS);
+   if (RES == 0) {
+      POST_MEM_WRITE( ARG1, sizeof(vki_gid_t) );
+      POST_MEM_WRITE( ARG2, sizeof(vki_gid_t) );
+      POST_MEM_WRITE( ARG3, sizeof(vki_gid_t) );
+   }
+}
+
+/* ---------------------------------------------------------------------
+   miscellaneous wrappers
+   ------------------------------------------------------------------ */
+
+#if 0
+PRE(sys_exit_group)
+{
+   ThreadId     t;
+   ThreadState* tst;
+
+   PRINT("exit_group( %ld )", ARG1);
+   PRE_REG_READ1(void, "exit_group", int, exit_code);
+
+   tst = VG_(get_ThreadState)(tid);
+
+   /* A little complex; find all the threads with the same threadgroup
+      as this one (including this one), and mark them to exit */
+   for (t = 1; t < VG_N_THREADS; t++) {
+      if ( /* not alive */
+           VG_(threads)[t].status == VgTs_Empty 
+           ||
+	   /* not our group */
+           VG_(threads)[t].os_state.threadgroup != tst->os_state.threadgroup
+         )
+         continue;
+
+      VG_(threads)[t].exitreason = VgSrc_ExitSyscall;
+      VG_(threads)[t].os_state.exitcode = ARG1;
+
+      if (t != tid)
+	 VG_(get_thread_out_of_syscall)(t);	/* unblock it, if blocked */
+   }
+
+   /* We have to claim the syscall already succeeded. */
+   SET_STATUS_Success(0);
+}
+#endif
+
+/* On FreeBSD, if any thread calls exit(2), then they are all shut down, pretty
+ * much like linux's exit_group().
+ */
+PRE(sys_exit)
+{
+   ThreadId     t;
+   ThreadState* tst;
+
+   PRINT("exit( %ld )", ARG1);
+   PRE_REG_READ1(void, "exit", int, status);
+   tst = VG_(get_ThreadState)(tid);
+
+   /* Mark all threads (including this one) to exit. */
+   for (t = 1; t < VG_N_THREADS; t++) {
+      if ( /* not alive */ VG_(threads)[t].status == VgTs_Empty )
+         continue;
+
+      VG_(threads)[t].exitreason = VgSrc_ExitThread;
+      VG_(threads)[t].os_state.exitcode = ARG1;
+
+      if (t != tid)
+	 VG_(get_thread_out_of_syscall)(t);	/* unblock it, if blocked */
+   }
+
+   /* We have to claim the syscall already succeeded. */
+   SET_STATUS_Success(0);
+}
+
+PRE(sys_getlogin_r)
+{
+   PRINT("sys_getlogin_r ( %#lx, %ld )",ARG1,ARG2);
+   PRE_REG_READ2(long, "getlogin_r",
+                 char *, buf, int, len);
+   PRE_MEM_WRITE( "getlogin_r(buf, len)", ARG1, ARG2 );
+}
+POST(sys_getlogin_r)
+{
+   if (ARG1 != 0) {
+      POST_MEM_WRITE( ARG1, ARG2 );
+   }
+}
+
+PRE(sys_pinsyscall)
+{
+// XXXTBD
+}
+
+PRE(sys_setlogin)
+{
+   PRINT("sys_setlogin ( %#lx )",ARG1);
+   PRE_REG_READ1(long, "setlogin", char *, buf);
+   PRE_MEM_RASCIIZ( "setlogin(buf)", ARG1 );
+}
+PRE(sys_mkfifo)
+{
+   PRINT("sys_mkfifo ( %#lx(%s), 0x%lx, 0x%lx )", ARG1, (char *)ARG1, ARG2, ARG3 );
+   PRE_REG_READ2(long, "mkfifo", const char *, pathname, int, mode);
+   PRE_MEM_RASCIIZ( "mkfifo(pathname)", ARG1 );
+}
+
+/* int quotactl(const char *path, int cmd, int id, void *addr); */
+
+PRE(sys_adjtime)
+{
+// XXXTBD
+}
+
+PRE(sys_quotactl)
+{
+   PRINT("sys_quotactl (%#lx, %ld, %ld, %#lx )", ARG1,ARG2,ARG3, ARG4);
+   PRE_REG_READ4(long, "quotactl",
+                 const char *, path, int, cmd, int, id,
+                 void *, addr);
+   PRE_MEM_RASCIIZ( "quotactl(path)", ARG1 );
+}
+
+PRE(sys_ypconnect)
+{
+   PRINT("sys_ypconnect ( %ld )", ARG1 );
+   PRE_REG_READ1(int, "ypconnect", int, type);
+}
+
+PRE(sys_nfssvc)
+{
+// XXXTBD
+}
+
+PRE(sys_mimmutable)
+{
+   PRINT("sys_mimmutable (%#lx, %ld )", ARG1,ARG2);
+   PRE_REG_READ2(long, "mimmutable", void *, addr, vki_size_t, len);
+}
+
+PRE(sys_waitid)
+{
+   PRINT("sys_waitid (%#lx, %ld )", ARG1,ARG2,ARG3,ARG4);
+   PRE_REG_READ4(long, "waitid",
+		 int, idtype, int, id, vki_siginfo_t, info, int, options);
+}
+
+/* int getdomainname(char *domainname, int len); */
+PRE(sys_getdomainname)
+{
+   PRINT("sys_getdomainname ( %#lx, %ld )",ARG1,ARG2);
+   PRE_REG_READ2(long, "getdomainname",
+                 char *, buf, int, len);
+   PRE_MEM_WRITE( "getdomainname(buf, len)", ARG1, ARG2 );
+}
+POST(sys_getdomainname)
+{
+   if (ARG1 != 0) {
+      POST_MEM_WRITE( ARG1, ARG2 );
+   }
+}
+/* int setdomainname(char *domainname, int len); */
+PRE(sys_setdomainname)
+{
+   PRINT("sys_setdomainname ( %#lx )",ARG1);
+   PRE_REG_READ1(long, "setdomainname", char *, buf);
+   PRE_MEM_RASCIIZ( "setdomainname(buf)", ARG1 );
+}
+
+#if 0
+PRE(sys_uname)
+{
+   PRINT("sys_uname ( %#lx )", ARG1);
+   PRE_REG_READ1(long, "uname", struct utsname *, buf);
+   PRE_MEM_WRITE( "uname(buf)", ARG1, sizeof(struct vki_utsname) );
+}
+
+POST(sys_uname)
+{
+   if (ARG1 != 0) {
+      POST_MEM_WRITE( ARG1, sizeof(struct vki_utsname) );
+   }
+}
+#endif
+
+PRE(sys_lstat)
+{
+   PRINT("sys_lstat ( %#lx(%s), %#lx )",ARG1,(char *)ARG1,ARG2);
+   PRE_REG_READ2(long, "lstat", char *, file_name, struct stat *, buf);
+   PRE_MEM_RASCIIZ( "lstat(file_name)", ARG1 );
+   PRE_MEM_WRITE( "lstat(buf)", ARG2, sizeof(struct vki_stat) );
+}
+
+POST(sys_lstat)
+{
+   vg_assert(SUCCESS);
+   if (RES == 0) {
+      POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
+   }
+}
+
+PRE(sys_stat)
+{
+   PRINT("sys_stat ( %#lx(%s), %#lx )",ARG1,(char *)ARG1,ARG2);
+   PRE_REG_READ2(long, "stat", char *, file_name, struct stat *, buf);
+   PRE_MEM_RASCIIZ( "stat(file_name)", ARG1 );
+   PRE_MEM_WRITE( "stat(buf)", ARG2, sizeof(struct vki_stat) );
+}
+
+POST(sys_stat)
+{
+   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
+}
+
+PRE(sys_fstat)
+{
+   PRINT("sys_fstat ( %ld, %#lx )",ARG1,ARG2);
+   PRE_REG_READ2(long, "fstat", unsigned long, fd, struct stat *, buf);
+   PRE_MEM_WRITE( "fstat(buf)", ARG2, sizeof(struct vki_stat) );
+}
+
+POST(sys_fstat)
+{
+   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
+}
+
+PRE(sys_pathconf)
+{
+   PRINT("sys_pathconf ( %#lx(%s), %ld )",ARG1,(char *)ARG1,ARG2);
+   PRE_REG_READ2(long, "pathconf", char *, file_name, int, name);
+   PRE_MEM_RASCIIZ( "pathconf(file_name)", ARG1 );
+}
+
+PRE(sys_fpathconf)
+{
+   PRINT("sys_fpathconf ( %ld, %ld )",ARG1,ARG2);
+   PRE_REG_READ2(long, "fpathconf", int, fd, int, name);
+}
+
+PRE(sys_lchmod)
+{
+   PRINT("sys_lchmod ( %#lx(%s), %ld )", ARG1,(char *)ARG1,ARG2);
+   PRE_REG_READ2(long, "lchmod", const char *, path, vki_mode_t, mode);
+   PRE_MEM_RASCIIZ( "lchmod(path)", ARG1 );
+}
+
+PRE(sys_issetugid)
+{
+   PRINT("sys_issetugid ()");
+   PRE_REG_READ0(long, "issetugid");
+}
+
+PRE(sys_revoke)
+{
+   PRINT("sys_vhangup ( )");
+   PRE_REG_READ0(long, "vhangup");
+}
+PRE(sys_undelete)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_undelete ( %#lx(%s) )", ARG1,(char *)ARG1);
+   PRE_REG_READ1(long, "undelete", const char *, pathname);
+   PRE_MEM_RASCIIZ( "undelete(pathname)", ARG1 );
+}
+PRE(sys_yield)
+{
+   *flags |= SfMayBlock;
+   PRINT("yield()");
+   PRE_REG_READ0(long, "yield");
+}
+
+PRE(sys_sched_yield)
+{
+   *flags |= SfMayBlock;
+   PRINT("sched_yield()");
+}
+
+#if 0
+PRE(sys_sysinfo)
+{
+   PRINT("sys_sysinfo ( %#lx )",ARG1);
+   PRE_REG_READ1(long, "sysinfo", struct sysinfo *, info);
+   PRE_MEM_WRITE( "sysinfo(info)", ARG1, sizeof(struct vki_sysinfo) );
+}
+
+POST(sys_sysinfo)
+{
+   POST_MEM_WRITE( ARG1, sizeof(struct vki_sysinfo) );
+}
+#endif
+
+/* int __sysctl(int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen); */
+/*               ARG1        ARG2          ARG3         ARG4           ARG5        ARG6 */
+
+PRE(sys___sysctl)
+{
+   PRINT("sys_sysctl ( %#lx, %ld, %#lx, %#lx, %#lx, %ld )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6 );
+   PRE_REG_READ6(long, "__sysctl", int *, name, unsigned int, namelen, void *, old,
+		 vki_size_t *, oldlenp, void *, new, vki_size_t, newlen);
+   PRE_MEM_READ("sysctl(name)", ARG1, ARG2 * sizeof(int));
+   if (ARG5 != (UWord)NULL)
+      PRE_MEM_READ("sysctl(new)", (Addr)ARG5, ARG6);
+   if (ARG4 != (UWord)NULL) {
+      if (ARG3 != (UWord)NULL) {
+         PRE_MEM_READ("sysctl(oldlenp)", (Addr)ARG4, sizeof(vki_size_t));
+         PRE_MEM_WRITE("sysctl(oldval)", (Addr)ARG3, *(vki_size_t *)ARG4);
+      }
+      PRE_MEM_WRITE("sysctl(oldlenp)", (Addr)ARG4, sizeof(vki_size_t));
+   }
+}
+POST(sys___sysctl)
+{
+   if (ARG4 != (UWord)NULL) {
+      POST_MEM_WRITE((Addr)ARG4, sizeof(vki_size_t));
+      if (ARG3 != (UWord)NULL)
+         POST_MEM_WRITE((Addr)ARG3, *(vki_size_t *)ARG4);
+   }
+}
+
+PRE(sys_sendfile)
+{
+   *flags |= SfMayBlock;
+#if defined(VGP_x86_openbsd)
+   PRINT("sys_sendfile ( %ld, %ld, %llu, %ld, %#lx, %#lx, %lu )", ARG1,ARG2,LOHI64(ARG3,ARG4),ARG5,ARG6,ARG7,ARG8);
+#elif defined(VGP_amd64_openbsd)
+   PRINT("sys_sendfile ( %ld, %ld, %lu, %ld, %#lx, %#lx, %lu )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7);
+#else
+#  error Unknown platform
+#endif
+   PRE_REG_READ7(ssize_t, "sendfile",
+                 int, fd, int, s, unsigned int, offset_low,
+		 unsigned int, offset_high,
+                 void *, hdtr, vki_off_t *, sbytes, int, flags);
+   if (ARG3 != 0)
+      PRE_MEM_WRITE( "sendfile(offset)", ARG3, sizeof(vki_off_t) );
+}
+POST(sys_sendfile)
+{
+   if (ARG3 != 0 ) {
+      POST_MEM_WRITE( ARG3, sizeof( vki_off_t ) );
+   }
+}
+
+PRE(sys_seteuid)
+{
+   PRINT("sys_seteuid ( %ld )", ARG1);
+   PRE_REG_READ1(long, "seteuid", vki_uid_t, uid);
+}
+
+PRE(sys_setegid)
+{
+   PRINT("sys_setegid ( %ld )", ARG1);
+   PRE_REG_READ1(long, "setegid", vki_gid_t, gid);
+}
+
+PRE(sys_lutimes)
+{
+   PRINT("sys_lutimes ( %#lx(%s), %#lx )", ARG1,(char *)ARG1,ARG2);
+   PRE_REG_READ2(long, "lutimes", char *, filename, struct timeval *, tvp);
+   PRE_MEM_RASCIIZ( "lutimes(filename)", ARG1 );
+   if (ARG2 != 0)
+      PRE_MEM_READ( "lutimes(tvp)", ARG2, sizeof(struct vki_timeval) );
+}
+
+PRE(sys_futimes)
+{
+   PRINT("sys_lutimes ( %ld, %#lx )", ARG1,ARG2);
+   PRE_REG_READ2(long, "futimes", int, fd, struct timeval *, tvp);
+   if (ARG2 != 0)
+      PRE_MEM_READ( "futimes(tvp)", ARG2, sizeof(struct vki_timeval) );
+}
+
+PRE(sys_mquery)
+{
+   SysRes r;
+
+   PRINT("sys_mquery ( %#lx, %lu, %ld, %ld, %ld, 0x%lx)",
+         ARG1, (UWord)ARG2, ARG3, ARG4, ARG5, ARG6 );
+   PRE_REG_READ6(void *, "mquery",
+                 void *, addr, vki_size_t, len, int, prot,  int, flags,
+                 int, fd, vki_off_t, pos);
+}
+
+PRE(sys_utrace)
+{
+   PRINT("sys_utrace ( %#lx, %lu )", ARG1, ARG2);
+   PRE_REG_READ2(long, "utrace", const void *, buf, vki_size_t, len);
+   PRE_MEM_READ( "utrace(buf,len)", ARG2, ARG3 );
+}
+
+PRE(sys_getdtablecount)
+{
+   PRINT("sys_getdtablecount ( )");
+   PRE_REG_READ0(long, "getdtablecount");
+}
+
+PRE(sys_kqueue)
+{
+   PRINT("sys_kqueue ()");
+}
+POST(sys_kqueue)
+{
+   if (!ML_(fd_allowed)(RES, "kqueue", tid, True)) {
+      VG_(close)(RES);
+      SET_STATUS_Failure( VKI_EMFILE );
+   } else {
+      if (VG_(clo_track_fds)) {
+         ML_(record_fd_open_nameless)(tid, RES);
+      }
+   }
+}
+
+PRE(sys_kevent)
+{
+   /* struct kevent {
+        uintptr_t ident;  -- identifier for this event
+	short     filter; -- filter for event
+	u_short   flags;  -- action flags for kqueue
+	u_int     fflags; -- filter flag value
+	intptr_t  data;   -- filter data value
+	void      *udata; -- opaque user data identifier
+      };
+      int kevent(int kq, const struct kevent *changelist, int nchanges,
+                 struct kevent *eventlist, int nevents,
+                 const struct timespec *timeout);
+   */
+   *flags |= SfMayBlock;
+   PRINT("sys_kevent ( %ld, %#lx, %ld, %#lx, %ld, %#lx )\n", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
+   PRE_REG_READ6(long, "kevent",
+                 int, fd, struct vki_kevent *, newev, int, num_newev,
+		 struct vki_kevent *, ret_ev, int, num_retev,
+		 struct timespec *, timeout);
+   if (ARG2 != 0 && ARG3 != 0)
+      PRE_MEM_READ( "kevent(changeevent)", ARG2, sizeof(struct vki_kevent)*ARG3 );
+   if (ARG4 != 0 && ARG5 != 0)
+      PRE_MEM_WRITE( "kevent(events)", ARG4, sizeof(struct vki_kevent)*ARG5);
+   if (ARG6 != 0)
+      PRE_MEM_READ( "kevent(timeout)",
+                    ARG6, sizeof(struct vki_timespec));
+}
+
+POST(sys_kevent)
+{
+   vg_assert(SUCCESS);
+   if (RES > 0) {
+      if (ARG4 != 0)
+         POST_MEM_WRITE( ARG4, sizeof(struct vki_kevent)*RES) ;
+   }
+}
+
+PRE(sys___getcwd)
+{
+   PRINT("sys___getcwd ( %#lx, %lu )", ARG1,ARG2);
+   PRE_REG_READ2(long, "__getcwd", char *, buf, unsigned int, size);
+   PRE_MEM_WRITE( "__getcwd(buf)", ARG1, ARG2 );
+}
+
+POST(sys___getcwd)
+{
+   vg_assert(SUCCESS);
+   if (RES == 0) {
+      // QQQ it is unclear if this is legal or not, but the
+      // QQQ kernel just wrote it there...
+      // QQQ Why oh why didn't phk return the length from __getcwd()?
+      UInt len = VG_(strlen) ( (char *)ARG1 ) + 1;
+      POST_MEM_WRITE( ARG1, len );
+   }
+}
+
+// getfsstat() takes a length in bytes, but returns the number of structures
+// returned, not a length.
+PRE(sys_getfsstat)
+{
+   PRINT("sys_getfsstat ( %#lx, %ld, %ld )",ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "getfsstat", struct vki_statfs *, buf, long, len, int, flags);
+   PRE_MEM_WRITE( "getfsstat(buf)", ARG1, ARG2 );
+}
+POST(sys_getfsstat)
+{
+   vg_assert(SUCCESS);
+   if (RES > 0) {
+      POST_MEM_WRITE( ARG1, RES * sizeof(struct vki_statfs) );
+   }
+}
+
+PRE(sys_fhopen)
+{
+   PRINT("sys_open ( %#lx, %ld )",ARG1,ARG2);
+   PRE_REG_READ2(long, "open",
+                 struct fhandle *, fhp, int, flags);
+   PRE_MEM_READ( "fhopen(fhp)", ARG1, sizeof(struct vki_fhandle) );
+
+   /* Otherwise handle normally */
+   *flags |= SfMayBlock;
+}
+
+POST(sys_fhopen)
+{
+   vg_assert(SUCCESS);
+   if (!ML_(fd_allowed)(RES, "fhopen", tid, True)) {
+      VG_(close)(RES);
+      SET_STATUS_Failure( VKI_EMFILE );
+   } else {
+      if (VG_(clo_track_fds))
+         ML_(record_fd_open_nameless)(tid, RES);
+   }
+}
+
+PRE(sys_fhstat)
+{
+   PRINT("sys_fhstat ( %#lx, %#lx )",ARG1,ARG2);
+   PRE_REG_READ2(long, "fhstat", struct fhandle *, fhp, struct stat *, buf);
+   PRE_MEM_READ( "fhstat(fhp)", ARG1, sizeof(struct vki_fhandle) );
+   PRE_MEM_WRITE( "fhstat(buf)", ARG2, sizeof(struct vki_stat) );
+}
+
+POST(sys_fhstat)
+{
+   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
+}
+
+PRE(sys_fhstatfs)
+{
+   PRINT("sys_fstatfs ( %#lx, %#lx )",ARG1,ARG2);
+   PRE_REG_READ2(long, "fhstatfs",
+                 struct fhandle *, fhp, struct statfs *, buf);
+   PRE_MEM_READ( "fhstatfs(fhp)", ARG1, sizeof(struct vki_fhandle) );
+   PRE_MEM_WRITE( "fhstatfs(buf)", ARG2, sizeof(struct vki_statfs) );
+}
+
+POST(sys_fhstatfs)
+{
+   POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) );
+}
+
+#if 0 /* XXX */
+PRE(sys_fhstatfs6)
+{
+   PRINT("sys_fstatfs6 ( %#lx, %#lx )",ARG1,ARG2);
+   PRE_REG_READ2(long, "fhstatfs6",
+                 struct fhandle *, fhp, struct statfs *, buf);
+   PRE_MEM_READ( "fhstatfs6(fhp)", ARG1, sizeof(struct vki_fhandle) );
+   PRE_MEM_WRITE( "fhstatfs6(buf)", ARG2, sizeof(struct vki_statfs6) );
+}
+
+POST(sys_fhstatfs6)
+{
+   POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs6) );
+}
+
+PRE(sys_fstatfs6)
+{
+   PRINT("sys_fstatfs6 ( %ld, %#lx )",ARG1,ARG2);
+   PRE_REG_READ2(long, "fstatfs6",
+                 unsigned int, fd, struct statfs *, buf);
+   PRE_MEM_WRITE( "fstatfs6(buf)", ARG2, sizeof(struct vki_statfs6) );
+}
+
+POST(sys_fstatfs6)
+{
+   POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs6) );
+}
+#endif
+
+PRE(sys_statfs)
+{
+   PRINT("sys_statfs ( %#lx(%s), %#lx )",ARG1,(char *)ARG1,ARG2);
+   PRE_REG_READ2(long, "statfs", const char *, path, struct statfs *, buf);
+   PRE_MEM_RASCIIZ( "statfs(path)", ARG1 );
+   PRE_MEM_WRITE( "statfs(buf)", ARG2, sizeof(struct vki_statfs) );
+}
+POST(sys_statfs)
+{
+   POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) );
+}
+
+
+#if 0
+/* ---------------------------------------------------------------------
+   aio_* wrappers
+   ------------------------------------------------------------------ */
+
+// Nb: this wrapper has to pad/unpad memory around the syscall itself,
+// and this allows us to control exactly the code that gets run while
+// the padding is in place.
+
+PRE(sys_io_setup)
+{
+   PRINT("sys_io_setup ( %lu, %#lx )", ARG1,ARG2);
+   PRE_REG_READ2(long, "io_setup",
+                 unsigned, nr_events, vki_aio_context_t *, ctxp);
+   PRE_MEM_WRITE( "io_setup(ctxp)", ARG2, sizeof(vki_aio_context_t) );
+}
+
+POST(sys_io_setup)
+{
+   SizeT size;
+   struct vki_aio_ring *r;
+           
+   size = VG_PGROUNDUP(sizeof(struct vki_aio_ring) +
+                       ARG1*sizeof(struct vki_io_event));
+   r = *(struct vki_aio_ring **)ARG2;
+   vg_assert(ML_(valid_client_addr)((Addr)r, size, tid, "io_setup"));
+
+   ML_(notify_aspacem_and_tool_of_mmap)( (Addr)r, size,
+                                         VKI_PROT_READ | VKI_PROT_WRITE,
+                                         VKI_MAP_ANONYMOUS, -1, 0 );
+
+   POST_MEM_WRITE( ARG2, sizeof(vki_aio_context_t) );
+}
+
+// Nb: This wrapper is "Special" because we need 'size' to do the unmap
+// after the syscall.  We must get 'size' from the aio_ring structure,
+// before the syscall, while the aio_ring structure still exists.  (And we
+// know that we must look at the aio_ring structure because Tom inspected the
+// kernel and glibc sources to see what they do, yuk.)
+//
+// XXX This segment can be implicitly unmapped when aio
+// file-descriptors are closed...
+PRE(sys_io_destroy)
+{
+   struct vki_aio_ring *r;
+   SizeT size;
+      
+   PRINT("sys_io_destroy ( %llu )", (ULong)ARG1);
+   PRE_REG_READ1(long, "io_destroy", vki_aio_context_t, ctx);
+
+   // If we are going to seg fault (due to a bogus ARG1) do it as late as
+   // possible...
+   r = (struct vki_aio_ring *)ARG1;
+   size = VG_PGROUNDUP(sizeof(struct vki_aio_ring) + 
+                       r->nr*sizeof(struct vki_io_event));
+
+   SET_STATUS_from_SysRes( VG_(do_syscall1)(SYSNO, ARG1) );
+
+   if (SUCCESS && RES == 0) { 
+      Bool d = VG_(am_notify_munmap)( ARG1, size );
+      VG_TRACK( die_mem_munmap, ARG1, size );
+      if (d)
+         VG_(discard_translations)( (Addr64)ARG1, (ULong)size, 
+                                    "PRE(sys_io_destroy)" );
+   }  
+}  
+
+PRE(sys_io_getevents)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_io_getevents ( %llu, %lld, %lld, %#lx, %#lx )",
+         (ULong)ARG1,(Long)ARG2,(Long)ARG3,ARG4,ARG5);
+   PRE_REG_READ5(long, "io_getevents",
+                 vki_aio_context_t, ctx_id, long, min_nr, long, nr,
+                 struct io_event *, events,
+                 struct timespec *, timeout);
+   if (ARG3 > 0)
+      PRE_MEM_WRITE( "io_getevents(events)",
+                     ARG4, sizeof(struct vki_io_event)*ARG3 );
+   if (ARG5 != 0)
+      PRE_MEM_READ( "io_getevents(timeout)",
+                    ARG5, sizeof(struct vki_timespec));
+}
+POST(sys_io_getevents)
+{
+   Int i;
+   vg_assert(SUCCESS);
+   if (RES > 0) {
+      POST_MEM_WRITE( ARG4, sizeof(struct vki_io_event)*RES );
+      for (i = 0; i < RES; i++) {
+         const struct vki_io_event *vev = ((struct vki_io_event *)ARG4) + i;
+         const struct vki_iocb *cb = (struct vki_iocb *)(Addr)vev->obj;
+
+         switch (cb->aio_lio_opcode) {
+         case VKI_IOCB_CMD_PREAD:
+            if (vev->result > 0)
+               POST_MEM_WRITE( cb->aio_buf, vev->result );
+            break;
+            
+         case VKI_IOCB_CMD_PWRITE:
+            break;
+           
+         default:
+            VG_(message)(Vg_DebugMsg,
+                        "Warning: unhandled io_getevents opcode: %u\n",
+                        cb->aio_lio_opcode);
+            break;
+         }
+      }
+   }
+}
+
+PRE(sys_io_submit)
+{
+   Int i;
+
+   PRINT("sys_io_submit ( %llu, %ld, %#lx )", (ULong)ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "io_submit",
+                 vki_aio_context_t, ctx_id, long, nr,
+                 struct iocb **, iocbpp);
+   PRE_MEM_READ( "io_submit(iocbpp)", ARG3, ARG2*sizeof(struct vki_iocb *) );
+   if (ARG3 != 0) {
+      for (i = 0; i < ARG2; i++) {
+         struct vki_iocb *cb = ((struct vki_iocb **)ARG3)[i];
+         PRE_MEM_READ( "io_submit(iocb)", (Addr)cb, sizeof(struct vki_iocb) );
+         switch (cb->aio_lio_opcode) {
+         case VKI_IOCB_CMD_PREAD:
+            PRE_MEM_WRITE( "io_submit(PREAD)", cb->aio_buf, cb->aio_nbytes );
+            break;
+
+         case VKI_IOCB_CMD_PWRITE:
+            PRE_MEM_READ( "io_submit(PWRITE)", cb->aio_buf, cb->aio_nbytes );
+            break;
+           
+         default:
+            VG_(message)(Vg_DebugMsg,"Warning: unhandled io_submit opcode: %u\n",
+                         cb->aio_lio_opcode);
+            break;
+         }
+      }
+   }
+}
+
+PRE(sys_io_cancel)
+{
+   PRINT("sys_io_cancel ( %llu, %#lx, %#lx )", (ULong)ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "io_cancel",
+                 vki_aio_context_t, ctx_id, struct iocb *, iocb,
+                 struct io_event *, result);
+   PRE_MEM_READ( "io_cancel(iocb)", ARG2, sizeof(struct vki_iocb) );
+   PRE_MEM_WRITE( "io_cancel(result)", ARG3, sizeof(struct vki_io_event) );
+}
+POST(sys_io_cancel)
+{
+   POST_MEM_WRITE( ARG3, sizeof(struct vki_io_event) );
+}
+
+/* ---------------------------------------------------------------------
+   inotify_* wrappers
+   ------------------------------------------------------------------ */
+
+PRE(sys_inotify_init)
+{
+   PRINT("sys_inotify_init ( )");
+   PRE_REG_READ0(long, "inotify_init");
+}
+POST(sys_inotify_init)
+{
+   vg_assert(SUCCESS);
+   if (!ML_(fd_allowed)(RES, "inotify_init", tid, True)) {
+      VG_(close)(RES);
+      SET_STATUS_Failure( VKI_EMFILE );
+   } else {
+      if (VG_(clo_track_fds))
+         ML_(record_fd_open_nameless) (tid, RES);
+   }
+}
+
+PRE(sys_inotify_add_watch)
+{
+   PRINT( "sys_inotify_add_watch ( %ld, %#lx, %lx )", ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "inotify_add_watch", int, fd, char *, path, int, mask);
+   PRE_MEM_RASCIIZ( "inotify_add_watch(path)", ARG2 );
+}
+
+PRE(sys_inotify_rm_watch)
+{
+   PRINT( "sys_inotify_rm_watch ( %ld, %lx )", ARG1,ARG2);
+   PRE_REG_READ2(long, "inotify_rm_watch", int, fd, int, wd);
+}
+
+/* ---------------------------------------------------------------------
+   mq_* wrappers
+   ------------------------------------------------------------------ */
+
+PRE(sys_mq_open)
+{
+   PRINT("sys_mq_open( %#lx(%s), %ld, %lld, %#lx )",
+         ARG1,(char *)ARG1,ARG2,(ULong)ARG3,ARG4);
+   PRE_REG_READ4(long, "mq_open",
+                 const char *, name, int, oflag, vki_mode_t, mode,
+                 struct mq_attr *, attr);
+   PRE_MEM_RASCIIZ( "mq_open(name)", ARG1 );
+   if ((ARG2 & VKI_O_CREAT) != 0 && ARG4 != 0) {
+      const struct vki_mq_attr *attr = (struct vki_mq_attr *)ARG4;
+      PRE_MEM_READ( "mq_open(attr->mq_maxmsg)",
+                     (Addr)&attr->mq_maxmsg, sizeof(attr->mq_maxmsg) );
+      PRE_MEM_READ( "mq_open(attr->mq_msgsize)",
+                     (Addr)&attr->mq_msgsize, sizeof(attr->mq_msgsize) );
+   }
+}
+POST(sys_mq_open)
+{
+   vg_assert(SUCCESS);
+   if (!ML_(fd_allowed)(RES, "mq_open", tid, True)) {
+      VG_(close)(RES);
+      SET_STATUS_Failure( VKI_EMFILE );
+   } else {
+      if (VG_(clo_track_fds))
+         ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1);
+   }
+}
+
+PRE(sys_mq_unlink)
+{
+   PRINT("sys_mq_unlink ( %#lx(%s) )", ARG1,(char *)ARG1);
+   PRE_REG_READ1(long, "mq_unlink", const char *, name);
+   PRE_MEM_RASCIIZ( "mq_unlink(name)", ARG1 );
+}
+
+PRE(sys_mq_timedsend)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_mq_timedsend ( %ld, %#lx, %llu, %ld, %#lx )",
+         ARG1,ARG2,(ULong)ARG3,ARG4,ARG5);
+   PRE_REG_READ5(long, "mq_timedsend",
+                 vki_mqd_t, mqdes, const char *, msg_ptr, vki_size_t, msg_len,
+                 unsigned int, msg_prio, const struct timespec *, abs_timeout);
+   if (!ML_(fd_allowed)(ARG1, "mq_timedsend", tid, False)) {
+      SET_STATUS_Failure( VKI_EBADF );
+   } else {
+      PRE_MEM_READ( "mq_timedsend(msg_ptr)", ARG2, ARG3 );
+      if (ARG5 != 0)
+         PRE_MEM_READ( "mq_timedsend(abs_timeout)", ARG5,
+                        sizeof(struct vki_timespec) );
+   }
+}
+
+PRE(sys_mq_timedreceive)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_mq_timedreceive( %ld, %#lx, %llu, %#lx, %#lx )",
+         ARG1,ARG2,(ULong)ARG3,ARG4,ARG5);
+   PRE_REG_READ5(ssize_t, "mq_timedreceive",
+                 vki_mqd_t, mqdes, char *, msg_ptr, vki_size_t, msg_len,
+                 unsigned int *, msg_prio,
+                 const struct timespec *, abs_timeout);
+   if (!ML_(fd_allowed)(ARG1, "mq_timedreceive", tid, False)) {
+      SET_STATUS_Failure( VKI_EBADF );
+   } else {
+      PRE_MEM_WRITE( "mq_timedreceive(msg_ptr)", ARG2, ARG3 );
+      if (ARG4 != 0)
+         PRE_MEM_WRITE( "mq_timedreceive(msg_prio)",
+                        ARG4, sizeof(unsigned int) );
+      if (ARG5 != 0)
+         PRE_MEM_READ( "mq_timedreceive(abs_timeout)",
+                        ARG5, sizeof(struct vki_timespec) );
+   }
+}
+POST(sys_mq_timedreceive)
+{
+   POST_MEM_WRITE( ARG2, ARG3 );
+   if (ARG4 != 0)
+      POST_MEM_WRITE( ARG4, sizeof(unsigned int) );
+}
+
+PRE(sys_mq_notify)
+{
+   PRINT("sys_mq_notify( %ld, %#lx )", ARG1,ARG2 );
+   PRE_REG_READ2(long, "mq_notify",
+                 vki_mqd_t, mqdes, const struct sigevent *, notification);
+   if (!ML_(fd_allowed)(ARG1, "mq_notify", tid, False))
+      SET_STATUS_Failure( VKI_EBADF );
+   else if (ARG2 != 0)
+      PRE_MEM_READ( "mq_notify(notification)",
+                    ARG2, sizeof(struct vki_sigevent) );
+}
+
+PRE(sys_mq_getsetattr)
+{
+   PRINT("sys_mq_getsetattr( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3 );
+   PRE_REG_READ3(long, "mq_getsetattr",
+                 vki_mqd_t, mqdes, const struct mq_attr *, mqstat,
+                 struct mq_attr *, omqstat);
+   if (!ML_(fd_allowed)(ARG1, "mq_getsetattr", tid, False)) {
+      SET_STATUS_Failure( VKI_EBADF );
+   } else {
+      if (ARG2 != 0) {
+         const struct vki_mq_attr *attr = (struct vki_mq_attr *)ARG2;
+         PRE_MEM_READ( "mq_getsetattr(mqstat->mq_flags)",
+                        (Addr)&attr->mq_flags, sizeof(attr->mq_flags) );
+      }
+      if (ARG3 != 0)
+         PRE_MEM_WRITE( "mq_getsetattr(omqstat)", ARG3,
+                        sizeof(struct vki_mq_attr) );
+   }   
+}
+POST(sys_mq_getsetattr)
+{
+   if (ARG3 != 0)
+      POST_MEM_WRITE( ARG3, sizeof(struct vki_mq_attr) );
+}
+
+#endif
+
+/* ---------------------------------------------------------------------
+   clock_* wrappers
+   ------------------------------------------------------------------ */
+
+PRE(sys_clock_settime)
+{
+   PRINT("sys_clock_settime( %ld, %#lx )", ARG1,ARG2);
+   PRE_REG_READ2(long, "clock_settime", 
+                 vki_clockid_t, clk_id, const struct timespec *, tp);
+   PRE_MEM_READ( "clock_settime(tp)", ARG2, sizeof(struct vki_timespec) );
+}
+
+PRE(sys_clock_gettime)
+{
+   PRINT("sys_clock_gettime( %ld, %#lx )" , ARG1,ARG2);
+   PRE_REG_READ2(long, "clock_gettime", 
+                 vki_clockid_t, clk_id, struct timespec *, tp);
+   PRE_MEM_WRITE( "clock_gettime(tp)", ARG2, sizeof(struct vki_timespec) );
+}
+POST(sys_clock_gettime)
+{
+   POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) );
+}
+
+PRE(sys_clock_getres)
+{
+   PRINT("sys_clock_getres( %ld, %#lx )" , ARG1,ARG2);
+   // Nb: we can't use "RES" as the param name because that's a macro
+   // defined above!
+   PRE_REG_READ2(long, "clock_getres", 
+                 vki_clockid_t, clk_id, struct timespec *, res);
+   if (ARG2 != 0)
+      PRE_MEM_WRITE( "clock_getres(res)", ARG2, sizeof(struct vki_timespec) );
+}
+POST(sys_clock_getres)
+{
+   if (ARG2 != 0)
+      POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) );
+}
+
+#if 0
+PRE(sys_clock_nanosleep)
+{
+   *flags |= SfMayBlock|SfPostOnFail;
+   PRINT("sys_clock_nanosleep( %ld, %ld, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4);
+   PRE_REG_READ4(int32_t, "clock_nanosleep",
+                 vki_clockid_t, clkid, int, flags,
+                 const struct timespec *, rqtp, struct timespec *, rmtp);
+   PRE_MEM_READ( "clock_nanosleep(rqtp)", ARG3, sizeof(struct vki_timespec) );
+   if (ARG4 != 0)
+      PRE_MEM_WRITE( "clock_nanosleep(rmtp)", ARG4, sizeof(struct vki_timespec) );
+}
+POST(sys_clock_nanosleep)
+{
+   if (ARG4 != 0 && FAILURE && RES_unchecked == VKI_EINTR)
+      POST_MEM_WRITE( ARG4, sizeof(struct vki_timespec) );
+}
+
+/* ---------------------------------------------------------------------
+   timer_* wrappers
+   ------------------------------------------------------------------ */
+
+PRE(sys_timer_create)
+{
+   PRINT("sys_timer_create( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "timer_create",
+                 vki_clockid_t, clockid, struct sigevent *, evp,
+                 vki_timer_t *, timerid);
+   if (ARG2 != 0)
+      PRE_MEM_READ( "timer_create(evp)", ARG2, sizeof(struct vki_sigevent) );
+   PRE_MEM_WRITE( "timer_create(timerid)", ARG3, sizeof(vki_timer_t) );
+}
+POST(sys_timer_create)
+{
+   POST_MEM_WRITE( ARG3, sizeof(vki_timer_t) );
+}
+
+PRE(sys_timer_settime)
+{
+   PRINT("sys_timer_settime( %lld, %ld, %#lx, %#lx )", (ULong)ARG1,ARG2,ARG3,ARG4);
+   PRE_REG_READ4(long, "timer_settime", 
+                 vki_timer_t, timerid, int, flags,
+                 const struct itimerspec *, value,
+                 struct itimerspec *, ovalue);
+   PRE_MEM_READ( "timer_settime(value)", ARG3,
+                  sizeof(struct vki_itimerspec) );
+   if (ARG4 != 0)
+       PRE_MEM_WRITE( "timer_settime(ovalue)", ARG4,
+                      sizeof(struct vki_itimerspec) );
+}
+POST(sys_timer_settime)
+{
+   if (ARG4 != 0)
+      POST_MEM_WRITE( ARG4, sizeof(struct vki_itimerspec) );
+}
+
+PRE(sys_timer_gettime)
+{
+   PRINT("sys_timer_gettime( %lld, %#lx )", (ULong)ARG1,ARG2);
+   PRE_REG_READ2(long, "timer_gettime", 
+                 vki_timer_t, timerid, struct itimerspec *, value);
+   PRE_MEM_WRITE( "timer_gettime(value)", ARG2,
+                  sizeof(struct vki_itimerspec));
+}
+POST(sys_timer_gettime)
+{
+   POST_MEM_WRITE( ARG2, sizeof(struct vki_itimerspec) );
+}
+
+PRE(sys_timer_getoverrun)
+{
+   PRINT("sys_timer_getoverrun( %#lx )", ARG1);
+   PRE_REG_READ1(long, "timer_getoverrun", vki_timer_t, timerid);
+}
+
+PRE(sys_timer_delete)
+{
+   PRINT("sys_timer_delete( %#lx )", ARG1);
+   PRE_REG_READ1(long, "timer_delete", vki_timer_t, timerid);
+}
+
+/* ---------------------------------------------------------------------
+   sched_* wrappers
+   ------------------------------------------------------------------ */
+
+PRE(sys_sched_setparam)
+{
+   PRINT("sched_setparam ( %ld, %#lx )", ARG1, ARG2 );
+   PRE_REG_READ2(long, "sched_setparam", 
+                 vki_pid_t, pid, struct sched_param *, p);
+   PRE_MEM_READ( "sched_setparam(p)", ARG2, sizeof(struct vki_sched_param) );
+}
+POST(sys_sched_setparam)
+{
+   POST_MEM_WRITE( ARG2, sizeof(struct vki_sched_param) );
+}
+
+PRE(sys_sched_getparam)
+{
+   PRINT("sched_getparam ( %ld, %#lx )", ARG1, ARG2 );
+   PRE_REG_READ2(long, "sched_getparam", 
+                 vki_pid_t, pid, struct sched_param *, p);
+   PRE_MEM_WRITE( "sched_getparam(p)", ARG2, sizeof(struct vki_sched_param) );
+}
+POST(sys_sched_getparam)
+{
+   POST_MEM_WRITE( ARG2, sizeof(struct vki_sched_param) );
+}
+
+PRE(sys_sched_getscheduler)
+{
+   PRINT("sys_sched_getscheduler ( %ld )", ARG1);
+   PRE_REG_READ1(long, "sched_getscheduler", vki_pid_t, pid);
+}
+
+PRE(sys_sched_setscheduler)
+{
+   PRINT("sys_sched_setscheduler ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "sched_setscheduler", 
+                 vki_pid_t, pid, int, policy, struct sched_param *, p);
+   if (ARG3 != 0)
+      PRE_MEM_READ( "sched_setscheduler(p)", 
+		    ARG3, sizeof(struct vki_sched_param));
+}
+
+PRE(sys_sched_yield)
+{
+   *flags |= SfMayBlock;
+   PRINT("sched_yield()");
+   PRE_REG_READ0(long, "sched_yield");
+}
+#endif
+
+PRE(sys_sched_get_priority_max)
+{
+   PRINT("sched_get_priority_max ( %ld )", ARG1);
+   PRE_REG_READ1(long, "sched_get_priority_max", int, policy);
+}
+
+PRE(sys_sched_get_priority_min)
+{
+   PRINT("sched_get_priority_min ( %ld )", ARG1);
+   PRE_REG_READ1(long, "sched_get_priority_min", int, policy);
+}
+
+#if 0
+PRE(sys_sched_setaffinity)
+{
+   PRINT("sched_setaffinity ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "sched_setaffinity", 
+                 vki_pid_t, pid, unsigned int, len, unsigned long *, mask);
+   PRE_MEM_READ( "sched_setaffinity(mask)", ARG3, ARG2);
+}
+
+PRE(sys_sched_getaffinity)
+{
+   PRINT("sched_getaffinity ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "sched_getaffinity", 
+                 vki_pid_t, pid, unsigned int, len, unsigned long *, mask);
+   PRE_MEM_WRITE( "sched_getaffinity(mask)", ARG3, ARG2);
+}
+POST(sys_sched_getaffinity)
+{
+   POST_MEM_WRITE(ARG3, ARG2);
+}
+
+#endif
+
+/* ---------------------------------------------------------------------
+   miscellaneous wrappers
+   ------------------------------------------------------------------ */
+
+PRE(sys_munlockall)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_munlockall ( )");
+   PRE_REG_READ0(long, "munlockall");
+}
+
+// Pipe on freebsd doesn't have args, and uses dual returns!
+PRE(sys_pipe)
+{
+   PRINT("sys_pipe ( %#lx )", ARG1);
+   PRE_REG_READ1(int, "pipe", int *, filedes);
+   PRE_MEM_WRITE( "pipe(filedes)", ARG1, 2*sizeof(int) );
+}
+POST(sys_pipe)
+{
+   Int *p = (Int *)ARG1;
+   if (!ML_(fd_allowed)(p[0], "pipe", tid, True) ||
+       !ML_(fd_allowed)(p[1], "pipe", tid, True)) {
+      VG_(close)(p[0]);
+      VG_(close)(p[1]);
+      SET_STATUS_Failure( VKI_EMFILE );
+   } else {
+      POST_MEM_WRITE( ARG1, 2*sizeof(int) );
+      if (VG_(clo_track_fds)) {
+         ML_(record_fd_open_nameless)(tid, p[0]);
+         ML_(record_fd_open_nameless)(tid, p[1]);
+      }
+   }
+}
+
+/* XXX copied from syswrap-linux.c */
+/* pipe2 (a kernel 2.6.twentysomething invention) is like pipe, except
+   there's a second arg containing flags to be applied to the new file
+   descriptors.  It hardly seems worth the effort to factor out the
+   duplicated code, hence: */
+PRE(sys_pipe2)
+{
+   PRINT("sys_pipe2 ( %#lx, %#lx )", ARG1, ARG2);
+   PRE_REG_READ2(int, "pipe", int *, filedes, long, flags);
+   PRE_MEM_WRITE( "pipe2(filedes)", ARG1, 2*sizeof(int) );
+}
+POST(sys_pipe2)
+{
+   Int *p = (Int *)ARG1;
+   if (!ML_(fd_allowed)(p[0], "pipe2", tid, True) ||
+       !ML_(fd_allowed)(p[1], "pipe2", tid, True)) {
+      VG_(close)(p[0]);
+      VG_(close)(p[1]);
+      SET_STATUS_Failure( VKI_EMFILE );
+   } else {
+      POST_MEM_WRITE( ARG1, 2*sizeof(int) );
+      if (VG_(clo_track_fds)) {
+         ML_(record_fd_open_nameless)(tid, p[0]);
+         ML_(record_fd_open_nameless)(tid, p[1]);
+      }
+   }
+}
+
+/* XXX copied from syswrap-linux.c */
+PRE(sys_dup3)
+{
+   PRINT("sys_dup3 ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "dup3", unsigned int, oldfd, unsigned int, newfd, int, flags);
+   if (!ML_(fd_allowed)(ARG2, "dup3", tid, True))
+      SET_STATUS_Failure( VKI_EBADF );
+}
+
+POST(sys_dup3)
+{
+   vg_assert(SUCCESS);
+   if (VG_(clo_track_fds))
+      ML_(record_fd_open_named)(tid, RES);
+}
+#if 0
+PRE(sys_quotactl)
+{
+   PRINT("sys_quotactl (0x%lx, %#lx, 0x%lx, 0x%lx )", ARG1,ARG2,ARG3, ARG4);
+   PRE_REG_READ4(long, "quotactl",
+                 unsigned int, cmd, const char *, special, vki_qid_t, id,
+                 void *, addr);
+   PRE_MEM_RASCIIZ( "quotactl(special)", ARG2 );
+}
+
+PRE(sys_waitid)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_waitid( %ld, %ld, %#lx, %ld, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5);
+   PRE_REG_READ5(int32_t, "sys_waitid",
+                 int, which, vki_pid_t, pid, struct vki_siginfo *, infop,
+                 int, options, struct vki_rusage *, ru);
+   PRE_MEM_WRITE( "waitid(infop)", ARG3, sizeof(struct vki_siginfo) );
+   if (ARG5 != 0)
+      PRE_MEM_WRITE( "waitid(ru)", ARG5, sizeof(struct vki_rusage) );
+}
+POST(sys_waitid)
+{
+   POST_MEM_WRITE( ARG3, sizeof(struct vki_siginfo) );
+   if (ARG5 != 0)
+      POST_MEM_WRITE( ARG5, sizeof(struct vki_rusage) );
+}
+
+/* ---------------------------------------------------------------------
+   utime wrapper
+   ------------------------------------------------------------------ */
+
+PRE(sys_utime)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_utime ( %#lx, %#lx )", ARG1,ARG2);
+   PRE_REG_READ2(long, "utime", char *, filename, struct utimbuf *, buf);
+   PRE_MEM_RASCIIZ( "utime(filename)", ARG1 );
+   if (ARG2 != 0)
+      PRE_MEM_READ( "utime(buf)", ARG2, sizeof(struct vki_utimbuf) );
+}
+
+#endif
+
+/* ---------------------------------------------------------------------
+   thr* wrappers
+   ------------------------------------------------------------------ */
+
+PRE(sys_thr_self)
+{
+   PRINT( "sys_thr_self ( %#lx )", ARG1 );
+   PRE_REG_READ1(long, "thr_self", long *, "id");
+   PRE_MEM_WRITE( "thr_self()", ARG1, sizeof(long));
+}
+POST(sys_thr_self)
+{
+   POST_MEM_WRITE( ARG1, sizeof(long));
+}
+
+PRE(sys_thr_exit)
+{
+   ThreadState *tst;
+
+   PRINT( "sys_thr_exit ( %#lx )", ARG1 );
+   PRE_REG_READ1(long, "thr_exit", long *, "status");
+
+   if (ARG1)
+      PRE_MEM_WRITE( "thr_exit(status)", ARG1, sizeof(long) );
+   tst = VG_(get_ThreadState)(tid);
+   tst->exitreason = VgSrc_ExitThread;
+   tst->os_state.exitcode = ARG1;
+   SET_STATUS_Success(0);
+}
+
+PRE(sys_thr_set_name)
+{
+   PRINT( "sys_thr_set_name ( %ld, %#lx )", ARG1, ARG2 );
+   PRE_REG_READ2(long, "thr_set_name", long, "id", const char *, "name");
+   PRE_MEM_RASCIIZ( "sys_thr_set_name(threadname)", ARG2);
+}
+
+PRE(sys_thr_kill)
+{
+   PRINT("sys_thr_kill ( %ld, %ld )", ARG1,ARG2);
+   PRE_REG_READ2(long, "thr_kill", long, id, int, sig);
+   if (!ML_(client_signal_OK)(ARG2)) {
+      SET_STATUS_Failure( VKI_EINVAL );
+      return;
+   }
+
+   /* Check to see if this kill gave us a pending signal */
+   *flags |= SfPollAfter;
+
+   if (VG_(clo_trace_signals))
+      VG_(message)(Vg_DebugMsg, "thr_kill: sending signal %ld to tid %ld\n",
+                   ARG2, ARG1);
+
+   /* If we're sending SIGKILL, check to see if the target is one of
+      our threads and handle it specially. */
+   if (ARG2 == VKI_SIGKILL && ML_(do_sigkill)(ARG1, -1)) {
+      SET_STATUS_Success(0);
+      return;
+   }
+
+   /* Ask to handle this syscall via the slow route, since that's the
+      only one that sets tst->status to VgTs_WaitSys.  If the result
+      of doing the syscall is an immediate run of
+      async_signalhandler() in m_signals, then we need the thread to
+      be properly tidied away.  I have the impression the previous
+      version of this wrapper worked on x86/amd64 only because the
+      kernel did not immediately deliver the async signal to this
+      thread (on ppc it did, which broke the assertion re tst->status
+      at the top of async_signalhandler()). */
+   *flags |= SfMayBlock;
+}
+POST(sys_thr_kill)
+{
+   if (VG_(clo_trace_signals))
+      VG_(message)(Vg_DebugMsg, "thr_kill: sent signal %ld to tid %ld\n",
+                   ARG2, ARG1);
+}
+PRE(sys_thr_kill2)
+{
+   PRINT("sys_thr_kill2 ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "tgkill", int, pid, long, tid, int, sig);
+   if (!ML_(client_signal_OK)(ARG3)) {
+      SET_STATUS_Failure( VKI_EINVAL );
+      return;
+   }
+
+   /* Check to see if this kill gave us a pending signal */
+   *flags |= SfPollAfter;
+
+   if (VG_(clo_trace_signals))
+      VG_(message)(Vg_DebugMsg, "thr_kill2: sending signal %ld to pid %ld/%ld\n",
+                   ARG3, ARG1, ARG2);
+
+   /* If we're sending SIGKILL, check to see if the target is one of
+      our threads and handle it specially. */
+   if (ARG3 == VKI_SIGKILL && ML_(do_sigkill)(ARG2, ARG1)) {
+      SET_STATUS_Success(0);
+      return;
+   }
+
+   /* Ask to handle this syscall via the slow route, since that's the
+      only one that sets tst->status to VgTs_WaitSys.  If the result
+      of doing the syscall is an immediate run of
+      async_signalhandler() in m_signals, then we need the thread to
+      be properly tidied away.  I have the impression the previous
+      version of this wrapper worked on x86/amd64 only because the
+      kernel did not immediately deliver the async signal to this
+      thread (on ppc it did, which broke the assertion re tst->status
+      at the top of async_signalhandler()). */
+   *flags |= SfMayBlock;
+}
+POST(sys_thr_kill2)
+{
+   if (VG_(clo_trace_signals))
+      VG_(message)(Vg_DebugMsg, "thr_kill2: sent signal %ld to pid %ld/%ld\n",
+                   ARG3, ARG1, ARG2);
+}
+
+PRE(sys_thr_wake)
+{
+   PRINT("sys_thr_wake ( %ld )", ARG1);
+   PRE_REG_READ1(long, "thr_wake", long, id);
+}
+
+/* ---------------------------------------------------------------------
+   umtx* wrappers
+   ------------------------------------------------------------------ */
+
+PRE(sys__umtx_op)
+{
+// ThreadState *tst;
+
+   /* 5 args are always passed through.  The last two can vary, but
+      they're always pointers.  They may not be used though. */
+   switch(ARG2) {
+   case VKI_UMTX_OP_LOCK:
+      PRINT( "sys__umtx_op ( %#lx, LOCK, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5);
+      PRE_REG_READ5(long, "_umtx_op_lock",
+                    struct umtx *, obj, int, op, unsigned long, id,
+                    void *, zero, struct vki_timespec *, timeout);
+      PRE_MEM_READ( "_umtx_op_lock(mtx)", ARG1, sizeof(struct vki_umtx) );
+      if (ARG5)
+	 PRE_MEM_READ( "_umtx_op_lock(timespec)", ARG5, sizeof(struct vki_timespec) );
+      PRE_MEM_WRITE( "_umtx_op_lock(mtx)", ARG1, sizeof(struct vki_umtx) );
+      *flags |= SfMayBlock;
+      break;
+   case VKI_UMTX_OP_UNLOCK:
+      PRINT( "sys__umtx_op ( %#lx, UNLOCK, %ld)", ARG1, ARG3);
+      PRE_REG_READ3(long, "_umtx_op_unlock",
+                    struct umtx *, obj, int, op, unsigned long, id);
+      PRE_MEM_READ( "_umtx_op_unlock(mtx)", ARG1, sizeof(struct vki_umtx) );
+      PRE_MEM_WRITE( "_umtx_op_unlock(mtx)", ARG1, sizeof(struct vki_umtx) );
+      break;
+   case VKI_UMTX_OP_WAIT:
+      PRINT( "sys__umtx_op ( %#lx, WAIT, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5);
+      PRE_REG_READ5(long, "_umtx_op_wait",
+                    struct umtx *, obj, int, op, unsigned long, id,
+                    void *, zero, struct vki_timespec *, timeout);
+      PRE_MEM_READ( "_umtx_op_wait(mtx)", ARG1, sizeof(struct vki_umtx) );
+      if (ARG5)
+	 PRE_MEM_READ( "_umtx_op_wait(timespec)", ARG5, sizeof(struct vki_timespec) );
+      *flags |= SfMayBlock;
+      break;
+   case VKI_UMTX_OP_WAKE:
+      PRINT( "sys__umtx_op ( %#lx, WAKE, %ld)", ARG1, ARG3);
+      PRE_REG_READ3(long, "_umtx_op_wake",
+                    struct umtx *, obj, int, op, unsigned long, id);
+      PRE_MEM_READ( "_umtx_op_wake(mtx)", ARG1, sizeof(struct vki_umtx) );
+      break;
+   case VKI_UMTX_OP_MUTEX_TRYLOCK:
+      PRINT( "sys__umtx_op ( %#lx, MUTEX_TRYLOCK, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5);
+      PRE_REG_READ5(long, "_umtx_op_mutex_trylock",
+                    struct umutex *, obj, int, op, unsigned long, noid,
+                    void *, zero, struct vki_timespec *, timeout);
+      PRE_MEM_READ( "_umtx_op_mutex_trylock(mutex)", ARG1, sizeof(struct vki_umutex) );
+      if (ARG5)
+	 PRE_MEM_READ( "_umtx_op_mutex_trylock(timespec)", ARG5, sizeof(struct vki_timespec) );
+      PRE_MEM_WRITE( "_umtx_op_mutex_trylock(mutex)", ARG1, sizeof(struct vki_umutex) );
+      break;
+   case VKI_UMTX_OP_MUTEX_LOCK:
+      PRINT( "sys__umtx_op ( %#lx, MUTEX_LOCK, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5);
+      PRE_REG_READ5(long, "_umtx_op_mutex_lock",
+                    struct umutex *, obj, int, op, unsigned long, noid,
+                    void *, zero, struct vki_timespec *, timeout);
+      PRE_MEM_READ( "_umtx_op_mutex_lock(mutex)", ARG1, sizeof(struct vki_umutex) );
+      if (ARG5)
+	 PRE_MEM_READ( "_umtx_op_mutex_lock(timespec)", ARG5, sizeof(struct vki_timespec) );
+      PRE_MEM_WRITE( "_umtx_op_mutex_lock(mutex)", ARG1, sizeof(struct vki_umutex) );
+      *flags |= SfMayBlock;
+      break;
+   case VKI_UMTX_OP_MUTEX_UNLOCK:
+      PRINT( "sys__umtx_op ( %#lx, MUTEX_UNLOCK)", ARG1);
+      PRE_REG_READ2(long, "_umtx_op_mutex_unlock",
+                    struct umutex *, obj, int, op);
+      PRE_MEM_READ( "_umtx_op_mutex_unlock(mutex)", ARG1, sizeof(struct vki_umutex) );
+      PRE_MEM_WRITE( "_umtx_op_mutex_unlock(mutex)", ARG1, sizeof(struct vki_umutex) );
+      break;
+   case VKI_UMTX_OP_SET_CEILING:
+      PRINT( "sys__umtx_op ( %#lx, SET_CEILING, %ld, %#lx)", ARG1, ARG3, ARG4);
+      PRE_REG_READ4(long, "_umtx_op_set_ceiling",
+                    struct umutex *, obj, int, op, unsigned int, ceiling,
+                    unsigned int *, old_ceiling);
+      PRE_MEM_READ( "_umtx_op_set_ceiling(mutex)", ARG1, sizeof(struct vki_umutex) );
+      PRE_MEM_WRITE( "_umtx_op_set_ceiling(mutex)", ARG1, sizeof(struct vki_umutex) );
+      if (ARG4)
+         PRE_MEM_WRITE( "_umtx_op_set_ceiling(old_ceiling)", ARG4, sizeof(vki_uint32_t) );
+      break;
+   case VKI_UMTX_OP_CV_WAIT:
+      PRINT( "sys__umtx_op ( %#lx, CV_WAIT, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5);
+      PRE_REG_READ5(long, "_umtx_op_cv_wait",
+                    struct ucond *, obj, int, op, unsigned long, wflags,
+                    struct umutex *, umtx, struct vki_timespec *, timeout);
+      PRE_MEM_READ( "_umtx_op_cv_wait(cond)", ARG1, sizeof(struct vki_ucond) );
+      PRE_MEM_WRITE( "_umtx_op_cv_wait(cond)", ARG1, sizeof(struct vki_ucond) );
+      PRE_MEM_READ( "_umtx_op_cv_wait(mutex)", ARG4, sizeof(struct vki_umutex) );
+      PRE_MEM_WRITE( "_umtx_op_cv_wait(mutex)", ARG4, sizeof(struct vki_umutex) );
+      if (ARG5)
+	 PRE_MEM_READ( "_umtx_op_cv_wait(timespec)", ARG5, sizeof(struct vki_timespec) );
+      *flags |= SfMayBlock;
+      break;
+   case VKI_UMTX_OP_CV_SIGNAL:
+      PRINT( "sys__umtx_op ( %#lx, CV_SIGNAL)", ARG1);
+      PRE_REG_READ2(long, "_umtx_op_cv_signal",
+                    struct ucond *, obj, int, op);
+      PRE_MEM_READ( "_umtx_op_cv_signal(cond)", ARG1, sizeof(struct vki_ucond) );
+      PRE_MEM_WRITE( "_umtx_op_cv_signal(cond)", ARG1, sizeof(struct vki_ucond) );
+      break;
+   case VKI_UMTX_OP_CV_BROADCAST:
+      PRINT( "sys__umtx_op ( %#lx, CV_BROADCAST, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5);
+      PRE_REG_READ2(long, "_umtx_op_cv_broadcast",
+                    struct ucond *, obj, int, op);
+      PRE_MEM_READ( "_umtx_op_cv_broadcast(cond)", ARG1, sizeof(struct vki_ucond) );
+      PRE_MEM_WRITE( "_umtx_op_cv_broadcast(cond)", ARG1, sizeof(struct vki_ucond) );
+      break;
+   case VKI_UMTX_OP_WAIT_UINT:
+      PRINT( "sys__umtx_op ( %#lx, CV_WAIT_UINT, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5);
+      PRE_REG_READ5(long, "_umtx_op_wait_uint",
+                    int *, obj, int, op, unsigned long, id,
+                    void *, zero, struct vki_timespec *, timeout);
+      PRE_MEM_READ( "_umtx_op_wait(uint)", ARG1, sizeof(int) );
+      if (ARG5)
+	 PRE_MEM_READ( "_umtx_op_wait(timespec)", ARG5, sizeof(struct vki_timespec) );
+      *flags |= SfMayBlock;
+      break;
+   case VKI_UMTX_OP_RW_RDLOCK:
+      PRINT( "sys__umtx_op ( %#lx, RW_RDLOCK, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5);
+      PRE_REG_READ5(long, "_umtx_op_rw_rdlock",
+                    struct urwlock *, obj, int, op, unsigned long, noid,
+                    void *, zero, struct vki_timespec *, timeout);
+      PRE_MEM_READ( "_umtx_op_rw_rdlock(rw)", ARG1, sizeof(struct vki_urwlock) );
+      PRE_MEM_WRITE( "_umtx_op_rw_rdlock(rw)", ARG1, sizeof(struct vki_urwlock) );
+      *flags |= SfMayBlock;
+      break;
+   case VKI_UMTX_OP_RW_WRLOCK:
+      PRINT( "sys__umtx_op ( %#lx, RW_WRLOCK, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5);
+      PRE_REG_READ5(long, "_umtx_op_rw_wrlock",
+                    struct urwlock *, obj, int, op, unsigned long, noid,
+                    void *, zero, struct vki_timespec *, timeout);
+      PRE_MEM_READ( "_umtx_op_rw_wrlock(rw)", ARG1, sizeof(struct vki_urwlock) );
+      PRE_MEM_WRITE( "_umtx_op_rw_wrlock(rw)", ARG1, sizeof(struct vki_urwlock) );
+      *flags |= SfMayBlock;
+      break;
+   case VKI_UMTX_OP_RW_UNLOCK:
+      PRINT( "sys__umtx_op ( %#lx, RW_UNLOCK, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5);
+      PRE_REG_READ2(long, "_umtx_op_rw_unlock",
+                    struct urwlock *, obj, int, op);
+      PRE_MEM_READ( "_umtx_op_rw_unlock(rw)", ARG1, sizeof(struct vki_urwlock) );
+      PRE_MEM_WRITE( "_umtx_op_rw_unlock(rw)", ARG1, sizeof(struct vki_urwlock) );
+      break;
+   case VKI_UMTX_OP_WAIT_UINT_PRIVATE:
+      PRINT( "sys__umtx_op ( %#lx, CV_WAIT_UINT_PRIVATE, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5);
+      PRE_REG_READ5(long, "_umtx_op_wait_uint_private",
+                    int *, obj, int, op, unsigned long, id,
+                    void *, zero, struct vki_timespec *, timeout);
+      PRE_MEM_READ( "_umtx_op_wait_private(uint)", ARG1, sizeof(int) );
+      if (ARG5)
+	 PRE_MEM_READ( "_umtx_op_wait_private(umtx_time)", ARG5, sizeof(struct vki_umtx_time) );
+      *flags |= SfMayBlock;
+      break;
+   case VKI_UMTX_OP_WAKE_PRIVATE:
+      PRINT( "sys__umtx_op ( %#lx, CV_WAKE_PRIVATE, %ld)", ARG1, ARG3);
+      PRE_REG_READ3(long, "_umtx_op_wake_private",
+                    struct umtx *, obj, int, op, unsigned long, id);
+      PRE_MEM_READ( "_umtx_op_wake_private(mtx)", ARG1, sizeof(struct vki_umtx) );
+      break;
+   case VKI_UMTX_OP_MUTEX_WAIT:
+      PRINT( "sys__umtx_op ( %#lx, MUTEX_WAIT, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5);
+      PRE_REG_READ2(long, "_umtx_op_mutex_wait",
+                    struct umutex *, obj, int, op);
+      PRE_MEM_READ( "_umtx_op_mutex_wait(mutex)", ARG1, sizeof(struct vki_umutex) );
+      PRE_MEM_WRITE( "_umtx_op_mutex_wait(mutex)", ARG1, sizeof(struct vki_umutex) );
+      *flags |= SfMayBlock;
+      break;
+   case VKI_UMTX_OP_MUTEX_WAKE:
+      PRINT( "sys__umtx_op ( %#lx, MUTEX_WAKE, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5);
+      PRE_REG_READ2(long, "_umtx_op_mutex_wake",
+                    struct umutex *, obj, int, op);
+      PRE_MEM_READ( "_umtx_op_mutex_wake(mutex)", ARG1, sizeof(struct vki_umutex) );
+      PRE_MEM_WRITE( "_umtx_op_mutex_wake(mutex)", ARG1, sizeof(struct vki_umutex) );
+      break;
+   case VKI_UMTX_OP_SEM_WAIT:
+      PRINT( "sys__umtx_op ( %#lx, SEM_WAIT, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5);
+      PRE_REG_READ5(long, "_umtx_op_sem_wait",
+                    struct usem *, obj, int, op, unsigned long, id,
+                    void *, zero, struct vki_timespec *, timeout);
+      PRE_MEM_READ( "_umtx_op_sem_wait(usem)", ARG1, sizeof(struct vki_usem) );
+      PRE_MEM_WRITE( "_umtx_op_sem_wait(usem)", ARG1, sizeof(struct vki_usem) );
+      if (ARG5)
+	 PRE_MEM_READ( "_umtx_op_sem_wait(umtx_time)", ARG5, sizeof(struct vki_umtx_time) );
+      *flags |= SfMayBlock;
+      break;
+   case VKI_UMTX_OP_SEM_WAKE:
+      PRINT( "sys__umtx_op ( %#lx, SEM_WAKE, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5);
+      PRE_REG_READ2(long, "_umtx_op_sem_wake",
+                    struct umutex *, obj, int, op);
+      PRE_MEM_READ( "_umtx_op_sem_wake(mutex)", ARG1, sizeof(struct vki_usem) );
+      PRE_MEM_WRITE( "_umtx_op_sem_wake(mutex)", ARG1, sizeof(struct vki_usem) );
+      break;
+   case VKI_UMTX_OP_NWAKE_PRIVATE:
+      PRINT( "sys__umtx_op ( %#lx, NWAKE_PRIVATE, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5);
+      PRE_REG_READ3(long, "_umtx_op_nwake_private",
+                    struct umutex *, obj, int, op, int, count);
+      PRE_MEM_READ( "_umtx_op_nwake_private(mtxs)", ARG1, ARG3 * sizeof(void *) );
+      PRE_MEM_WRITE( "_umtx_op_mutex_wake(mtxs)", ARG1, sizeof(struct vki_umutex) );
+      break;
+   case VKI_UMTX_OP_MUTEX_WAKE2:
+      PRINT( "sys__umtx_op ( %#lx, MUTEX_WAKE2, %ld, %#lx, %#lx)", ARG1, ARG3, ARG4, ARG5);
+      PRE_REG_READ3(long, "_umtx_op_mutex_wake2",
+                    struct umutex *, obj, int, op, unsigned long, flags);
+      PRE_MEM_READ( "_umtx_op_mutex_wake(mutex)", ARG1, sizeof(struct vki_umutex) );
+      PRE_MEM_WRITE( "_umtx_op_mutex_wake(mutex)", ARG1, sizeof(struct vki_umutex) );
+      break;
+   default:
+      PRINT( "sys__umtx_op ( %#lx, %ld(UNKNOWN), %ld, %#lx, %#lx )", ARG1, ARG2, ARG3, ARG4, ARG5);
+      break;
+   }
+//   tst = VG_(get_ThreadState)(tid);
+//PRINT(" [[ UMTX_OP %d: me=%d arg1 %#lx = %#lx (%ld) ]]", ARG2, tst->os_state.lwpid, ARG1, *(UWord *)ARG1, *(UWord *)ARG1 & 0x7fffffff);
+}
+
+POST(sys__umtx_op)
+{
+//PRINT("[[ POST_UMTX_OP %d: arg1 %#lx = %#lx (%ld) ]]\n", ARG2, ARG1, *(UWord *)ARG1, *(UWord *)ARG1 & 0x7fffffff);
+   switch(ARG2) {
+   case VKI_UMTX_OP_LOCK:
+      if (SUCCESS)
+         POST_MEM_WRITE( ARG1, sizeof(struct vki_umtx) );
+      break;
+   case VKI_UMTX_OP_UNLOCK:
+      if (SUCCESS)
+         POST_MEM_WRITE( ARG1, sizeof(struct vki_umtx) );
+      break;
+   case VKI_UMTX_OP_WAIT:
+   case VKI_UMTX_OP_WAKE:
+   case VKI_UMTX_OP_WAIT_UINT:
+   case VKI_UMTX_OP_WAIT_UINT_PRIVATE:
+   case VKI_UMTX_OP_WAKE_PRIVATE:
+      break;
+   case VKI_UMTX_OP_MUTEX_TRYLOCK:
+   case VKI_UMTX_OP_MUTEX_LOCK:
+   case VKI_UMTX_OP_MUTEX_UNLOCK:
+   case VKI_UMTX_OP_MUTEX_WAIT:		/* Sets/clears contested bits */
+   case VKI_UMTX_OP_MUTEX_WAKE:		/* Sets/clears contested bits */
+      if (SUCCESS)
+         POST_MEM_WRITE( ARG1, sizeof(struct vki_umutex) );
+      break;
+   case VKI_UMTX_OP_SET_CEILING:
+      if (SUCCESS) {
+         POST_MEM_WRITE( ARG1, sizeof(struct vki_umutex) );
+	 if (ARG4)
+            POST_MEM_WRITE( ARG4, sizeof(vki_uint32_t) );
+      }
+      break;
+   case VKI_UMTX_OP_CV_WAIT:
+      if (SUCCESS) {
+         POST_MEM_WRITE( ARG1, sizeof(struct vki_ucond) );
+         POST_MEM_WRITE( ARG4, sizeof(struct vki_umutex) );
+      }
+      break;
+   case VKI_UMTX_OP_CV_SIGNAL:
+      if (SUCCESS) {
+         POST_MEM_WRITE( ARG1, sizeof(struct vki_ucond) );
+      }
+      break;
+   case VKI_UMTX_OP_CV_BROADCAST:
+      if (SUCCESS) {
+         POST_MEM_WRITE( ARG1, sizeof(struct vki_ucond) );
+      }
+      break;
+   case VKI_UMTX_OP_RW_RDLOCK:
+   case VKI_UMTX_OP_RW_WRLOCK:
+   case VKI_UMTX_OP_RW_UNLOCK:
+      if (SUCCESS) {
+         POST_MEM_WRITE( ARG1, sizeof(struct vki_urwlock) );
+      }
+      break;
+   default:
+      break;
+   }
+}
+
+PRE(sys__umtx_lock)
+{
+   PRINT( "sys__umtx_lock ( %#lx )", ARG1);
+   PRE_REG_READ1(long, "_umtx_lock", struct vki_umtx *, umtx);
+   PRE_MEM_READ( "_umtx_lock(mtx)", ARG1, sizeof(struct vki_umtx) );
+   PRE_MEM_WRITE( "_umtx_lock(mtx)", ARG1, sizeof(struct vki_umtx) );
+}
+
+POST(sys__umtx_lock)
+{
+   if (SUCCESS)
+       POST_MEM_WRITE(ARG1, sizeof(struct vki_umtx));
+}
+
+PRE(sys__umtx_unlock)
+{
+   PRINT( "sys__umtx_unlock ( %#lx )", ARG1);
+   PRE_REG_READ1(long, "_umtx_unlock", struct vki_umtx *, umtx);
+   PRE_MEM_READ( "_umtx_unlock(mtx)", ARG1, sizeof(struct vki_umtx) );
+   PRE_MEM_WRITE( "_umtx_unlock(mtx)", ARG1, sizeof(struct vki_umtx) );
+}
+
+POST(sys__umtx_unlock)
+{
+   if (SUCCESS)
+      POST_MEM_WRITE(ARG1, sizeof(struct vki_umtx));
+}
+
+PRE(sys_rtprio_thread)
+{
+   PRINT( "sys_rtprio_thread ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3 );
+   PRE_REG_READ3(long, "rtprio_thread",
+      int, "function", __vki_lwpid_t, "lwpid", struct vki_rtprio *, "rtp");
+   if (ARG1 == VKI_RTP_SET) {
+      PRE_MEM_READ( "rtprio_thread(set)", ARG3, sizeof(struct vki_rtprio));
+   } else if (ARG1 == VKI_RTP_LOOKUP) {
+      PRE_MEM_WRITE( "rtprio_thread(lookup)", ARG3, sizeof(struct vki_rtprio));
+   } else {
+	/* PHK ?? */
+   }
+}
+POST(sys_rtprio_thread)
+{
+   if (ARG1 == VKI_RTP_LOOKUP && RES == 0)
+      POST_MEM_WRITE( ARG3, sizeof(struct vki_rtprio));
+}
+
+/* ---------------------------------------------------------------------
+   sig* wrappers
+   ------------------------------------------------------------------ */
+
+PRE(sys_sigpending)
+{
+   PRINT( "sys_sigpending ( %#" FMT_REGWORD "x )", ARG1 );
+   PRE_REG_READ1(int, "sigpending", vki_sigset_t *, set);
+   PRE_MEM_WRITE( "sigpending(set)", ARG1, sizeof(vki_sigset_t));
+}
+
+POST(sys_sigpending)
+{
+   POST_MEM_WRITE( ARG1, sizeof(vki_sigset_t) ) ;
+}
+
+/* ---------------------------------------------------------------------
+   rt_sig* wrappers
+   ------------------------------------------------------------------ */
+
+static int sigformat[_VKI_NSIG];
+
+PRE(sys_sigaction4)
+{
+   PRINT("sys_sigaction ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "sigaction",
+                 int, signum, const struct sigaction *, act,
+                 struct sigaction *, oldact);
+
+   if (ARG2 != 0) {
+      struct vki_sigaction *sa = (struct vki_sigaction *)ARG2;
+      PRE_MEM_READ( "sigaction(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
+      PRE_MEM_READ( "sigaction(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
+      PRE_MEM_READ( "sigaction(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
+      if (ARG1 < _VKI_NSIG)
+	 sigformat[ARG1] = 4;
+   }
+   if (ARG3 != 0)
+      PRE_MEM_WRITE( "sigaction(oldact)", ARG3, sizeof(struct vki_sigaction));
+
+   /* process the signal immediately. */
+   SET_STATUS_from_SysRes(
+      VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t *)ARG2,
+                            (vki_sigaction_fromK_t *)ARG3)
+   );
+}
+POST(sys_sigaction4)
+{
+   vg_assert(SUCCESS);
+   if (RES == 0 && ARG3 != 0)
+      POST_MEM_WRITE( ARG3, sizeof(struct vki_sigaction));
+}
+
+/* Identical, but warns the signal handler to expect the different sigframe */
+PRE(sys_sigaction)
+{
+   PRINT("sys_sigaction6 ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "sigaction6",
+                 int, signum, const struct sigaction *, act,
+                 struct sigaction *, oldact);
+
+   if (ARG2 != 0) {
+      struct vki_sigaction *sa = (struct vki_sigaction *)ARG2;
+      PRE_MEM_READ( "sigaction6(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
+      PRE_MEM_READ( "sigaction6(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
+      PRE_MEM_READ( "sigaction6(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
+      if (ARG1 < _VKI_NSIG)
+	 sigformat[ARG1] = 6;
+   }
+   if (ARG3 != 0)
+      PRE_MEM_WRITE( "sigaction6(oldact)", ARG3, sizeof(struct vki_sigaction));
+
+   SET_STATUS_from_SysRes(
+      VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t *)ARG2,
+                            (vki_sigaction_fromK_t *)ARG3)
+   );
+}
+POST(sys_sigaction)
+{
+   vg_assert(SUCCESS);
+   if (RES == 0 && ARG3 != 0)
+      POST_MEM_WRITE( ARG3, sizeof(struct vki_sigaction));
+}
+
+
+PRE(sys_sigprocmask)
+{
+   PRINT("sys_sigprocmask ( %ld, %#lx )",ARG1,ARG2);
+   PRE_REG_READ2(long, "sigprocmask", 
+                 int, how, vki_sigset_t, set);
+
+   vki_sigset_t set, oldset;
+   set = (vki_sigset_t)ARG2;
+   oldset = 0;
+   (void) VG_(do_sys_sigprocmask) ( tid, ARG1 /*how*/, 
+				    (vki_sigset_t*) &set,
+				    (vki_sigset_t*) &oldset );
+
+   /* Fill SysRes with oldset. */
+   SET_STATUS_Success(oldset);
+
+   if (SUCCESS)
+      *flags |= SfPollAfter;
+}
+#if 0
+POST(sys_sigprocmask)
+{
+   vg_assert(SUCCESS);
+}
+#endif
+
+/* Not in 4.x */
+PRE(sys_sigtimedwait)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_sigtimedwait ( %#lx, %#lx, %#lx )",
+         ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "sigtimedwait", 
+                 const vki_sigset_t *, set, vki_siginfo_t *, info,
+                 const struct timespec *, timeout);
+   if (ARG1 != 0) 
+      PRE_MEM_READ(  "sigtimedwait(set)",  ARG1, sizeof(vki_sigset_t));
+   if (ARG2 != 0)
+      PRE_MEM_WRITE( "sigtimedwait(info)", ARG2, sizeof(vki_siginfo_t) );
+   if (ARG3 != 0)
+      PRE_MEM_READ( "sigtimedwait(timeout)",
+                    ARG3, sizeof(struct vki_timespec) );
+}
+POST(sys_sigtimedwait)
+{
+   if (ARG2 != 0)
+      POST_MEM_WRITE( ARG2, sizeof(vki_siginfo_t) );
+}
+
+/* Not in 4.x */
+PRE(sys_sigwaitinfo)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_sigwaitinfo ( %#lx, %#lx )",
+         ARG1,ARG2);
+   PRE_REG_READ2(long, "sigwaitinfo", 
+                 const vki_sigset_t *, set, vki_siginfo_t *, info);
+   if (ARG1 != 0) 
+      PRE_MEM_READ(  "sigwaitinfo(set)",  ARG1, sizeof(vki_sigset_t));
+   if (ARG2 != 0)
+      PRE_MEM_WRITE( "sigwaitinfo(info)", ARG2, sizeof(vki_siginfo_t) );
+}
+POST(sys_sigwaitinfo)
+{
+   if (ARG2 != 0)
+      POST_MEM_WRITE( ARG2, sizeof(vki_siginfo_t) );
+}
+
+#if 0	/* not on freebsd 4.x */
+PRE(sys_rt_sigqueueinfo)
+{
+   PRINT("sys_rt_sigqueueinfo(%ld, %ld, %#lx)", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "rt_sigqueueinfo", 
+                 int, pid, int, sig, vki_siginfo_t *, uinfo);
+   if (ARG2 != 0)
+      PRE_MEM_READ( "rt_sigqueueinfo(uinfo)", ARG3, sizeof(vki_siginfo_t) );
+}
+POST(sys_rt_sigqueueinfo)
+{
+   if (!ML_(client_signal_OK)(ARG2))
+      SET_STATUS_Failure( VKI_EINVAL );
+}
+#endif
+
+PRE(sys_sigsuspend)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_sigsuspend ( %#lx )", ARG1 );
+   PRE_REG_READ1(int, "rt_sigsuspend", vki_sigset_t *, mask)
+   if (ARG1 != (Addr)NULL) {
+      PRE_MEM_READ( "rt_sigsuspend(mask)", ARG1, sizeof(vki_sigset_t) );
+   }
+}
+
+#if 0
+/* ---------------------------------------------------------------------
+   linux msg* wrapper helpers
+   ------------------------------------------------------------------ */
+
+void
+ML_(linux_PRE_sys_msgsnd) ( ThreadId tid,
+                            UWord arg0, UWord arg1, UWord arg2, UWord arg3 )
+{
+   /* int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg); */
+   struct vki_msgbuf *msgp = (struct vki_msgbuf *)arg1;
+   PRE_MEM_READ( "msgsnd(msgp->mtype)", (Addr)&msgp->mtype, sizeof(msgp->mtype) );
+   PRE_MEM_READ( "msgsnd(msgp->mtext)", (Addr)&msgp->mtext, arg2 );
+}
+
+void
+ML_(linux_PRE_sys_msgrcv) ( ThreadId tid,
+                            UWord arg0, UWord arg1, UWord arg2,
+                            UWord arg3, UWord arg4 )
+{
+   /* ssize_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz,
+                     long msgtyp, int msgflg); */
+   struct vki_msgbuf *msgp = (struct vki_msgbuf *)arg1;
+   PRE_MEM_WRITE( "msgrcv(msgp->mtype)", (Addr)&msgp->mtype, sizeof(msgp->mtype) );
+   PRE_MEM_WRITE( "msgrcv(msgp->mtext)", (Addr)&msgp->mtext, arg2 );
+}
+void
+ML_(linux_POST_sys_msgrcv) ( ThreadId tid,
+                             UWord res,
+                             UWord arg0, UWord arg1, UWord arg2,
+                             UWord arg3, UWord arg4 )
+{
+   struct vki_msgbuf *msgp = (struct vki_msgbuf *)arg1;
+   POST_MEM_WRITE( (Addr)&msgp->mtype, sizeof(msgp->mtype) );
+   POST_MEM_WRITE( (Addr)&msgp->mtext, res );
+}
+
+void
+ML_(linux_PRE_sys_msgctl) ( ThreadId tid,
+                            UWord arg0, UWord arg1, UWord arg2 )
+{
+   /* int msgctl(int msqid, int cmd, struct msqid_ds *buf); */
+   switch (arg1 /* cmd */) {
+   case VKI_IPC_INFO:
+   case VKI_MSG_INFO:
+   case VKI_IPC_INFO|VKI_IPC_64:
+   case VKI_MSG_INFO|VKI_IPC_64:
+      PRE_MEM_WRITE( "msgctl(IPC_INFO, buf)",
+                     arg2, sizeof(struct vki_msginfo) );
+      break;
+   case VKI_IPC_STAT:
+   case VKI_MSG_STAT:
+      PRE_MEM_WRITE( "msgctl(IPC_STAT, buf)",
+                     arg2, sizeof(struct vki_msqid_ds) );
+      break;
+   case VKI_IPC_STAT|VKI_IPC_64:
+   case VKI_MSG_STAT|VKI_IPC_64:
+      PRE_MEM_WRITE( "msgctl(IPC_STAT, arg.buf)",
+                     arg2, sizeof(struct vki_msqid64_ds) );
+      break;
+   case VKI_IPC_SET:
+      PRE_MEM_READ( "msgctl(IPC_SET, arg.buf)",
+                    arg2, sizeof(struct vki_msqid_ds) );
+      break;
+   case VKI_IPC_SET|VKI_IPC_64:
+      PRE_MEM_READ( "msgctl(IPC_SET, arg.buf)",
+                    arg2, sizeof(struct vki_msqid64_ds) );
+      break;
+   }
+}
+void
+ML_(linux_POST_sys_msgctl) ( ThreadId tid,
+                             UWord res,
+                             UWord arg0, UWord arg1, UWord arg2 )
+{
+   switch (arg1 /* cmd */) {
+   case VKI_IPC_INFO:
+   case VKI_MSG_INFO:
+   case VKI_IPC_INFO|VKI_IPC_64:
+   case VKI_MSG_INFO|VKI_IPC_64:
+      POST_MEM_WRITE( arg2, sizeof(struct vki_msginfo) );
+      break;
+   case VKI_IPC_STAT:
+   case VKI_MSG_STAT:
+      POST_MEM_WRITE( arg2, sizeof(struct vki_msqid_ds) );
+      break;
+   case VKI_IPC_STAT|VKI_IPC_64:
+   case VKI_MSG_STAT|VKI_IPC_64:
+      POST_MEM_WRITE( arg2, sizeof(struct vki_msqid64_ds) );
+      break;
+   }
+}
+
+#endif
+
+PRE(sys_chflags)
+{
+   PRINT("sys_chflags ( %#lx(%s), 0x%lx )", ARG1,(char *)ARG1,ARG2);
+   PRE_REG_READ2(long, "chown",
+                 const char *, path, vki_int32_t, flags);
+   PRE_MEM_RASCIIZ( "chflags(path)", ARG1 );
+}
+
+PRE(sys_chflagsat)
+{
+// XXXTBD
+}
+
+PRE(sys_fchflags)
+{
+   PRINT("sys_fchflags ( %ld, %ld )", ARG1,ARG2);
+   PRE_REG_READ2(long, "fchflags", unsigned int, fildes, vki_int32_t, flags);
+}
+
+PRE(sys_profil)
+{
+// XXXTBD
+}
+
+PRE(sys_ktrace)
+{
+// XXXTBD
+}
+
+PRE(sys_acct)
+{
+// XXXTBD
+}
+
+PRE(sys_reboot)
+{
+// XXXTBD
+}
+
+PRE(sys_getfh)
+{
+// XXXTBD
+}
+
+PRE(sys___tmpfd)
+{
+   PRINT("sys___tmpfd ( %ld )", ARG1 );
+   PRE_REG_READ1(int, "__tmpfd", int, flags);
+}
+
+POST(sys_getfh)
+{
+// XXXTBD
+}
+
+PRE(sys_swapctl)
+{
+// XXXTBD
+}
+
+PRE(sys_setrlimit)
+{
+// XXXTBD
+}
+
+PRE(sys_getpgid)
+{
+// XXXTBD
+}
+
+PRE(sys_msgget)
+{
+// XXXTBD
+}
+
+PRE(sys_msgsnd)
+{
+// XXXTBD
+}
+
+PRE(sys_msgrcv)
+{
+// XXXTBD
+}
+
+PRE(sys_nanosleep)
+{
+// XXXTBD
+}
+
+PRE(sys_minherit)
+{
+// XXXTBD
+}
+
+PRE(sys_lchown)
+{
+// XXXTBD
+}
+
+PRE(sys_getsid)
+{
+// XXXTBD
+}
+
+PRE(sys_msync)
+{
+// XXXTBD
+}
+
+PRE(sys_preadv)
+{
+// XXXTBD
+}
+POST(sys_preadv)
+{
+// XXXTBD
+}
+
+PRE(sys_pwritev)
+{
+// XXXTBD
+}
+
+PRE(sys_closefrom)
+{
+// XXXTBD
+}
+
+PRE(sys_sigaltstack)
+{
+// XXXTBD
+}
+
+PRE(sys_msgctl)
+{
+// XXXTBD
+}
+
+PRE(sys_getthrid)
+{
+// XXXTBD
+}
+
+PRE(sys___thrsleep)
+{
+   *flags |= SfMayBlock;
+   PRINT("__thrsleep( %#lx, %ld, %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5);
+   PRE_REG_READ5(int, "__thrsleep",
+                 void *, id,
+                 int, clock_id,
+                 struct timespec *, abstime,
+                 void *, lock,
+                 int *, abort);
+   if (ARG3 != 0)
+      PRE_MEM_READ(" __thrsleep(abstime)", ARG3, sizeof(struct timespec));
+   if (ARG5 != 0)
+      PRE_MEM_READ(" __thrsleep(abort)", ARG5, sizeof (int));
+}
+
+PRE(sys___thrwakeup)
+{
+   PRINT("__thrwakeup( %#lx, %ld, %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5);
+   PRE_REG_READ2(int, "__thrwakeup",
+                 void *, id,
+                 int, count);
+}
+
+PRE(sys___threxit)
+{
+   ThreadState* tst;
+   /* simple; just make this thread exit */
+   PRINT("__threxit( %#lx )", ARG1);
+   PRE_REG_READ1(void, "__threxit", void *, value_ptr);
+   tst = VG_(get_ThreadState)(tid);
+   /* Set the thread's status to be exiting, then claim that the
+      syscall succeeded. */
+   tst->exitreason = VgSrc_ExitThread;
+   /* tst->os_state.exitcode = ARG1; */
+   SET_STATUS_Success(0);
+}
+
+PRE(sys___thrsigdivert)
+{
+// XXXTBD
+}
+
+PRE(sys_thrkill)
+{
+// XXXTBD
+}
+
+PRE(sys_adjfreq)
+{
+// XXXTBD
+}
+
+PRE(sys_setrtable)
+{
+// XXXTBD
+}
+
+PRE(sys_getrtable)
+{
+// XXXTBD
+}
+
+PRE(sys_sendsyslog)
+{
+// XXXTBD
+}
+
+PRE(sys_futex)
+{
+   /*
+      arg    param                              used by ops
+
+      ARG1 - uint32_t *uaddr			all
+      ARG2 - int op
+      ARG3 - int val				WAIT,WAKE,REQUEUE
+      ARG4 - struct timespec *utime		WAIT,     REQUEUE
+      ARG5 - uint32_t *uaddr2			          REQUEUE
+    */
+   PRINT("sys_futex ( %#lx, %ld, %ld, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5);
+   switch(ARG2 & ~VKI_FUTEX_PRIVATE_FLAG) {
+   case VKI_FUTEX_WAIT:
+      PRE_REG_READ4(long, "futex",
+                    vki_uint32_t *, uaddr, int, op, int, val,
+                    struct timespec *, utime);
+      break;
+   case VKI_FUTEX_WAKE:
+      PRE_REG_READ3(long, "futex",
+                    vki_uint32_t *, uaddr, int, op, int, val);
+      break;
+   case VKI_FUTEX_REQUEUE:
+      PRE_REG_READ5(long, "futex",
+                    vki_uint32_t *, uaddr, int, op, int, val,
+                    struct timespec *, utime, vki_uint32_t *, uaddr2);
+      break;
+   default:
+      PRE_REG_READ2(long, "futex", vki_uint32_t *, uaddr, int, op);
+      break;
+   }
+
+   *flags |= SfMayBlock;
+
+   switch(ARG2 & ~VKI_FUTEX_PRIVATE_FLAG) {
+   case VKI_FUTEX_WAIT:
+      PRE_MEM_READ( "futex(uaddr)", ARG1, sizeof(Int) );
+      if (ARG4 != 0)
+	 PRE_MEM_READ( "futex(timeout)", ARG4, sizeof(struct vki_timespec) );
+      break;
+
+   case VKI_FUTEX_WAKE:
+      /* no additional pointers */
+      break;
+
+   case VKI_FUTEX_REQUEUE:
+      PRE_MEM_READ( "futex(uaddr)", ARG1, sizeof(Int) );
+      PRE_MEM_READ( "futex(val2)", ARG4, sizeof(Int) );
+      PRE_MEM_READ( "futex(uaddr2)", ARG5, sizeof(Int) );
+      break;
+
+   default:
+      SET_STATUS_Failure( VKI_ENOSYS );   // some futex function we don't understand
+      break;
+   }
+}
+POST(sys_futex)
+{
+   vg_assert(SUCCESS);
+   POST_MEM_WRITE( ARG1, sizeof(int) );
+}
+
+PRE(sys_utimensat)
+{
+// XXXTBD
+}
+
+PRE(sys_futimens)
+{
+// XXXTBD
+}
+
+PRE(sys_kbind)
+{
+// XXXTBD
+}
+
+PRE(sys___set_tcb)
+{
+// XXXTBD
+}
+
+PRE(sys___get_tcb)
+{
+// XXXTBD
+}
+
+
+#if 0
+PRE(sys_modfind)
+{
+   PRINT("sys_modfind ( %#lx )",ARG1);
+   PRE_REG_READ1(long, "modfind", char *, modname);
+   PRE_MEM_RASCIIZ( "modfind(modname)", ARG1 );
+}
+
+PRE(sys_modstat)
+{
+   PRINT("sys_modstat ( %ld, %#lx )",ARG1,ARG2);
+   PRE_REG_READ2(long, "modstat", int, modid, struct module_stat *, buf);
+   PRE_MEM_WRITE( "modstat(buf)", ARG2, sizeof(struct vki_module_stat) );
+}
+
+POST(sys_modstat)
+{
+   POST_MEM_WRITE( ARG2, sizeof(struct vki_module_stat) );
+}
+#endif
+
+PRE(sys_lkmnosys0)
+{
+   PRINT("sys_lkmnosys0 ()");
+   PRE_REG_READ0(long, "lkmnosys0");
+}
+
+PRE(sys_lkmnosys1)
+{
+   PRINT("sys_lkmnosys1 ()");
+   PRE_REG_READ0(long, "lkmnosys1");
+}
+
+PRE(sys_lkmnosys2)
+{
+   PRINT("sys_lkmnosys2 ()");
+   PRE_REG_READ0(long, "lkmnosys2");
+}
+
+PRE(sys_lkmnosys3)
+{
+   PRINT("sys_lkmnosys3 ()");
+   PRE_REG_READ0(long, "lkmnosys3");
+}
+
+PRE(sys_lkmnosys4)
+{
+   PRINT("sys_lkmnosys4 ()");
+   PRE_REG_READ0(long, "lkmnosys4");
+}
+
+PRE(sys_lkmnosys5)
+{
+   PRINT("sys_lkmnosys5 ()");
+   PRE_REG_READ0(long, "lkmnosys5");
+}
+
+PRE(sys_lkmnosys6)
+{
+   PRINT("sys_lkmnosys6 ()");
+   PRE_REG_READ0(long, "lkmnosys6");
+}
+
+PRE(sys_lkmnosys7)
+{
+   PRINT("sys_lkmnosys7 ()");
+   PRE_REG_READ0(long, "lkmnosys7");
+}
+
+PRE(sys_lkmnosys8)
+{
+   PRINT("sys_lkmnosys8 ()");
+   PRE_REG_READ0(long, "lkmnosys8");
+}
+
+#if 0
+PRE(sys_kenv)
+{
+   PRINT("sys_kenv ( %ld, %#lx, %#lx, %ld )", ARG1,ARG2,ARG3,ARG4);
+   PRE_REG_READ4(long, "kenv",
+                 int, action, const char *, name, char *, value, int, len);
+   switch (ARG1) {
+   case VKI_KENV_GET:
+   case VKI_KENV_SET:
+   case VKI_KENV_UNSET:
+      PRE_MEM_RASCIIZ("kenv(name)", ARG2);
+      /* FALLTHROUGH */
+   case VKI_KENV_DUMP:
+      break;
+   default:
+      I_die_here;
+   }
+}
+
+POST(sys_kenv)
+{
+   if (SUCCESS) {
+      switch (ARG1) {
+      case VKI_KENV_GET:
+         POST_MEM_WRITE(ARG3, ARG4);
+         break;
+      case VKI_KENV_DUMP:
+         if (ARG3 != (Addr)NULL)
+            POST_MEM_WRITE(ARG3, ARG4);
+         break;
+      }
+   }
+}
+#endif
+
+#if 0
+PRE(sys_uuidgen)
+{
+   PRINT("sys_uuidgen ( %#lx, %ld )", ARG1,ARG2);
+   PRE_REG_READ2(long, "uuidgen",
+		 struct vki_uuid *, store, int, count);
+   PRE_MEM_WRITE( "uuidgen(store)", ARG1, ARG2 * sizeof(struct vki_uuid));
+}
+
+POST(sys_uuidgen)
+{
+   if (SUCCESS)
+      POST_MEM_WRITE( ARG1, ARG2 * sizeof(struct vki_uuid) );
+}
+#endif
+
+
+PRE(sys_shmget)
+{
+   PRINT("sys_shmget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "shmget", vki_key_t, key, vki_size_t, size, int, shmflg);
+}
+
+PRE(sys_shmat)
+{
+   UWord arg2tmp;
+   PRINT("sys_shmat ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "shmat",
+                 int, shmid, const void *, shmaddr, int, shmflg);
+   arg2tmp = ML_(generic_PRE_sys_shmat)(tid, ARG1,ARG2,ARG3);
+   if (arg2tmp == 0)
+      SET_STATUS_Failure( VKI_EINVAL );
+   else
+      ARG2 = arg2tmp;
+}
+
+POST(sys_shmat)
+{
+   ML_(generic_POST_sys_shmat)(tid, RES,ARG1,ARG2,ARG3);
+}
+
+PRE(sys_shmdt)
+{
+   PRINT("sys_shmdt ( %#lx )",ARG1);
+   PRE_REG_READ1(long, "shmdt", const void *, shmaddr);
+   if (!ML_(generic_PRE_sys_shmdt)(tid, ARG1))
+      SET_STATUS_Failure( VKI_EINVAL );
+}
+
+POST(sys_shmdt)
+{
+   ML_(generic_POST_sys_shmdt)(tid, RES,ARG1);
+}
+
+PRE(sys_shmctl)
+{
+   PRINT("sys_shmctl ( %ld, %ld, %#lx )",ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "shmctl",
+                 int, shmid, int, cmd, struct vki_shmid_ds *, buf);
+   switch (ARG2 /* cmd */) {
+   case VKI_IPC_STAT:
+      PRE_MEM_WRITE( "shmctl(IPC_STAT, buf)",
+                     ARG3, sizeof(struct vki_shmid_ds) );
+      break;
+   case VKI_IPC_SET:
+      PRE_MEM_READ( "shmctl(IPC_SET, buf)",
+                    ARG3, sizeof(struct vki_shmid_ds) );
+      break;
+   }
+}
+
+#if 0
+PRE(sys_shmctl7)
+{
+   PRINT("sys_shmctl7 ( %ld, %ld, %#lx )",ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "shmctl",
+                 int, shmid, int, cmd, struct vki_shmid_ds7 *, buf);
+   switch (ARG2 /* cmd */) {
+   case VKI_IPC_STAT:
+      PRE_MEM_WRITE( "shmctl7(IPC_STAT, buf)",
+                     ARG3, sizeof(struct vki_shmid_ds7) );
+      break;
+   case VKI_IPC_SET:
+      PRE_MEM_READ( "shmctl7(IPC_SET, buf)",
+                    ARG3, sizeof(struct vki_shmid_ds7) );
+      break;
+   }
+}
+#endif
+
+POST(sys_shmctl)
+{
+   if (ARG2 == VKI_IPC_STAT) {
+      POST_MEM_WRITE( ARG3, sizeof(struct vki_shmid_ds) );
+   }
+}
+
+#if 0
+POST(sys_shmctl7)
+{
+   if (ARG2 == VKI_IPC_STAT) {
+      POST_MEM_WRITE( ARG3, sizeof(struct vki_shmid_ds7) );
+   }
+}
+#endif
+
+PRE(sys_semget)
+{
+   PRINT("sys_semget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "semget", vki_key_t, key, int, nsems, int, semflg);
+}
+
+PRE(sys_shm_open)
+{
+   PRE_REG_READ3(long, "shm_open",
+                const char *, "name", int, "flags", vki_mode_t, "mode");
+   if (ARG1 == VKI_SHM_ANON) {
+      PRINT("sys_shm_open(%#lx(SHM_ANON), %ld, %ld)", ARG1, ARG2, ARG3);
+   } else {
+      PRINT("sys_shm_open(%#lx(%s), %ld, %ld)", ARG1, (char *)ARG1, ARG2, ARG3);
+      PRE_MEM_RASCIIZ( "shm_open(filename)", ARG1 );
+   }
+   *flags |= SfMayBlock;
+}
+
+POST(sys_shm_open)
+{
+   vg_assert(SUCCESS);
+   if (!ML_(fd_allowed)(RES, "shm_open", tid, True)) {
+      VG_(close)(RES);
+      SET_STATUS_Failure( VKI_EMFILE );
+   } else {
+      if (VG_(clo_track_fds))
+         ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG1);
+   }
+}
+
+PRE(sys_shm_unlink)
+{
+   PRINT("sys_shm_unlink(%#lx(%s))", ARG1, (char *)ARG1);
+   PRE_REG_READ1(long, "shm_unlink",
+                 const char *, "name");
+
+   PRE_MEM_RASCIIZ( "shm_unlink(filename)", ARG1 );
+
+   *flags |= SfMayBlock;
+}
+
+PRE(sys_semop)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_semop ( %ld, %#lx, %lu )",ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "semop",
+                 int, semid, struct sembuf *, sops, unsigned, nsoops);
+   ML_(generic_PRE_sys_semop)(tid, ARG1,ARG2,ARG3);
+}
+
+struct ipc_perm7 {
+	unsigned short	cuid;	/* creator user id */
+	unsigned short	cgid;	/* creator group id */
+	unsigned short	uid;	/* user id */
+	unsigned short	gid;	/* group id */
+	unsigned short	mode;	/* r/w permission */
+	unsigned short	seq;	/* sequence # (to generate unique ipcid) */
+	vki_key_t	key;	/* user specified msg/sem/shm key */
+};
+
+struct semid_ds7 {
+	struct ipc_perm7 sem_perm;	/* operation permission struct */
+	struct sem	*sem_base;	/* pointer to first semaphore in set */
+	unsigned short	sem_nsems;	/* number of sems in set */
+	vki_time_t	sem_otime;	/* last operation time */
+	long		sem_pad1;	/* SVABI/386 says I need this here */
+	vki_time_t	sem_ctime;	/* last change time */
+    					/* Times measured in secs since */
+    					/* 00:00:00 GMT, Jan. 1, 1970 */
+	long		sem_pad2;	/* SVABI/386 says I need this here */
+	long		sem_pad3[4];	/* SVABI/386 says I need this here */
+};
+
+#if 0
+PRE(sys___semctl7)
+{
+   switch (ARG3) {
+   case VKI_IPC_INFO:
+   case VKI_SEM_INFO:
+      PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
+      PRE_REG_READ4(long, "semctl",
+                    int, semid, int, semnum, int, cmd, struct seminfo *, arg);
+      break;
+   case VKI_IPC_STAT:
+   case VKI_SEM_STAT:
+   case VKI_IPC_SET:
+      PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
+      PRE_REG_READ4(long, "semctl",
+                    int, semid, int, semnum, int, cmd, struct semid_ds7 *, arg);
+      break;
+   case VKI_GETALL:
+   case VKI_SETALL:
+      PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
+      PRE_REG_READ4(long, "semctl",
+                    int, semid, int, semnum, int, cmd, unsigned short *, arg);
+      break;
+   default:
+      PRINT("sys_semctl ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
+      PRE_REG_READ3(long, "semctl",
+                    int, semid, int, semnum, int, cmd);
+      break;
+   }
+   ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4);
+}
+
+POST(sys___semctl7)
+{
+   ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4);
+}
+#endif
+
+PRE(sys___semctl)
+{
+   switch (ARG3) {
+   case VKI_IPC_INFO:
+   case VKI_SEM_INFO:
+      PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
+      PRE_REG_READ4(long, "semctl",
+                    int, semid, int, semnum, int, cmd, struct seminfo *, arg);
+      break;
+   case VKI_IPC_STAT:
+   case VKI_SEM_STAT:
+   case VKI_IPC_SET:
+      PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
+      PRE_REG_READ4(long, "semctl",
+                    int, semid, int, semnum, int, cmd, struct semid_ds *, arg);
+      break;
+   case VKI_GETALL:
+   case VKI_SETALL:
+      PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
+      PRE_REG_READ4(long, "semctl",
+                    int, semid, int, semnum, int, cmd, unsigned short *, arg);
+      break;
+   default:
+      PRINT("sys_semctl ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
+      PRE_REG_READ3(long, "semctl",
+                    int, semid, int, semnum, int, cmd);
+      break;
+   }
+   ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4);
+}
+
+POST(sys___semctl)
+{
+   ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4);
+}
+
+#if 0
+PRE(sys_eaccess)
+{
+   PRINT("sys_eaccess ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2);
+   PRE_REG_READ2(long, "eaccess", const char *, pathname, int, mode);
+   PRE_MEM_RASCIIZ( "eaccess(pathname)", ARG1 );
+}
+#endif
+
+
+/* ---------------------------------------------------------------------
+   *at wrappers
+   ------------------------------------------------------------------ */
+
+PRE(sys_openat)
+{
+   HChar  name[30];
+   SysRes sres;
+
+   if (ARG3 & VKI_O_CREAT) {
+      // 4-arg version
+      PRINT("sys_openat ( %ld, %#lx(%s), %ld, %ld )",ARG1,ARG2,(char*)ARG2,ARG3,ARG4);
+      PRE_REG_READ4(long, "openat",
+                    int, dfd, const char *, filename, int, flags, int, mode);
+   } else {
+      // 3-arg version
+      PRINT("sys_openat ( %ld, %#lx(%s), %ld )",ARG1,ARG2,(char*)ARG2,ARG3);
+      PRE_REG_READ3(long, "openat",
+                    int, dfd, const char *, filename, int, flags);
+   }
+
+   if (ARG1 != VKI_AT_FDCWD && !ML_(fd_allowed)(ARG1, "openat", tid, False))
+      SET_STATUS_Failure( VKI_EBADF );
+   else
+      PRE_MEM_RASCIIZ( "openat(filename)", ARG2 );
+
+   /* Handle the case where the open is of /proc/curproc/cmdline or
+      /proc/<pid>/cmdline, and just give it a copy of the fd for the
+      fake file we cooked up at startup (in m_main).  Also, seek the
+      cloned fd back to the start. */
+
+   VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)());
+   if (ML_(safe_to_deref)( (void*)ARG2, 1 )
+       && (VG_(strcmp)((HChar *)ARG2, name) == 0 
+           || VG_(strcmp)((HChar *)ARG2, "/proc/curproc/cmdline") == 0)) {
+      sres = VG_(dup)( VG_(cl_cmdline_fd) );
+      SET_STATUS_from_SysRes( sres );
+      if (!sr_isError(sres)) {
+         OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET );
+         if (off < 0)
+            SET_STATUS_Failure( VKI_EMFILE );
+      }
+      return;
+   }
+
+   /* Otherwise handle normally */
+   *flags |= SfMayBlock;
+}
+
+POST(sys_openat)
+{
+   vg_assert(SUCCESS);
+   if (!ML_(fd_allowed)(RES, "openat", tid, True)) {
+      VG_(close)(RES);
+      SET_STATUS_Failure( VKI_EMFILE );
+   } else {
+      if (VG_(clo_track_fds))
+         ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG2);
+   }
+}
+
+PRE(sys_mkdirat)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_mkdirat ( %ld, %#lx(%s), %ld )", ARG1,ARG2,(char*)ARG2,ARG3);
+   PRE_REG_READ3(long, "mkdirat",
+                 int, dfd, const char *, pathname, int, mode);
+   PRE_MEM_RASCIIZ( "mkdirat(pathname)", ARG2 );
+}
+
+PRE(sys_mkfifoat)
+{
+  PRINT("sys_mkfifoat ( %ld, %#lx(%s), 0x%lx )", ARG1,ARG2,(char*)ARG2,ARG3 );
+   PRE_REG_READ3(long, "mkfifoat",
+                 int, dfd, const char *, pathname, int, mode);
+   PRE_MEM_RASCIIZ( "mkfifoat(pathname)", ARG2 );
+}
+
+PRE(sys_mknodat)
+{
+  PRINT("sys_mknodat ( %ld, %#lx(%s), 0x%lx, 0x%lx )", ARG1,ARG2,(char*)ARG2,ARG3,ARG4 );
+   PRE_REG_READ4(long, "mknodat",
+                 int, dfd, const char *, pathname, int, mode, unsigned, dev);
+   PRE_MEM_RASCIIZ( "mknodat(pathname)", ARG2 );
+}
+
+PRE(sys_fchownat)
+{
+   PRINT("sys_fchownat ( %ld, %#lx(%s), 0x%lx, 0x%lx )", ARG1,ARG2,(char*)ARG2,ARG3,ARG4);
+   PRE_REG_READ4(long, "fchownat",
+                 int, dfd, const char *, path,
+                 vki_uid_t, owner, vki_gid_t, group);
+   PRE_MEM_RASCIIZ( "fchownat(path)", ARG2 );
+}
+
+#if 0
+PRE(sys_futimesat)
+{
+   PRINT("sys_futimesat ( %ld, %#lx(%s), %#lx )", ARG1,ARG2,(char*)ARG2,ARG3);
+   PRE_REG_READ3(long, "futimesat",
+                 int, dfd, char *, filename, struct timeval *, tvp);
+   if (ARG2 != 0)
+      PRE_MEM_RASCIIZ( "futimesat(filename)", ARG2 );
+   if (ARG3 != 0)
+      PRE_MEM_READ( "futimesat(tvp)", ARG3, 2 * sizeof(struct vki_timeval) );
+}
+#endif
+
+PRE(sys_fstatat)
+{
+   PRINT("sys_fstatat ( %ld, %#lx(%s), %#lx )", ARG1,ARG2,(char*)ARG2,ARG3);
+   PRE_REG_READ3(long, "fstatat",
+                 int, dfd, char *, file_name, struct stat *, buf);
+   PRE_MEM_RASCIIZ( "fstatat(file_name)", ARG2 );
+   PRE_MEM_WRITE( "fstatat(buf)", ARG3, sizeof(struct vki_stat) );
+}
+
+POST(sys_fstatat)
+{
+   POST_MEM_WRITE( ARG3, sizeof(struct vki_stat) );
+}
+
+PRE(sys_unlinkat)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_unlinkat ( %ld, %#lx(%s) )", ARG1,ARG2,(char*)ARG2);
+   PRE_REG_READ2(long, "unlinkat", int, dfd, const char *, pathname);
+   PRE_MEM_RASCIIZ( "unlinkat(pathname)", ARG2 );
+}
+
+PRE(sys_renameat)
+{
+   PRINT("sys_renameat ( %ld, %#lx(%s), %ld, %#lx(%s) )", ARG1,ARG2,(char*)ARG2,ARG3,ARG4,(char*)ARG4);
+   PRE_REG_READ4(long, "renameat",
+                 int, olddfd, const char *, oldpath,
+                 int, newdfd, const char *, newpath);
+   PRE_MEM_RASCIIZ( "renameat(oldpath)", ARG2 );
+   PRE_MEM_RASCIIZ( "renameat(newpath)", ARG4 );
+}
+
+PRE(sys_linkat)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_linkat ( %ld, %#lx(%s), %ld, %#lx(%s), %ld )",ARG1,ARG2,(char*)ARG2,ARG3,ARG4,(char*)ARG4,ARG5);
+   PRE_REG_READ5(long, "linkat",
+                 int, olddfd, const char *, oldpath,
+                 int, newdfd, const char *, newpath,
+                 int, flags);
+   PRE_MEM_RASCIIZ( "linkat(oldpath)", ARG2);
+   PRE_MEM_RASCIIZ( "linkat(newpath)", ARG4);
+}
+
+PRE(sys_symlinkat)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_symlinkat ( %#lx(%s), %ld, %#lx(%s) )",ARG1,(char*)ARG1,ARG2,ARG3,(char*)ARG3);
+   PRE_REG_READ3(long, "symlinkat",
+                 const char *, oldpath, int, newdfd, const char *, newpath);
+   PRE_MEM_RASCIIZ( "symlinkat(oldpath)", ARG1 );
+   PRE_MEM_RASCIIZ( "symlinkat(newpath)", ARG3 );
+}
+
+PRE(sys_readlinkat)
+{
+   HChar name[25];
+   Word  saved = SYSNO;
+
+   PRINT("sys_readlinkat ( %ld, %#lx(%s), %#lx, %llu )", ARG1,ARG2,(char*)ARG2,ARG3,(ULong)ARG4);
+   PRE_REG_READ4(long, "readlinkat",
+                 int, dfd, const char *, path, char *, buf, int, bufsiz);
+   PRE_MEM_RASCIIZ( "readlinkat(path)", ARG2 );
+   PRE_MEM_WRITE( "readlinkat(buf)", ARG3,ARG4 );
+
+   /*
+    * Handle the case where readlinkat is looking at /proc/curproc/file or
+    * /proc/<pid>/file.
+    */
+   VG_(sprintf)(name, "/proc/%d/file", VG_(getpid)());
+   if (ML_(safe_to_deref)((void*)ARG2, 1)
+       && (VG_(strcmp)((HChar *)ARG2, name) == 0 
+           || VG_(strcmp)((HChar *)ARG2, "/proc/curproc/file") == 0)) {
+      VG_(sprintf)(name, "/proc/self/fd/%d", VG_(cl_exec_fd));
+      SET_STATUS_from_SysRes( VG_(do_syscall4)(saved, ARG1, (UWord)name, 
+                                                      ARG3, ARG4));
+   } else {
+      /* Normal case */
+      SET_STATUS_from_SysRes( VG_(do_syscall4)(saved, ARG1, ARG2, ARG3, ARG4));
+   }
+
+   if (SUCCESS && RES > 0)
+      POST_MEM_WRITE( ARG3, RES );
+}
+
+PRE(sys_fchmodat)
+{
+   PRINT("sys_fchmodat ( %ld, %#lx(%s), %ld )", ARG1,ARG2,(char*)ARG2,ARG3);
+   PRE_REG_READ3(long, "fchmodat",
+                 int, dfd, const char *, path, vki_mode_t, mode);
+   PRE_MEM_RASCIIZ( "fchmodat(path)", ARG2 );
+}
+
+PRE(sys_faccessat)
+{
+   PRINT("sys_faccessat ( %ld, %#lx(%s), %ld )", ARG1,ARG2,(char*)ARG2,ARG3);
+   PRE_REG_READ3(long, "faccessat",
+                 int, dfd, const char *, pathname, int, mode);
+   PRE_MEM_RASCIIZ( "faccessat(pathname)", ARG2 );
+}
+
+/* ---------------------------------------------------------------------
+   __acl* wrappers
+   ------------------------------------------------------------------ */
+
+#if 0
+PRE(sys___acl_get_file)
+{
+   PRINT("sys___acl_get_file ( %#lx(%s), %ld, %#lx )", ARG1,(char *)ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "__acl_get_file",
+                 const char *, path, int, acltype, struct vki_acl *, aclp);
+   PRE_MEM_WRITE( "__acl_get_file(aclp)", ARG3, sizeof(struct vki_acl) );
+}
+
+POST(sys___acl_get_file)
+{
+   vg_assert(SUCCESS);
+   if (RES == 0) {
+      POST_MEM_WRITE( ARG3, sizeof(struct vki_acl) );
+   }
+}
+
+PRE(sys___acl_set_file)
+{
+   PRINT("sys___acl_set_file ( %#lx(%s), %ld, %#lx )", ARG1,(char *)ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "__acl_set_file",
+                 const char *, path, int, acltype, struct vki_acl *, aclp);
+   PRE_MEM_READ( "__acl_set_file(aclp)", ARG3, sizeof(struct vki_acl) );
+}
+
+PRE(sys___acl_get_fd)
+{
+   PRINT("sys___acl_get_fd ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "__acl_get_fd",
+                 int, fd, int, acltype, struct vki_acl *, aclp);
+   PRE_MEM_WRITE( "__acl_get_file(aclp)", ARG3, sizeof(struct vki_acl) );
+}
+
+POST(sys___acl_get_fd)
+{
+   vg_assert(SUCCESS);
+   if (RES == 0) {
+      POST_MEM_WRITE( ARG3, sizeof(struct vki_acl) );
+   }
+}
+
+PRE(sys___acl_set_fd)
+{
+   PRINT("sys___acl_set_fd ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "__acl_set_fd",
+                 int, fd, int, acltype, struct vki_acl *, aclp);
+   PRE_MEM_READ( "__acl_get_file(aclp)", ARG3, sizeof(struct vki_acl) );
+}
+
+PRE(sys___acl_delete_file)
+{
+   PRINT("sys___acl_delete_file ( %#lx(%s), %ld )", ARG1,(char *)ARG1,ARG2);
+   PRE_REG_READ2(long, "__acl_delete_file",
+                 const char *, path, int, acltype);
+}
+
+PRE(sys___acl_delete_fd)
+{
+   PRINT("sys___acl_delete_fd ( %ld, %ld )", ARG1,ARG2);
+   PRE_REG_READ2(long, "__acl_delete_fd",
+                 int, fd, int, acltype);
+}
+
+PRE(sys___acl_aclcheck_file)
+{
+   PRINT("sys___acl_aclcheck_file ( %#lx(%s), %ld, %#lx )", ARG1,(char *)ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "__acl_aclcheck_file",
+                 const char *, path, int, acltype, struct vki_acl *, aclp);
+   PRE_MEM_READ( "__acl_aclcheck_file(aclp)", ARG3, sizeof(struct vki_acl) );
+}
+
+PRE(sys___acl_aclcheck_fd)
+{
+   PRINT("sys___acl_aclcheck_fd ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "__acl_aclcheck_fd",
+                 int, fd, int, acltype, struct vki_acl *, aclp);
+   PRE_MEM_READ( "__acl_aclcheck_fd(aclp)", ARG3, sizeof(struct vki_acl) );
+}
+
+PRE(sys___acl_get_link)
+{
+   PRINT("sys___acl_get_link ( %#lx(%s), %ld, %#lx )", ARG1,(char *)ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "__acl_get_link",
+                 const char *, path, int, acltype, struct vki_acl *, aclp);
+   PRE_MEM_WRITE( "__acl_get_link(aclp)", ARG3, sizeof(struct vki_acl) );
+}
+
+POST(sys___acl_get_link)
+{
+   vg_assert(SUCCESS);
+   if (RES == 0) {
+      POST_MEM_WRITE( ARG3, sizeof(struct vki_acl) );
+   }
+}
+
+PRE(sys___acl_set_link)
+{
+   PRINT("sys___acl_set_link ( %#lx(%s), %ld, %#lx )", ARG1,(char *)ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "__acl_set_link",
+                 const char *, path, int, acltype, struct vki_acl *, aclp);
+   PRE_MEM_READ( "__acl_set_link(aclp)", ARG3, sizeof(struct vki_acl) );
+}
+
+PRE(sys___acl_delete_link)
+{
+   PRINT("sys___acl_delete_link ( %#lx(%s), %ld )", ARG1,(char *)ARG1,ARG2);
+   PRE_REG_READ2(long, "__acl_delete_link",
+                 const char *, path, int, acltype);
+}
+
+PRE(sys___acl_aclcheck_link)
+{
+   PRINT("sys___acl_aclcheck_link ( %#lx(%s), %ld, %#lx )", ARG1,(char *)ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "__acl_aclcheck_link",
+                 const char *, path, int, acltype, struct vki_acl *, aclp);
+   PRE_MEM_READ( "__acl_aclcheck_link(aclp)", ARG3, sizeof(struct vki_acl) );
+}
+#endif
+
+POST(sys_getcontext)
+{
+   POST_MEM_WRITE( ARG1, sizeof(struct vki_ucontext) );
+}
+
+POST(sys_swapcontext)
+{
+   if (SUCCESS)
+      POST_MEM_WRITE( ARG1, sizeof(struct vki_ucontext) );
+}
+
+PRE(sys_fcntl)
+{
+   switch (ARG2) {
+   // These ones ignore ARG3.
+   case VKI_F_GETFD:
+   case VKI_F_GETFL:
+   case VKI_F_GETOWN:
+      PRINT("sys_fcntl ( %ld, %ld )", ARG1,ARG2);
+      PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
+      break;
+
+   // These ones use ARG3 as "arg".
+   case VKI_F_DUPFD:
+   case VKI_F_SETFD:
+   case VKI_F_SETFL:
+   case VKI_F_SETOWN:
+      PRINT("sys_fcntl[ARG3=='arg'] ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
+      PRE_REG_READ3(long, "fcntl",
+                    unsigned int, fd, unsigned int, cmd, unsigned long, arg);
+      break;
+
+   // These ones use ARG3 as "lock" - obsolete.
+   case VKI_F_OSETLKW:
+      *flags |= SfMayBlock;
+      /* FALLTHROUGH */
+   case VKI_F_OGETLK:
+   case VKI_F_OSETLK:
+      PRINT("sys_fcntl[ARG3=='lock'] ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3);
+      PRE_REG_READ3(long, "fcntl",
+                    unsigned int, fd, unsigned int, cmd,
+                    struct oflock *, lock);
+      break;
+
+   // This one uses ARG3 as "oldd" and ARG4 as "newd".
+   case VKI_F_DUP2FD:
+      PRINT("sys_fcntl[ARG3=='oldd', ARG4=='newd'] ( %ld, %ld, %ld, %ld )",
+         ARG1,ARG2,ARG3,ARG4);
+      PRE_REG_READ4(long, "fcntl",
+                    unsigned int, fd, unsigned int, cmd,
+                    unsigned long, oldd, unsigned long, newd);
+      break;
+
+   // These ones use ARG3 as "lock".
+   case VKI_F_SETLKW:
+      *flags |= SfMayBlock;
+      /* FALLTHROUGH */
+   case VKI_F_GETLK:
+   case VKI_F_SETLK:
+   case VKI_F_SETLK_REMOTE:
+      PRINT("sys_fcntl[ARG3=='lock'] ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3);
+      PRE_REG_READ3(long, "fcntl",
+                    unsigned int, fd, unsigned int, cmd,
+                    struct flock *, lock);
+      break;
+
+   default:
+      PRINT("sys_fcntl[UNKNOWN] ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
+      I_die_here;
+      break;
+   }
+}
+
+POST(sys_fcntl)
+{
+   vg_assert(SUCCESS);
+   if (ARG2 == VKI_F_DUPFD) {
+      if (!ML_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) {
+         VG_(close)(RES);
+         SET_STATUS_Failure( VKI_EMFILE );
+      } else {
+         if (VG_(clo_track_fds))
+            ML_(record_fd_open_named)(tid, RES);
+      }
+   }
+}
+
+PRE(sys_ioctl)
+{
+   UInt dir  = _VKI_IOC_DIR(ARG2);
+   UInt size = _VKI_IOC_SIZE(ARG2);
+   *flags |= SfMayBlock;
+   PRINT("sys_ioctl ( %ld, 0x%lx, %#lx )",ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "ioctl",
+                 unsigned int, fd, unsigned int, request, unsigned long, arg);
+
+/* On FreeBSD, ALL ioctl's are IOR/IOW encoded.  Just use the default decoder */
+   if (SimHintiS(SimHint_lax_ioctls, VG_(clo_sim_hints))) {
+      /* 
+      * Be very lax about ioctl handling; the only
+      * assumption is that the size is correct. Doesn't
+      * require the full buffer to be initialized when
+      * writing.  Without this, using some device
+      * drivers with a large number of strange ioctl
+      * commands becomes very tiresome.
+      */
+   } else if (/* size == 0 || */ dir == _VKI_IOC_NONE) {
+	 static Int moans = 3;
+	 if (moans > 0 && !VG_(clo_xml)) {
+	    moans--;
+	    VG_(message)(Vg_UserMsg, 
+			 "Warning: noted but unhandled ioctl 0x%lx"
+			 " with no size/direction hints",
+			 ARG2); 
+	    VG_(message)(Vg_UserMsg, 
+			 "   This could cause spurious value errors"
+			 " to appear.");
+	    VG_(message)(Vg_UserMsg, 
+			 "   See README_MISSING_SYSCALL_OR_IOCTL for "
+			 "guidance on writing a proper wrapper." );
+	 }
+   } else {
+	 if ((dir & _VKI_IOC_WRITE) && size > 0)
+	    PRE_MEM_READ( "ioctl(generic)", ARG3, size);
+	 if ((dir & _VKI_IOC_READ) && size > 0)
+	    PRE_MEM_WRITE( "ioctl(generic)", ARG3, size);
+   }
+}
+
+POST(sys_ioctl)
+{
+  UInt dir  = _VKI_IOC_DIR(ARG2);
+  UInt size = _VKI_IOC_SIZE(ARG2);
+  vg_assert(SUCCESS);
+  if (size > 0 && (dir & _VKI_IOC_READ)
+     && RES == 0 && ARG3 != (Addr)NULL)
+	 POST_MEM_WRITE(ARG3, size);
+}
+
+PRE(sys_ptrace)
+{
+   struct vki_ptrace_io_desc *io_desc;
+   PRINT("sys_ptrace ( %ld, %ld, 0x%lx, %ld)", ARG1, ARG2, ARG3, ARG4);
+
+   PRE_REG_READ4(int, "ptrace", int, request, int, pid, char *, addr, int, data);
+
+   switch (ARG1) {
+      case VKI_PTRACE_TRACEME:
+         break;
+      case VKI_PTRACE_READ_I:
+      case VKI_PTRACE_READ_D:
+         break;
+
+      case VKI_PTRACE_WRITE_I:
+      case VKI_PTRACE_WRITE_D:
+         break;
+
+      case VKI_PTRACE_IO:
+         PRE_MEM_READ("ptrace", ARG3, sizeof(struct vki_ptrace_io_desc));
+         io_desc = (struct vki_ptrace_io_desc *)ARG3;
+         switch (io_desc->piod_op) {
+            case VKI_PIOD_READ_D:
+            case VKI_PIOD_READ_I:
+               PRE_MEM_WRITE( "ptrace", (UWord)io_desc->piod_addr, io_desc->piod_len);
+               break;
+            case VKI_PIOD_WRITE_D:
+            case VKI_PIOD_WRITE_I:
+               PRE_MEM_READ( "ptrace", (UWord)io_desc->piod_addr, io_desc->piod_len);
+               break;
+         }
+         break;
+
+      case VKI_PTRACE_CONTINUE:
+         break;
+
+      case VKI_PTRACE_STEP:
+         break;
+
+      case VKI_PTRACE_KILL:
+         break;
+
+      case VKI_PTRACE_ATTACH:
+         break;
+
+      case VKI_PTRACE_DETACH:
+         break;
+
+      case VKI_PTRACE_GETREGS:
+         PRE_MEM_WRITE("ptrace", ARG3, sizeof(struct vki_user_regs_struct));
+         break;
+
+      case VKI_PTRACE_SETREGS:
+         PRE_MEM_READ("ptrace", ARG3, sizeof(struct vki_user_regs_struct));
+         break;
+
+      case VKI_PTRACE_GETFPREGS:
+         PRE_MEM_WRITE( "ptrace", ARG3, sizeof(struct vki_fpreg));
+         break;
+
+      case VKI_PTRACE_SETFPREGS:
+         PRE_MEM_READ( "ptrace", ARG3, sizeof(struct vki_fpreg));
+         break;
+
+      case VKI_PTRACE_GETDBREGS:
+         PRE_MEM_WRITE( "ptrace", ARG3, sizeof(struct vki_dbreg));
+         break;
+
+      case VKI_PTRACE_SETDBREGS:
+         PRE_MEM_READ( "ptrace", ARG3, sizeof(struct vki_dbreg));
+         break;
+
+      case VKI_PTRACE_LWPINFO:
+         PRE_MEM_WRITE( "ptrace", ARG3, sizeof(struct vki_ptrace_lwpinfo));
+         break;
+
+      case VKI_PTRACE_GETNUMLWPS:
+         break;
+
+      case VKI_PTRACE_GETLWPLIST:
+         PRE_MEM_WRITE( "ptrace", ARG3, sizeof(vki_lwpid_t) * ARG4);
+         break;
+
+      case VKI_PTRACE_SETSTEP:
+         break;
+
+      case VKI_PTRACE_CLEARSTEP:
+         break;
+
+      case VKI_PTRACE_SUSPEND:
+         break;
+
+      case VKI_PTRACE_RESUME:
+         break;
+
+      case VKI_PTRACE_TO_SCE:
+         break;
+
+      case VKI_PTRACE_TO_SCX:
+         break;
+
+      case VKI_PTRACE_SYSCALL:
+         break;
+
+      case VKI_PTRACE_VM_TIMESTAMP:
+         break;
+
+      case VKI_PTRACE_VM_ENTRY:
+         PRE_MEM_WRITE( "ptrace", ARG3, sizeof(struct vki_ptrace_vm_entry));
+         break;
+   }
+}
+
+POST(sys_ptrace)
+{
+   struct vki_ptrace_io_desc *io_desc;
+
+   switch (ARG1) {
+      case VKI_PTRACE_TRACEME:
+         break;
+      case VKI_PTRACE_READ_I:
+      case VKI_PTRACE_READ_D:
+         break;
+
+      case VKI_PTRACE_WRITE_I:
+      case VKI_PTRACE_WRITE_D:
+         break;
+
+      case VKI_PTRACE_IO:
+         io_desc = (struct vki_ptrace_io_desc *)ARG3;
+         switch (io_desc->piod_op) {
+            case VKI_PIOD_READ_D:
+            case VKI_PIOD_READ_I:
+               if (RES != -1)
+                  POST_MEM_WRITE((UWord)io_desc->piod_addr, io_desc->piod_len);
+               break;
+            case VKI_PIOD_WRITE_D:
+            case VKI_PIOD_WRITE_I:
+               break;
+         }
+         break;
+
+      case VKI_PTRACE_CONTINUE:
+         break;
+
+      case VKI_PTRACE_STEP:
+         break;
+
+      case VKI_PTRACE_KILL:
+         break;
+
+      case VKI_PTRACE_ATTACH:
+         break;
+
+      case VKI_PTRACE_DETACH:
+         break;
+
+      case VKI_PTRACE_GETREGS:
+         if (RES != -1)
+            POST_MEM_WRITE(ARG3, sizeof(struct vki_user_regs_struct));
+         break;
+
+      case VKI_PTRACE_SETREGS:
+         break;
+
+      case VKI_PTRACE_GETFPREGS:
+         if (RES != -1)
+            POST_MEM_WRITE(ARG3, sizeof(struct vki_fpreg));
+         break;
+
+      case VKI_PTRACE_SETFPREGS:
+         break;
+
+      case VKI_PTRACE_GETDBREGS:
+         if (RES != -1)
+            POST_MEM_WRITE(ARG3, sizeof(struct vki_dbreg));
+         break;
+
+      case VKI_PTRACE_SETDBREGS:
+         break;
+
+      case VKI_PTRACE_LWPINFO:
+         if (RES != -1)
+            POST_MEM_WRITE(ARG3, sizeof(struct vki_ptrace_lwpinfo));
+         break;
+
+      case VKI_PTRACE_GETNUMLWPS:
+         break;
+
+      case VKI_PTRACE_GETLWPLIST:
+         if (RES != -1)
+            POST_MEM_WRITE(ARG3, sizeof(vki_lwpid_t) * RES);
+         break;
+
+      case VKI_PTRACE_SETSTEP:
+         break;
+
+      case VKI_PTRACE_CLEARSTEP:
+         break;
+
+      case VKI_PTRACE_SUSPEND:
+         break;
+
+      case VKI_PTRACE_RESUME:
+         break;
+
+      case VKI_PTRACE_TO_SCE:
+         break;
+
+      case VKI_PTRACE_TO_SCX:
+         break;
+
+      case VKI_PTRACE_SYSCALL:
+         break;
+
+      case VKI_PTRACE_VM_TIMESTAMP:
+         break;
+
+      case VKI_PTRACE_VM_ENTRY:
+         if (RES != -1)
+            POST_MEM_WRITE(ARG3, sizeof(struct vki_ptrace_vm_entry));
+         break;
+   }
+}
+
+#if 0
+PRE(sys_cpuset_setaffinity)
+{
+	PRE_MEM_READ("cpuset_setaffinity", ARG5, ARG4);
+}
+#endif
+
+PRE(sys_getentropy)
+{
+   PRINT("sys_getentropy ()");
+   PRE_REG_READ2(int, "getentropy", void *, buf, vki_size_t, buflen);
+   PRE_MEM_WRITE("getentropy(buf)", ARG1, ARG2);
+}
+
+POST(sys_getentropy)
+{
+   if (SUCCESS) {
+      POST_MEM_WRITE(ARG1, ARG2);
+   }
+}
+
+#undef PRE
+#undef POST
+
+const SyscallTableEntry ML_(syscall_table)[] = {
+   // syscall (handled specially)			// 0
+  
+  BSDX_(__NR_exit,		sys_exit),		// 1
+  BSDX_(__NR_fork,		sys_fork),		// 2
+  GENXY(__NR_read,		sys_read),		// 3
+  GENX_(__NR_write,		sys_write),		// 4
+  GENXY(__NR_open,		sys_open),		// 5
+  
+  GENXY(__NR_close,		sys_close),		// 6
+  BSDXY(__NR_getentropy,	sys_getentropy),	// 7
+  BSDX_(__NR___tfork,		sys___tfork),		// 8
+  GENX_(__NR_link,		sys_link),		// 9
+  GENX_(__NR_unlink,		sys_unlink),		// 10
+  
+  GENXY(__NR_wait4,		sys_wait4),		// 11
+  GENX_(__NR_chdir,		sys_chdir),		// 12
+  GENX_(__NR_fchdir,		sys_fchdir),		// 13
+  GENX_(__NR_mknod,		sys_mknod),		// 14
+  GENX_(__NR_chmod,		sys_chmod),		// 15
+
+  GENX_(__NR_chown,		sys_chown),		// 16
+  //BSDX_(__NR_break,		sys_obreak),		// 17
+  BSDX_(__NR_getdtablecount,	sys_getdtablecount),	// 18
+  GENXY(__NR_getrusage,		sys_getrusage),		// 19
+  GENX_(__NR_getpid,		sys_getpid),		// 20
+
+  BSDX_(__NR_mount,		sys_mount),		// 21
+  BSDX_(__NR_unmount,		sys_unmount),		// 22
+  GENX_(__NR_setuid,		sys_setuid),		// 23
+  GENX_(__NR_getuid,		sys_getuid),		// 24
+  GENX_(__NR_geteuid,		sys_geteuid),		// 25
+
+  BSDX_(__NR_ptrace,		sys_ptrace),		// 26
+  // unimpl ptrace					// 26
+  BSDX_(__NR_recvmsg,		sys_recvmsg),		// 27
+  BSDX_(__NR_sendmsg,		sys_sendmsg),		// 28
+  BSDXY(__NR_recvfrom,		sys_recvfrom),		// 29
+  BSDXY(__NR_accept,		sys_accept),		// 30
+
+  BSDX_(__NR_getpeername,	sys_getpeername),	// 31
+  BSDX_(__NR_getsockname,	sys_getsockname),	// 32
+  GENX_(__NR_access,		sys_access),		// 33
+  BSDX_(__NR_chflags,		sys_chflags),		// 34
+  BSDX_(__NR_fchflags,		sys_fchflags),		// 35
+
+  GENX_(__NR_sync,		sys_sync),		// 36
+  BSDX_(__NR_msyscall,		sys_msyscall),		// 37
+  BSDXY(__NR_stat,		sys_stat),		// 38
+  GENX_(__NR_getppid,		sys_getppid),		// 39
+  BSDXY(__NR_lstat,		sys_lstat),		// 40
+
+  GENX_(__NR_dup,		sys_dup),		// 41
+  BSDXY(__NR_fstatat,		sys_fstatat),		// 42
+  GENX_(__NR_getegid,		sys_getegid),		// 43
+  BSDX_(__NR_profil,		sys_profil),		// 44
+  BSDX_(__NR_ktrace,		sys_ktrace),		// 45
+
+  BSDXY(__NR_sigaction,		sys_sigaction),		// 46
+  GENX_(__NR_getgid,		sys_getgid),		// 47
+  BSDX_(__NR_sigprocmask,	sys_sigprocmask),	// 48
+  BSDX_(__NR_mmap,		sys_mmap),		// 49
+  BSDX_(__NR_setlogin,		sys_setlogin),		// 50
+
+  BSDX_(__NR_acct,		sys_acct),		// 51
+  // unimpl acct					// 51
+  BSDX_(__NR_sigpending,	sys_sigpending),	// 52
+  BSDXY(__NR_fstat,		sys_fstat),		// 53
+  BSDXY(__NR_ioctl,		sys_ioctl),		// 54
+  BSDX_(__NR_reboot,		sys_reboot),		// 55
+
+  BSDX_(__NR_revoke,		sys_revoke),		// 56
+  GENX_(__NR_symlink,		sys_symlink),		// 57
+  GENX_(__NR_readlink,		sys_readlink),		// 58
+  GENX_(__NR_execve,		sys_execve),		// 59
+  GENX_(__NR_umask,		sys_umask),		// 60
+
+  GENX_(__NR_chroot,		sys_chroot),		// 61
+  BSDXY(__NR_getfsstat,		sys_getfsstat),		// 62
+  GENXY(__NR_statfs,		sys_statfs),		// 63
+  GENXY(__NR_fstatfs,		sys_fstatfs),		// 64
+  BSDXY(__NR_fhstatfs,		sys_fhstatfs),		// 65
+
+  BSDX_(__NR_vfork,		sys_vfork),		// 66
+  GENXY(__NR_gettimeofday,	sys_gettimeofday),	// 67
+  GENX_(__NR_settimeofday,	sys_settimeofday),	// 68
+  GENX_(__NR_setitimer,		sys_setitimer),		// 69
+  GENXY(__NR_getitimer,		sys_getitimer),		// 70
+
+  GENX_(__NR_select,		sys_select),		// 71
+  BSDXY(__NR_kevent,		sys_kevent),		// 72
+  GENX_(__NR_munmap,		sys_munmap),		// 73
+  GENXY(__NR_mprotect,		sys_mprotect),		// 74
+  GENX_(__NR_madvise,		sys_madvise),		// 75
+
+  GENX_(__NR_utimes,		sys_utimes),		// 76
+  BSDX_(__NR_futimes,		sys_futimes),		// 77
+  BSDX_(__NR_mquery,		sys_mquery),		// 78
+  GENXY(__NR_getgroups,		sys_getgroups),		// 79
+  GENX_(__NR_setgroups,		sys_setgroups),		// 80
+
+  GENX_(__NR_getpgrp,		sys_getpgrp),		// 81
+  GENX_(__NR_setpgid,		sys_setpgid),		// 82
+  BSDXY(__NR_futex,		sys_futex),		// 83
+  BSDX_(__NR_utimensat,		sys_utimensat),		// 84
+  BSDX_(__NR_futimens,		sys_futimens),		// 85
+
+  BSDX_(__NR_kbind,		sys_kbind),		// 86
+  BSDXY(__NR_clock_gettime,	sys_clock_gettime),	// 87
+  BSDX_(__NR_clock_settime,	sys_clock_settime),	// 88
+  BSDXY(__NR_clock_getres,	sys_clock_getres),	// 89
+  GENXY(__NR_dup2,		sys_dup2),		// 90
+
+  GENX_(__NR_nanosleep,		sys_nanosleep),		// 91
+  BSDXY(__NR_fcntl,		sys_fcntl),		// 92
+  BSDXY(__NR_accept4,		sys_accept4),		// 93
+  BSDX_(__NR___thrsleep,	sys___thrsleep),	// 94
+  GENX_(__NR_fsync,		sys_fsync),		// 95
+
+  GENX_(__NR_setpriority,	sys_setpriority),	// 96
+  BSDX_(__NR_socket,		sys_socket),		// 97
+  BSDX_(__NR_connect,		sys_connect),		// 98
+  GENXY(__NR_getdents,		sys_getdents),		// 99
+  GENX_(__NR_getpriority,	sys_getpriority),	// 100
+
+  BSDXY(__NR_pipe2,		sys_pipe2),		// 101
+  BSDXY(__NR_dup3,		sys_dup3),		// 102
+  BSDX_(__NR_sigreturn,		sys_sigreturn),		// 103
+  BSDX_(__NR_bind,		sys_bind),		// 104
+  BSDX_(__NR_setsockopt,	sys_setsockopt),	// 105
+
+  BSDX_(__NR_listen,		sys_listen),		// 106
+  BSDX_(__NR_chflagsat,		sys_chflagsat),		// 107
+  BSDX_(__NR_pledge,		sys_pledge),		// 108
+  BSDX_(__NR_ppoll,		sys_ppoll),		// 109
+  BSDX_(__NR_pselect,		sys_pselect),		// 110
+
+  BSDX_(__NR_sigsuspend,	sys_sigsuspend),	// 111
+  BSDX_(__NR_sendsyslog,	sys_sendsyslog),	// 112
+  // obsol orecvmsg					// 113
+  BSDX_(__NR_unveil,		sys_unveil),		// 114
+  BSDXY(__NR___realpath,	sys___realpath),	// 115
+  BSDXY(__NR_recvmmsg,		sys_recvmmsg),		// 116
+  BSDX_(__NR_sendmmsg,		sys_sendmmsg),		// 117
+
+  BSDX_(__NR_getsockopt,	sys_getsockopt),	// 118
+  BSDX_(__NR_thrkill,		sys_thrkill),		// 119
+  GENXY(__NR_readv,		sys_readv),		// 120
+
+  GENX_(__NR_writev,		sys_writev),		// 121
+  GENX_(__NR_kill,		sys_kill),		// 122
+  GENX_(__NR_fchown,		sys_fchown),		// 123
+  GENX_(__NR_fchmod,		sys_fchmod),		// 124
+  // obsol orecvfrom					// 125
+
+  GENX_(__NR_setreuid,		sys_setreuid),		// 126
+  GENX_(__NR_setregid,		sys_setregid),		// 127
+  GENX_(__NR_rename,		sys_rename),		// 128
+  // obsol otruncate					// 129
+  // obsol oftruncate					// 130
+
+  GENX_(__NR_flock,		sys_flock),		// 131
+  BSDX_(__NR_mkfifo,		sys_mkfifo),		// 132
+  BSDX_(__NR_sendto,		sys_sendto),		// 133
+  BSDX_(__NR_shutdown,		sys_shutdown),		// 134
+  BSDXY(__NR_socketpair,	sys_socketpair),	// 135
+
+  GENX_(__NR_mkdir,		sys_mkdir),		// 136
+  GENX_(__NR_rmdir,		sys_rmdir),		// 137
+  // obsol 4.2 sigreturn				// 139
+  BSDX_(__NR_adjtime,		sys_adjtime),		// 140
+
+  BSDX_(__NR_getlogin_r,	sys_getlogin_r),	// 141
+  // obsol ogethostid					// 142
+  // obsol osethostid					// 143
+  // obsol ogetrlimit					// 144
+  // obsol osetrlimit					// 145
+
+  BSDX_(__NR_pinsyscall,	sys_pinsyscall),	// 146
+  GENX_(__NR_setsid,		sys_setsid),		// 147
+  BSDX_(__NR_quotactl,		sys_quotactl),		// 148
+  // obsol oquota					// 149
+  BSDX_(__NR_ypconnect,		sys_ypconnect),		// 150
+
+  // unimpl 						// 151
+  // unimpl 						// 152
+  // unimpl 						// 153
+  // unimpl 						// 154
+  BSDX_(__NR_nfssvc,		sys_nfssvc),		// 155
+
+  // obsol ogetdirentries				// 156
+  // obsol statfs25					// 157
+  // obsol fstatfs25					// 158
+  BSDX_(__NR_mimmutable,	sys_mimmutable),	// 159
+  BSDX_(__NR_waitid,		sys_waitid),		// 160
+
+  BSDXY(__NR_getfh,		sys_getfh),		// 161
+  // obsol ogetdomainname				// 162
+  // obsol osetdomainname				// 163
+  BSDX_(__NR___tmpfd,		sys___tmpfd),		// 164
+  BSDX_(__NR_sysarch,		sys_sysarch),		// 165
+
+  BSDX_(__NR_lseek,		sys_lseek),		// 166
+  BSDX_(__NR_truncate,		sys_truncate),		// 167
+  BSDX_(__NR_ftruncate,		sys_ftruncate),		// 168
+  BSDXY(__NR_pread,		sys_pread),		// 169
+  BSDX_(__NR_pwrite,		sys_pwrite),		// 170
+
+  BSDXY(__NR_preadv,		sys_preadv),		// 171
+  BSDX_(__NR_pwritev,		sys_pwritev),		// 172
+  BSDXY(__NR_pad_pread,		sys_pread),		// 173
+  BSDX_(__NR_pad_pwrite,	sys_pwrite),		// 174
+  // unimpl ntp_gettime					// 175
+
+  // unimpl ntp_adjtime					// 176
+  // unimpl 						// 177
+  // unimpl 						// 178
+  // unimpl 						// 179
+  // unimpl 						// 180
+
+  GENX_(__NR_setgid,		sys_setgid),		// 181
+  BSDX_(__NR_setegid,		sys_setegid),		// 182
+  BSDX_(__NR_seteuid,		sys_seteuid),		// 183
+  // obsol lfs_bmapv					// 184
+  // obsol lfs_markv					// 185
+
+  // obsol lfs_segclean					// 186
+  // obsol lfs_segwait					// 187
+  // obsol stat35					// 188
+  // obsol fstat35					// 189
+  // obsol lstat35					// 190
+
+  BSDX_(__NR_pathconf,		sys_pathconf),		// 191
+  BSDX_(__NR_fpathconf,		sys_fpathconf),		// 192
+  BSDX_(__NR_swapctl,		sys_swapctl),		// 193
+  GENX_(__NR_getrlimit,		sys_getrlimit),		// 194
+  BSDX_(__NR_setrlimit,		sys_setrlimit),		// 195
+
+  // obsol ogetdirentries48				// 196
+  BSDX_(__NR_pad_mmap,		sys_mmap),		// 197
+  // BSDX_(__NR___syscall,		sys___syscall),		// 198
+  BSDX_(__NR_pad_lseek,		sys_lseek),		// 199
+  BSDX_(__NR_pad_truncate,	sys_truncate),		// 200
+
+  BSDX_(__NR_pad_ftruncate,	sys_ftruncate),		// 201
+  BSDXY(__NR_sysctl,		sys___sysctl),		// 202
+  GENX_(__NR_mlock,		sys_mlock),		// 203
+  GENX_(__NR_munlock,		sys_munlock),		// 204
+  // unimpl sys_undelete				// 205
+
+  BSDX_(__NR_getpgid,		sys_getpgid),		// 207
+  // obsol nnpfspioctl					// 208
+  BSDX_(__NR_utrace,		sys_utrace),		// 209
+
+  // unimpl 						// 220
+
+  BSDX_(__NR_semget,		sys_semget),		// 221
+  // obsol semop35					// 222
+  // obsol semconfig35					// 223
+  // unimpl 						// 224
+  BSDX_(__NR_msgget,		sys_msgget),		// 225
+
+  BSDX_(__NR_msgsnd,		sys_msgsnd),		// 226
+  BSDX_(__NR_msgrcv,		sys_msgrcv),		// 227
+  // unimpl msgctl					// 224
+  // unimpl msgget					// 225
+
+  // unimpl msgsnd					// 226
+  // unimpl msgrcv					// 227
+  BSDX_(__NR_shmat,		sys_shmat),		// 228
+  // unimpl 						// 229
+  BSDX_(__NR_shmdt,		sys_shmdt),		// 230
+
+  // obsol shmget35					// 231
+  // unimpl timer_create				// 235
+
+  // unimpl timer_delete				// 236
+  // unimpl timer_settime				// 237
+  // unimpl timer_gettime				// 238
+  // unimpl timer_getoverrun				// 239
+
+  // unimpl 						// 241
+  // unimpl 						// 242
+  // unimpl 						// 243
+  // unimpl 						// 244
+  // unimpl 						// 245
+
+  // unimpl 						// 246
+  // unimpl 						// 247
+  // unimpl 						// 248
+  // unimpl 						// 249
+  BSDX_(__NR_minherit,		sys_minherit),		// 250
+
+  // obsol rfork					// 251
+  GENX_(__NR_poll,		sys_poll),		// 252
+  BSDX_(__NR_issetugid,		sys_issetugid),		// 253
+  BSDX_(__NR_lchown,		sys_lchown),		// 254
+  BSDX_(__NR_getsid,		sys_getsid),		// 255
+
+  BSDX_(__NR_msync,		sys_msync),		// 256
+  // obsol semctl35					// 257
+  // obsol shmctl35					// 258
+  // obsol msgctl35					// 259
+  // unimpl 						// 260
+
+  // unimpl 						// 261
+  // unimpl 						// 262
+  BSDXY(__NR_pipe,		sys_pipe),		// 263
+  BSDX_(__NR_fhopen,		sys_fhopen),		// 264
+  // unimpl 						// 265
+
+  // unimpl 						// 266
+  BSDXY(__NR_pad_preadv,	sys_preadv),		// 267
+  BSDX_(__NR_pad_pwritev,	sys_pwritev),		// 268
+  BSDX_(__NR_kqueue,		sys_kqueue),		// 269
+
+  GENX_(__NR_mlockall,		sys_mlockall),		// 271
+  BSDX_(__NR_munlockall,	sys_munlockall),	// 272
+  // unimpl sys_getpeereid				// 273
+  // unimpl sys_extattrctl				// 274
+  // unimpl sys_extattr_set_file			// 275
+
+  // unimpl sys_extattr_get_file			// 276
+  // unimpl sys_extattr_delete_file			// 277
+  // unimpl sys_extattr_set_fd				// 278
+  // unimpl sys_extattr_get_fd				// 279
+  // unimpl sys_extattr_delete_fd			// 280
+
+  BSDXY(__NR_getresuid,		sys_getresuid),		// 281
+  BSDX_(__NR_setresuid,		sys_setresuid),		// 282
+  BSDXY(__NR_getresgid,		sys_getresgid),		// 283
+  BSDX_(__NR_setresgid,		sys_setresgid),		// 284
+  // obsol sys_omquery					// 285
+
+  BSDX_(__NR_pad_mquery,	sys_mquery),		// 286
+  BSDX_(__NR_closefrom,		sys_closefrom),		// 287
+  BSDX_(__NR_sigaltstack,	sys_sigaltstack),	// 288
+  BSDX_(__NR_shmget,		sys_shmget),		// 289
+  // unimpl shmget					// 289
+  BSDX_(__NR_semop,		sys_semop),		// 290
+
+  BSDXY(__NR_fhstat,		sys_fhstat),		// 294
+  BSDX_(__NR___semctl,		sys___semctl),		// 295
+
+  BSDX_(__NR_shmctl,		sys_shmctl),		// 296
+  BSDX_(__NR_msgctl,		sys_msgctl),		// 297
+  BSDX_(__NR_sched_yield,	sys_sched_yield),	// 298
+  BSDX_(__NR_getthrid,		sys_getthrid),		// 299
+
+  BSDX_(__NR___thrwakeup,	sys___thrwakeup),	// 301
+  BSDX_(__NR___threxit,		sys___threxit),		// 302
+  BSDX_(__NR___thrsigdivert,	sys___thrsigdivert),	// 303
+  BSDXY(__NR___getcwd,		sys___getcwd),		// 304
+  BSDX_(__NR_adjfreq,		sys_adjfreq),		// 305
+
+  BSDX_(__NR_setrtable,		sys_setrtable),		// 310
+  BSDX_(__NR_getrtable,		sys_getrtable),		// 311
+  BSDX_(__NR_faccessat,		sys_faccessat),		// 313
+  BSDX_(__NR_fchmodat,		sys_fchmodat),		// 314
+  BSDX_(__NR_fchownat,		sys_fchownat),		// 315
+
+  BSDX_(__NR_linkat,		sys_linkat),		// 317
+  BSDX_(__NR_mkdirat,		sys_mkdirat),		// 318
+  BSDX_(__NR_mkfifoat,		sys_mkfifoat),		// 319
+  BSDX_(__NR_mknodat,		sys_mknodat),		// 320
+
+  BSDX_(__NR_openat,		sys_openat),		// 321
+  BSDX_(__NR_readlinkat,	sys_readlinkat),	// 322
+  BSDX_(__NR_renameat,		sys_renameat),		// 323
+  BSDX_(__NR_symlinkat,		sys_symlinkat),		// 324
+  BSDX_(__NR_unlinkat,		sys_unlinkat),		// 325
+
+  BSDX_(__NR___set_tcb,		sys___set_tcb),		// 329
+  BSDX_(__NR___get_tcb,		sys___get_tcb),		// 330
+
+  BSDX_(__NR_fake_sigreturn,	sys_fake_sigreturn),	// 1000, fake sigreturn
+};
+
+const SyscallTableEntry* ML_(get_openbsd_syscall_entry) ( UInt sysno )
+{
+   const UInt syscall_table_size
+      = sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]);
+
+   /* Is it in the contiguous initial section of the table? */
+   if (sysno < syscall_table_size) {
+      const SyscallTableEntry* sys = &ML_(syscall_table)[sysno];
+      if (sys->before == NULL) {
+         return NULL; /* no entry */
+      }
+      return sys;
+   }
+
+   /* Can't find a wrapper */
+   return NULL;
+}
+
+#endif	// defined(VGO_openbsd)
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
