--- coregrind/m_syswrap/syswrap-main.c.orig
+++ coregrind/m_syswrap/syswrap-main.c
@@ -300,7 +300,7 @@
                                       const vki_sigset_t *syscall_mask,
                                       const vki_sigset_t *restore_mask,
                                       Word sigsetSzB );
-#elif defined(VGO_freebsd)
+#elif defined(VGO_freebsd) || defined(VGO_openbsd)
 extern
 UWord ML_(do_syscall_for_client_WRK)( Word syscallno, 
                                       void* guest_state,
@@ -350,7 +350,7 @@
 {
    vki_sigset_t saved;
    UWord err;
-#  if defined(VGO_freebsd)
+#  if defined(VGO_freebsd) || defined(VGO_openbsd)
    Int real_syscallno;
 #  endif
 #  if defined(VGO_linux)
@@ -369,6 +369,12 @@
             real_syscallno, &tst->arch.vex,
             syscall_mask, &saved, sizeof(vki_sigset_t)
          );
+#  elif defined(VGO_openbsd)
+   real_syscallno = syscallno;
+   err = ML_(do_syscall_for_client_WRK)(
+            real_syscallno, &tst->arch.vex,
+            syscall_mask, &saved, sizeof(vki_sigset_t)
+         );
 #  elif defined(VGO_darwin)
    switch (VG_DARWIN_SYSNO_CLASS(syscallno)) {
       case VG_DARWIN_SYSCALL_CLASS_UNIX:
@@ -623,6 +629,112 @@
       canonical->arg8  = stack[2];
    }
 
+#elif defined(VGP_x86_freebsd)
+   VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
+   UWord *stack = (UWord *)gst->guest_ESP;
+
+   // FreeBSD supports different calling conventions
+   switch (gst->guest_EAX) {
+   case __NR_syscall:
+      canonical->class = VG_FREEBSD_SYSCALL0;
+      canonical->sysno = stack[1];
+      stack += 1;
+      break;
+   case __NR___syscall:
+      canonical->class = VG_FREEBSD_SYSCALL198;
+      canonical->sysno = stack[1];
+      stack += 2;
+      break;
+   default:
+      canonical->class = 0;
+      canonical->sysno = gst->guest_EAX;
+      break;
+   }
+   // stack[0] is a (fake) return address
+   canonical->arg1  = stack[1];
+   canonical->arg2  = stack[2];
+   canonical->arg3  = stack[3];
+   canonical->arg4  = stack[4];
+   canonical->arg5  = stack[5];
+   canonical->arg6  = stack[6];
+   canonical->arg7  = stack[7];
+   canonical->arg8  = stack[8];
+
+#elif defined(VGP_amd64_freebsd)
+   VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
+   UWord *stack = (UWord *)gst->guest_RSP;
+
+   // FreeBSD supports different calling conventions
+   switch (gst->guest_RAX) {
+   case __NR_syscall:
+      canonical->class = VG_FREEBSD_SYSCALL0;
+      canonical->sysno = gst->guest_RDI;
+      break;
+   case __NR___syscall:
+      canonical->class = VG_FREEBSD_SYSCALL198;
+      canonical->sysno = gst->guest_RDI;
+      break;
+   default:
+      canonical->class = 0;
+      canonical->sysno = gst->guest_RAX;
+      break;
+   }
+   // stack[0] is a (fake) return address
+   if (canonical->class != VG_FREEBSD_SYSCALL0 && canonical->class != VG_FREEBSD_SYSCALL198) {
+      // stack[0] is return address
+      canonical->arg1  = gst->guest_RDI;
+      canonical->arg2  = gst->guest_RSI;
+      canonical->arg3  = gst->guest_RDX;
+      canonical->arg4  = gst->guest_R10;
+      canonical->arg5  = gst->guest_R8;
+      canonical->arg6  = gst->guest_R9;
+      canonical->arg7  = stack[1];
+      canonical->arg8  = stack[2];
+   } else {
+      // stack[0] is return address
+      canonical->arg1  = gst->guest_RSI;
+      canonical->arg2  = gst->guest_RDX;
+      canonical->arg3  = gst->guest_R10;
+      canonical->arg4  = gst->guest_R8;
+      canonical->arg5  = gst->guest_R9;
+      canonical->arg6  = stack[1];
+      canonical->arg7  = stack[2];
+      canonical->arg8  = stack[3];
+   }
+
+#elif defined(VGP_x86_openbsd)
+   VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
+   UWord *stack = (UWord *)gst->guest_ESP;
+
+   canonical->class = 0;
+   canonical->sysno = gst->guest_EAX;
+   // stack[0] is a (fake) return address
+   canonical->arg1  = stack[1];
+   canonical->arg2  = stack[2];
+   canonical->arg3  = stack[3];
+   canonical->arg4  = stack[4];
+   canonical->arg5  = stack[5];
+   canonical->arg6  = stack[6];
+   canonical->arg7  = stack[7];
+   canonical->arg8  = stack[8];
+
+#elif defined(VGP_amd64_openbsd)
+   VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
+   UWord *stack = (UWord *)gst->guest_RSP;
+
+   canonical->klass = 0;
+   canonical->sysno = gst->guest_RAX;
+   // stack[0] is return address
+   canonical->arg1  = gst->guest_RDI;
+   canonical->arg2  = gst->guest_RSI;
+   canonical->arg3  = gst->guest_RDX;
+   canonical->arg4  = gst->guest_R10;
+   canonical->arg5  = gst->guest_R8;
+   canonical->arg6  = gst->guest_R9;
+   canonical->arg7  = stack[1];
+   canonical->arg8  = stack[2];
+
+
 #elif defined(VGP_arm_linux)
    VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla;
    canonical->sysno = gst->guest_R7;
@@ -1015,6 +1127,36 @@
        stack[2]       = canonical->arg8;
    }
 
+#elif defined(VGP_x86_openbsd)
+   VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
+   UWord *stack = (UWord *)gst->guest_ESP;
+
+   // stack[0] is a (fake) return address
+   gst->guest_EAX = canonical->sysno;
+   stack[1] = canonical->arg1;
+   stack[2] = canonical->arg2;
+   stack[3] = canonical->arg3;
+   stack[4] = canonical->arg4;
+   stack[5] = canonical->arg5;
+   stack[6] = canonical->arg6;
+   stack[7] = canonical->arg7;
+   stack[8] = canonical->arg8;
+
+#elif defined(VGP_amd64_openbsd)
+   VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
+   UWord *stack = (UWord *)gst->guest_RSP;
+
+   // stack[0] is a (fake) return address
+   gst->guest_RAX = canonical->sysno;
+   gst->guest_RDI = canonical->arg1;
+   gst->guest_RSI = canonical->arg2;
+   gst->guest_RDX = canonical->arg3;
+   gst->guest_R10 = canonical->arg4;
+   gst->guest_R8  = canonical->arg5;
+   gst->guest_R9  = canonical->arg6;
+   stack[1]       = canonical->arg7;
+   stack[2]       = canonical->arg8;
+
 #elif defined(VGP_arm_linux)
    VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla;
    gst->guest_R7 = canonical->sysno;
@@ -1209,6 +1351,15 @@
                         (flags & 1) != 0 ? True : False);
    canonical->what = SsComplete;
 
+#  elif defined(VGP_x86_openbsd)
+   /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */
+   VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
+   UInt flags = LibVEX_GuestX86_get_eflags(gst);
+
+   canonical->sres = VG_(mk_SysRes_x86_openbsd)(gst->guest_EAX, gst->guest_EDX,
+                        (flags & 1) != 0 ? True : False);
+   canonical->what = SsComplete;
+
 #  elif defined(VGP_arm_linux)
    VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla;
    canonical->sres = VG_(mk_SysRes_arm_linux)( gst->guest_R0 );
@@ -1248,6 +1399,14 @@
                         (flags & 1) != 0 ? True : False);
    canonical->what = SsComplete;
 
+#  elif defined(VGP_amd64_openbsd)
+   /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */
+   VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
+   ULong flags = LibVEX_GuestAMD64_get_rflags(gst);
+   canonical->sres = VG_(mk_SysRes_amd64_openbsd)(gst->guest_RAX, gst->guest_RDX,
+                        (flags & 1) != 0 ? True : False);
+   canonical->what = SsComplete;
+
 #  elif defined(VGP_x86_darwin)
    /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */
    VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
@@ -1451,7 +1610,7 @@
    VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 
              OFFSET_arm64_X0, sizeof(UWord) );
 
-#elif defined(VGP_x86_freebsd)
+#elif defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd)
    VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
    vg_assert(canonical->what == SsComplete);
    if (sr_isError(canonical->sres)) {
@@ -1470,13 +1629,18 @@
    VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
       offsetof(VexGuestX86State, guest_CC_DEP1), sizeof(UInt) );
  
-#elif defined(VGP_amd64_freebsd)
+#elif defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd)
    VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
    vg_assert(canonical->what == SsComplete);
    if (sr_isError(canonical->sres)) {
       gst->guest_RAX = sr_Err(canonical->sres);
       LibVEX_GuestAMD64_put_rflag_c(1, gst);
    } else {
+#if defined(VGP_amd64_openbsd)
+      if (!canonical->sres._hasVal2) {
+         canonical->sres._val2 = gst->guest_RDX;
+      }
+#endif
       gst->guest_RAX = sr_Res(canonical->sres);
       gst->guest_RDX = sr_ResHI(canonical->sres);
       LibVEX_GuestAMD64_put_rflag_c(0, gst);
@@ -1719,7 +1883,7 @@
    layout->o_arg7   = OFFSET_ppc64_GPR9;
    layout->uu_arg8  = -1; /* impossible value */
 
-#elif defined(VGP_x86_freebsd)
+#elif defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd)
    layout->o_sysno  = OFFSET_x86_EAX;
    // syscall parameters are on stack in C convention
    layout->s_arg1   = sizeof(UWord) * 1;
@@ -1731,7 +1895,7 @@
    layout->s_arg7   = sizeof(UWord) * 7;
    layout->s_arg8   = sizeof(UWord) * 8;
  
-#elif defined(VGP_amd64_freebsd)
+#elif defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd)
    layout->o_sysno  = OFFSET_amd64_RAX;
    layout->o_arg1   = OFFSET_amd64_RDI;
    layout->o_arg2   = OFFSET_amd64_RSI;
@@ -1923,6 +2087,9 @@
 #  elif defined(VGO_freebsd)
    sys = ML_(get_freebsd_syscall_entry)( syscallno );
 
+#  elif defined(VGO_openbsd)
+   sys = ML_(get_openbsd_syscall_entry)( syscallno );
+
 #  elif defined(VGO_darwin)
    Int idx = VG_DARWIN_SYSNO_INDEX(syscallno);
 
@@ -2564,7 +2731,7 @@
 /* These are addresses within ML_(do_syscall_for_client_WRK).  See
    syscall-$PLAT.S for details. 
 */
-#if defined(VGO_linux) || defined(VGO_freebsd)
+#if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd)
   extern const Addr ML_(blksys_setup);
   extern const Addr ML_(blksys_restart);
   extern const Addr ML_(blksys_complete);
@@ -2745,7 +2912,7 @@
       vg_assert(p[0] == 0x01 && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0xD4);
    }
 
-#elif defined(VGP_x86_freebsd)
+#elif defined(VGP_x86_freebsd) || defined(VGP_x86_openbsd)
    /* XXX: we support different syscall methods. */
    arch->vex.guest_EIP -= 2;             // sizeof(int $0x80)
 
@@ -2765,7 +2932,7 @@
       vg_assert(p[0] == 0xcd && p[1] == 0x80);
    }
 
-#elif defined(VGP_amd64_freebsd)
+#elif defined(VGP_amd64_freebsd) || defined(VGP_amd64_openbsd)
    /* XXX: we support different syscall methods. */
    arch->vex.guest_RIP -= 2;             // sizeof(syscall)
 
@@ -3035,7 +3202,7 @@
    th_regs = &tst->arch;
    sci     = & syscallInfo[tid];
 
-#  if defined(VGO_linux) || defined(VGO_freebsd)
+#  if defined(VGO_linux) || defined(VGO_freebsd) || defined(VGO_openbsd)
    outside_range
       = ip < ML_(blksys_setup) || ip >= ML_(blksys_finished);
    in_setup_to_restart
@@ -3057,10 +3224,20 @@
       = (ip >= ML_(blksys_complete) && ip < ML_(blksys_committed)) ||
       ((ip+8) == ML_(blksys_complete));
 #else
+#  if !defined(VGO_openbsd)
    at_restart
       = ip == ML_(blksys_restart); 
    in_complete_to_committed
       = ip >= ML_(blksys_complete) && ip < ML_(blksys_committed); 
+#  else
+// XXX At least on OpenBSD/amd64, if a blocking syscall is interrupted
+// XXX by SIGINT, IP points to right after the `syscall' instruction in
+// XXX `ML_(do_syscall_for_client_WRK)()'.
+   at_restart
+      = ip == ML_(blksys_restart) || ip == ML_(blksys_complete);
+   in_complete_to_committed
+      = ip > ML_(blksys_complete) && ip < ML_(blksys_committed);
+#  endif
 #endif
 
    in_committed_to_finished
