]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
FreeBSD support, patch 12
authorPaul Floyd <pjfloyd@wanadoo.fr>
Sat, 9 Oct 2021 13:01:08 +0000 (15:01 +0200)
committerPaul Floyd <pjfloyd@wanadoo.fr>
Sat, 9 Oct 2021 13:01:08 +0000 (15:01 +0200)
coregrind modified files

57 files changed:
NEWS
coregrind/m_aspacemgr/aspacemgr-common.c
coregrind/m_aspacemgr/aspacemgr-linux.c
coregrind/m_aspacemgr/priv_aspacemgr.h
coregrind/m_coredump/coredump-elf.c
coregrind/m_debuginfo/d3basics.c
coregrind/m_debuginfo/debuginfo.c
coregrind/m_debuginfo/priv_readpdb.h
coregrind/m_debuginfo/readdwarf.c
coregrind/m_debuginfo/readdwarf3.c
coregrind/m_debuginfo/readelf.c
coregrind/m_debuginfo/readpdb.c
coregrind/m_debuginfo/storage.c
coregrind/m_debuglog.c
coregrind/m_gdbserver/gdb/signals.h
coregrind/m_gdbserver/remote-utils.c
coregrind/m_gdbserver/signals.c
coregrind/m_libcassert.c
coregrind/m_libcfile.c
coregrind/m_libcprint.c
coregrind/m_libcproc.c
coregrind/m_libcsetjmp.c
coregrind/m_libcsignal.c
coregrind/m_machine.c
coregrind/m_main.c
coregrind/m_redir.c
coregrind/m_replacemalloc/vg_replace_malloc.c
coregrind/m_scheduler/scheduler.c
coregrind/m_scheduler/sema.c
coregrind/m_sigframe/sigframe-common.c
coregrind/m_signals.c
coregrind/m_stacktrace.c
coregrind/m_syscall.c
coregrind/m_syswrap/priv_types_n_macros.h
coregrind/m_syswrap/syswrap-generic.c
coregrind/m_syswrap/syswrap-main.c
coregrind/m_trampoline.S
coregrind/m_translate.c
coregrind/m_ume/elf.c
coregrind/m_ume/main.c
coregrind/m_ume/priv_ume.h
coregrind/m_vki.c
coregrind/m_vkiscnums.c
coregrind/pub_core_aspacemgr.h
coregrind/pub_core_debuginfo.h
coregrind/pub_core_gdbserver.h
coregrind/pub_core_initimg.h
coregrind/pub_core_libcproc.h
coregrind/pub_core_machine.h
coregrind/pub_core_mallocfree.h
coregrind/pub_core_sigframe.h
coregrind/pub_core_syscall.h
coregrind/pub_core_syswrap.h
coregrind/pub_core_trampoline.h
coregrind/vg_preloaded.c
coregrind/vgdb.c
include/pub_tool_libcproc.h

diff --git a/NEWS b/NEWS
index 68315a77ad31863800a7bc565673aa6ad6c2ab16..e5414c02b49be89e9e82d1e5c6aa5c5bbeef8a69 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,8 +4,9 @@ Release 3.??.? (?? 2021)
 This release supports X86/Linux, AMD64/Linux, ARM32/Linux, ARM64/Linux,
 PPC32/Linux, PPC64BE/Linux, PPC64LE/Linux, S390X/Linux, MIPS32/Linux,
 MIPS64/Linux, ARM/Android, ARM64/Android, MIPS32/Android, X86/Android,
-X86/Solaris, AMD64/Solaris and AMD64/MacOSX 10.12.  There is also preliminary
-support for X86/macOS 10.13, AMD64/macOS 10.13 and nanoMIPS/Linux.
+X86/Solaris, AMD64/Solaris, AMD64/MacOSX 10.12, X86/FreeBSD and
+AMD64/FreeBSD.  There is also preliminary support for X86/macOS 10.13,
+AMD64/macOS 10.13 and nanoMIPS/Linux.
 
 * ==================== CORE CHANGES ===================
 
@@ -25,6 +26,8 @@ support for X86/macOS 10.13, AMD64/macOS 10.13 and nanoMIPS/Linux.
   - ISA 3.0 support for the darn instruction added.
   - ISA 3.0 support for the vector system call instruction scv added.
   - ISA 3.0 support for the copy, paste and cpabort instructions added.
+* Support for X86/FreeBSD and AMD64/FreeBSD has been added.
 
 * ==================== TOOL CHANGES ====================
 
@@ -56,6 +59,19 @@ are not entered into bugzilla tend to get forgotten about or ignored.
 439590  glibc-2.34 breaks suppressions against obj:*/lib*/libc-2.*so*
 440670  unhandled ppc64le-linux syscall: 252 (statfs64) and 253 (fstatfs64)
 432387  s390x: z15 instructions support
+439046  valgrind is unusably large when linked with lld
+433437  FreeBSD support, part 1
+433438  FreeBSD support, part 2
+433439  FreeBSD support, part 3
+433469  FreeBSD support, part 4
+433473  FreeBSD support, part 5
+433477  FreeBSD support, part 6
+433479  FreeBSD support, part 7
+433504  FreeBSD support, part 8
+433506  FreeBSD support, part 9
+433507  FreeBSD support, part 10
+433508  FreeBSD support, part 11
+433510  FreeBSD support, part 12
 440906  Fix impossible constraint issue in P10 testcase.
 441512  Remove a unneeded / unnecessary prefix check.
 441534  Update the expected output for test_isa_3_1_VRT.
index 214b54a35e46f5a1abea3f5c8463cce3daed3aa7..6814410c091e89f86898da334ab9e1c2c33124a6 100644 (file)
@@ -35,6 +35,7 @@
    ************************************************************* */
 
 #include "priv_aspacemgr.h"
+#include "pub_core_libcassert.h"
 #include "config.h"
 
 
@@ -171,6 +172,16 @@ SysRes VG_(am_do_mmap_NO_NOTIFY)( Addr start, SizeT length, UInt prot,
    }
    res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length,
                           prot, flags, (UInt)fd, offset);
+#  elif defined(VGP_x86_freebsd)
+   if (flags & VKI_MAP_ANONYMOUS && fd == 0)
+      fd = -1;
+   res = VG_(do_syscall7)(__NR_mmap, (UWord)start, length,
+                         prot, flags, fd, offset, offset >> 32ul);
+#  elif defined(VGP_amd64_freebsd)
+   if ((flags & VKI_MAP_ANONYMOUS) && fd == 0)
+      fd = -1;
+   res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length,
+                         prot, flags, fd, offset);
 #  elif defined(VGP_x86_solaris)
    /* MAP_ANON with fd==0 is EINVAL. */
    if (fd == 0 && (flags & VKI_MAP_ANONYMOUS))
@@ -255,7 +266,7 @@ SysRes ML_(am_open) ( const HChar* pathname, Int flags, Int mode )
    /* ARM64 wants to use __NR_openat rather than __NR_open. */
    SysRes res = VG_(do_syscall4)(__NR_openat,
                                  VKI_AT_FDCWD, (UWord)pathname, flags, mode);
-#  elif defined(VGO_linux) || defined(VGO_darwin)
+#  elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
    SysRes res = VG_(do_syscall3)(__NR_open, (UWord)pathname, flags, mode);
 #  elif defined(VGO_solaris)
    SysRes res = VG_(do_syscall4)(__NR_openat, VKI_AT_FDCWD, (UWord)pathname,
@@ -283,7 +294,7 @@ Int ML_(am_readlink)(const HChar* path, HChar* buf, UInt bufsiz)
 #  if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
    res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
                                            (UWord)path, (UWord)buf, bufsiz);
-#  elif defined(VGO_linux) || defined(VGO_darwin)
+#  elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
    res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
 #  elif defined(VGO_solaris)
    res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path,
@@ -296,7 +307,7 @@ Int ML_(am_readlink)(const HChar* path, HChar* buf, UInt bufsiz)
 
 Int ML_(am_fcntl) ( Int fd, Int cmd, Addr arg )
 {
-#  if defined(VGO_linux) || defined(VGO_solaris)
+#  if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
 #  if defined(VGP_nanomips_linux)
    SysRes res = VG_(do_syscall3)(__NR_fcntl64, fd, cmd, arg);
 #  else
@@ -330,7 +341,8 @@ Bool ML_(am_get_fd_d_i_m)( Int fd,
       *mode = (UInt)bufx.stx_mode;
       return True;
    }
-#  endif
+#  endif // VGO_linux only
+
 #  if defined(VGO_linux) && defined(__NR_fstat64)
    /* fstat64 is second candidate as it can cope with minor and major device
       numbers outside the 0-255 range and it works properly for x86
@@ -343,7 +355,8 @@ Bool ML_(am_get_fd_d_i_m)( Int fd,
       *mode = (UInt) buf64.st_mode;
       return True;
    }
-#  endif
+#  endif // VGO_linux and defined __NR_fstat64
+
 #  if defined(__NR_fstat)
    struct vki_stat buf;
    res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)&buf);
@@ -353,7 +366,7 @@ Bool ML_(am_get_fd_d_i_m)( Int fd,
       *mode = (UInt) buf.st_mode;
       return True;
    }
-#  endif
+#  endif // defined __NR_fstat
    return False;
 #  elif defined(VGO_solaris)
 #  if defined(VGP_x86_solaris)
@@ -372,11 +385,30 @@ Bool ML_(am_get_fd_d_i_m)( Int fd,
       return True;
    }
    return False;
+#  elif defined(VGO_freebsd)
+   struct vki_freebsd11_stat buf;
+#if (FREEBSD_VERS >= FREEBSD_12)
+   SysRes res = VG_(do_syscall2)(__NR_freebsd11_fstat, fd, (UWord)&buf);
+#else
+   SysRes res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)&buf);
+#endif
+   if (!sr_isError(res)) {
+      *dev  = (ULong)buf.st_dev;
+      *ino  = (ULong)buf.st_ino;
+      *mode = (UInt) buf.st_mode;
+      return True;
+   }
+   return False;
 #  else
 #    error Unknown OS
 #  endif
 }
 
+#if defined(VGO_freebsd)
+#define        M_FILEDESC_BUF  1000000
+static Char filedesc_buf[M_FILEDESC_BUF];
+#endif
+   
 Bool ML_(am_resolve_filename) ( Int fd, /*OUT*/HChar* buf, Int nbuf )
 {
 #if defined(VGO_linux)
@@ -389,6 +421,38 @@ Bool ML_(am_resolve_filename) ( Int fd, /*OUT*/HChar* buf, Int nbuf )
    else
       return False;
 
+#elif defined(VGO_freebsd)
+   Int mib[4];
+   SysRes sres;
+   vki_size_t len;
+   Char *bp, *eb;
+   struct vki_kinfo_file *kf;
+
+   mib[0] = VKI_CTL_KERN;
+   mib[1] = VKI_KERN_PROC;
+   mib[2] = VKI_KERN_PROC_FILEDESC;
+   mib[3] = sr_Res(VG_(do_syscall0)(__NR_getpid));
+   len = sizeof(filedesc_buf);
+   sres = VG_(do_syscall6)(__NR___sysctl, (UWord)mib, 4, (UWord)filedesc_buf,
+      (UWord)&len, 0, 0);
+   if (sr_isError(sres)) {
+       VG_(debugLog)(0, "sysctl(kern.proc.filedesc)", "%s\n", VG_(strerror)(sr_Err(sres)));
+       ML_(am_exit)(1);
+   }
+   /* Walk though the list. */
+   bp = filedesc_buf;
+   eb = filedesc_buf + len;
+   while (bp < eb) {
+      kf = (struct vki_kinfo_file *)bp;
+      if (kf->kf_fd == fd)
+         break;
+      bp += kf->kf_structsize;
+   }
+   if (bp >= eb || *kf->kf_path == '\0')
+     VG_(strncpy)( buf, "[unknown]", nbuf );
+   else
+     VG_(strncpy)( buf, kf->kf_path, nbuf );
+   return True;
 #elif defined(VGO_darwin)
    HChar tmp[VKI_MAXPATHLEN+1];
    if (0 == ML_(am_fcntl)(fd, VKI_F_GETPATH, (UWord)tmp)) {
index 0eb314316169f79651b92c55e3bca2c3e6460849..9a69f3850f1a7d9fb37e95034f7ac4c686003a62 100644 (file)
@@ -4,7 +4,7 @@
 /*--- The address space manager: segment initialisation and        ---*/
 /*--- tracking, stack operations                                   ---*/
 /*---                                                              ---*/
-/*--- Implementation for Linux (and Darwin!)     aspacemgr-linux.c ---*/
+/*--- Implementation for Linux, Darwin, Solaris and FreeBSD        ---*/
 /*--------------------------------------------------------------------*/
 
 /*
@@ -30,7 +30,7 @@
    The GNU General Public License is contained in the file COPYING.
 */
 
-#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
+#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 /* *************************************************************
    DO NOT INCLUDE ANY OTHER FILES HERE.
@@ -314,6 +314,8 @@ Addr VG_(clo_aspacem_minAddr)
 # endif
 #elif defined(VGO_solaris)
    = (Addr) 0x00100000; // 1MB
+#elif defined(VGO_freebsd)
+   = (Addr) 0x04000000; // 64M
 #else
 #endif
 
@@ -367,7 +369,12 @@ static void parse_procselfmaps (
 #  define ARM_LINUX_FAKE_COMMPAGE_END1  0xFFFF1000
 #endif
 
-
+#if !defined(VKI_MAP_STACK)
+/* this is only defined for FreeBSD
+ * for readability, define it to 0
+ * for other platforms */
+#define VKI_MAP_STACK 0
+#endif
 
 /*-----------------------------------------------------------------*/
 /*---                                                           ---*/
@@ -871,7 +878,7 @@ static void sync_check_mapping_callback ( Addr addr, SizeT len, UInt prot,
          cmp_devino = False;
 #endif
 
-#if defined(VGO_darwin)
+#if defined(VGO_darwin) || defined(VGO_freebsd)
       // GrP fixme kernel info doesn't have dev/inode
       cmp_devino = False;
       
@@ -1491,7 +1498,13 @@ static void init_nsegment ( /*OUT*/NSegment* seg )
    seg->mode     = 0;
    seg->offset   = 0;
    seg->fnIdx    = -1;
-   seg->hasR = seg->hasW = seg->hasX = seg->hasT = seg->isCH = False;
+
+   seg->hasR     = seg->hasW = seg->hasX = seg->hasT
+                 = seg->isCH = False;
+#if defined(VGO_freebsd)
+   seg->isFF     = False;
+#endif
+
 }
 
 /* Make an NSegment which holds a reservation. */
@@ -1637,6 +1650,81 @@ Addr VG_(am_startup) ( Addr sp_at_startup )
 
    suggested_clstack_end = -1; // ignored; Mach-O specifies its stack
 
+   // --- Freebsd ------------------------------------------
+#elif defined(VGO_freebsd)
+
+
+   VG_(debugLog)(2, "aspacem",
+                    "        sp_at_startup = 0x%010lx (supplied)\n",
+                    sp_at_startup );
+
+# if VG_WORDSIZE == 4
+
+   aspacem_maxAddr = VG_PGROUNDDN( sp_at_startup ) - 1;
+# else
+   aspacem_maxAddr = (Addr) (Addr)0x800000000UL - 1; // 32G
+#  ifdef ENABLE_INNER
+   { Addr cse = VG_PGROUNDDN( sp_at_startup ) - 1;
+     if (aspacem_maxAddr > cse)
+        aspacem_maxAddr = cse;
+   }
+#    endif // ENABLE_INNER
+# endif
+
+   aspacem_cStart = aspacem_minAddr;
+   aspacem_vStart = VG_PGROUNDUP((aspacem_minAddr + aspacem_maxAddr + 1) / 2);
+
+#  ifdef ENABLE_INNER
+   aspacem_vStart -= 0x10000000UL; // 512M
+#  endif // ENABLE_INNER
+
+   // starting with FreeBSD 10.4, the stack is created with a zone
+   // that is marked MAP_GUARD. This zone is reserved but unmapped,
+   // and fills the space up to the end of the segment
+   // see man mmap
+
+   // Version number from
+   // https://www.freebsd.org/doc/en_US.ISO8859-1/books/porters-handbook/versions-10.html
+
+   // On x86 this is 0x3FE0000
+   // And on amd64 it is 0x1FFE0000 (536739840)
+   // There is less of an issue on amd64 as we just choose some arbitrary address rather then trying
+   // to squeeze in just below the host stack
+
+   // Some of this is in sys/vm/vm_map.c, for instance vm_map_stack and vm_map_stack_locked
+   // These refer to the kernel global sgrowsiz, which seems to be the initial size
+   // of the user stack, 128k on my system
+   //
+   // This seems to be in the sysctl kern.sgrowsiz
+   // Then there is kern.maxssiz which is the total stack size (grow size + guard area)
+   // In other words guard area = maxssiz - sgrowsiz
+
+#if (__FreeBSD_version >= 1003516)
+
+#if 0
+   // this block implements what is described above
+   // this makes no changes to the regression tests
+   // I'm keeping it for a rainy day.
+   // note this needs
+   // #include "pub_core_libcproc.h"
+   SizeT kern_maxssiz;
+   SizeT kern_sgrowsiz;
+   SizeT sysctl_size = sizeof(SizeT);
+   VG_(sysctlbyname)("kern.maxssiz", &kern_maxssiz, &sysctl_size, NULL, 0);
+   VG_(sysctlbyname)("kern.sgrowsiz", &kern_sgrowsiz, &sysctl_size, NULL, 0);
+
+   suggested_clstack_end = aspacem_maxAddr - (kern_maxssiz - kern_sgrowsiz) + VKI_PAGE_SIZE;
+#endif
+
+   suggested_clstack_end = aspacem_maxAddr - 64*1024*1024UL
+                                           + VKI_PAGE_SIZE;
+
+#else
+   suggested_clstack_end = aspacem_maxAddr - 16*1024*1024UL
+                                           + VKI_PAGE_SIZE;
+
+#endif
+
    // --- Solaris ------------------------------------------
 #elif defined(VGO_solaris)
 #  if VG_WORDSIZE == 4
@@ -1759,7 +1847,7 @@ Addr VG_(am_startup) ( Addr sp_at_startup )
    suggested_clstack_end = aspacem_maxAddr - 16*1024*1024ULL
                                            + VKI_PAGE_SIZE;
 
-#endif
+#endif /* #else of 'defined(VGO_solaris)' */
    // --- (end) --------------------------------------------
 
    aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_minAddr));
@@ -2165,13 +2253,13 @@ VG_(am_notify_client_mmap)( Addr a, SizeT len, UInt prot, UInt flags,
    needDiscard = any_Ts_in_range( a, len );
 
    init_nsegment( &seg );
-   seg.kind   = (flags & VKI_MAP_ANONYMOUS) ? SkAnonC : SkFileC;
+   seg.kind   = (flags & (VKI_MAP_ANONYMOUS | VKI_MAP_STACK)) ? SkAnonC : SkFileC;
    seg.start  = a;
    seg.end    = a + len - 1;
    seg.hasR   = toBool(prot & VKI_PROT_READ);
    seg.hasW   = toBool(prot & VKI_PROT_WRITE);
    seg.hasX   = toBool(prot & VKI_PROT_EXEC);
-   if (!(flags & VKI_MAP_ANONYMOUS)) {
+   if (!(flags & (VKI_MAP_ANONYMOUS | VKI_MAP_STACK))) {
       // Nb: We ignore offset requests in anonymous mmaps (see bug #126722)
       seg.offset = offset;
       if (ML_(am_get_fd_d_i_m)(fd, &dev, &ino, &mode)) {
@@ -2182,6 +2270,9 @@ VG_(am_notify_client_mmap)( Addr a, SizeT len, UInt prot, UInt flags,
       if (ML_(am_resolve_filename)(fd, buf, VKI_PATH_MAX)) {
          seg.fnIdx = ML_(am_allocate_segname)( buf );
       }
+#if defined(VGO_freebsd)
+      seg.isFF = (flags & VKI_MAP_FIXED);
+#endif
    }
    add_segment( &seg );
    AM_SANITY_CHECK;
@@ -2423,6 +2514,9 @@ SysRes VG_(am_mmap_named_file_fixed_client_flags)
    } else if (ML_(am_resolve_filename)(fd, buf, VKI_PATH_MAX)) {
       seg.fnIdx = ML_(am_allocate_segname)( buf );
    }
+#if defined(VGO_freebsd)
+   seg.isFF = (flags & VKI_MAP_FIXED);
+#endif
    add_segment( &seg );
 
    AM_SANITY_CHECK;
@@ -2733,6 +2827,9 @@ static SysRes VG_(am_mmap_file_float_valgrind_flags) ( SizeT length, UInt prot,
    if (ML_(am_resolve_filename)(fd, buf, VKI_PATH_MAX)) {
       seg.fnIdx = ML_(am_allocate_segname)( buf );
    }
+#if defined(VGO_freebsd)
+   seg.isFF = (flags & VKI_MAP_FIXED);
+#endif
    add_segment( &seg );
 
    AM_SANITY_CHECK;
@@ -3796,13 +3893,89 @@ Bool VG_(get_changed_segments)(
    return !css_overflowed;
 }
 
-#endif // defined(VGO_darwin)
 
 /*------END-procmaps-parser-for-Darwin---------------------------*/
 
+/*------BEGIN-procmaps-parser-for-Freebsd------------------------*/
+#elif defined(VGO_freebsd)
+
+/* Size of a smallish table used to read /proc/self/map entries. */
+#define M_PROCMAP_BUF 10485760 /* 10M */
+
+/* static ... to keep it out of the stack frame. */
+static char procmap_buf[M_PROCMAP_BUF];
+
+static void parse_procselfmaps (
+      void (*record_mapping)( Addr addr, SizeT len, UInt prot,
+                              ULong dev, ULong ino, Off64T offset,
+                              const HChar* filename ),
+      void (*record_gap)( Addr addr, SizeT len )
+   )
+{
+    Addr   start, endPlusOne, gapStart;
+    char* filename;
+    char   *p;
+    UInt          prot;
+    ULong  foffset, dev, ino;
+    struct vki_kinfo_vmentry *kve;
+    vki_size_t len;
+    Int    oid[4];
+    SysRes sres;
+
+    foffset = ino = 0; /* keep gcc-4.1.0 happy */
+
+    oid[0] = VKI_CTL_KERN;
+    oid[1] = VKI_KERN_PROC;
+    oid[2] = VKI_KERN_PROC_VMMAP;
+    oid[3] = sr_Res(VG_(do_syscall0)(__NR_getpid));
+    len = sizeof(procmap_buf);
+
+    sres = VG_(do_syscall6)(__NR___sysctl, (UWord)oid, 4, (UWord)procmap_buf,
+       (UWord)&len, 0, 0);
+    if (sr_isError(sres)) {
+       VG_(debugLog)(0, "procselfmaps", "sysctl %lu\n", sr_Err(sres));
+       ML_(am_exit)(1);
+    }
+    gapStart = Addr_MIN;
+    p = procmap_buf;
+    while (p < (char *)procmap_buf + len) {
+       kve = (struct vki_kinfo_vmentry *)p;
+       start      = (UWord)kve->kve_start;
+       endPlusOne = (UWord)kve->kve_end;
+       foffset    = kve->kve_offset;
+       filename   = kve->kve_path;
+       dev        = kve->kve_fsid;
+       ino        = kve->kve_fileid;
+       if (filename[0] != '/') {
+         filename = NULL;
+         foffset = 0;
+       }
+       prot = 0;
+       if (kve->kve_protection & VKI_KVME_PROT_READ)  prot |= VKI_PROT_READ;
+       if (kve->kve_protection & VKI_KVME_PROT_WRITE) prot |= VKI_PROT_WRITE;
+       if (kve->kve_protection & VKI_KVME_PROT_EXEC)  prot |= VKI_PROT_EXEC;
+       if (record_gap && gapStart < start)
+          (*record_gap) ( gapStart, start-gapStart );
+       if (record_mapping && start < endPlusOne)
+          (*record_mapping) ( start, endPlusOne-start,
+                              prot, dev, ino,
+                              foffset, filename );
+       gapStart = endPlusOne;
+       p += kve->kve_structsize;
+    }
+    if (record_gap && gapStart < Addr_MAX)
+       (*record_gap) ( gapStart, Addr_MAX - gapStart + 1 );
+}
+
+/*------END-procmaps-parser-for-Freebsd--------------------------*/
+
 /*------BEGIN-procmaps-parser-for-Solaris------------------------*/
 
-#if defined(VGO_solaris)
+#elif defined(VGO_solaris)
 
 /* Note: /proc/self/xmap contains extended information about already
    materialized mappings whereas /proc/self/rmap contains information about
@@ -4112,7 +4285,7 @@ Bool VG_(am_search_for_new_segment)(Addr *addr, SizeT *size, UInt *prot)
 
 /*------END-procmaps-parser-for-Solaris--------------------------*/
 
-#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
+#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
index fbc46aca7b9dfafd3856e8bd949f8633af5f97c4..161c5c295441b40b2a0825b7d35f9afb7d61d01e 100644 (file)
@@ -77,7 +77,7 @@ extern void   ML_(am_assert_fail) ( const HChar* expr,
                                     const HChar* fn );
 
 #define aspacem_assert(expr)                              \
-  ((void) (LIKELY(expr) ? 0 :                             \
+  ((void) (LIKELY(expr) ? (void)0 :                             \
            (ML_(am_assert_fail)(#expr,                    \
                                 __FILE__, __LINE__,       \
                                 __PRETTY_FUNCTION__))))
index daf85e6479d3ece98dbd5317171567ecba35ef6a..d0e8a03c947f4d675d6121161edd066a9b2eca12 100644 (file)
@@ -26,7 +26,7 @@
    The GNU General Public License is contained in the file COPYING.
 */
 
-#if defined(VGO_linux)
+#if defined(VGO_linux) || defined(VGO_freebsd)
 
 #include "pub_core_basics.h"
 #include "pub_core_vki.h"
@@ -90,6 +90,9 @@ static void fill_ehdr(ESZ(Ehdr) *ehdr, Int num_phdrs)
    ehdr->e_ident[EI_CLASS]   = VG_ELF_CLASS;
    ehdr->e_ident[EI_DATA]    = VG_ELF_DATA2XXX;
    ehdr->e_ident[EI_VERSION] = EV_CURRENT;
+#if defined(VGO_freebsd)
+   ehdr->e_ident[EI_OSABI]   = ELFOSABI_FREEBSD;
+#endif
 
    ehdr->e_type = ET_CORE;
    ehdr->e_machine = VG_ELF_MACHINE;
@@ -193,6 +196,19 @@ static void write_note(Int fd, const struct note *n)
    VG_(write)(fd, &n->note, note_size(n));
 }
 
+#if defined(VGO_freebsd)
+static void fill_prpsinfo(const ThreadState *tst,
+                          struct vki_elf_prpsinfo *prpsinfo)
+{
+   VG_(memset)(prpsinfo, 0, sizeof(*prpsinfo));
+
+   prpsinfo->pr_version = VKI_PRPSINFO_VERSION;
+   prpsinfo->pr_psinfosz = sizeof(struct vki_elf_prpsinfo);
+   VG_(client_fname)(prpsinfo->pr_fname, sizeof(prpsinfo->pr_fname), False);
+   // why?
+   VG_(strncpy)(prpsinfo->pr_psargs, prpsinfo->pr_fname, sizeof(prpsinfo->pr_psargs) - 1);
+}
+#else
 static void fill_prpsinfo(const ThreadState *tst,
                           struct vki_elf_prpsinfo *prpsinfo)
 {
@@ -223,6 +239,7 @@ static void fill_prpsinfo(const ThreadState *tst,
    
    VG_(client_fname)(prpsinfo->pr_fname, sizeof(prpsinfo->pr_fname), False);
 }
+#endif
 
 static void fill_prstatus(const ThreadState *tst, 
                          /*OUT*/struct vki_elf_prstatus *prs, 
@@ -238,6 +255,16 @@ static void fill_prstatus(const ThreadState *tst,
 
    VG_(memset)(prs, 0, sizeof(*prs));
 
+#if defined(VGO_freebsd)
+   prs->pr_version = VKI_PRSTATUS_VERSION;
+   prs->pr_statussz = sizeof(struct vki_elf_prstatus);
+   prs->pr_gregsetsz = sizeof(vki_elf_gregset_t);
+   prs->pr_fpregsetsz = sizeof(vki_elf_fpregset_t);
+   prs->pr_osreldate = VG_(getosreldate)();
+
+   prs->pr_cursig = si->si_signo;
+   prs->pr_pid = tst->os_state.lwpid;
+#else
    prs->pr_info.si_signo = si->si_signo;
    prs->pr_info.si_code = si->si_code;
    prs->pr_info.si_errno = 0;
@@ -248,6 +275,7 @@ static void fill_prstatus(const ThreadState *tst,
    prs->pr_ppid = 0;
    prs->pr_pgrp = VG_(getpgrp)();
    prs->pr_sid = VG_(getpgrp)();
+#endif
    
 #if defined(VGP_s390x_linux)
    /* prs->pr_reg has struct type. Need to take address. */
@@ -461,6 +489,45 @@ static void fill_prstatus(const ThreadState *tst,
    regs[VKI_MIPS32_EF_CP0_STATUS] = arch->vex.guest_CP0_status;
    regs[VKI_MIPS32_EF_CP0_EPC]    = arch->vex.guest_PC;
 #  undef DO
+#elif defined(VGP_amd64_freebsd)
+   regs->rflags = LibVEX_GuestAMD64_get_rflags( &((ThreadArchState*)arch)->vex );
+   regs->rsp    = arch->vex.guest_RSP;
+   regs->rip    = arch->vex.guest_RIP;
+   regs->rbx    = arch->vex.guest_RBX;
+   regs->rcx    = arch->vex.guest_RCX;
+   regs->rdx    = arch->vex.guest_RDX;
+   regs->rsi    = arch->vex.guest_RSI;
+   regs->rdi    = arch->vex.guest_RDI;
+   regs->rbp    = arch->vex.guest_RBP;
+   regs->rax    = arch->vex.guest_RAX;
+   regs->r8     = arch->vex.guest_R8;
+   regs->r9     = arch->vex.guest_R9;
+   regs->r10    = arch->vex.guest_R10;
+   regs->r11    = arch->vex.guest_R11;
+   regs->r12    = arch->vex.guest_R12;
+   regs->r13    = arch->vex.guest_R13;
+   regs->r14    = arch->vex.guest_R14;
+   regs->r15    = arch->vex.guest_R15;
+#elif defined(VGP_x86_freebsd)
+   regs->eflags = LibVEX_GuestX86_get_eflags( &arch->vex );
+   regs->esp    = arch->vex.guest_ESP;
+   regs->eip    = arch->vex.guest_EIP;
+
+   regs->ebx    = arch->vex.guest_EBX;
+   regs->ecx    = arch->vex.guest_ECX;
+   regs->edx    = arch->vex.guest_EDX;
+   regs->esi    = arch->vex.guest_ESI;
+   regs->edi    = arch->vex.guest_EDI;
+   regs->ebp    = arch->vex.guest_EBP;
+   regs->eax    = arch->vex.guest_EAX;
+
+   regs->cs     = arch->vex.guest_CS;
+   regs->ds     = arch->vex.guest_DS;
+   regs->ss     = arch->vex.guest_SS;
+   regs->es     = arch->vex.guest_ES;
+   regs->fs     = arch->vex.guest_FS;
+   regs->gs     = arch->vex.guest_GS;
+
 #else
 #  error Unknown ELF platform
 #endif
@@ -587,6 +654,16 @@ static void fill_fpu(const ThreadState *tst, vki_elf_fpregset_t *fpu)
 #  undef DO
 #elif defined(VGP_nanomips_linux)
 
+#elif defined(VGP_x86_freebsd)
+
+#elif defined(VGP_amd64_freebsd)
+
+#  define DO(n)  VG_(memcpy)(fpu->xmm_space + n * 4, \
+                             &arch->vex.guest_YMM##n[0], 16)
+   DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
+   DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
+#  undef DO
+
 #else
 #  error Unknown ELF platform
 #endif
index 1bc5f8f0520bb4689fb859babc1564866d861ffe..555e1e00d0d768cebfb14dc50f214d9b66f49106 100644 (file)
@@ -498,11 +498,11 @@ static Bool get_Dwarf_Reg( /*OUT*/Addr* a, Word regno, const RegSummary* regs )
 {
    vg_assert(regs);
 #  if defined(VGP_x86_linux) || defined(VGP_x86_darwin) \
-      || defined(VGP_x86_solaris)
+      || defined(VGP_x86_solaris) || defined(VGP_x86_freebsd)
    if (regno == 5/*EBP*/) { *a = regs->fp; return True; }
    if (regno == 4/*ESP*/) { *a = regs->sp; return True; }
 #  elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) \
-        || defined(VGP_amd64_solaris)
+        || defined(VGP_amd64_solaris) || defined(VGP_amd64_freebsd)
    if (regno == 6/*RBP*/) { *a = regs->fp; return True; }
    if (regno == 7/*RSP*/) { *a = regs->sp; return True; }
 #  elif defined(VGP_ppc32_linux)
index e2218f266823b2ca70c2aee13d4da979b9b7783a..2e5b9b0192cd8a1c51163264306e71e5974b418d 100644 (file)
@@ -57,7 +57,7 @@
 #include "priv_tytypes.h"
 #include "priv_storage.h"
 #include "priv_readdwarf.h"
-#if defined(VGO_linux) || defined(VGO_solaris)
+#if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
 # include "priv_readelf.h"
 # include "priv_readdwarf3.h"
 # include "priv_readpdb.h"
@@ -814,7 +814,7 @@ void VG_(di_initialise) ( void )
 /*---                                                        ---*/
 /*--------------------------------------------------------------*/
 
-#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
+#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 /* Helper (indirect) for di_notify_ACHIEVE_ACCEPT_STATE */
 static Bool overlaps_DebugInfoMappings ( const DebugInfoMapping* map1,
@@ -965,7 +965,7 @@ static ULong di_notify_ACHIEVE_ACCEPT_STATE ( struct _DebugInfo* di )
    truncate_DebugInfoMapping_overlaps( di, di->fsm.maps );
 
    /* And acquire new info. */
-#  if defined(VGO_linux) || defined(VGO_solaris)
+#  if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
    ok = ML_(read_elf_debug_info)( di );
 #  elif defined(VGO_darwin)
    ok = ML_(read_macho_debug_info)( di );
@@ -1204,6 +1204,13 @@ ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd )
    if (!(is_rx_map || is_rw_map || is_ro_map))
       return 0;
 
+#if defined(VGO_freebsd)
+   /* Ignore non-fixed read-only mappings.  The dynamic linker may be
+    * mapping something for its own transient purposes. */
+   if (!seg->isFF && is_ro_map)
+      return 0;
+#endif
+
    /* Peer at the first few bytes of the file, to see if it is an ELF */
    /* object file. Ignore the file if we do not have read permission. */
    VG_(memset)(buf1k, 0, sizeof(buf1k));
@@ -1247,7 +1254,7 @@ ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd )
    vg_assert(sr_Res(preadres) > 0 && sr_Res(preadres) <= sizeof(buf1k) );
 
    /* We're only interested in mappings of object files. */
-#  if defined(VGO_linux) || defined(VGO_solaris)
+#  if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
    if (!ML_(is_elf_object_file)( buf1k, (SizeT)sr_Res(preadres), False ))
       return 0;
 #  elif defined(VGO_darwin)
@@ -1696,7 +1703,7 @@ void VG_(di_notify_pdb_debuginfo)( Int fd_obj, Addr avma_obj,
    if (pdbname) ML_(dinfo_free)(pdbname);
 }
 
-#endif /* defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) */
+#endif /* defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd) */
 
 
 /*------------------------------------------------------------*/
@@ -2290,6 +2297,8 @@ Vg_FnNameKind VG_(get_fnname_kind) ( const HChar* name )
        VG_STREQ("generic_start_main", name) ||  // Yellow Dog doggedness
        VG_STREQN(19, "generic_start_main.", name) || // gcc optimization
        VG_STREQ("_start", name) ||
+#      elif defined(VGO_freebsd)
+       VG_STREQ("_start", name) || // FreeBSD libc
 #      elif defined(VGO_darwin)
        // See readmacho.c for an explanation of this.
        VG_STREQ("start_according_to_valgrind", name) ||  // Darwin, darling
index b8f5958103458664e97fef3f8adccc7259b4bb99..b9b8fb3a2c1e30ad02a4506dff1c80af265d077d 100644 (file)
@@ -30,7 +30,7 @@
    The GNU General Public License is contained in the file COPYING.
 */
 
-#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
+#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 #ifndef __PRIV_READPDB_H
 #define __PRIV_READPDB_H
@@ -57,7 +57,7 @@ HChar* ML_(find_name_of_pdb_file)( const HChar* pename );
 
 #endif /* ndef __PRIV_READPDB_H */
 
-#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
+#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
index bcacca4cb930283b04964a60ecb8109cfc4dfe62..39a2946870042057d863b688d292e20c97c4d2ef 100644 (file)
@@ -27,7 +27,7 @@
    The GNU General Public License is contained in the file COPYING.
 */
 
-#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
+#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 #include "pub_core_basics.h"
 #include "pub_core_debuginfo.h"
@@ -1961,11 +1961,11 @@ void ML_(read_debuginfo_dwarf1) (
 
 /* --------------- Decls --------------- */
 
-#if defined(VGP_x86_linux) || defined(VGP_x86_solaris)
+#if defined(VGP_x86_linux) || defined(VGP_x86_solaris) || defined(VGP_x86_freebsd)
 #  define FP_REG         5
 #  define SP_REG         4
 #  define RA_REG_DEFAULT 8
-#elif defined(VGP_amd64_linux) || defined(VGP_amd64_solaris)
+#elif defined(VGP_amd64_linux) || defined(VGP_amd64_solaris) || defined(VGP_amd64_freebsd)
 #  define FP_REG         6
 #  define SP_REG         7
 #  define RA_REG_DEFAULT 16
@@ -4522,7 +4522,7 @@ void ML_(read_callframe_info_dwarf3)
     return;
 }
 
-#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
+#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
index 4ac23a3c4d38a9139442ef9c8a8448d196332b90..18eecea9f311f6918fe1c43208295d2c023dde40 100644 (file)
@@ -33,7 +33,7 @@
    without prior written permission.
 */
 
-#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
+#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 /* REFERENCE (without which this code will not make much sense):
 
@@ -5879,7 +5879,7 @@ ML_(new_dwarf3_reader) (
    TRACE_SYMTAB("\n");
 #endif
 
-#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
+#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
index e424e3e7e8bb10ac33f2154636249c9a222bafc7..c586e3f3329db53c63aa97274d43b606a3ddb23b 100644 (file)
@@ -27,7 +27,7 @@
    The GNU General Public License is contained in the file COPYING.
 */
 
-#if defined(VGO_linux) || defined(VGO_solaris)
+#if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 #include "pub_core_basics.h"
 #include "pub_core_vki.h"
@@ -45,6 +45,7 @@
 #include "pub_core_syscall.h"
 #include "pub_core_tooliface.h"    /* VG_(needs) */
 #include "pub_core_xarray.h"
+#include "pub_core_libcproc.h"
 #include "priv_misc.h"             /* dinfo_zalloc/free/strdup */
 #include "priv_image.h"
 #include "priv_d3basics.h"
@@ -1118,6 +1119,80 @@ void read_elf_symtab__ppc64be_linux(
    VG_(OSetGen_Destroy)( oset );
 }
 
+#if defined(VGO_freebsd)
+
+/**
+ * read_and_set_osrel
+ *
+ * "osrel" is in an Elf note. It has values such as 1201000 for FreeBSD 12.1
+ * Some of the behaviour related to SIGSEGV and SIGBUS signals depends on the
+ * kernel reading this value.
+ *
+ * However in the case of Valgrind, the host is strictly statically linked and
+ * does not contain the NT_FREEBSD_ABI_TAG note. And even if it did, we want to
+ * override the value with that of the guest.
+ *
+ * At some later date we might want to look at the value of "fctl0" (note with the
+ * NT_FREEBSD_FEATURE_CTL type). This seems to be related to Address Space Layout
+ * Randomization. No hurry at the moment.
+ *
+ * See /usr/src/sys/kern/imgact_elf.c for details on how the kernel reads these
+ * notes.
+ */
+static
+void read_and_set_osrel(DiImage* img)
+{
+    if (is_elf_object_file_by_DiImage(img, False)) {
+       Word i;
+
+       ElfXX_Ehdr ehdr;
+       ML_(img_get)(&ehdr, img, 0, sizeof(ehdr));
+       /* Skip the phdrs when we have to search the shdrs. In separate
+          .debug files the phdrs might not be valid (they are a copy of
+          the main ELF file) and might trigger assertions when getting
+          image notes based on them. */
+       for (i = 0; i < ehdr.e_phnum; i++) {
+          ElfXX_Phdr phdr;
+          ML_(img_get)(&phdr, img,
+                       ehdr.e_phoff + i * ehdr.e_phentsize, sizeof(phdr));
+
+          if (phdr.p_type == PT_NOTE) {
+             ElfXX_Off note_ioff = phdr.p_offset;
+
+             while (note_ioff < phdr.p_offset + phdr.p_filesz) {
+                ElfXX_Nhdr note[2];
+                ML_(img_get)(note, img, (DiOffT)note_ioff, sizeof(note));
+                DiOffT name_ioff = note_ioff + sizeof(ElfXX_Nhdr);
+                //DiOffT desc_ioff = name_ioff + ((note[0].n_namesz + 3) & ~3);
+                if (ML_(img_strcmp_c)(img, name_ioff, "FreeBSD") == 0
+                    && note[0].n_type == NT_FREEBSD_ABI_TAG) {
+
+                    u_int32_t osrel = note[1].n_type;
+                    int name[4];
+                    name[0] = CTL_KERN;
+                    name[1] = KERN_PROC;
+                    name[2] = KERN_PROC_OSREL;
+                    name[3] = VG_(getpid)();
+                    SizeT newlen = sizeof(osrel);
+                    Int error = VG_(sysctl)(name, 4, NULL, NULL, &osrel, newlen);
+                    if (error == -1) {
+                        VG_(message)(Vg_DebugMsg, "Warning: failed to set osrel for current process with value %d\n", osrel);
+                    } else {
+                        if (VG_(clo_verbosity) > 1) {
+                            VG_(message)(Vg_DebugMsg, "Set osrel for current process with value %d\n", osrel);
+                        }
+                    }
+                }
+                note_ioff = note_ioff + sizeof(ElfXX_Nhdr)
+                                      + ((note[0].n_namesz + 3) & ~3)
+                                      + ((note[0].n_descsz + 3) & ~3);
+             }
+          }
+       }
+    }
+
+}
+#endif
 
 /*
  * Look for a build-id in an ELF image. The build-id specification
@@ -1701,7 +1776,7 @@ static HChar* readlink_path (const HChar *path)
 #if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
       res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
                                               (UWord)path, (UWord)buf, bufsiz);
-#elif defined(VGO_linux) || defined(VGO_darwin)
+#elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
       res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
 #elif defined(VGO_solaris)
       res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path,
@@ -1939,14 +2014,14 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
    for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
       const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
       if (map->rx)
-         TRACE_SYMTAB("rx_map:  avma %#lx   size %lu  foff %ld\n",
-                      map->avma, map->size, map->foff);
+         TRACE_SYMTAB("rx_map:  avma %#lx   size %lu  foff %lld\n",
+                      map->avma, map->size, (Long)map->foff);
    }
    for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
       const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
       if (map->rw)
-         TRACE_SYMTAB("rw_map:  avma %#lx   size %lu  foff %ld\n",
-                      map->avma, map->size, map->foff);
+         TRACE_SYMTAB("rw_map:  avma %#lx   size %lu  foff %lld\n",
+                      map->avma, map->size, (Long)map->foff);
    }
 
    if (phdr_mnent == 0
@@ -2039,6 +2114,11 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
                      item.svma_limit = a_phdr.p_vaddr + a_phdr.p_memsz;
                      item.bias       = map->avma - map->foff
                                        + a_phdr.p_offset - a_phdr.p_vaddr;
+#if (FREEBSD_VERS >= FREEBSD_12_2)
+                     if ((long long int)item.bias < 0LL) {
+                        item.bias = 0;
+                     }
+#endif
                      if (map->rw
                          && (a_phdr.p_flags & (PF_R | PF_W))
                             == (PF_R | PF_W)) {
@@ -2166,8 +2246,8 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
    for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
       const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
       if (map->rx)
-         TRACE_SYMTAB("rx: at %#lx are mapped foffsets %ld .. %lu\n",
-                      map->avma, map->foff, map->foff + map->size - 1 );
+         TRACE_SYMTAB("rx: at %#lx are mapped foffsets %lld .. %lld\n",
+                      map->avma, (Long)map->foff, (Long)(map->foff + map->size - 1) );
    }
    TRACE_SYMTAB("rx: contains these svma regions:\n");
    for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) {
@@ -2179,8 +2259,8 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
    for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
       const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
       if (map->rw)
-         TRACE_SYMTAB("rw: at %#lx are mapped foffsets %ld .. %lu\n",
-                      map->avma, map->foff, map->foff + map->size - 1 );
+         TRACE_SYMTAB("rw: at %#lx are mapped foffsets %lld .. %lld\n",
+                      map->avma, (Long)map->foff, (Long)(map->foff + map->size - 1) );
    }
    TRACE_SYMTAB("rw: contains these svma regions:\n");
    for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) {
@@ -2222,10 +2302,11 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
          }
       }
 
-      TRACE_SYMTAB(" [sec %2ld]  %s %s  al%4u  foff %6ld .. %6lu  "
+      TRACE_SYMTAB(" [sec %2ld]  %s %s  al%4u  foff %6lld .. %6lld  "
                    "  svma %p  name \"%s\"\n", 
                    i, inrx ? "rx" : "  ", inrw ? "rw" : "  ", alyn,
-                   foff, (size == 0) ? foff : foff+size-1, (void *) svma, name);
+                   (Long) foff, (size == 0) ? (Long)foff : (Long)(foff+size-1),
+                   (void *) svma, name);
 
       /* Check for sane-sized segments.  SHT_NOBITS sections have zero
          size in the file and their offsets are just conceptual. */
@@ -2540,7 +2621,8 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
          || defined(VGP_arm_linux) || defined (VGP_s390x_linux) \
          || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
          || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-         || defined(VGP_x86_solaris) || defined(VGP_amd64_solaris)
+         || defined(VGP_x86_solaris) || defined(VGP_amd64_solaris) \
+         || defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd)
       /* Accept .plt where mapped as rx (code) */
       if (0 == VG_(strcmp)(name, ".plt")) {
          if (inrx && !di->plt_present) {
@@ -2876,6 +2958,12 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
          |dimg| to it. */
       vg_assert(dimg == NULL && aimg == NULL);
 
+#if defined(VGO_freebsd)
+      /*  */
+      read_and_set_osrel(mimg);
+
+#endif
+
       /* Look for a build-id */
       HChar* buildid = find_buildid(mimg, False, False);
 
@@ -3512,7 +3600,7 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
    /* NOTREACHED */
 }
 
-#endif // defined(VGO_linux) || defined(VGO_solaris)
+#endif // defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
index f9128e30cfc510a5df4dafa5f24cb9bbff5cbdc9..a53cf48c445558cbf12906bdb56c7153950d9de1 100644 (file)
@@ -33,7 +33,7 @@
    The GNU General Public License is contained in the file COPYING.
 */
 
-#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
+#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 #include "pub_core_basics.h"
 #include "pub_core_debuginfo.h"
@@ -2604,7 +2604,7 @@ HChar* ML_(find_name_of_pdb_file)( const HChar* pename )
    return res;
 }
 
-#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
+#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
index 48a92b4029f48bd33194a0dfa4c6e2df8f181e5d..9ba74076c11ef1a2c63668f2324c4424ae6e66a2 100644 (file)
@@ -365,6 +365,11 @@ void ML_(addSym) ( struct _DebugInfo* di, DiSym* sym )
    vg_assert(sym->pri_name != NULL);
    vg_assert(sym->sec_names == NULL);
 
+#if defined(VGO_freebsd)
+   if (sym->size == 0)
+      sym->size = 1;
+#endif
+
    /* Ignore zero-sized syms. */
    if (sym->size == 0) return;
 
@@ -1534,7 +1539,7 @@ Bool preferName ( const DebugInfo* di,
    vlena = VG_(strlen)(a_name);
    vlenb = VG_(strlen)(b_name);
 
-#  if defined(VGO_linux) || defined(VGO_solaris)
+#  if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
 #    define VERSION_CHAR '@'
 #  elif defined(VGO_darwin)
 #    define VERSION_CHAR '$'
index ce4714d1bfbfd9042bddc999fd19fa01baab7117..355c3caf5b0aa568673fc815a531806fa0c92c28 100644 (file)
@@ -435,6 +435,89 @@ static UInt local_sys_getpid ( void )
    return (UInt)(__res);
 }
 
+#elif defined(VGP_x86_freebsd)
+static UInt local_sys_write_stderr (const HChar* buf, Int n )
+{
+   Int result;
+
+   __asm__ volatile (
+      "movl  %2, %%eax\n"    /* push n */
+      "movl  %1, %%edx\n"    /* push buf */
+      "pushl %%eax\n"
+      "pushl %%edx\n"
+      "movl  $2, %%eax\n"    /* push stderr */
+      "pushl %%eax\n"
+      "movl  $"VG_STRINGIFY(__NR_write)", %%eax\n"
+      "pushl %%eax\n"        /* push write syscall id */
+      "int   $0x80\n"        /* write(stderr, buf, n) */
+      "jnc   1f\n"           /* jump if no error */
+      "movl  $-1, %%eax\n"   /* return -1 if error */
+      "1: "
+      "movl  %%eax, %0\n"    /* __res = eax */
+      "addl  $16, %%esp\n"   /* pop x4 */
+      : /*wr*/    "=mr" (result)
+      : /*rd*/    "g" (buf), "g" (n)
+      : /*trash*/ "eax", "edx", "cc"
+   );
+   return result >= 0 ? result : -1;
+}
+
+static UInt local_sys_getpid ( void )
+{
+   UInt __res;
+   __asm__ volatile (
+      "movl $20, %%eax\n"  /* set %eax = __NR_getpid */
+      "int  $0x80\n"       /* getpid() */
+      "movl %%eax, %0\n"   /* set __res = eax */
+      : "=mr" (__res)
+      :
+      : "eax" );
+   return __res;
+}
+
+#elif defined(VGP_amd64_freebsd)
+__attribute__((noinline))
+static UInt local_sys_write_stderr (const HChar* buf, Int n )
+{
+   volatile Long block[2];
+   block[0] = (Long)buf;
+   block[1] = n;
+   __asm__ volatile (
+      "subq  $256, %%rsp\n"     /* don't trash the stack redzone */
+      "pushq %%r15\n"           /* r15 is callee-save */
+      "movq  %0, %%r15\n"       /* r15 = &block */
+      "pushq %%r15\n"           /* save &block */
+      "movq  $"VG_STRINGIFY(__NR_write)", %%rax\n" /* rax = __NR_write */
+      "movq  $2, %%rdi\n"       /* rdi = stderr */
+      "movq  0(%%r15), %%rsi\n" /* rsi = buf */
+      "movq  8(%%r15), %%rdx\n" /* rdx = n */
+      "syscall\n"               /* write(stderr, buf, n) */
+      "popq  %%r15\n"           /* reestablish &block */
+      "movq  %%rax, 0(%%r15)\n" /* block[0] = result */
+      "popq  %%r15\n"           /* restore r15 */
+      "addq  $256, %%rsp\n"     /* restore stack ptr */
+      : /*wr*/
+      : /*rd*/    "r" (block)
+      : /*trash*/ "rax", "rdi", "rsi", "rdx", "memory", "cc", "rcx", "r8", "r9", "r11"
+   );
+   if (block[0] < 0)
+      block[0] = -1;
+   return (UInt)block[0];
+}
+
+static UInt local_sys_getpid ( void )
+{
+   UInt __res;
+   __asm__ volatile (
+      "movq $20, %%rax\n"  /* set %rax = __NR_getpid */
+      "syscall\n"          /* getpid() */
+      "movl %%eax, %0\n"   /* set __res = %eax */
+      : "=mr" (__res)
+      :
+      : "rax", "rcx");//, "r11" );
+   return __res;
+}
+
 #elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
 
 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
index d04a5747716ce08b0d9a27d4fa684f838ab6038b..4857475fa38e675261e665f125e9e66f23a53c83 100644 (file)
@@ -137,6 +137,9 @@ enum target_signal
     /* Used internally by Solaris threads.  See signal(5) on Solaris.  */
     TARGET_SIGNAL_CANCEL = 76,
 
+    /* Similar to the above, but for FreeBSD */
+    TARGET_SIGNAL_THR = 77,
+
     /* Yes, this pains me, too.  But LynxOS didn't have SIG32, and now
        GNU/Linux does, and we can't disturb the numbering, since it's
        part of the remote protocol.  Note that in some GDB's
index 2d13b79f3d3434e3d0da3854b1395bc90e17599f..559d8dd8e9b1629fad38a6a3bd8a4fcf18f0f989 100644 (file)
@@ -27,6 +27,7 @@
 #include "pub_core_libcsignal.h"
 #include "pub_core_options.h"
 #include "pub_core_aspacemgr.h"
+#include "pub_core_syswrap.h"
 
 #include "server.h"
 
@@ -322,7 +323,11 @@ void remote_open (const HChar *name)
        (Addr) VG_(threads), VG_N_THREADS, sizeof(ThreadState), 
        offsetof(ThreadState, status),
        offsetof(ThreadState, os_state) + offsetof(ThreadOSstate, lwpid),
-       0};
+       0
+#if VEX_HOST_WORDSIZE == 8
+         , 0
+#endif
+   };
 
    user = VG_(getenv)("LOGNAME");
    if (user == NULL) user = VG_(getenv)("USER");
@@ -519,12 +524,30 @@ void remote_close (void)
         from_gdb ? from_gdb : "NULL",
         to_gdb ? to_gdb : "NULL",
         shared_mem ? shared_mem : "NULL");
-   if (pid == pid_from_to_creator && from_gdb && VG_(unlink) (from_gdb) == -1)
-      warning ("could not unlink %s\n", from_gdb);
-   if (pid == pid_from_to_creator && to_gdb && VG_(unlink) (to_gdb) == -1)
-      warning ("could not unlink %s\n", to_gdb);
-   if (pid == pid_from_to_creator && shared_mem && VG_(unlink) (shared_mem) == -1)
-      warning ("could not unlink %s\n", shared_mem);
+
+   // PJF this is not ideal
+   // if the guest enters capability mode then the unlink calls will fail
+   // this may well also apply to Linux and seccomp
+   // I don't have any thoughts on how to fix it, other than forking early on
+   // having the child run the guest and the parent wait()ing and then
+   // the parent doing the cleanup
+
+   Bool unlinkPossible = True;
+#if defined(VGO_freebsd)
+   unlinkPossible = (VG_(get_capability_mode)() == False);
+#endif
+
+   if (unlinkPossible == True) {
+      if (pid == pid_from_to_creator && from_gdb && VG_(unlink) (from_gdb) == -1)
+         warning ("could not unlink %s\n", from_gdb);
+      if (pid == pid_from_to_creator && to_gdb && VG_(unlink) (to_gdb) == -1)
+         warning ("could not unlink %s\n", to_gdb);
+      if (pid == pid_from_to_creator && shared_mem && VG_(unlink) (shared_mem) == -1)
+         warning ("could not unlink %s\n", shared_mem);
+   } else {
+       VG_(debugLog)(1, "remote close",
+                        "cannot unlink gdb pipes\n");
+   }
    free (from_gdb);
    from_gdb = NULL;
    free (to_gdb);
index 24948a19a46381f5c073615a92a22a03ddd08771..9aee90fcba8a979ece4344ef5c3be004327ba09e 100644 (file)
@@ -404,6 +404,10 @@ enum target_signal target_signal_from_host (int hostsig)
    if (hostsig == VKI_SIGCANCEL)
       return TARGET_SIGNAL_CANCEL;
 #endif
+#if defined(VKI_SIGTHR)
+   if (hostsig == VKI_SIGTHR)
+      return TARGET_SIGNAL_THR;
+#endif
 #if defined (VKI_SIGLWP)
    if (hostsig == VKI_SIGLWP)
       return TARGET_SIGNAL_LWP;
@@ -657,6 +661,10 @@ int do_target_signal_to_host (enum target_signal oursig,
    case TARGET_SIGNAL_CANCEL:
       return VKI_SIGCANCEL;
 #endif
+#if defined (VKI_SIGTHR)
+   case TARGET_SIGNAL_THR:
+      return VKI_SIGTHR;
+#endif
 #if defined (VKI_SIGLWP)
    case TARGET_SIGNAL_LWP:
       return VKI_SIGLWP;
index ec63fccefb28ab58d9c538b70c41d59689cafe62..35f37f88df311ed5ec58ac9abf400b239668ebd7 100644 (file)
@@ -49,7 +49,7 @@
    ------------------------------------------------------------------ */
 
 #if defined(VGP_x86_linux) || defined(VGP_x86_darwin) \
-    || defined(VGP_x86_solaris)
+    || defined(VGP_x86_solaris) || defined(VGP_x86_freebsd)
 #  define GET_STARTREGS(srP)                              \
       { UInt eip, esp, ebp;                               \
         __asm__ __volatile__(                             \
@@ -66,7 +66,7 @@
         (srP)->misc.X86.r_ebp = ebp;                      \
       }
 #elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) \
-      || defined(VGP_amd64_solaris)
+      || defined(VGP_amd64_solaris) || defined(VGP_amd64_freebsd)
 #  define GET_STARTREGS(srP)                              \
       { ULong rip, rsp, rbp;                              \
         __asm__ __volatile__(                             \
@@ -309,7 +309,7 @@ void VG_(exit_now)( Int status )
 {
 #if defined(VGO_linux)
    (void)VG_(do_syscall1)(__NR_exit_group, status );
-#elif defined(VGO_darwin) || defined(VGO_solaris)
+#elif defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
    (void)VG_(do_syscall1)(__NR_exit, status );
 #else
 #  error Unknown OS
index 3a8fed85d9f6daf63ca06ae5f5887b23b7215572..598027c6d9d40e7cd696db96dff7b33dc2749bc4 100644 (file)
@@ -67,6 +67,11 @@ Int VG_(safe_fd)(Int oldfd)
    return newfd;
 }
 
+#if defined(VGO_freebsd)
+#define M_FILEDESC_BUF  1000000
+static Char filedesc_buf[M_FILEDESC_BUF];
+#endif
+
 /* Given a file descriptor, attempt to deduce its filename.  To do
    this, we use /proc/self/fd/<FD>.  If this doesn't point to a file,
    or if it doesn't exist, we return False. 
@@ -113,6 +118,46 @@ Bool VG_(resolve_filename) ( Int fd, const HChar** result )
    *result = NULL;
    return False;
 
+#elif defined(VGO_freebsd)
+   Int mib[4];
+   SysRes sres;
+   vki_size_t len;
+   Char *bp, *eb;
+   struct vki_kinfo_file *kf;
+   static HChar *buf = NULL;
+   static SizeT  bufsiz = 0;
+
+   if (buf == NULL) {   // first time
+      bufsiz = 500;
+      buf = VG_(malloc)("resolve_filename", bufsiz);
+   }
+
+   mib[0] = VKI_CTL_KERN;
+   mib[1] = VKI_KERN_PROC;
+   mib[2] = VKI_KERN_PROC_FILEDESC;
+   mib[3] = sr_Res(VG_(do_syscall0)(__NR_getpid));
+   len = sizeof(filedesc_buf);
+   sres = VG_(do_syscall6)(__NR___sysctl, (UWord)mib, 4, (UWord)filedesc_buf,
+      (UWord)&len, 0, 0);
+   if (sr_isError(sres)) {
+       VG_(debugLog)(0, "sysctl(kern.proc.filedesc)", "%s\n", VG_(strerror)(sr_Err(sres)));
+       return False;
+   }
+   /* Walk though the list. */
+   bp = filedesc_buf;
+   eb = filedesc_buf + len;
+   while (bp < eb) {
+      kf = (struct vki_kinfo_file *)bp;
+      if (kf->kf_fd == fd)
+         break;
+      bp += kf->kf_structsize;
+   }
+   if (bp >= eb || *kf->kf_path == '\0')
+     VG_(strncpy)( buf, "[unknown]", bufsiz );
+   else
+     VG_(strncpy)( buf, kf->kf_path, bufsiz );
+   *result = buf;
+   return True;
 #  elif defined(VGO_darwin)
    HChar tmp[VKI_MAXPATHLEN+1];
    if (0 == VG_(fcntl)(fd, VKI_F_GETPATH, (UWord)tmp)) {
@@ -143,6 +188,9 @@ SysRes VG_(mknod) ( const HChar* pathname, Int mode, UWord dev )
 #  elif defined(VGO_linux) || defined(VGO_darwin)
    SysRes res = VG_(do_syscall3)(__NR_mknod,
                                  (UWord)pathname, mode, dev);
+#  elif defined(VGO_freebsd)
+   SysRes res = VG_(do_syscall3)(__NR_freebsd11_mknod,
+                                 (UWord)pathname, mode, dev);
 #  elif defined(VGO_solaris)
    SysRes res = VG_(do_syscall4)(__NR_mknodat,
                                  VKI_AT_FDCWD, (UWord)pathname, mode, dev);
@@ -158,7 +206,7 @@ SysRes VG_(open) ( const HChar* pathname, Int flags, Int mode )
    /* ARM64 wants to use __NR_openat rather than __NR_open. */
    SysRes res = VG_(do_syscall4)(__NR_openat,
                                  VKI_AT_FDCWD, (UWord)pathname, flags, mode);
-#  elif defined(VGO_linux)
+#  elif defined(VGO_linux) || defined(VGO_freebsd)
    SysRes res = VG_(do_syscall3)(__NR_open,
                                  (UWord)pathname, flags, mode);
 #  elif defined(VGO_darwin)
@@ -186,7 +234,7 @@ Int VG_(fd_open) (const HChar* pathname, Int flags, Int mode)
 void VG_(close) ( Int fd )
 {
    /* Hmm.  Return value is not checked.  That's uncool. */
-#  if defined(VGO_linux) || defined(VGO_solaris)
+#  if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
    (void)VG_(do_syscall1)(__NR_close, fd);
 #  elif defined(VGO_darwin)
    (void)VG_(do_syscall1)(__NR_close_nocancel, fd);
@@ -198,7 +246,7 @@ void VG_(close) ( Int fd )
 Int VG_(read) ( Int fd, void* buf, Int count)
 {
    Int    ret;
-#  if defined(VGO_linux) || defined(VGO_solaris)
+#  if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
    SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count);
 #  elif defined(VGO_darwin)
    SysRes res = VG_(do_syscall3)(__NR_read_nocancel, fd, (UWord)buf, count);
@@ -218,7 +266,7 @@ Int VG_(read) ( Int fd, void* buf, Int count)
 Int VG_(write) ( Int fd, const void* buf, Int count)
 {
    Int    ret;
-#  if defined(VGO_linux) || defined(VGO_solaris)
+#  if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
    SysRes res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count);
 #  elif defined(VGO_darwin)
    SysRes res = VG_(do_syscall3)(__NR_write_nocancel, fd, (UWord)buf, count);
@@ -254,6 +302,13 @@ Int VG_(pipe) ( Int fd[2] )
 #  elif defined(VGO_linux)
    SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
    return sr_isError(res) ? -1 : 0;
+#  elif defined(VGO_freebsd)
+   SysRes res = VG_(do_syscall0)(__NR_freebsd10_pipe);
+   if (!sr_isError(res)) {
+      fd[0] = sr_Res(res);
+      fd[1] = sr_ResHI(res);
+   }
+   return sr_isError(res) ? -1 : 0;
 #  elif defined(VGO_darwin)
    /* __NR_pipe is UX64, so produces a double-word result */
    SysRes res = VG_(do_syscall0)(__NR_pipe);
@@ -281,7 +336,7 @@ Int VG_(pipe) ( Int fd[2] )
 
 Off64T VG_(lseek) ( Int fd, Off64T offset, Int whence )
 {
-#  if defined(VGO_linux) || defined(VGP_amd64_darwin)
+#  if defined(VGO_linux) || defined(VGP_amd64_darwin) || defined(VGP_amd64_freebsd)
 #  if defined(__NR__llseek)
    Off64T result;
    SysRes res = VG_(do_syscall5)(__NR__llseek, fd,
@@ -293,7 +348,7 @@ Off64T VG_(lseek) ( Int fd, Off64T offset, Int whence )
    vg_assert(sizeof(Off64T) == sizeof(sr_Res(res)));
    return sr_isError(res) ? (-1) : sr_Res(res);
 #  endif
-#  elif defined(VGP_x86_darwin)
+#  elif defined(VGP_x86_darwin) || defined(VGP_x86_freebsd)
    SysRes res = VG_(do_syscall4)(__NR_lseek, fd, 
                                  offset & 0xffffffff, offset >> 32, whence);
    return sr_isError(res) ? (-1) : sr_Res(res);
@@ -424,6 +479,18 @@ SysRes VG_(stat) ( const HChar* file_name, struct vg_stat* vgbuf )
          TRANSLATE_TO_vg_stat(vgbuf, &buf64);
       return res;
    }
+#  elif defined(VGO_freebsd)
+   {
+      struct vki_freebsd11_stat buf;
+#if (FREEBSD_VERS >= FREEBSD_12)
+      res = VG_(do_syscall2)(__NR_freebsd11_stat, (UWord)file_name, (UWord)&buf);
+#else
+      res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)&buf);
+#endif
+      if (!sr_isError(res))
+         TRANSLATE_TO_vg_stat(vgbuf, &buf);
+      return res;
+   }
 #  else
 #    error Unknown OS
 #  endif
@@ -487,6 +554,19 @@ Int VG_(fstat) ( Int fd, struct vg_stat* vgbuf )
          TRANSLATE_TO_vg_stat(vgbuf, &buf64);
       return sr_isError(res) ? (-1) : 0;
    }
+#  elif defined(VGO_freebsd)
+   {
+     struct vki_freebsd11_stat buf;
+#if (FREEBSD_VERS >= FREEBSD_12)
+     res = VG_(do_syscall2)(__NR_freebsd11_fstat, (RegWord)fd, (RegWord)(Addr)&buf);
+#else
+     res = VG_(do_syscall2)(__NR_fstat, (RegWord)fd, (RegWord)(Addr)&buf);
+#endif
+     if (!sr_isError(res)) {
+        TRANSLATE_TO_vg_stat(vgbuf, &buf);
+     }
+     return sr_isError(res) ? (-1) : 0;
+   }
 #  else
 #    error Unknown OS
 #  endif
@@ -524,7 +604,7 @@ Bool VG_(is_dir) ( const HChar* f )
 
 SysRes VG_(dup) ( Int oldfd )
 {
-#  if defined(VGO_linux) || defined(VGO_darwin)
+#  if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
    return VG_(do_syscall1)(__NR_dup, oldfd);
 #  elif defined(VGO_solaris)
    return VG_(do_syscall3)(__NR_fcntl, oldfd, F_DUPFD, 0);
@@ -546,7 +626,7 @@ SysRes VG_(dup2) ( Int oldfd, Int newfd )
       return VG_(mk_SysRes_Success)(newfd);
    }
    return VG_(do_syscall3)(__NR_dup3, oldfd, newfd, 0);
-#  elif defined(VGO_linux) || defined(VGO_darwin)
+#  elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
    return VG_(do_syscall2)(__NR_dup2, oldfd, newfd);
 #  elif defined(VGO_solaris)
    return VG_(do_syscall3)(__NR_fcntl, oldfd, F_DUP2FD, newfd);
@@ -558,7 +638,7 @@ SysRes VG_(dup2) ( Int oldfd, Int newfd )
 /* Returns -1 on error. */
 Int VG_(fcntl) ( Int fd, Int cmd, Addr arg )
 {
-#  if defined(VGO_linux) || defined(VGO_solaris)
+#  if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
 #  if defined(VGP_nanomips_linux)
    SysRes res = VG_(do_syscall3)(__NR_fcntl64, fd, cmd, arg);
 #  else
@@ -581,7 +661,7 @@ Int VG_(rename) ( const HChar* old_name, const HChar* new_name )
    SysRes res = VG_(do_syscall5)(__NR_renameat2, VKI_AT_FDCWD, (UWord)old_name,
                                  VKI_AT_FDCWD, (UWord)new_name, 0);
 
-#  elif defined(VGO_linux) || defined(VGO_darwin)
+#  elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
    SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
 #  else
 #    error "Unknown OS"
@@ -594,7 +674,7 @@ Int VG_(unlink) ( const HChar* file_name )
 #  if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
    SysRes res = VG_(do_syscall2)(__NR_unlinkat, VKI_AT_FDCWD,
                                                 (UWord)file_name);
-#  elif defined(VGO_linux) || defined(VGO_darwin)
+#  elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
    SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
 #  elif defined(VGO_solaris)
    SysRes res = VG_(do_syscall3)(__NR_unlinkat, VKI_AT_FDCWD,
@@ -616,7 +696,7 @@ static HChar *startup_wd;
    changes. */
 void VG_(record_startup_wd) ( void )
 {
-#  if defined(VGO_linux) || defined(VGO_solaris)
+#  if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
    /* Simple: just ask the kernel */
    SysRes res;
    SizeT szB = 0;
@@ -624,7 +704,11 @@ void VG_(record_startup_wd) ( void )
       szB += 500;
       startup_wd = VG_(realloc)("startup_wd", startup_wd, szB);
       VG_(memset)(startup_wd, 0, szB);
+#   if defined(VGO_linux) || defined(VGO_solaris)
       res = VG_(do_syscall2)(__NR_getcwd, (UWord)startup_wd, szB-1);
+#   elif defined(VGO_freebsd)
+      res = VG_(do_syscall2)(__NR___getcwd, (UWord)startup_wd, szB-1);
+#   endif
    } while (sr_isError(res) && sr_Err(res) == VKI_ERANGE);
 
    if (sr_isError(res)) {
@@ -679,6 +763,8 @@ SysRes VG_(poll) (struct vki_pollfd *fds, Int nfds, Int timeout)
                           (UWord)NULL);
 #  elif defined(VGO_linux)
    res = VG_(do_syscall3)(__NR_poll, (UWord)fds, nfds, timeout);
+#  elif defined(VGO_freebsd)
+   res = VG_(do_syscall3)(__NR_poll, (UWord)fds, nfds, timeout);
 #  elif defined(VGO_darwin)
    res = VG_(do_syscall3)(__NR_poll_nocancel, (UWord)fds, nfds, timeout);
 #  elif defined(VGO_solaris)
@@ -712,7 +798,7 @@ SSizeT VG_(readlink) (const HChar* path, HChar* buf, SizeT bufsiz)
 #  if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
    res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
                                            (UWord)path, (UWord)buf, bufsiz);
-#  elif defined(VGO_linux) || defined(VGO_darwin)
+#  elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
    res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
 #  elif defined(VGO_solaris)
    res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path,
@@ -790,7 +876,7 @@ Int VG_(access) ( const HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
              | (ixusr ? VKI_X_OK : 0);
 #  if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
    SysRes res = VG_(do_syscall3)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path, w);
-#  elif defined(VGO_linux) || defined(VGO_darwin)
+#  elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
    SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
 #  elif defined(VGO_solaris)
    SysRes res = VG_(do_syscall4)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path,
@@ -937,6 +1023,15 @@ SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset )
       || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
    res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset);
    return res;
+#  elif defined(VGP_amd64_freebsd)
+   vg_assert(sizeof(OffT) == 8);
+   res = VG_(do_syscall4)(__NR_pread, fd, (UWord)buf, count, offset);
+   return res;
+#  elif defined(VGP_x86_freebsd)
+   vg_assert(sizeof(OffT) == 8);
+   res = VG_(do_syscall5)(__NR_pread, fd, (UWord)buf, count, 
+                          offset & 0xffffffff, offset >> 32);
+   return res;
 #  elif defined(VGP_amd64_darwin)
    vg_assert(sizeof(OffT) == 8);
    res = VG_(do_syscall4)(__NR_pread_nocancel, fd, (UWord)buf, count, offset);
@@ -1088,7 +1183,7 @@ UShort VG_(ntohs) ( UShort x )
 */
 Int VG_(connect_via_socket)( const HChar* str )
 {
-#  if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
+#  if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
    Int sd, res;
    struct vki_sockaddr_in servAddr;
    UInt   ip   = 0;
@@ -1189,7 +1284,7 @@ Int VG_(socket) ( Int domain, Int type, Int protocol )
 
 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
         || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
-        || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
+        || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
    SysRes res;
    res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
    return sr_isError(res) ? -1 : sr_Res(res);
@@ -1244,7 +1339,7 @@ Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen )
 
 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
         || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
-        || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
+        || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
    SysRes res;
    res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
    return sr_isError(res) ? -1 : sr_Res(res);
@@ -1291,7 +1386,7 @@ Int VG_(write_socket)( Int sd, const void *msg, Int count )
 
 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
         || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
-        || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
+        || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
    SysRes res;
    res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg, 
                                        count, VKI_MSG_NOSIGNAL, 0,0);
@@ -1328,7 +1423,8 @@ Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
 
 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
         || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
-        || defined(VGP_nanomips_linux)
+        || defined(VGP_nanomips_linux) || defined(VGO_freebsd) \
+        || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
    SysRes res;
    res = VG_(do_syscall3)( __NR_getsockname,
                            (UWord)sd, (UWord)name, (UWord)namelen );
@@ -1367,7 +1463,7 @@ Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
 
 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
         || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
-        || defined(VGP_nanomips_linux)
+        || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
    SysRes res;
    res = VG_(do_syscall3)( __NR_getpeername,
                            (UWord)sd, (UWord)name, (UWord)namelen );
@@ -1408,7 +1504,8 @@ Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
 
 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
         || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
-        || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
+        || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
+        || defined(VGO_freebsd)
    SysRes res;
    res = VG_(do_syscall5)( __NR_getsockopt,
                            (UWord)sd, (UWord)level, (UWord)optname, 
@@ -1459,7 +1556,7 @@ Int VG_(setsockopt) ( Int sd, Int level, Int optname, void *optval,
                            (UWord)optval, (UWord)optlen );
    return sr_isError(res) ? -1 : sr_Res(res);
 
-#  elif defined(VGO_darwin)
+#  elif defined(VGO_darwin) || defined(VGO_freebsd)
    SysRes res;
    res = VG_(do_syscall5)( __NR_setsockopt,
                            (UWord)sd, (UWord)level, (UWord)optname, 
index 022209a12b8efa3b6fc3a23c3faa86d78d068658..168008288550b7199111189c564ce629ea6f313f 100644 (file)
@@ -1184,7 +1184,7 @@ void VG_(err_config_error) ( const HChar* format, ... )
    VG_(sr_as_string)()
    ------------------------------------------------------------------ */
 
-#if defined(VGO_linux)
+#if defined(VGO_linux) || defined(VGO_freebsd)
 // FIXME: Does this function need to be adjusted for MIPS's _valEx ?
 const HChar *VG_(sr_as_string) ( SysRes sr )
 {
index ae3804f99039088da2278f922d0e6e05f41cb70d..7425c9c8873339e5e4131fc8016c15ce2e50d1f9 100644 (file)
@@ -41,6 +41,7 @@
 #include "pub_core_syscall.h"
 #include "pub_core_xarray.h"
 #include "pub_core_clientstate.h"
+#include "pub_core_debuglog.h"   // VG_(debugLog)
 
 #if defined(VGO_darwin)
 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
@@ -65,7 +66,7 @@ HChar** VG_(client_envp) = NULL;
 const HChar *VG_(libdir) = VG_LIBDIR;
 
 const HChar *VG_(LD_PRELOAD_var_name) =
-#if defined(VGO_linux) || defined(VGO_solaris)
+#if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
    "LD_PRELOAD";
 #elif defined(VGO_darwin)
    "DYLD_INSERT_LIBRARIES";
@@ -346,7 +347,7 @@ void VG_(client_cmd_and_args)(HChar *buffer, SizeT buf_size)
 
 Int VG_(waitpid)(Int pid, Int *status, Int options)
 {
-#  if defined(VGO_linux)
+#  if defined(VGO_linux) || defined(VGO_freebsd)
    SysRes res = VG_(do_syscall4)(__NR_wait4,
                                  pid, (UWord)status, options, 0);
    return sr_isError(res) ? -1 : sr_Res(res);
@@ -581,10 +582,10 @@ Int VG_(system) ( const HChar* cmd )
    return zzz == -1 ? -1 : 0;
 }
 
-Int VG_(sysctl)(Int *name, UInt namelen, void *oldp, SizeT *oldlenp, void *newp, SizeT newlen)
+Int VG_(sysctl)(Int *name, UInt namelen, void *oldp, SizeT *oldlenp, const void *newp, SizeT newlen)
 {
    SysRes res;
-#  if defined(VGO_darwin)
+#  if defined(VGO_darwin) || defined(VGO_freebsd)
    res = VG_(do_syscall6)(__NR___sysctl,
                            (UWord)name, namelen, (UWord)oldp, (UWord)oldlenp, (UWord)newp, newlen);
 #  else
@@ -718,6 +719,15 @@ Int VG_(gettid)(void)
 
    return sr_Res(res);
 
+#  elif defined(VGO_freebsd)
+   SysRes res;
+   long tid;
+
+   res = VG_(do_syscall1)(__NR_thr_self, (UWord)&tid);
+   if (sr_isError(res))
+      tid = sr_Res(VG_(do_syscall0)(__NR_getpid));
+   return tid;
+
 #  elif defined(VGO_darwin)
    // Darwin's gettid syscall is something else.
    // Use Mach thread ports for lwpid instead.
@@ -744,7 +754,7 @@ Int VG_(getpgrp) ( void )
    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
 #  if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
    return sr_Res( VG_(do_syscall1)(__NR_getpgid, 0) );
-#  elif defined(VGO_linux) || defined(VGO_darwin)
+#  elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
    return sr_Res( VG_(do_syscall0)(__NR_getpgrp) );
 #  elif defined(VGO_solaris)
    /* Uses the shared pgrpsys syscall, 0 for the getpgrp variant. */
@@ -757,7 +767,7 @@ Int VG_(getpgrp) ( void )
 Int VG_(getppid) ( void )
 {
    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
-#  if defined(VGO_linux) || defined(VGO_darwin)
+#  if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
    return sr_Res( VG_(do_syscall0)(__NR_getppid) );
 #  elif defined(VGO_solaris)
    /* Uses the shared getpid/getppid syscall, val2 contains a parent pid. */
@@ -770,7 +780,7 @@ Int VG_(getppid) ( void )
 Int VG_(geteuid) ( void )
 {
    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
-#  if defined(VGO_linux) || defined(VGO_darwin)
+#  if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
    {
 #     if defined(__NR_geteuid32)
       // We use the 32-bit version if it's supported.  Otherwise, IDs greater
@@ -791,7 +801,7 @@ Int VG_(geteuid) ( void )
 
 Int VG_(getegid) ( void )
 {
-#  if defined(VGO_linux) || defined(VGO_darwin)
+#  if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
 #    if defined(__NR_getegid32)
    // We use the 32-bit version if it's supported.  Otherwise, IDs greater
@@ -838,7 +848,8 @@ Int VG_(getgroups)( Int size, UInt* list )
         || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)  \
         || defined(VGO_darwin) || defined(VGP_s390x_linux)    \
         || defined(VGP_mips32_linux) || defined(VGP_arm64_linux) \
-        || defined(VGO_solaris) || defined(VGP_nanomips_linux)
+        || defined(VGO_solaris) || defined(VGP_nanomips_linux) \
+        || defined(VGO_freebsd)
    SysRes sres;
    sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list);
    if (sr_isError(sres))
@@ -857,7 +868,7 @@ Int VG_(getgroups)( Int size, UInt* list )
 Int VG_(ptrace) ( Int request, Int pid, void *addr, void *data )
 {
    SysRes res;
-#  if defined(VGO_linux) || defined(VGO_darwin)
+#  if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
    res = VG_(do_syscall4)(__NR_ptrace, request, pid, (UWord)addr, (UWord)data);
 #  elif defined(VGO_solaris)
    /* There is no ptrace syscall on Solaris.  Such requests has to be
@@ -887,7 +898,7 @@ Int VG_(fork) ( void )
       return -1;
    return sr_Res(res);
 
-#  elif defined(VGO_linux)
+#  elif defined(VGO_linux) || defined(VGO_freebsd)
    SysRes res;
    res = VG_(do_syscall0)(__NR_fork);
    if (sr_isError(res))
@@ -955,6 +966,13 @@ UInt VG_(read_millisecond_timer) ( void )
      }
    }
 
+#  elif defined(VGO_freebsd)
+   { SysRes res;
+     struct vki_timeval tv_now;
+     res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL);
+     vg_assert(! sr_isError(res));
+     now = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec;
+   }
 #  elif defined(VGO_darwin)
    // Weird: it seems that gettimeofday() doesn't fill in the timeval, but
    // rather returns the tv_sec as the low 32 bits of the result and the
@@ -978,7 +996,7 @@ UInt VG_(read_millisecond_timer) ( void )
    return (now - base) / 1000;
 }
 
-#  if defined(VGO_linux) || defined(VGO_solaris)
+#  if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
 void VG_(clock_gettime) ( struct vki_timespec *ts, vki_clockid_t clk_id )
 {
     SysRes res;
@@ -1030,6 +1048,16 @@ UInt VG_(get_user_milliseconds)(void)
       }
    }
 
+#  elif defined(VGO_freebsd)
+   {
+      struct vki_rusage ru;
+      VG_(memset)(&ru, 0, sizeof(ru));
+      SysRes sr = VG_(do_syscall2)(__NR_getrusage, VKI_RUSAGE_SELF, (UWord)&ru);
+      if (!sr_isError(sr)) {
+         res = ru.ru_utime.tv_sec * 1000 + ru.ru_utime.tv_usec / 1000;
+      }
+   }
+
 #  elif defined(VGO_darwin)
    res = 0;
 
@@ -1105,6 +1133,62 @@ void VG_(do_atfork_child)(ThreadId tid)
          (*atforks[i].child)(tid);
 }
 
+/* ---------------------------------------------------------------------
+   FreeBSD sysctlbyname(), modfind(), etc
+   ------------------------------------------------------------------ */
+
+#if defined(VGO_freebsd)
+Int VG_(sysctlbyname)(const HChar *name, void *oldp, SizeT *oldlenp, const void *newp, SizeT newlen)
+{
+   Int oid[2];
+   Int real_oid[10];
+   SizeT oidlen;
+   int error;
+
+   oid[0] = 0;         /* magic */
+   oid[1] = 3;         /* undocumented */
+   oidlen = sizeof(real_oid);
+   error = VG_(sysctl)(oid, 2, real_oid, &oidlen, name, VG_(strlen)(name));
+   if (error < 0)
+      return error;
+   oidlen /= sizeof(int);
+   error = VG_(sysctl)(real_oid, oidlen, oldp, oldlenp, newp, newlen);
+   return error;
+}
+
+Int VG_(getosreldate)(void)
+{
+   static Int osreldate = 0;
+   SizeT osreldatel;
+
+   if (osreldate == 0) {
+      osreldatel = sizeof(osreldate);
+      VG_(sysctlbyname)("kern.osreldate", &osreldate, &osreldatel, 0, 0);
+   }
+   return (osreldate);
+}
+
+Bool VG_(is32on64)(void)
+{
+#if defined(VGP_amd64_freebsd)
+   return False;
+#elif defined(VGP_x86_freebsd)
+   SysRes res;
+   struct vg_stat stat_buf;
+   res = VG_(stat)("/libexec/ld-elf32.so.1", &stat_buf);
+   if (!sr_isError(res)) {
+      // file exists, we're running on amd64
+      VG_(debugLog)(1, "check-os-bitness", "i386 executable on amd64 kernel\n");
+      return True;
+   } else {
+      VG_(debugLog)(1, "check-os-bitness", "i386 executable on i386 kernel\n");
+      return False;
+   }
+#else
+#  error Unknown platform
+#endif
+}
+#endif
 
 /* ---------------------------------------------------------------------
    icache invalidation
index abb8f23e7254268ada1ca1c1e1d6b9ccfd96a95d..4f1ecb1502a661165d06683ae5066226e0ec9f2f 100644 (file)
@@ -37,7 +37,7 @@
 /* See include/pub_tool_libcsetjmp.h for background and rationale. */
 
 /* The alternative implementations are for ppc{32,64}-linux and
-   {amd64,x86}-{linux,darwin,solaris}.  See #259977.  That leaves only
+   {amd64,x86}-{linux,darwin,solaris,freebsd}.  See #259977.  That leaves only
    {arm,s390x}-linux using the gcc builtins now.
 */
 
@@ -377,16 +377,16 @@ __asm__(
 #endif /* VGP_ppc64be_linux */
 
 
-/* -------- amd64-{linux,darwin,solaris} -------- */
+/* -------- amd64-{linux,darwin,solaris,freebsd} -------- */
 
 #if defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) || \
-    defined(VGP_amd64_solaris)
+    defined(VGP_amd64_solaris) || defined(VGP_amd64_freebsd)
 
 __asm__(
 ".text"  "\n"
 ""       "\n"
 
-#if defined(VGP_amd64_linux) || defined(VGP_amd64_solaris)
+#if defined(VGP_amd64_linux) || defined(VGP_amd64_solaris) || defined(VGP_amd64_freebsd)
 ".global VG_MINIMAL_SETJMP"  "\n"  // rdi = jmp_buf
 "VG_MINIMAL_SETJMP:"  "\n"
 
@@ -423,7 +423,7 @@ __asm__(
 ""       "\n"
 
 
-#if defined(VGP_amd64_linux) || defined(VGP_amd64_solaris)
+#if defined(VGP_amd64_linux) || defined(VGP_amd64_solaris) || defined(VGP_amd64_freebsd)
 ".global VG_MINIMAL_LONGJMP"  "\n"
 "VG_MINIMAL_LONGJMP:"  "\n"    // rdi = jmp_buf
 
@@ -471,19 +471,19 @@ __asm__(
 #endif
 );
 
-#endif /* VGP_amd64_linux || VGP_amd64_darwin || VGP_amd64_solaris */
+#endif /* VGP_amd64_linux || VGP_amd64_darwin || VGP_amd64_solaris || VGP_amd64_freebsd */
 
 
-/* -------- x86-{linux,darwin,solaris} -------- */
+/* -------- x86-{linux,darwin,solaris,freebsd} -------- */
 
 #if defined(VGP_x86_linux) || defined(VGP_x86_darwin) || \
-    defined(VGP_x86_solaris)
+    defined(VGP_x86_solaris) || defined(VGP_x86_freebsd)
 
 __asm__(
 ".text"  "\n"
 ""       "\n"
 
-#if defined(VGP_x86_linux) || defined(VGP_x86_solaris)
+#if defined(VGP_x86_linux) || defined(VGP_x86_solaris) || defined(VGP_x86_freebsd)
 ".global VG_MINIMAL_SETJMP"  "\n"  // eax = jmp_buf
 "VG_MINIMAL_SETJMP:"  "\n"
 
@@ -514,7 +514,7 @@ __asm__(
 ""       "\n"
 
 
-#if defined(VGP_x86_linux) || defined(VGP_x86_solaris)
+#if defined(VGP_x86_linux) || defined(VGP_x86_solaris) || defined(VGP_x86_freebsd)
 ".global VG_MINIMAL_LONGJMP"  "\n"
 "VG_MINIMAL_LONGJMP:"  "\n"    // eax = jmp_buf
 
@@ -548,7 +548,7 @@ __asm__(
 #endif
 );
 
-#endif /* VGP_x86_linux || VGP_x86_darwin || VGP_x86_solaris */
+#endif /* VGP_x86_linux || VGP_x86_darwin || VGP_x86_solaris || VGP_x86_freebsd */
 
 #if defined(VGP_mips32_linux)
 
index 35d1247f72c9a94d2961dbda2203963e9b6287ef..a32b53a2f4cefb65cdaccc81fddde345adc402f1 100644 (file)
@@ -34,6 +34,7 @@
 #include "pub_core_libcassert.h"
 #include "pub_core_syscall.h"
 #include "pub_core_libcsignal.h"    /* self */
+#include "pub_core_libcproc.h"
 
 #if !defined(VGO_solaris)
 #   define _VKI_MAXSIG (_VKI_NSIG - 1)
@@ -214,7 +215,7 @@ void VG_(sigcomplementset)( vki_sigset_t* dst, const vki_sigset_t* src )
 */
 Int VG_(sigprocmask)( Int how, const vki_sigset_t* set, vki_sigset_t* oldset)
 {
-#  if defined(VGO_linux) || defined(VGO_solaris)
+#  if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
 #  if defined(__NR_rt_sigprocmask)
    SysRes res = VG_(do_syscall4)(__NR_rt_sigprocmask, 
                                  how, (UWord)set, (UWord)oldset, 
@@ -317,6 +318,18 @@ Int VG_(sigaction) ( Int signum,
    SysRes res = VG_(do_syscall3)(__NR_sigaction,
                                  signum, (UWord)act, (UWord)oldact);
    return sr_isError(res) ? -1 : 0;
+   
+#  elif defined(VGO_freebsd)
+   SysRes res = VG_(do_syscall3)(__NR_sigaction,
+                                 signum, (UWord)act, (UWord)oldact);
+   return sr_isError(res) ? -1 : 0;
+
+
+#  elif defined(VGO_freebsd)
+   SysRes res = VG_(do_syscall3)(__NR_sigaction,
+                                 signum, (UWord)act, (UWord)oldact);
+   return sr_isError(res) ? -1 : 0;
+
 
 #  else
 #    error "Unsupported OS"
@@ -329,7 +342,7 @@ void
 VG_(convert_sigaction_fromK_to_toK)( const vki_sigaction_fromK_t* fromK,
                                      /*OUT*/vki_sigaction_toK_t* toK )
 {
-#  if defined(VGO_linux) || defined(VGO_solaris)
+#  if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
    *toK = *fromK;
 #  elif defined(VGO_darwin)
    toK->ksa_handler = fromK->ksa_handler;
@@ -346,7 +359,7 @@ Int VG_(kill)( Int pid, Int signo )
 {
 #  if defined(VGO_linux) || defined(VGO_solaris)
    SysRes res = VG_(do_syscall2)(__NR_kill, pid, signo);
-#  elif defined(VGO_darwin)
+#  elif defined(VGO_darwin) || defined(VGO_freebsd)
    SysRes res = VG_(do_syscall3)(__NR_kill,
                                  pid, signo, 1/*posix-compliant*/);
 #  else
@@ -385,6 +398,11 @@ Int VG_(tkill)( Int lwpid, Int signo )
 #     endif
    return sr_isError(res) ? -1 : 0;
 
+#  elif defined(VGO_freebsd)
+   SysRes res;
+   res = VG_(do_syscall2)(__NR_thr_kill, lwpid, signo);
+   return sr_isError(res) ? -1 : 0;
+
 #  else
 #    error "Unsupported plat"
 #  endif
@@ -411,7 +429,7 @@ Int VG_(tkill)( Int lwpid, Int signo )
 /* ---------- sigtimedwait_zero: Linux ----------- */
 
 #if defined(VGO_linux)
-Int VG_(sigtimedwait_zero)( const vki_sigset_t *set, 
+Int VG_(sigtimedwait_zero)( const vki_sigset_t *set,
                             vki_siginfo_t *info )
 {
    static const struct vki_timespec zero = { 0, 0 };
@@ -548,6 +566,19 @@ Int VG_(sigtimedwait_zero)( const vki_sigset_t *set, vki_siginfo_t *info )
    return sr_isError(res) ? -1 : sr_Res(res);
 }
 
+#elif defined(VGO_freebsd)
+
+
+Int VG_(sigtimedwait_zero)( const vki_sigset_t *set, 
+                            vki_siginfo_t *info )
+{
+   static const struct vki_timespec zero = { 0, 0 };
+
+   SysRes res = VG_(do_syscall3)(__NR_sigtimedwait, (UWord)set, (UWord)info,
+                                   (UWord)&zero);
+   return sr_isError(res) ? -1 : sr_Res(res);
+}
+
 #else
 #  error "Unknown OS"
 #endif
index ab436aec6e062446d2c8f1689ed0d4b76f849c61..0b60ecc0fd444e7a6192ff7169221217c26b4179 100644 (file)
@@ -30,6 +30,7 @@
 #include "pub_core_threadstate.h"
 #include "pub_core_libcassert.h"
 #include "pub_core_libcbase.h"
+#include "pub_core_libcprint.h"
 #include "pub_core_libcfile.h"
 #include "pub_core_libcprint.h"
 #include "pub_core_libcproc.h"
@@ -906,6 +907,20 @@ Bool VG_(machine_get_hwcaps)( void )
      if (!have_cx8)
         return False;
 
+#if defined(VGP_x86_freebsd)
+     if (have_sse1 || have_sse2) {
+       Int sc, error;
+       SizeT scl;
+       /* Regardless of whether cpuid says, the OS has to enable SSE first! */
+       scl = sizeof(sc);
+       error = VG_(sysctlbyname)("hw.instruction_sse", &sc, &scl, 0, 0);
+       if (error == -1 || sc != 1) {
+           have_sse1 = 0;
+           have_sse2 = 0;
+           VG_(message)(Vg_UserMsg, "Warning: cpu has SSE, but the OS has not enabled it.  Disabling in valgrind!");
+       }
+     }
+#endif
      /* Figure out if this is an AMD that can do MMXEXT. */
      have_mmxext = False;
      if (0 == VG_(strcmp)(vstr, "AuthenticAMD")
@@ -2353,7 +2368,7 @@ Int VG_(machine_get_size_of_largest_guest_register) ( void )
 void* VG_(fnptr_to_fnentry)( void* f )
 {
 #  if defined(VGP_x86_linux) || defined(VGP_amd64_linux)  \
-      || defined(VGP_arm_linux) || defined(VGO_darwin)          \
+      || defined(VGP_arm_linux) || defined(VGO_darwin) || defined(VGO_freebsd) \
       || defined(VGP_ppc32_linux) || defined(VGP_ppc64le_linux) \
       || defined(VGP_s390x_linux) || defined(VGP_mips32_linux) \
       || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
index 68edc4d4997372bc55ad695715492fa78b664f2d..56f9c6cbf036da29832ea5bb0402dd79b89774ee 100644 (file)
@@ -1120,7 +1120,11 @@ void main_process_cmd_line_options( void )
 
 /* Number of file descriptors that Valgrind tries to reserve for
    its own use - just a small constant. */
+#if defined(VGO_freebsd)
+#define N_RESERVED_FDS (20)
+#else
 #define N_RESERVED_FDS (12)
+#endif
 
 static void setup_file_descriptors(void)
 {
@@ -1344,6 +1348,27 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp )
       VG_(exit)(1);
    }
 
+   //--------------------------------------------------------------
+   // FreeBSD check security.bsd.unprivileged_proc_debug sysctl
+   // This needs to be done before aspacemgr starts, otherwise that
+   // will fail with mysterious error codes
+   //--------------------------------------------------------------
+#if defined(VGO_freebsd)
+   Int val;
+   SizeT len = sizeof(val);
+   Int error = VG_(sysctlbyname)("security.bsd.unprivileged_proc_debug", &val, &len, 0, 0);
+   if (error != -1 && val != 1) {
+       VG_(debugLog)(0, "main", "Valgrind: FATAL:\n");
+       VG_(debugLog)(0, "main", "security.bsd.unprivileged_proc_debug sysctl is 0.\n");
+       VG_(debugLog)(0, "main", "   Set this sysctl with\n");
+       VG_(debugLog)(0, "main", "   'sysctl security.bsd.unprivileged_proc_debug=1'.\n");
+       VG_(debugLog)(0, "main", "   Cannot continue.\n");
+
+       VG_(exit)(1);
+   }
+#endif
+
+
    //--------------------------------------------------------------
    // Start up the address space manager, and determine the
    // approximate location of the client's stack
@@ -1550,7 +1575,7 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp )
    if (!need_help) {
       VG_(debugLog)(1, "main", "Create initial image\n");
 
-#     if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
+#     if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
       the_iicii.argv              = argv;
       the_iicii.envp              = envp;
       the_iicii.toolname          = VG_(clo_toolname);
@@ -1802,7 +1827,7 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp )
    addr2dihandle = VG_(newXA)( VG_(malloc), "main.vm.2",
                                VG_(free), sizeof(Addr_n_ULong) );
 
-#  if defined(VGO_linux) || defined(VGO_solaris)
+#  if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
    { Addr* seg_starts;
      Int   n_seg_starts;
      Addr_n_ULong anu;
@@ -2326,7 +2351,7 @@ void shutdown_actions_NORETURN( ThreadId tid,
 */
 static void final_tidyup(ThreadId tid)
 {
-#if defined(VGO_linux) || defined(VGO_solaris)
+#if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
    Addr freeres_wrapper = VG_(client_freeres_wrapper);
 
    vg_assert(VG_(is_running_thread)(tid));
@@ -2474,6 +2499,7 @@ static void final_tidyup(ThreadId tid)
    VG_(set_default_handler)(VKI_SIGBUS);
    VG_(set_default_handler)(VKI_SIGILL);
    VG_(set_default_handler)(VKI_SIGFPE);
+   VG_(set_default_handler)(VKI_SIGSYS);
 
    // We were exiting, so assert that...
    vg_assert(VG_(is_exiting)(tid));
@@ -2988,7 +3014,7 @@ asm(
 ".previous                                              \n\t"
 );
 #else
-#  error "Unknown linux platform"
+#  error "Unknown platform"
 #endif
 
 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
@@ -3256,6 +3282,113 @@ void _start_in_C_solaris ( UWord* pArgc )
    VG_(exit)(r);
 }
 
+/*====================================================================*/
+/*=== Getting to main() alive: FreeBSD                             ===*/
+/*====================================================================*/
+#elif defined(VGO_freebsd)
+
+#if defined(VGP_x86_freebsd)
+asm("\n"
+    ".text\n"
+    "\t.globl _start\n"
+    "\t.type _start,@function\n"
+    "_start:\n"
+    /* set up the new stack in %eax */
+    "\tmovl  $vgPlain_interim_stack, %eax\n"
+    "\taddl  $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %eax\n"
+    "\taddl  $"VG_STRINGIFY(VG_DEFAULT_STACK_ACTIVE_SZB)", %eax\n"
+    /* allocate at least 16 bytes on the new stack, and aligned */
+    "\tsubl  $16, %eax\n"
+    "\tandl  $~15, %eax\n"
+    /* install it, and collect the original one */
+    "\txchgl %eax, %esp\n"
+    "\tsubl  $12, %esp\n"  /* Keep stack 16-byte aligned. */
+    /* call _start_in_C_freebsd, passing it the startup %esp */
+    "\tpushl %eax\n"
+    "\tcall  _start_in_C_freebsd\n"
+    "\thlt\n"
+    ".previous\n"
+);
+#elif defined(VGP_amd64_freebsd)
+
+// @todo PJF I don't really understand why this is done this way
+// other amd64 platforms just put the new stack address in rdi
+// then do an exchange so that the stack pointer points to the
+// new stack and rdi (which is the 1st argument in the amd64 sysv abi)
+// contains the old stack
+
+// instead for amd64 the same thing is done for rsi, the second
+// function argument and rdi is unchanged
+//
+// In gdb I see the initial rdp is 8+rsp
+// e.g.
+// rdi            0x7fffffffe3b0
+// rsp            0x7fffffffe3a8
+//
+// Maybe on FreeBSD the pointer to argc is 16byte aligned and can be 8 bytes above the
+// start of the stack?
+
+asm("\n"
+    ".text\n"
+    "\t.globl _start\n"
+    "\t.type _start,@function\n"
+    "_start:\n"
+    /* set up the new stack in %rsi */
+    "\tmovq  $vgPlain_interim_stack, %rsi\n"
+    "\taddq  $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %rsi\n"
+    "\taddq  $"VG_STRINGIFY(VG_DEFAULT_STACK_ACTIVE_SZB)", %rsi\n"
+    "\tandq  $~15, %rsi\n"
+    /* install it, and collect the original one */
+    "\txchgq %rsi, %rsp\n"
+    /* call _start_in_C_freebsd, passing it the startup %rsp */
+    "\tcall  _start_in_C_freebsd\n"
+    "\thlt\n"
+    ".previous\n"
+);
+#endif
+
+void *memcpy(void *dest, const void *src, size_t n);
+void *memcpy(void *dest, const void *src, size_t n) {
+   return VG_(memcpy)(dest, src, n);
+}
+void* memmove(void *dest, const void *src, SizeT n);
+void* memmove(void *dest, const void *src, SizeT n) {
+   return VG_(memmove)(dest,src,n);
+}
+void* memset(void *s, int c, SizeT n);
+void* memset(void *s, int c, SizeT n) {
+  return VG_(memset)(s,c,n);
+}
+
+__attribute__ ((used))
+void _start_in_C_freebsd ( UWord* pArgc, UWord *initial_sp );
+__attribute__ ((used))
+void _start_in_C_freebsd ( UWord* pArgc, UWord *initial_sp )
+{
+   Int     r;
+   Word    argc = pArgc[0];
+   HChar** argv = (HChar**)&pArgc[1];
+   HChar** envp = (HChar**)&pArgc[1+argc+1];
+
+   INNER_REQUEST
+      ((void) VALGRIND_STACK_REGISTER
+       (&VG_(interim_stack).bytes[0],
+        &VG_(interim_stack).bytes[0] + sizeof(VG_(interim_stack))));
+
+   VG_(memset)( &the_iicii, 0, sizeof(the_iicii) );
+   VG_(memset)( &the_iifii, 0, sizeof(the_iifii) );
+
+#if defined(VGP_amd64_freebsd)
+   the_iicii.sp_at_startup = (Addr)initial_sp;
+#else
+   the_iicii.sp_at_startup = (Addr)pArgc;
+#endif
+
+   r = valgrind_main( (Int)argc, argv, envp );
+   /* NOTREACHED */
+   VG_(exit)(r);
+}
+
 #else
 #  error "Unknown OS"
 #endif
@@ -3710,6 +3843,13 @@ UWord voucher_mach_msg_set ( UWord arg1 )
 #endif
 
 
+Word VG_(get_usrstack)(void)
+{
+   return VG_PGROUNDDN(the_iicii.clstack_end - the_iifii.clstack_max_size);
+}
+
+
+
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
 /*--------------------------------------------------------------------*/
index 1a1117e47eacda051d7bd82171fc93d31935e682..66a3c0c4f90699d590c3f1c91b77cb066724bb87 100644 (file)
@@ -1212,6 +1212,9 @@ Bool VG_(is_soname_ld_so) (const HChar *soname)
    if (VG_STREQ(soname, VG_U_LD_LINUX_AARCH64_SO_1)) return True;
    if (VG_STREQ(soname, VG_U_LD_LINUX_ARMHF_SO_3))   return True;
    if (VG_STREQ(soname, VG_U_LD_LINUX_MIPSN8_S0_1))  return True;
+#  elif defined(VGO_freebsd)
+   if (VG_STREQ(soname, VG_U_LD_ELF_SO_1))   return True;
+   if (VG_STREQ(soname, VG_U_LD_ELF32_SO_1))   return True;
 #  elif defined(VGO_darwin)
    if (VG_STREQ(soname, VG_U_DYLD)) return True;
 #  elif defined(VGO_solaris)
@@ -1527,6 +1530,8 @@ void VG_(redir_initialise) ( void )
 #     endif
    }
 
+#  elif defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd)
+/* XXX do something real if needed */
 #  elif defined(VGP_x86_darwin)
    /* If we're using memcheck, use these intercepts right from
       the start, otherwise dyld makes a lot of noise. */
index 7e0229ca17cc0721ac918d241444f67c130e5c3d..9711b6573af17cc93e26448c169c4a4f2f3996e3 100644 (file)
    10140 MALLOPT
    10150 MALLOC_TRIM
    10160 POSIX_MEMALIGN
-   10170 MALLOC_USABLE_SIZE
-   10180 PANIC
-   10190 MALLOC_STATS
-   10200 MALLINFO
-   10210 DEFAULT_ZONE
-   10220 CREATE_ZONE
-   10230 ZONE_FROM_PTR
-   10240 ZONE_CHECK
-   10250 ZONE_REGISTER
-   10260 ZONE_UNREGISTER
-   10270 ZONE_SET_NAME
-   10280 ZONE_GET_NAME
+   10170 ALIGNED_ALL0C
+   10180 MALLOC_USABLE_SIZE
+   10190 PANIC
+   10200 MALLOC_STATS
+   10210 MALLINFO
+   10220 DEFAULT_ZONE
+   10230 CREATE_ZONE
+   10240 ZONE_FROM_PTR
+   10250 ZONE_CHECK
+   10260 ZONE_REGISTER
+   10270 ZONE_UNREGISTER
+   10280 ZONE_SET_NAME
+   10290 ZONE_GET_NAME
 */
 
 /* 2 Apr 05: the Portland Group compiler, which uses cfront/ARM style
@@ -379,6 +380,10 @@ extern int *__errno_location (void) __attribute__((weak));
  ALLOC_or_NULL(VG_Z_LIBC_SONAME,      malloc,      malloc);
  ALLOC_or_NULL(SO_SYN_MALLOC,         malloc,      malloc);
 
+#elif defined(VGO_freebsd)
+ ALLOC_or_NULL(VG_Z_LIBC_SONAME,      malloc,      malloc);
+ ALLOC_or_NULL(SO_SYN_MALLOC,         malloc,      malloc);
+
 #elif defined(VGO_darwin)
  ALLOC_or_NULL(VG_Z_LIBC_SONAME,      malloc,      malloc);
  ALLOC_or_NULL(SO_SYN_MALLOC,         malloc,      malloc);
@@ -417,6 +422,20 @@ extern int *__errno_location (void) __attribute__((weak));
   ALLOC_or_BOMB(SO_SYN_MALLOC,         _Znwm,          __builtin_new);
  #endif
 
+#elif defined(VGO_freebsd)
+ // operator new(unsigned int), GNU mangling
+ #if VG_WORDSIZE == 4
+  ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwj,          __builtin_new);
+  ALLOC_or_BOMB(VG_Z_LIBCXX_SONAME,    _Znwj,          __builtin_new);
+  ALLOC_or_BOMB(SO_SYN_MALLOC,         _Znwj,          __builtin_new);
+ #endif
+ // operator new(unsigned long), GNU mangling
+ #if VG_WORDSIZE == 8
+  ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwm,          __builtin_new);
+  ALLOC_or_BOMB(VG_Z_LIBCXX_SONAME,    _Znwm,          __builtin_new);
+  ALLOC_or_BOMB(SO_SYN_MALLOC,         _Znwm,          __builtin_new);
+ #endif
+
 #elif defined(VGO_darwin)
  // operator new(unsigned int), GNU mangling
  #if VG_WORDSIZE == 4
@@ -461,6 +480,20 @@ extern int *__errno_location (void) __attribute__((weak));
   ALLOC_or_BOMB_ALIGNED(SO_SYN_MALLOC,         _ZnwmSt11align_val_t, __builtin_new_aligned);
  #endif
 
+#elif defined(VGO_freebsd)
+ // operator new(unsigned int), GNU mangling
+ #if VG_WORDSIZE == 4
+  ALLOC_or_BOMB_ALIGNED(VG_Z_LIBSTDCXX_SONAME, _ZnwjSt11align_val_t, __builtin_new_aligned);
+  ALLOC_or_BOMB_ALIGNED(VG_Z_LIBCXX_SONAME,    _ZnwjSt11align_val_t, __builtin_new_aligned);
+  ALLOC_or_BOMB_ALIGNED(SO_SYN_MALLOC,         _ZnwjSt11align_val_t, __builtin_new_aligned);
+ #endif
+ // operator new(unsigned long), GNU mangling
+ #if VG_WORDSIZE == 8
+  ALLOC_or_BOMB_ALIGNED(VG_Z_LIBSTDCXX_SONAME, _ZnwmSt11align_val_t, __builtin_new_aligned);
+  ALLOC_or_BOMB_ALIGNED(VG_Z_LIBCXX_SONAME,    _ZnwmSt11align_val_t, __builtin_new_aligned);
+  ALLOC_or_BOMB_ALIGNED(SO_SYN_MALLOC,         _ZnwmSt11align_val_t, __builtin_new_aligned);
+ #endif
+
 #elif defined(VGO_darwin)
 
 #elif defined(VGO_solaris)
@@ -497,6 +530,20 @@ extern int *__errno_location (void) __attribute__((weak));
   ALLOC_or_NULL(SO_SYN_MALLOC,         _ZnwmRKSt9nothrow_t,  __builtin_new);
  #endif
 
+#elif defined(VGO_freebsd)
+ // operator new(unsigned, std::nothrow_t const&), GNU mangling
+ #if VG_WORDSIZE == 4
+  ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnwjRKSt9nothrow_t,  __builtin_new);
+  ALLOC_or_BOMB(VG_Z_LIBCXX_SONAME,    _ZnwjRKSt9nothrow_t,  __builtin_new);
+  ALLOC_or_NULL(SO_SYN_MALLOC,         _ZnwjRKSt9nothrow_t,  __builtin_new);
+ #endif
+ // operator new(unsigned long, std::nothrow_t const&), GNU mangling
+ #if VG_WORDSIZE == 8
+  ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnwmRKSt9nothrow_t,  __builtin_new);
+  ALLOC_or_NULL(VG_Z_LIBCXX_SONAME,    _ZnwmRKSt9nothrow_t,  __builtin_new);
+  ALLOC_or_NULL(SO_SYN_MALLOC,         _ZnwjRKSt9nothrow_t,  __builtin_new);
+ #endif
+
 #elif defined(VGO_darwin)
  // operator new(unsigned, std::nothrow_t const&), GNU mangling
  #if VG_WORDSIZE == 4
@@ -541,6 +588,20 @@ extern int *__errno_location (void) __attribute__((weak));
   ALLOC_or_NULL_ALIGNED(SO_SYN_MALLOC,         _ZnwmSt11align_val_tRKSt9nothrow_t,  __builtin_new_aligned);
  #endif
 
+#elif defined(VGO_freebsd)
+ // operator new(unsigned int, std::align_val_t, std::nothrow_t const&), GNU mangling
+ #if VG_WORDSIZE == 4
+  ALLOC_or_NULL_ALIGNED(VG_Z_LIBSTDCXX_SONAME, _ZnwjSt11align_val_tRKSt9nothrow_t,  __builtin_new_aligned);
+  ALLOC_or_NULL_ALIGNED(VG_Z_LIBCXX_SONAME,    _ZnwjSt11align_val_tRKSt9nothrow_t,  __builtin_new_aligned);
+  ALLOC_or_NULL_ALIGNED(SO_SYN_MALLOC,         _ZnwjSt11align_val_tRKSt9nothrow_t,  __builtin_new_aligned);
+ #endif
+ // operator new(unsigned long, std::align_val_t, std::nothrow_t const&), GNU mangling
+ #if VG_WORDSIZE == 8
+  ALLOC_or_NULL_ALIGNED(VG_Z_LIBSTDCXX_SONAME, _ZnwmSt11align_val_tRKSt9nothrow_t,  __builtin_new_aligned);
+  ALLOC_or_NULL_ALIGNED(VG_Z_LIBCXX_SONAME,    _ZnwmSt11align_val_tRKSt9nothrow_t,  __builtin_new_aligned);
+  ALLOC_or_NULL_ALIGNED(SO_SYN_MALLOC,         _ZnwmSt11align_val_tRKSt9nothrow_t,  __builtin_new_aligned);
+ #endif
+
 #elif defined(VGO_darwin)
 
 #elif defined(VGO_solaris)
@@ -579,6 +640,20 @@ extern int *__errno_location (void) __attribute__((weak));
   ALLOC_or_BOMB(SO_SYN_MALLOC,         _Znam,             __builtin_vec_new );
  #endif
 
+#elif defined(VGO_freebsd)
+ // operator new[](unsigned int), GNU mangling
+ #if VG_WORDSIZE == 4
+  ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znaj,             __builtin_vec_new );
+  ALLOC_or_BOMB(VG_Z_LIBCXX_SONAME,    _Znaj,             __builtin_vec_new );
+  ALLOC_or_BOMB(SO_SYN_MALLOC,         _Znaj,             __builtin_vec_new );
+ #endif
+ // operator new[](unsigned long), GNU mangling
+ #if VG_WORDSIZE == 8
+  ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znam,             __builtin_vec_new );
+  ALLOC_or_BOMB(VG_Z_LIBCXX_SONAME,    _Znam,             __builtin_vec_new );
+  ALLOC_or_BOMB(SO_SYN_MALLOC,         _Znaj,             __builtin_vec_new );
+ #endif
+
 #elif defined(VGO_darwin)
  // operator new[](unsigned int), GNU mangling
  #if VG_WORDSIZE == 4
@@ -623,6 +698,20 @@ extern int *__errno_location (void) __attribute__((weak));
   ALLOC_or_BOMB_ALIGNED(SO_SYN_MALLOC,         _ZnamSt11align_val_t, __builtin_vec_new_aligned );
  #endif
 
+#elif defined(VGO_freebsd)
+ // operator new[](unsigned int, std::align_val_t), GNU mangling
+ #if VG_WORDSIZE == 4
+  ALLOC_or_BOMB_ALIGNED(VG_Z_LIBSTDCXX_SONAME, _ZnajSt11align_val_t, __builtin_vec_new_aligned );
+  ALLOC_or_BOMB_ALIGNED(VG_Z_LIBCXX_SONAME,    _ZnajSt11align_val_t, __builtin_vec_new_aligned );
+  ALLOC_or_BOMB_ALIGNED(SO_SYN_MALLOC,         _ZnajSt11align_val_t, __builtin_vec_new_aligned );
+ #endif
+ // operator new[](unsigned long, std::align_val_t), GNU mangling
+ #if VG_WORDSIZE == 8
+  ALLOC_or_BOMB_ALIGNED(VG_Z_LIBSTDCXX_SONAME, _ZnamSt11align_val_t, __builtin_vec_new_aligned );
+  ALLOC_or_BOMB_ALIGNED(VG_Z_LIBCXX_SONAME,    _ZnamSt11align_val_t, __builtin_vec_new_aligned );
+  ALLOC_or_BOMB_ALIGNED(SO_SYN_MALLOC,         _ZnamSt11align_val_t, __builtin_vec_new_aligned );
+ #endif
+
 #elif defined(VGO_darwin)
 
 #elif defined(VGO_solaris)
@@ -658,6 +747,20 @@ extern int *__errno_location (void) __attribute__((weak));
   ALLOC_or_NULL(SO_SYN_MALLOC,         _ZnamRKSt9nothrow_t, __builtin_vec_new );
  #endif
 
+#elif defined(VGO_freebsd)
+ // operator new[](unsigned, std::nothrow_t const&), GNU mangling
+ #if VG_WORDSIZE == 4
+  ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnajRKSt9nothrow_t, __builtin_vec_new );
+  ALLOC_or_NULL(VG_Z_LIBCXX_SONAME,    _ZnajRKSt9nothrow_t, __builtin_vec_new );
+  ALLOC_or_NULL(SO_SYN_MALLOC,         _ZnajRKSt9nothrow_t, __builtin_vec_new );
+ #endif
+ // operator new[](unsigned long, std::nothrow_t const&), GNU mangling
+ #if VG_WORDSIZE == 8
+  ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnamRKSt9nothrow_t, __builtin_vec_new );
+  ALLOC_or_NULL(VG_Z_LIBCXX_SONAME,    _ZnamRKSt9nothrow_t, __builtin_vec_new );
+  ALLOC_or_NULL(SO_SYN_MALLOC,         _ZnajRKSt9nothrow_t, __builtin_vec_new );
+ #endif
+
 #elif defined(VGO_darwin)
  // operator new[](unsigned, std::nothrow_t const&), GNU mangling
  #if VG_WORDSIZE == 4
@@ -702,6 +805,20 @@ extern int *__errno_location (void) __attribute__((weak));
   ALLOC_or_NULL_ALIGNED(SO_SYN_MALLOC,         _ZnamSt11align_val_tRKSt9nothrow_t, __builtin_vec_new_aligned );
  #endif
 
+#elif defined(VGO_freebsd)
+ // operator new[](unsigned int, std::align_val_t, std::nothrow_t const&), GNU mangling
+ #if VG_WORDSIZE == 4
+  ALLOC_or_NULL_ALIGNED(VG_Z_LIBSTDCXX_SONAME, _ZnajSt11align_val_tRKSt9nothrow_t, __builtin_vec_new_aligned );
+  ALLOC_or_NULL_ALIGNED(VG_Z_LIBCXX_SONAME,    _ZnajSt11align_val_tRKSt9nothrow_t, __builtin_vec_new_aligned );
+  ALLOC_or_NULL_ALIGNED(SO_SYN_MALLOC,         _ZnajSt11align_val_tRKSt9nothrow_t, __builtin_vec_new_aligned );
+ #endif
+ // operator new[](unsigned long, std::align_val_t, std::nothrow_t const&), GNU mangling
+ #if VG_WORDSIZE == 8
+  ALLOC_or_NULL_ALIGNED(VG_Z_LIBSTDCXX_SONAME, _ZnamSt11align_val_tRKSt9nothrow_t, __builtin_vec_new_aligned );
+  ALLOC_or_NULL_ALIGNED(VG_Z_LIBCXX_SONAME,    _ZnamSt11align_val_tRKSt9nothrow_t, __builtin_vec_new_aligned );
+  ALLOC_or_NULL_ALIGNED(SO_SYN_MALLOC,         _ZnamSt11align_val_tRKSt9nothrow_t, __builtin_vec_new_aligned );
+ #endif
+
 #elif defined(VGO_darwin)
 
 #elif defined(VGO_solaris)
@@ -754,6 +871,10 @@ extern int *__errno_location (void) __attribute__((weak));
  FREE(VG_Z_LIBC_SONAME,       free,                 free );
  FREE(SO_SYN_MALLOC,          free,                 free );
 
+#elif defined(VGO_freebsd)
+ FREE(VG_Z_LIBC_SONAME,       free,                 free );
+ FREE(SO_SYN_MALLOC,          free,                 free );
+
 #elif defined(VGO_darwin)
  FREE(VG_Z_LIBC_SONAME,       free,                 free );
  FREE(SO_SYN_MALLOC,          free,                 free );
@@ -815,6 +936,21 @@ extern int *__errno_location (void) __attribute__((weak));
 #endif
 
 
+#elif defined(VGO_freebsd)
+ FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdlPv,               __builtin_delete );
+ FREE(VG_Z_LIBCXX_SONAME,     _ZdlPv,               __builtin_delete );
+ FREE(SO_SYN_MALLOC,          _ZdlPv,               __builtin_delete );
+ // operator delete(void*, unsigned long), C++14, GNU mangling
+#if __SIZEOF_SIZE_T__ == 4
+ FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdlPvj,               __builtin_delete );
+ FREE(VG_Z_LIBCXX_SONAME,     _ZdlPvj,               __builtin_delete );
+ FREE(SO_SYN_MALLOC,          _ZdlPvj,               __builtin_delete );
+#elif __SIZEOF_SIZE_T__ == 8
+ FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdlPvm,               __builtin_delete );
+ FREE(VG_Z_LIBCXX_SONAME,     _ZdlPvm,               __builtin_delete );
+ FREE(SO_SYN_MALLOC,          _ZdlPvm,               __builtin_delete );
+#endif
+
 #elif defined(VGO_darwin)
  // operator delete(void*), GNU mangling
  //FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdlPv,               __builtin_delete );
@@ -860,6 +996,23 @@ extern int *__errno_location (void) __attribute__((weak));
  FREE(SO_SYN_MALLOC,          _ZdlPvmSt11align_val_t,               __builtin_delete_aligned );
 #endif
 
+#elif defined(VGO_freebsd)
+ // operator delete(void*, std::align_val_t), GNU mangling
+ FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdlPvSt11align_val_t,               __builtin_delete_aligned );
+ FREE(VG_Z_LIBCXX_SONAME,     _ZdlPvSt11align_val_t,               __builtin_delete_aligned );
+ FREE(SO_SYN_MALLOC,          _ZdlPvSt11align_val_t,               __builtin_delete_aligned );
+
+ // operator delete(void*, unsigned int, std::align_val_t), GNU mangling
+#if __SIZEOF_SIZE_T__ == 4
+ FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdlPvjSt11align_val_t,               __builtin_delete_aligned );
+ FREE(VG_Z_LIBCXX_SONAME,     _ZdlPvjSt11align_val_t,               __builtin_delete_aligned );
+ FREE(SO_SYN_MALLOC,          _ZdlPvjSt11align_val_t,               __builtin_delete_aligned );
+ // operator delete(void*, unsigned long, std::align_val_t), GNU mangling
+#elif __SIZEOF_SIZE_T__ == 8
+ FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdlPvmSt11align_val_t,               __builtin_delete_aligned );
+ FREE(VG_Z_LIBCXX_SONAME,     _ZdlPvmSt11align_val_t,               __builtin_delete_aligned );
+ FREE(SO_SYN_MALLOC,          _ZdlPvmSt11align_val_t,               __builtin_delete_aligned );
+#endif
 
 #elif defined(VGO_darwin)
 
@@ -890,6 +1043,12 @@ extern int *__errno_location (void) __attribute__((weak));
  FREE(VG_Z_LIBC_SONAME,      _ZdlPvRKSt9nothrow_t,  __builtin_delete );
  FREE(SO_SYN_MALLOC,         _ZdlPvRKSt9nothrow_t,  __builtin_delete );
 
+#elif defined(VGO_freebsd)
+ // operator delete(void*, std::nothrow_t const&), GNU mangling
+ FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPvRKSt9nothrow_t,  __builtin_delete );
+ FREE(VG_Z_LIBCXX_SONAME,    _ZdlPvRKSt9nothrow_t,  __builtin_delete );
+ FREE(SO_SYN_MALLOC,         _ZdlPvRKSt9nothrow_t,  __builtin_delete );
+
 #elif defined(VGO_darwin)
  // operator delete(void*, std::nothrow_t const&), GNU mangling
  //FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPvRKSt9nothrow_t,  __builtin_delete );
@@ -913,6 +1072,12 @@ extern int *__errno_location (void) __attribute__((weak));
 
  // no sized version of this operator
 
+#elif defined(VGO_freebsd)
+ // operator delete(void*, std::align_val_t, std::nothrow_t const&), GNU mangling
+ FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPvSt11align_val_tRKSt9nothrow_t,  __builtin_delete_aligned );
+ FREE(VG_Z_LIBCXX_SONAME,    _ZdlPvSt11align_val_tRKSt9nothrow_t,  __builtin_delete_aligned );
+ FREE(SO_SYN_MALLOC,         _ZdlPvSt11align_val_tRKSt9nothrow_t,  __builtin_delete_aligned );
+
 #elif defined(VGO_darwin)
 
 #elif defined(VGO_solaris)
@@ -951,6 +1116,22 @@ extern int *__errno_location (void) __attribute__((weak));
  FREE(SO_SYN_MALLOC,          _ZdaPvm,              __builtin_vec_delete );
 #endif
 
+#elif defined(VGO_freebsd)
+ // operator delete[](void*), GNU mangling
+ FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdaPv,               __builtin_vec_delete );
+ FREE(VG_Z_LIBCXX_SONAME,     _ZdaPv,               __builtin_vec_delete );
+ FREE(SO_SYN_MALLOC,          _ZdaPv,               __builtin_vec_delete );
+ // operator delete[](void*, unsigned long), C++14, GNU mangling
+  #if __SIZEOF_SIZE_T__ == 4
+  FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdaPvj,              __builtin_vec_delete );
+  FREE(VG_Z_LIBCXX_SONAME,     _ZdaPvj,              __builtin_vec_delete );
+  FREE(SO_SYN_MALLOC,          _ZdaPvj,              __builtin_vec_delete );
+ #elif __SIZEOF_SIZE_T__ == 8
+  FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdaPvm,              __builtin_vec_delete );
+  FREE(VG_Z_LIBCXX_SONAME,     _ZdaPvm,              __builtin_vec_delete );
+  FREE(SO_SYN_MALLOC,          _ZdaPvm,              __builtin_vec_delete );
+ #endif
+
 #elif defined(VGO_darwin)
  // operator delete[](void*), not mangled (for gcc 2.96)
  //FREE(VG_Z_LIBSTDCXX_SONAME,   __builtin_vec_delete, __builtin_vec_delete );
@@ -999,6 +1180,24 @@ extern int *__errno_location (void) __attribute__((weak));
  FREE(SO_SYN_MALLOC,          _ZdaPvmSt11align_val_t, __builtin_vec_delete_aligned );
 #endif
 
+#elif defined(VGO_freebsd)
+ // operator delete[](void*, std::align_val_t), GNU mangling
+ FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdaPvSt11align_val_t, __builtin_vec_delete_aligned );
+ FREE(VG_Z_LIBCXX_SONAME,     _ZdaPvSt11align_val_t, __builtin_vec_delete_aligned );
+ FREE(SO_SYN_MALLOC,          _ZdaPvSt11align_val_t, __builtin_vec_delete_aligned );
+
+ // operator delete[](void*, unsigned int, std::align_val_t), GNU mangling
+ #if __SIZEOF_SIZE_T__ == 4
+ FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdaPvjSt11align_val_t, __builtin_vec_delete_aligned );
+ FREE(VG_Z_LIBCXX_SONAME,     _ZdaPvjSt11align_val_t, __builtin_vec_delete_aligned );
+ FREE(SO_SYN_MALLOC,          _ZdaPvjSt11align_val_t, __builtin_vec_delete_aligned );
+ // operator delete[](void*, unsigned long, std::align_val_t), GNU mangling
+ #elif __SIZEOF_SIZE_T__ == 8
+ FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdaPvmSt11align_val_t, __builtin_vec_delete_aligned );
+ FREE(VG_Z_LIBCXX_SONAME,     _ZdaPvmSt11align_val_t, __builtin_vec_delete_aligned );
+ FREE(SO_SYN_MALLOC,          _ZdaPvmSt11align_val_t, __builtin_vec_delete_aligned );
+#endif
+
 #elif defined(VGO_darwin)
 
 #elif defined(VGO_solaris)
@@ -1027,6 +1226,12 @@ extern int *__errno_location (void) __attribute__((weak));
  FREE(VG_Z_LIBC_SONAME,       _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
  FREE(SO_SYN_MALLOC,          _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
 
+#elif defined(VGO_freebsd)
+ // operator delete[](void*, std::nothrow_t const&), GNU mangling
+ FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
+ FREE(VG_Z_LIBCXX_SONAME,     _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
+ FREE(SO_SYN_MALLOC,          _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
+
 #elif defined(VGO_darwin)
  // operator delete[](void*, std::nothrow_t const&), GNU mangling
  //FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
@@ -1050,6 +1255,12 @@ extern int *__errno_location (void) __attribute__((weak));
 
  // no sized version of this operator
 
+#elif defined(VGO_freebsd)
+ // operator delete[](void*, std::align_val_t, std::nothrow_t const&), GNU mangling
+ FREE(VG_Z_LIBSTDCXX_SONAME,  _ZdaPvSt11align_val_tRKSt9nothrow_t, __builtin_vec_delete_aligned );
+ FREE(VG_Z_LIBCXX_SONAME,     _ZdaPvSt11align_val_tRKSt9nothrow_t, __builtin_vec_delete_aligned );
+ FREE(SO_SYN_MALLOC,          _ZdaPvSt11align_val_tRKSt9nothrow_t, __builtin_vec_delete_aligned );
+
 #elif defined(VGO_darwin)
 
 #elif defined(VGO_solaris)
@@ -1116,6 +1327,10 @@ extern int *__errno_location (void) __attribute__((weak));
  CALLOC(VG_Z_LIBC_SONAME, calloc);
  CALLOC(SO_SYN_MALLOC,    calloc);
 
+#elif defined(VGO_freebsd)
+ CALLOC(VG_Z_LIBC_SONAME, calloc);
+ CALLOC(SO_SYN_MALLOC,    calloc);
+
 #elif defined(VGO_darwin)
  CALLOC(VG_Z_LIBC_SONAME, calloc);
  CALLOC(SO_SYN_MALLOC,    calloc);
@@ -1187,10 +1402,46 @@ extern int *__errno_location (void) __attribute__((weak));
       return v; \
    }
 
+#define REALLOCF(soname, fnname) \
+   \
+   void* VG_REPLACE_FUNCTION_EZU(10091,soname,fnname) \
+            ( void* ptrV, SizeT new_size );\
+   void* VG_REPLACE_FUNCTION_EZU(10091,soname,fnname) \
+            ( void* ptrV, SizeT new_size ) \
+   { \
+      void* v; \
+      \
+      if (!init_done) init(); \
+      MALLOC_TRACE("reallocf(%p,%llu)", ptrV, (ULong)new_size ); \
+      \
+      if (ptrV == NULL) \
+         /* We need to call a malloc-like function; so let's use \
+            one which we know exists. */ \
+         return VG_REPLACE_FUNCTION_EZU(10010,VG_Z_LIBC_SONAME,malloc) \
+                   (new_size); \
+      if (new_size <= 0) { \
+         VG_REPLACE_FUNCTION_EZU(10050,VG_Z_LIBC_SONAME,free)(ptrV); \
+         MALLOC_TRACE(" = 0\n"); \
+         return NULL; \
+      } \
+      v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_realloc, ptrV, new_size ); \
+      MALLOC_TRACE(" = %p\n", v ); \
+      if (v == NULL) \
+         VG_REPLACE_FUNCTION_EZU(10050,VG_Z_LIBC_SONAME,free)(ptrV); \
+      MALLOC_TRACE(" = %p\n", v ); \
+      return v; \
+   }
+
 #if defined(VGO_linux)
  REALLOC(VG_Z_LIBC_SONAME, realloc);
  REALLOC(SO_SYN_MALLOC,    realloc);
 
+#elif defined(VGO_freebsd)
+ REALLOC(VG_Z_LIBC_SONAME, realloc);
+ REALLOC(SO_SYN_MALLOC,    realloc);
+ REALLOCF(VG_Z_LIBC_SONAME, reallocf);
+ REALLOCF(SO_SYN_MALLOC, reallocf);
+
 #elif defined(VGO_darwin)
  REALLOC(VG_Z_LIBC_SONAME, realloc);
  REALLOC(SO_SYN_MALLOC,    realloc);
@@ -1265,6 +1516,10 @@ extern int *__errno_location (void) __attribute__((weak));
  MEMALIGN(VG_Z_LIBC_SONAME, memalign);
  MEMALIGN(SO_SYN_MALLOC,    memalign);
 
+#elif defined(VGO_freebsd)
+ MEMALIGN(VG_Z_LIBC_SONAME, memalign);
+ MEMALIGN(SO_SYN_MALLOC,    memalign);
+
 #elif defined(VGO_darwin)
  MEMALIGN(VG_Z_LIBC_SONAME, memalign);
  MEMALIGN(SO_SYN_MALLOC,    memalign);
@@ -1312,6 +1567,10 @@ extern int *__errno_location (void) __attribute__((weak));
  VALLOC(VG_Z_LIBC_SONAME, valloc);
  VALLOC(SO_SYN_MALLOC, valloc);
 
+#elif defined(VGO_freebsd)
+ VALLOC(VG_Z_LIBC_SONAME, valloc);
+ VALLOC(SO_SYN_MALLOC, valloc);
+
 #elif defined(VGO_darwin)
  VALLOC(VG_Z_LIBC_SONAME, valloc);
  VALLOC(SO_SYN_MALLOC, valloc);
@@ -1429,6 +1688,10 @@ extern int *__errno_location (void) __attribute__((weak));
  POSIX_MEMALIGN(VG_Z_LIBC_SONAME, posix_memalign);
  POSIX_MEMALIGN(SO_SYN_MALLOC,    posix_memalign);
 
+#elif defined(VGO_freebsd)
+ POSIX_MEMALIGN(VG_Z_LIBC_SONAME, posix_memalign);
+ POSIX_MEMALIGN(SO_SYN_MALLOC,    posix_memalign);
+
 #elif defined(VGO_darwin)
  //POSIX_MEMALIGN(VG_Z_LIBC_SONAME, posix_memalign);
 
@@ -1438,13 +1701,53 @@ extern int *__errno_location (void) __attribute__((weak));
 
 #endif
 
+ /*---------------------- aligned_alloc ----------------------*/
+
+ #define ALIGNED_ALLOC(soname, fnname) \
+    \
+    void* VG_REPLACE_FUNCTION_EZU(10170,soname,fnname) \
+           ( SizeT alignment, SizeT size ); \
+    void* VG_REPLACE_FUNCTION_EZU(10170,soname,fnname) \
+           ( SizeT alignment, SizeT size ) \
+    { \
+       void *mem; \
+       \
+       /* Test whether the alignment argument is valid.  It must be \
+          a power of two multiple of sizeof (void *).  */ \
+       if (alignment == 0 \
+           || alignment % sizeof (void *) != 0 \
+           || (alignment & (alignment - 1)) != 0) \
+          return 0; \
+       \
+       mem = VG_REPLACE_FUNCTION_EZU(10110,VG_Z_LIBC_SONAME,memalign) \
+                (alignment, size); \
+       \
+       return mem; \
+    }
+
+ #if defined(VGO_linux)
+  ALIGNED_ALLOC(VG_Z_LIBC_SONAME, aligned_alloc);
+  ALIGNED_ALLOC(SO_SYN_MALLOC,    aligned_alloc);
+
+#elif defined(VGO_freebsd)
+ ALIGNED_ALLOC(G_Z_LIBC_SONAME, aligned_alloc);
+ ALIGNED_ALLOC(SO_SYN_MALLOC,   aligned_alloc);
+
+ #elif defined(VGO_darwin)
+  //ALIGNED_ALLOC(VG_Z_LIBC_SONAME, aligned_alloc);
+
+ #elif defined(VGO_solaris)
+  ALIGNED_ALLOC(VG_Z_LIBC_SONAME, aligned_alloc);
+  ALIGNED_ALLOC(SO_SYN_MALLOC,    aligned_alloc);
+
+ #endif
 
 /*---------------------- malloc_usable_size ----------------------*/
 
 #define MALLOC_USABLE_SIZE(soname, fnname) \
    \
-   SizeT VG_REPLACE_FUNCTION_EZU(10170,soname,fnname) ( void* p ); \
-   SizeT VG_REPLACE_FUNCTION_EZU(10170,soname,fnname) ( void* p ) \
+   SizeT VG_REPLACE_FUNCTION_EZU(10180,soname,fnname) ( void* p ); \
+   SizeT VG_REPLACE_FUNCTION_EZU(10180,soname,fnname) ( void* p ) \
    {  \
       SizeT pszB; \
       \
@@ -1470,6 +1773,10 @@ extern int *__errno_location (void) __attribute__((weak));
   MALLOC_USABLE_SIZE(SO_SYN_MALLOC,    dlmalloc_usable_size);
 # endif
 
+#elif defined(VGO_freebsd)
+ MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, malloc_usable_size);
+ MALLOC_USABLE_SIZE(SO_SYN_MALLOC,    malloc_usable_size);
+
 #elif defined(VGO_darwin)
  //MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, malloc_usable_size);
  MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, malloc_size);
@@ -1491,8 +1798,8 @@ static void panic(const char *str)
 
 #define PANIC(soname, fnname) \
    \
-   void VG_REPLACE_FUNCTION_EZU(10180,soname,fnname) ( void ); \
-   void VG_REPLACE_FUNCTION_EZU(10180,soname,fnname) ( void )  \
+   void VG_REPLACE_FUNCTION_EZU(10190,soname,fnname) ( void ); \
+   void VG_REPLACE_FUNCTION_EZU(10190,soname,fnname) ( void )  \
    { \
       panic(#fnname); \
    }
@@ -1512,8 +1819,8 @@ static void panic(const char *str)
 
 #define MALLOC_STATS(soname, fnname) \
    \
-   void VG_REPLACE_FUNCTION_EZU(10190,soname,fnname) ( void ); \
-   void VG_REPLACE_FUNCTION_EZU(10190,soname,fnname) ( void )  \
+   void VG_REPLACE_FUNCTION_EZU(10200,soname,fnname) ( void ); \
+   void VG_REPLACE_FUNCTION_EZU(10200,soname,fnname) ( void )  \
    { \
       /* Valgrind's malloc_stats implementation does nothing. */ \
    }
@@ -1535,8 +1842,8 @@ static void panic(const char *str)
 // doesn't know that the call to mallinfo fills in mi.
 #define MALLINFO(soname, fnname) \
    \
-   struct vg_mallinfo VG_REPLACE_FUNCTION_EZU(10200,soname,fnname) ( void ); \
-   struct vg_mallinfo VG_REPLACE_FUNCTION_EZU(10200,soname,fnname) ( void ) \
+   struct vg_mallinfo VG_REPLACE_FUNCTION_EZU(10210,soname,fnname) ( void ); \
+   struct vg_mallinfo VG_REPLACE_FUNCTION_EZU(10210,soname,fnname) ( void ) \
    { \
       static struct vg_mallinfo mi; \
       DO_INIT; \
@@ -1597,8 +1904,8 @@ static vki_malloc_zone_t vg_default_zone = {
 
 #define DEFAULT_ZONE(soname, fnname) \
    \
-   void *VG_REPLACE_FUNCTION_EZU(10210,soname,fnname) ( void ); \
-   void *VG_REPLACE_FUNCTION_EZU(10210,soname,fnname) ( void )  \
+   void *VG_REPLACE_FUNCTION_EZU(10220,soname,fnname) ( void ); \
+   void *VG_REPLACE_FUNCTION_EZU(10220,soname,fnname) ( void )  \
    { \
       return &vg_default_zone; \
    }
@@ -1611,8 +1918,8 @@ DEFAULT_ZONE(SO_SYN_MALLOC,    malloc_default_purgeable_zone);
 
 #define CREATE_ZONE(soname, fnname) \
    \
-   void *VG_REPLACE_FUNCTION_EZU(10220,soname,fnname)(size_t sz, unsigned fl); \
-   void *VG_REPLACE_FUNCTION_EZU(10220,soname,fnname)(size_t sz, unsigned fl)  \
+   void *VG_REPLACE_FUNCTION_EZU(10230,soname,fnname)(size_t sz, unsigned fl); \
+   void *VG_REPLACE_FUNCTION_EZU(10230,soname,fnname)(size_t sz, unsigned fl)  \
    { \
       return &vg_default_zone; \
    }
@@ -1621,8 +1928,8 @@ CREATE_ZONE(VG_Z_LIBC_SONAME, malloc_create_zone);
 
 #define ZONE_FROM_PTR(soname, fnname) \
    \
-   void *VG_REPLACE_FUNCTION_EZU(10230,soname,fnname) ( void* ptr ); \
-   void *VG_REPLACE_FUNCTION_EZU(10230,soname,fnname) ( void* ptr )  \
+   void *VG_REPLACE_FUNCTION_EZU(10240,soname,fnname) ( void* ptr ); \
+   void *VG_REPLACE_FUNCTION_EZU(10240,soname,fnname) ( void* ptr )  \
    { \
       return &vg_default_zone; \
    }
@@ -1634,8 +1941,8 @@ ZONE_FROM_PTR(SO_SYN_MALLOC,    malloc_zone_from_ptr);
 // GrP fixme bypass libc's use of zone->introspect->check
 #define ZONE_CHECK(soname, fnname) \
    \
-   int VG_REPLACE_FUNCTION_EZU(10240,soname,fnname)(void* zone); \
-   int VG_REPLACE_FUNCTION_EZU(10240,soname,fnname)(void* zone)  \
+   int VG_REPLACE_FUNCTION_EZU(10250,soname,fnname)(void* zone); \
+   int VG_REPLACE_FUNCTION_EZU(10250,soname,fnname)(void* zone)  \
    { \
       TRIGGER_MEMCHECK_ERROR_IF_UNDEFINED(zone); \
       panic(#fnname); \
@@ -1648,8 +1955,8 @@ ZONE_CHECK(SO_SYN_MALLOC,    malloc_zone_check);
 
 #define ZONE_REGISTER(soname, fnname) \
    \
-   void VG_REPLACE_FUNCTION_EZU(10250,soname,fnname)(void* zone); \
-   void VG_REPLACE_FUNCTION_EZU(10250,soname,fnname)(void* zone)  \
+   void VG_REPLACE_FUNCTION_EZU(10260,soname,fnname)(void* zone); \
+   void VG_REPLACE_FUNCTION_EZU(10260,soname,fnname)(void* zone)  \
    { \
       TRIGGER_MEMCHECK_ERROR_IF_UNDEFINED(zone); \
    }
@@ -1660,8 +1967,8 @@ ZONE_REGISTER(SO_SYN_MALLOC,    malloc_zone_register);
 
 #define ZONE_UNREGISTER(soname, fnname) \
    \
-   void VG_REPLACE_FUNCTION_EZU(10260,soname,fnname)(void* zone); \
-   void VG_REPLACE_FUNCTION_EZU(10260,soname,fnname)(void* zone)  \
+   void VG_REPLACE_FUNCTION_EZU(10270,soname,fnname)(void* zone); \
+   void VG_REPLACE_FUNCTION_EZU(10270,soname,fnname)(void* zone)  \
    { \
       TRIGGER_MEMCHECK_ERROR_IF_UNDEFINED(zone); \
    }
@@ -1672,8 +1979,8 @@ ZONE_UNREGISTER(SO_SYN_MALLOC,    malloc_zone_unregister);
 
 #define ZONE_SET_NAME(soname, fnname) \
    \
-   void VG_REPLACE_FUNCTION_EZU(10270,soname,fnname)(void* zone, char* nm); \
-   void VG_REPLACE_FUNCTION_EZU(10270,soname,fnname)(void* zone, char* nm)  \
+   void VG_REPLACE_FUNCTION_EZU(10280,soname,fnname)(void* zone, char* nm); \
+   void VG_REPLACE_FUNCTION_EZU(10280,soname,fnname)(void* zone, char* nm)  \
    { \
       TRIGGER_MEMCHECK_ERROR_IF_UNDEFINED(zone); \
    }
@@ -1684,8 +1991,8 @@ ZONE_SET_NAME(SO_SYN_MALLOC,    malloc_set_zone_name);
 
 #define ZONE_GET_NAME(soname, fnname) \
    \
-   const char* VG_REPLACE_FUNCTION_EZU(10280,soname,fnname)(void* zone); \
-   const char* VG_REPLACE_FUNCTION_EZU(10280,soname,fnname)(void* zone)  \
+   const char* VG_REPLACE_FUNCTION_EZU(10290,soname,fnname)(void* zone); \
+   const char* VG_REPLACE_FUNCTION_EZU(10290,soname,fnname)(void* zone)  \
    { \
       TRIGGER_MEMCHECK_ERROR_IF_UNDEFINED(zone); \
       return vg_default_zone.zone_name; \
index 4420a22d719026fc4c517e1aad7806aeda81e7f0..ea36cd4f5640475277458ef34ddaf3b99d77bac5 100644 (file)
@@ -519,7 +519,7 @@ void VG_(vg_yield)(void)
    /* 
       Tell the kernel we're yielding.
     */
-#  if defined(VGO_linux) || defined(VGO_darwin)
+#  if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
    VG_(do_syscall0)(__NR_sched_yield);
 #  elif defined(VGO_solaris)
    VG_(do_syscall0)(__NR_yield);
@@ -545,6 +545,7 @@ static void block_signals(void)
    VG_(sigdelset)(&mask, VKI_SIGFPE);
    VG_(sigdelset)(&mask, VKI_SIGILL);
    VG_(sigdelset)(&mask, VKI_SIGTRAP);
+   VG_(sigdelset)(&mask, VKI_SIGSYS);
 
    /* Can't block these anyway */
    VG_(sigdelset)(&mask, VKI_SIGSTOP);
@@ -560,6 +561,8 @@ static void os_state_clear(ThreadState *tst)
    tst->os_state.stk_id = NULL_STK_ID;
 #  if defined(VGO_linux)
    /* no other fields to clear */
+#  elif defined(VGO_freebsd)
+   /* no other fields to clear */
 #  elif defined(VGO_darwin)
    tst->os_state.post_mach_trap_fn = NULL;
    tst->os_state.pthread           = 0;
index 61e10dcf0b0d90e87522e9847590a3740396f6f5..5954cdf8f3e79ba54cc7a894d6caea9cbe89f251 100644 (file)
@@ -108,8 +108,8 @@ void ML_(sema_down)( vg_sema_t *sema, Bool as_LL )
    INNER_REQUEST(ANNOTATE_RWLOCK_ACQUIRED(sema, /*is_w*/1));
 
    if (ret != 1) 
-      VG_(debugLog)(0, "scheduler", 
-                       "VG_(sema_down): read returned %d\n", ret);
+      VG_(debugLog)(1, "scheduler",
+                       "ML_(sema_down): read returned %d\n", ret);
 
    if (ret == -VKI_EINTR)
       goto again;
index fd33367bf5242988d409128131518de9887dadab..3812c22f83c0b8f55c9f8b43caeefb665b9aee80 100644 (file)
@@ -47,7 +47,7 @@ static void track_frame_memory ( Addr addr, SizeT size, ThreadId tid )
    VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB, size, tid );
 }
 
-#if defined(VGO_linux) || defined(VGO_solaris)
+#if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 /* Extend the stack segment downwards if needed so as to ensure the
    new signal frames are mapped to something.  Return a Bool
index b45afe59923245352ac17fdd1eeeb5e220f912be..9210db8e5e19ab4d59e4b5301132d36e9bcc952c 100644 (file)
@@ -514,6 +514,38 @@ typedef struct SigQueue {
       srP->misc.AMD64.r_rbp = (ULong)(ss->__rbp);
    }
 
+#elif defined(VGP_x86_freebsd)
+#  define VG_UCONTEXT_INSTR_PTR(uc)       ((UWord)(uc)->uc_mcontext.eip)
+#  define VG_UCONTEXT_STACK_PTR(uc)       ((UWord)(uc)->uc_mcontext.esp)
+#  define VG_UCONTEXT_FRAME_PTR(uc)       ((UWord)(uc)->uc_mcontext.ebp)
+#  define VG_UCONTEXT_SYSCALL_NUM(uc)     ((UWord)(uc)->uc_mcontext.eax)
+#  define VG_UCONTEXT_SYSCALL_SYSRES(uc)                        \
+      /* Convert the value in uc_mcontext.eax into a SysRes. */ \
+      VG_(mk_SysRes_x86_freebsd)( (uc)->uc_mcontext.eax, \
+        (uc)->uc_mcontext.edx, ((uc)->uc_mcontext.eflags & 1) != 0 ? True : False)
+#  define VG_UCONTEXT_LINK_REG(uc)        0 /* What is an LR for anyway? */
+#  define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc)        \
+      { (srP)->r_pc = (ULong)((uc)->uc_mcontext.eip);    \
+        (srP)->r_sp = (ULong)((uc)->uc_mcontext.esp);    \
+        (srP)->misc.X86.r_ebp = (uc)->uc_mcontext.ebp;   \
+      }
+
+#elif defined(VGP_amd64_freebsd)
+#  define VG_UCONTEXT_INSTR_PTR(uc)       ((uc)->uc_mcontext.rip)
+#  define VG_UCONTEXT_STACK_PTR(uc)       ((uc)->uc_mcontext.rsp)
+#  define VG_UCONTEXT_FRAME_PTR(uc)       ((uc)->uc_mcontext.rbp)
+#  define VG_UCONTEXT_SYSCALL_NUM(uc)     ((uc)->uc_mcontext.rax)
+#  define VG_UCONTEXT_SYSCALL_SYSRES(uc)                        \
+      /* Convert the value in uc_mcontext.rax into a SysRes. */ \
+      VG_(mk_SysRes_amd64_freebsd)( (uc)->uc_mcontext.rax, \
+     (uc)->uc_mcontext.rdx, ((uc)->uc_mcontext.rflags & 1) != 0 ? True : False )
+#  define VG_UCONTEXT_LINK_REG(uc)        0 /* No LR on amd64 either */
+#  define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc)        \
+      { (srP)->r_pc = (uc)->uc_mcontext.rip;             \
+        (srP)->r_sp = (uc)->uc_mcontext.rsp;             \
+        (srP)->misc.AMD64.r_rbp = (uc)->uc_mcontext.rbp; \
+      }
+
 #elif defined(VGP_s390x_linux)
 
 #  define VG_UCONTEXT_INSTR_PTR(uc)       ((uc)->uc_mcontext.regs.psw.addr)
@@ -631,7 +663,7 @@ typedef struct SigQueue {
 #if defined(VGO_linux)
 #  define VKI_SIGINFO_si_addr  _sifields._sigfault._addr
 #  define VKI_SIGINFO_si_pid   _sifields._kill._pid
-#elif defined(VGO_darwin) || defined(VGO_solaris)
+#elif defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
 #  define VKI_SIGINFO_si_addr  si_addr
 #  define VKI_SIGINFO_si_pid   si_pid
 #else
@@ -790,6 +822,9 @@ void calculate_SKSS_from_SCSS ( SKSS* dst )
       case VKI_SIGFPE:
       case VKI_SIGILL:
       case VKI_SIGTRAP:
+#if defined(VGO_freebsd)
+      case VKI_SIGSYS:
+#endif
         /* For these, we always want to catch them and report, even
            if the client code doesn't. */
         skss_handler = sync_signalhandler;
@@ -857,7 +892,8 @@ void calculate_SKSS_from_SCSS ( SKSS* dst )
       /* We don't set a signal stack, so ignore */
 
       /* always ask for SA_SIGINFO */
-      skss_flags |= VKI_SA_SIGINFO;
+      if (skss_handler != VKI_SIG_IGN && skss_handler != VKI_SIG_DFL)
+         skss_flags |= VKI_SA_SIGINFO;
 
       /* use our own restorer */
       skss_flags |= VKI_SA_RESTORER;
@@ -1020,7 +1056,14 @@ extern void my_sigreturn(void);
    "my_sigreturn:\n" \
    "ud2\n" \
    ".previous\n"
-
+#elif defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd)
+/* Not used on FreeBSD */
+# define _MY_SIGRETURN(name) \
+    ".text\n" \
+    ".globl my_sigreturn\n" \
+    "my_sigreturn:\n" \
+    "ud2\n" \
+    ".previous\n"
 #else
 #  error Unknown platform
 #endif
@@ -1064,7 +1107,7 @@ static void handle_SCSS_change ( Bool force_update )
       ksa.sa_flags    = skss.skss_per_sig[sig].skss_flags;
 #     if !defined(VGP_ppc32_linux) && \
          !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \
-         !defined(VGP_mips32_linux) && !defined(VGO_solaris)
+         !defined(VGP_mips32_linux) && !defined(VGO_solaris) && !defined(VGO_freebsd)
       ksa.sa_restorer = my_sigreturn;
 #     endif
       /* Re above ifdef (also the assertion below), PaulM says:
@@ -1111,7 +1154,8 @@ static void handle_SCSS_change ( Bool force_update )
 #        if !defined(VGP_ppc32_linux) && \
             !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \
             !defined(VGP_mips32_linux) && !defined(VGP_mips64_linux) && \
-            !defined(VGP_nanomips_linux) && !defined(VGO_solaris)
+            !defined(VGP_nanomips_linux) && !defined(VGO_solaris) && \
+            !defined(VGO_freebsd)
          vg_assert(ksa_old.sa_restorer == my_sigreturn);
 #        endif
          VG_(sigaddset)( &ksa_old.sa_mask, VKI_SIGKILL );
@@ -1231,7 +1275,7 @@ SysRes VG_(do_sys_sigaction) ( Int signo,
       old_act->ksa_handler = scss.scss_per_sig[signo].scss_handler;
       old_act->sa_flags    = scss.scss_per_sig[signo].scss_flags;
       old_act->sa_mask     = scss.scss_per_sig[signo].scss_mask;
-#     if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \
+#     if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
          !defined(VGO_solaris)
       old_act->sa_restorer = scss.scss_per_sig[signo].scss_restorer;
 #     endif
@@ -1244,7 +1288,7 @@ SysRes VG_(do_sys_sigaction) ( Int signo,
       scss.scss_per_sig[signo].scss_mask     = new_act->sa_mask;
 
       scss.scss_per_sig[signo].scss_restorer = NULL;
-#     if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \
+#     if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
          !defined(VGO_solaris)
       scss.scss_per_sig[signo].scss_restorer = new_act->sa_restorer;
 #     endif
@@ -1546,6 +1590,9 @@ const HChar *VG_(signame)(Int sigNo)
 #     if defined(VKI_SIGUNUSED) && (VKI_SIGUNUSED != VKI_SIGSYS)
       case VKI_SIGUNUSED: return "SIGUNUSED";
 #     endif
+#     if defined(VKI_SIGINFO)
+      case VKI_SIGINFO: return "SIGINFO";
+#     endif
 
       /* Solaris-specific signals. */
 #     if defined(VKI_SIGEMT)
@@ -1601,7 +1648,7 @@ void VG_(kill_self)(Int sigNo)
 
    sa.ksa_handler = VKI_SIG_DFL;
    sa.sa_flags = 0;
-#  if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \
+#  if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
       !defined(VGO_solaris)
    sa.sa_restorer = 0;
 #  endif
@@ -1638,7 +1685,21 @@ static Bool is_signal_from_kernel(ThreadId tid, int signum, int si_code)
    // macros but we don't use them here because other platforms don't have
    // them.
    return ( si_code > VKI_SI_USER ? True : False );
+#elif defined(VGO_freebsd)
+
+    // The comment below seems a bit out of date. From the siginfo manpage
 
+    // Full support for POSIX signal information first appeared in FreeBSD 7.0.
+    // The codes SI_USER and SI_KERNEL can be generated as of FreeBSD 8.1.  The
+    // code SI_LWP can be      generated as of FreeBSD 9.0.
+    if (si_code == VKI_SI_USER || si_code == VKI_SI_LWP)
+        return False;
+
+   // It looks like there's no reliable way to say where the signal came from
+   if (VG_(threads)[tid].status == VgTs_WaitSys) {
+      return False;
+   } else
+      return True;
 #  elif defined(VGO_darwin)
    // On Darwin 9.6.0, the si_code is completely unreliable.  It should be the
    // case that 0 means "user", and >0 means "kernel".  But:
@@ -1857,6 +1918,14 @@ static void default_action(const vki_siginfo_t *info, ThreadId tid)
            case VKI_BUS_ADRALN: event = "Invalid address alignment"; break;
            case VKI_BUS_ADRERR: event = "Non-existent physical address"; break;
            case VKI_BUS_OBJERR: event = "Hardware error"; break;
+#if defined(VGO_freebsd)
+        // This si_code can be generated for both SIGBUS and SIGSEGV on FreeBSD
+        // This is undocumented
+        case VKI_SEGV_PAGE_FAULT:
+        // It should get replaced with this non-standard value, which is documented.
+        case VKI_BUS_OOMERR:
+            event = "Access not within mapped region";
+#endif
            }
            break;
         } /* switch (sigNo) */
@@ -2322,7 +2391,7 @@ static int sanitize_si_code(int si_code)
       mask them off) sign extends them when exporting to user space so
       we do the same thing here. */
    return (Short)si_code;
-#elif defined(VGO_darwin) || defined(VGO_solaris)
+#elif defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
    return si_code;
 #else
 #  error Unknown OS
@@ -2459,9 +2528,9 @@ void async_signalhandler ( Int sigNo,
    info->si_code = sanitize_si_code(info->si_code);
 
    if (VG_(clo_trace_signals))
-      VG_(dmsg)("async signal handler: signal=%d, tid=%u, si_code=%d, "
+      VG_(dmsg)("async signal handler: signal=%d, vgtid=%d, tid=%u, si_code=%d, "
                 "exitreason %s\n",
-                sigNo, tid, info->si_code,
+                sigNo, VG_(gettid)(), tid, info->si_code,
                 VG_(name_of_VgSchedReturnCode)(tst->exitreason));
 
    /* See similar logic in VG_(poll_signals). */
@@ -2947,7 +3016,7 @@ void pp_ksigaction ( vki_sigaction_toK_t* sa )
    VG_(printf)("pp_ksigaction: handler %p, flags 0x%x, restorer %p\n", 
                sa->ksa_handler, 
                (UInt)sa->sa_flags, 
-#              if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \
+#              if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
                   !defined(VGO_solaris)
                   sa->sa_restorer
 #              else
@@ -2970,7 +3039,7 @@ void VG_(set_default_handler)(Int signo)
 
    sa.ksa_handler = VKI_SIG_DFL;
    sa.sa_flags = 0;
-#  if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \
+#  if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
       !defined(VGO_solaris)
    sa.sa_restorer = 0;
 #  endif
@@ -3092,7 +3161,7 @@ void VG_(sigstartup_actions) ( void )
 
         tsa.ksa_handler = (void *)sync_signalhandler;
         tsa.sa_flags = VKI_SA_SIGINFO;
-#        if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \
+#        if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
             !defined(VGO_solaris)
         tsa.sa_restorer = 0;
 #        endif
@@ -3120,7 +3189,7 @@ void VG_(sigstartup_actions) ( void )
       scss.scss_per_sig[i].scss_mask     = sa.sa_mask;
 
       scss.scss_per_sig[i].scss_restorer = NULL;
-#     if !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \
+#     if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
          !defined(VGO_solaris)
       scss.scss_per_sig[i].scss_restorer = sa.sa_restorer;
 #     endif
index d26280cc909aa6ecee5089ffd9d1085cdd8ce405..9467f3caf600eca2426316f7dcaba5be6b5abedb 100644 (file)
@@ -42,6 +42,7 @@
 #include "pub_core_xarray.h"
 #include "pub_core_clientstate.h"   // VG_(client__dl_sysinfo_int80)
 #include "pub_core_trampoline.h"
+#include "config.h"
 
 
 /*------------------------------------------------------------*/
@@ -92,7 +93,7 @@ do {                                                                  \
 /* ------------------------ x86 ------------------------- */
 
 #if defined(VGP_x86_linux) || defined(VGP_x86_darwin) \
-    || defined(VGP_x86_solaris)
+    || defined(VGP_x86_solaris) || defined(VGP_x86_freebsd)
 
 #define N_FP_CF_VERIF 1021
 // prime number so that size of fp_CF_verif is just below 4K or 8K
@@ -238,14 +239,14 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
    if (fp_min + 512 >= fp_max) {
       /* If the stack limits look bogus, don't poke around ... but
          don't bomb out either. */
-#  elif defined(VGO_solaris)
+#  elif defined(VGO_solaris) || defined(VGO_freebsd)
    if (fp_max == 0) {
       /* VG_(get_StackTrace)() can be called by tools very early when
          various tracing options are enabled. Don't proceed further
          if the stack limits look bogus.
        */
 #  endif
-#  if defined(VGO_linux) || defined(VGO_solaris)
+#  if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
       if (sps) sps[0] = uregs.xsp;
       if (fps) fps[0] = uregs.xbp;
       ips[0] = uregs.xip;
@@ -281,6 +282,26 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
    i = 1;
    if (do_stats) stats.nr++;
 
+   // Does this apply to macOS 10.14 and earlier?
+#  if defined(VGO_freebsd) && (FREEBSD_VERS < FREEBSD_13)
+   if (VG_(is_valid_tid)(tid_if_known) &&
+      VG_(is_in_syscall)(tid_if_known) &&
+      i < max_n_ips) {
+      /* On FreeBSD, all the system call stubs have no function
+       * prolog.  So instead of top of the stack being a new
+       * frame comprising a saved BP and a return address, we
+       * just have the return address in the caller's frame.
+       * Adjust for this by recording the return address.
+       */
+      if (debug)
+         VG_(printf)("     in syscall, use XSP-1\n");
+      ips[i] = *(Addr *)uregs.xsp - 1;
+      if (sps) sps[i] = uregs.xsp;
+      if (fps) fps[i] = uregs.xbp;
+      i++;
+   }
+#  endif
+
    while (True) {
 
       if (i >= max_n_ips)
@@ -498,7 +519,7 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
 /* ----------------------- amd64 ------------------------ */
 
 #if defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) \
-    || defined(VGP_amd64_solaris)
+    || defined(VGP_amd64_solaris) || defined(VGP_amd64_freebsd)
 
 UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
                                /*OUT*/Addr* ips, UInt max_n_ips,
@@ -573,16 +594,18 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
       VG_(printf)("     ipsS[%d]=%#08lx rbp %#08lx rsp %#08lx\n",
                   i-1, ips[i-1], uregs.xbp, uregs.xsp);
 
-#  if defined(VGO_darwin)
+#  if defined(VGO_darwin) || (defined(VGO_freebsd) && (FREEBSD_VERS < FREEBSD_13))
    if (VG_(is_valid_tid)(tid_if_known) &&
       VG_(is_in_syscall)(tid_if_known) &&
       i < max_n_ips) {
-      /* On Darwin, all the system call stubs have no function
+      /* On Darwin and FreeBSD, all the system call stubs have no function
        * prolog.  So instead of top of the stack being a new
        * frame comprising a saved BP and a return address, we
        * just have the return address in the caller's frame.
        * Adjust for this by recording the return address.
        */
+      if (debug)
+         VG_(printf)("     in syscall, use XSP-1\n");
       ips[i] = *(Addr *)uregs.xsp - 1;
       if (sps) sps[i] = uregs.xsp;
       if (fps) fps[i] = uregs.xbp;
index c12632d366572fae239c023453abde783cdbaa3a..ad3d71602e374dfb8b1499f1051f8258c40914b9 100644 (file)
@@ -364,6 +364,42 @@ SysRes VG_(mk_SysRes_amd64_solaris) ( Bool isErr, ULong val, ULong val2 )
    return res;
 }
 
+
+#elif defined(VGO_freebsd)
+
+SysRes VG_(mk_SysRes_x86_freebsd) ( UInt val, UInt val2, Bool err ) {
+   SysRes r;
+   r._isError = err;
+   r._val = val;
+   r._val2 = val2;
+   return r;
+}
+
+SysRes VG_(mk_SysRes_amd64_freebsd) ( ULong val, ULong val2, Bool err ) {
+   SysRes r;
+   r._isError = err;
+   r._val = val;
+   r._val2 = val2;
+   return r;
+}
+
+/* Generic constructors. */
+SysRes VG_(mk_SysRes_Error) ( UWord err ) {
+   SysRes r;
+   r._val     = err;
+   r._val2    = 0;
+   r._isError = True;
+   return r;
+}
+
+SysRes VG_(mk_SysRes_Success) ( UWord res ) {
+   SysRes r;
+   r._val     = res;
+   r._val2    = 0;
+   r._isError = False;
+   return r;
+}
+
 #else
 #  error "Unknown OS"
 #endif
@@ -671,6 +707,82 @@ asm(
 ".previous\n"
 );
 
+#elif defined(VGP_x86_freebsd)
+/* Incoming args (syscall number + up to 8 args) are on the stack.
+   FreeBSD has a syscall called 'syscall' that takes all args (including
+   the syscall number) off the stack.  Since we're called, the return
+   address is on the stack as expected, so we can just call syscall(2)
+   and it Just Works.  Error is when carry is set.
+*/
+extern ULong do_syscall_WRK (
+          UWord syscall_no, 
+          UWord a1, UWord a2, UWord a3,
+          UWord a4, UWord a5, UWord a6,
+          UWord a7, UWord a8, UInt *flags
+       );
+asm(
+".text\n"
+"do_syscall_WRK:\n"
+"      movl    $0,%eax\n"      /* syscall number = "syscall" (0) to avoid stack frobbing
+*/
+"      int     $0x80\n"
+"      jb      1f\n"
+"      ret\n"
+"1:    movl    40(%esp),%ecx\n"        /* store carry in *flags */
+"      movl    $1,(%ecx)\n"
+"      ret\n"
+".previous\n"
+);
+
+#elif defined(VGP_amd64_freebsd)
+extern UWord do_syscall_WRK (
+          UWord syscall_no,    /* %rdi */
+          UWord a1,            /* %rsi */
+          UWord a2,            /* %rdx */
+          UWord a3,            /* %rcx */
+          UWord a4,            /* %r8 */
+          UWord a5,            /* %r9 */
+          UWord a6,            /* 8(%rsp) */
+          UWord a7,            /* 16(%rsp) */
+          UWord a8,            /* 24(%rsp) */
+          UInt *flags,         /* 32(%rsp) */
+          UWord *rv2           /* 40(%rsp) */
+       );
+asm(
+".text\n"
+"do_syscall_WRK:\n"
+        /* Convert function calling convention --> syscall calling
+           convention */
+"      pushq   %rbp\n"
+"      movq    %rsp, %rbp\n"
+"      movq    %rdi, %rax\n"    /* syscall_no */
+"      movq    %rsi, %rdi\n"    /* a1 */
+"      movq    %rdx, %rsi\n"    /* a2 */
+"      movq    %rcx, %rdx\n"    /* a3 */
+"      movq    %r8,  %r10\n"    /* a4 */
+"      movq    %r9,  %r8\n"     /* a5 */
+"      movq    16(%rbp), %r9\n"  /* a6 last arg from stack, account for %rbp */
+"      movq    24(%rbp), %r11\n" /* a7 from stack */
+"      pushq  %r11\n"
+"      movq    32(%rbp), %r11\n" /* a8 from stack */
+"      pushq  %r11\n"
+"      subq    $8,%rsp\n"      /* fake return addr */
+"      syscall\n"
+"      jb      1f\n"
+"      movq    48(%rbp),%rsi\n"
+"      movq    %rdx, (%rsi)\n"
+"      movq    %rbp, %rsp\n"
+"      popq    %rbp\n"
+"      ret\n"
+"1:\n"
+"      movq    40(%rbp), %rsi\n"
+"      movl    $1,(%rsi)\n"
+"      movq    %rbp, %rsp\n"
+"      popq    %rbp\n"
+"      ret\n"
+".previous\n"
+);
+
 #elif defined(VGP_x86_darwin)
 
 /* Incoming args (syscall number + up to 8 args) come in on the stack
@@ -1027,6 +1139,21 @@ SysRes VG_(do_syscall) ( UWord sysno, RegWord a1, RegWord a2, RegWord a3,
    UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
    return VG_(mk_SysRes_amd64_linux)( val );
 
+#  elif defined(VGP_x86_freebsd)
+   ULong val;
+   UInt err = 0;
+   val = do_syscall_WRK(sysno, a1, a2, a3, a4, a5,
+                        a6, a7, a8, &err);
+   return VG_(mk_SysRes_x86_freebsd)( (UInt)val, (UInt)(val>>32), (err & 1) != 0 ? True : False);
+
+#  elif defined(VGP_amd64_freebsd)
+   UWord val;
+   UWord val2 = 0;
+   UInt err = 0;
+   val = do_syscall_WRK(sysno, a1, a2, a3, a4, a5,
+                        a6, a7, a8, &err, &val2);
+   return VG_(mk_SysRes_amd64_freebsd)( val, val2, (err & 1) != 0 ? True : False);
+
 #  elif defined(VGP_ppc32_linux)
    ULong ret     = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
    UInt  val     = (UInt)(ret>>32);
@@ -1257,6 +1384,9 @@ const HChar* VG_(strerror) ( UWord errnum )
    case VKI_EOVERFLOW:   return "Value too large for defined data type";
 #     if defined(VKI_ERESTARTSYS)
       case VKI_ERESTARTSYS: return "ERESTARTSYS";
+#     endif
+#     if defined(VKI_ERESTART)
+      case VKI_ERESTART: return "ERESTART";
 #     endif
    default:              return "VG_(strerror): unknown error";
    }
index 7a9fd3260fb90105b9dbd336b36490c736966950..3966cfa604f6aac8ae6fbfcee3d5be1f42add0c7 100644 (file)
@@ -50,6 +50,9 @@
 /* Arguments for a syscall. */
 typedef
    struct SyscallArgs {
+#if defined(VGO_freebsd)
+      Word klass;
+#endif
       Word sysno;
       RegWord arg1;
       RegWord arg2;
@@ -109,6 +112,31 @@ typedef
       Int o_arg6;
       Int o_arg7;
       Int uu_arg8;
+#     elif defined(VGP_x86_freebsd)
+      Int s_arg1;
+      Int s_arg2;
+      Int s_arg3;
+      Int s_arg4;
+      Int s_arg5;
+      Int s_arg6;
+      Int s_arg7;
+      Int s_arg8;
+#     elif defined(VGP_amd64_freebsd)
+      Int o_arg1;
+      Int o_arg2;
+      Int o_arg3;
+      Int o_arg4;
+      Int o_arg5;
+      // arg6 can either be a register or a stack
+      // depending on whether the syscall is 'syscall/__syscall'
+      // or any other syscall
+      union {
+         Int o_arg6;
+         Int s_arg6;
+      };
+      Int s_arg7;
+      Int s_arg8;
+      Bool arg6_is_reg;
 #     elif defined(VGP_mips32_linux)
       Int o_arg1;
       Int o_arg2;
@@ -213,6 +241,10 @@ extern const UInt ML_(syscall_table_size);
 extern
 SyscallTableEntry* ML_(get_solaris_syscall_entry)( UInt sysno );
 
+#elif defined(VGO_freebsd)
+extern
+const SyscallTableEntry* ML_(get_freebsd_syscall_entry)( UInt sysno );
+
 #else
 #  error Unknown OS
 #endif   
@@ -241,9 +273,9 @@ SyscallTableEntry* ML_(get_solaris_syscall_entry)( UInt sysno );
    void vgSysWrap_##auxstr##_##name##_before                     \
                                  ( ThreadId tid,                 \
                                    SyscallArgLayout* layout,     \
-                                   /*MOD*/SyscallArgs* arrghs,   \
-                                   /*OUT*/SyscallStatus* status, \
-                                   /*OUT*/UWord* flags           \
+                                   /*MOD*/ SyscallArgs* arrghs,   \
+                                   /*OUT*/ SyscallStatus* status, \
+                                   /*OUT*/ UWord* flags           \
                                  )
 
 #define DEFN_POST_TEMPLATE(auxstr, name)                         \
@@ -291,7 +323,7 @@ SyscallTableEntry* ML_(get_solaris_syscall_entry)( UInt sysno );
     vgSysWrap_##auxstr##_##name##_after
 
 /* Add a generic wrapper to a syscall table. */
-#if defined(VGO_linux) || defined(VGO_solaris)
+#if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
 #  define GENX_(sysno, name)  WRAPPER_ENTRY_X_(generic, sysno, name)
 #  define GENXY(sysno, name)  WRAPPER_ENTRY_XY(generic, sysno, name)
 #elif defined(VGO_darwin)
@@ -306,6 +338,11 @@ SyscallTableEntry* ML_(get_solaris_syscall_entry)( UInt sysno );
 #define LINX_(sysno, name)    WRAPPER_ENTRY_X_(linux, sysno, name) 
 #define LINXY(sysno, name)    WRAPPER_ENTRY_XY(linux, sysno, name)
 
+/* Add a FreeBSD-specific, arch-independent wrapper to a syscall
+   table. */
+#define BSDX_(sysno, name)    WRAPPER_ENTRY_X_(freebsd, sysno, name) 
+#define BSDXY(sysno, name)    WRAPPER_ENTRY_XY(freebsd, sysno, name)
+
 
 /* ---------------------------------------------------------------------
    Macros useful for writing wrappers concisely.  These refer to the
@@ -325,6 +362,7 @@ SyscallTableEntry* ML_(get_solaris_syscall_entry)( UInt sysno );
 #define ARG6   (arrghs->arg6)
 #define ARG7   (arrghs->arg7)
 #define ARG8   (arrghs->arg8)
+#define RETVAL2 (arrghs->retval2)
 
 /* Provide signed versions of the argument values */
 #define SARG1  ((Word)ARG1)
@@ -351,7 +389,7 @@ static inline UWord getRES ( SyscallStatus* st ) {
    return sr_Res(st->sres);
 }
 
-#if defined(VGO_darwin) || defined(VGO_solaris)
+#if defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
 static inline UWord getRESHI ( SyscallStatus* st ) {
    vg_assert(st->what == SsComplete);
    vg_assert(!sr_isError(st->sres));
@@ -372,6 +410,13 @@ static inline UWord getERR ( SyscallStatus* st ) {
         status->sres = VG_(mk_SysRes_Success)(zzz);  \
    } while (0)
 
+#ifdef VGO_freebsd
+#define SET_STATUS_Success2(zzz, zzz2)               \
+   do { status->what = SsComplete;                   \
+        status->sres = VG_(mk_SysRes_amd64_freebsd)(zzz, zzz2, False);  \
+   } while (0)
+#endif
+
 #define SET_STATUS_Failure(zzz)                      \
    do { Word wzz = (Word)(zzz);                      \
         /* Catch out wildly bogus error values. */   \
@@ -424,6 +469,35 @@ static inline UWord getERR ( SyscallStatus* st ) {
 #  define PRA5(s,t,a) PRRAn(5,s,t,a)
 #  define PRA6(s,t,a) PRRAn(6,s,t,a)
 
+#elif defined(VGP_x86_freebsd)
+   /* Up to 8 parameters, all on the stack. */
+#  define PRA1(s,t,a) PSRAn(1,s,t,a)
+#  define PRA2(s,t,a) PSRAn(2,s,t,a)
+#  define PRA3(s,t,a) PSRAn(3,s,t,a)
+#  define PRA4(s,t,a) PSRAn(4,s,t,a)
+#  define PRA5(s,t,a) PSRAn(5,s,t,a)
+#  define PRA6(s,t,a) PSRAn(6,s,t,a)
+#  define PRA7(s,t,a) PSRAn(7,s,t,a)
+#  define PRA8(s,t,a) PSRAn(8,s,t,a)
+
+#elif defined(VGP_amd64_freebsd)
+   /* Up to 8 parameters, 6 in registers, 2 on the stack. */
+   /* or 7 in registers and 3 on the stack */
+#  define PRA1(s,t,a) PRRAn(1,s,t,a)
+#  define PRA2(s,t,a) PRRAn(2,s,t,a)
+#  define PRA3(s,t,a) PRRAn(3,s,t,a)
+#  define PRA4(s,t,a) PRRAn(4,s,t,a)
+#  define PRA5(s,t,a) PRRAn(5,s,t,a)
+#  define PRA6(s,t,a) \
+   do { \
+      if (layout->arg6_is_reg) \
+         PRRAn(6,s,t,a); \
+       else \
+         PSRAn(6,s,t,a); \
+   } while (0)
+#  define PRA7(s,t,a) PSRAn(7,s,t,a)
+#  define PRA8(s,t,a) PSRAn(8,s,t,a)
+
 #elif defined(VGP_x86_darwin) || defined(VGP_x86_solaris)
    /* Up to 8 parameters, all on the stack. */
 #  define PRA1(s,t,a) PSRAn(1,s,t,a)
index 0739ccc9af41f6ff67a73e39757998f793e9b4cc..b1b982cc4a609b4e0338bc57316d296d2d9b6d65 100644 (file)
@@ -28,7 +28,7 @@
    The GNU General Public License is contained in the file COPYING.
 */
 
-#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
+#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 #include "pub_core_basics.h"
 #include "pub_core_vki.h"
@@ -938,7 +938,7 @@ void VG_(init_preopened_fds)(void)
   out:
    VG_(close)(sr_Res(f));
 
-#elif defined(VGO_darwin)
+#elif defined(VGO_darwin) || defined(VGO_freebsd)
    init_preopened_fds_without_proc_self_fd();
 
 #elif defined(VGO_solaris)
@@ -1142,6 +1142,10 @@ void pre_mem_read_sockaddr ( ThreadId tid,
 
    VG_(sprintf) ( outmsg, description, "sa_family" );
    PRE_MEM_READ( outmsg, (Addr) &sa->sa_family, sizeof(vki_sa_family_t));
+#if defined(VGO_freebsd)
+   VG_(sprintf) ( outmsg, description, "sa_len" );
+   PRE_MEM_READ( outmsg, (Addr) &sa->sa_len, sizeof(char));
+#endif
 
    /* Don't do any extra checking if we cannot determine the sa_family. */
    if (! ML_(safe_to_deref) (&sa->sa_family, sizeof(vki_sa_family_t)))
@@ -1819,7 +1823,15 @@ UInt get_sem_count( Int semid )
       return 0;
 
    return buf.sem_nsems;
+#  elif defined(__NR___semctl) /* FreeBSD */
+   struct vki_semid_ds buf;
+   arg.buf = &buf;
+   res = VG_(do_syscall4)(__NR___semctl, semid, 0, VKI_IPC_STAT, *(UWord *)&arg);
+
+   if (sr_isError(res))
+      return 0;
 
+   return buf.sem_nsems;
 #  elif defined(__NR_semsys) /* Solaris */
    struct vki_semid_ds buf;
    arg.buf = &buf;
@@ -1854,10 +1866,17 @@ ML_(generic_PRE_sys_semctl) ( ThreadId tid,
 #if defined(VKI_IPC_INFO)
    case VKI_IPC_INFO:
    case VKI_SEM_INFO:
+#if defined(VKI_IPC_64)
    case VKI_IPC_INFO|VKI_IPC_64:
    case VKI_SEM_INFO|VKI_IPC_64:
+#endif
+#if defined(VGO_freebsd)
+      PRE_MEM_WRITE( "semctl(IPC_INFO, arg.buf)",
+                     (Addr)arg.buf, sizeof(struct vki_semid_ds) );
+#else
       PRE_MEM_WRITE( "semctl(IPC_INFO, arg.buf)",
                      (Addr)arg.buf, sizeof(struct vki_seminfo) );
+#endif
       break;
 #endif
 
@@ -1933,9 +1952,15 @@ ML_(generic_POST_sys_semctl) ( ThreadId tid,
 #if defined(VKI_IPC_INFO)
    case VKI_IPC_INFO:
    case VKI_SEM_INFO:
+#if defined(VKI_IPC_64)
    case VKI_IPC_INFO|VKI_IPC_64:
    case VKI_SEM_INFO|VKI_IPC_64:
+#endif
+#if defined(VGO_freebsd)
+      POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_semid_ds) );
+#else
       POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_seminfo) );
+#endif
       break;
 #endif
 
@@ -2132,8 +2157,13 @@ ML_(generic_PRE_sys_shmctl) ( ThreadId tid,
    switch (arg1 /* cmd */) {
 #if defined(VKI_IPC_INFO)
    case VKI_IPC_INFO:
+#   if defined(VGO_freebsd)
+      PRE_MEM_WRITE( "shmctl(IPC_INFO, buf)",
+                     arg2, sizeof(struct vki_shmid_ds) );
+#   else
       PRE_MEM_WRITE( "shmctl(IPC_INFO, buf)",
                      arg2, sizeof(struct vki_shminfo) );
+#   endif
       break;
 #if defined(VKI_IPC_64)
    case VKI_IPC_INFO|VKI_IPC_64:
@@ -2191,12 +2221,18 @@ ML_(generic_POST_sys_shmctl) ( ThreadId tid,
    switch (arg1 /* cmd */) {
 #if defined(VKI_IPC_INFO)
    case VKI_IPC_INFO:
+#   if defined(VGO_freebsd)
+      POST_MEM_WRITE( arg2, sizeof(struct vki_shmid_ds) );
+#   else
       POST_MEM_WRITE( arg2, sizeof(struct vki_shminfo) );
+#   endif
       break;
+#if defined(VKI_IPC_64)
    case VKI_IPC_INFO|VKI_IPC_64:
       POST_MEM_WRITE( arg2, sizeof(struct vki_shminfo64) );
       break;
 #endif
+#endif
 
 #if defined(VKI_SHM_INFO)
    case VKI_SHM_INFO:
@@ -2735,6 +2771,7 @@ PRE(sys_getpriority)
    PRE_REG_READ2(long, "getpriority", int, which, int, who);
 }
 
+#if !defined(VGO_freebsd)
 PRE(sys_pwrite64)
 {
    *flags |= SfMayBlock;
@@ -2755,6 +2792,7 @@ PRE(sys_pwrite64)
 #endif
    PRE_MEM_READ( "pwrite64(buf)", ARG2, ARG3 );
 }
+#endif
 
 PRE(sys_sync)
 {
@@ -2799,6 +2837,7 @@ PRE(sys_getsid)
    PRE_REG_READ1(long, "getsid", vki_pid_t, pid);
 }
 
+#if !defined(VGO_freebsd)
 PRE(sys_pread64)
 {
    *flags |= SfMayBlock;
@@ -2826,6 +2865,7 @@ POST(sys_pread64)
       POST_MEM_WRITE( ARG2, RES );
    }
 }
+#endif
 
 PRE(sys_mknod)
 {
@@ -3363,7 +3403,7 @@ PRE(sys_fchmod)
    PRE_REG_READ2(long, "fchmod", unsigned int, fildes, vki_mode_t, mode);
 }
 
-#if !defined(VGP_nanomips_linux)
+#if !defined(VGP_nanomips_linux) && !defined (VGO_freebsd)
 PRE(sys_newfstat)
 {
    FUSE_COMPATIBLE_MAY_BLOCK();
@@ -3404,7 +3444,7 @@ PRE(sys_fork)
 
    if (!SUCCESS) return;
 
-#if defined(VGO_linux)
+#if defined(VGO_linux) || defined(VGO_freebsd)
    // RES is 0 for child, non-0 (the child's PID) for parent.
    is_child = ( RES == 0 ? True : False );
    child_pid = ( is_child ? -1 : RES );
@@ -3748,7 +3788,7 @@ void ML_(PRE_unknown_ioctl)(ThreadId tid, UWord request, UWord arg)
                unknown_ioctl[i] = request;
                moans--;
                VG_(umsg)("Warning: noted but unhandled ioctl 0x%lx"
-                         " with no size/direction hints.\n", request); 
+                         " with no size/direction hints.\n", request);
                VG_(umsg)("   This could cause spurious value errors to appear.\n");
                VG_(umsg)("   See README_MISSING_SYSCALL_OR_IOCTL for "
                          "guidance on writing a proper wrapper.\n" );
@@ -3884,7 +3924,7 @@ PRE(sys_link)
    PRE_MEM_RASCIIZ( "link(newpath)", ARG2);
 }
 
-#if !defined(VGP_nanomips_linux)
+#if !defined(VGP_nanomips_linux) && !defined(VGO_freebsd)
 PRE(sys_newlstat)
 {
    PRINT("sys_newlstat ( %#" FMT_REGWORD "x(%s), %#" FMT_REGWORD "x )", ARG1,
@@ -3934,7 +3974,11 @@ void handle_sys_mprotect(ThreadId tid, SyscallStatus* status,
                          Addr *addr, SizeT *len, Int *prot)
 {
    if (!ML_(valid_client_addr)(*addr, *len, tid, "mprotect")) {
+#if defined(VGO_freebsd)
+      SET_STATUS_Failure( VKI_EINVAL );
+#else
       SET_STATUS_Failure( VKI_ENOMEM );
+#endif
    } 
 #if defined(VKI_PROT_GROWSDOWN)
    else 
@@ -4195,7 +4239,7 @@ PRE(sys_read)
    PRINT("sys_read ( %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %"
          FMT_REGWORD "u )", ARG1, ARG2, ARG3);
    PRE_REG_READ3(ssize_t, "read",
-                 unsigned int, fd, char *, buf, vki_size_t, count);
+                 int, fd, char *, buf, vki_size_t, count);
 
    if (!ML_(fd_allowed)(ARG1, "read", tid, False))
       SET_STATUS_Failure( VKI_EBADF );
@@ -4284,7 +4328,8 @@ PRE(sys_poll)
 
 POST(sys_poll)
 {
-   if (RES >= 0) {
+   // RES is UWord so always >= 0
+   if (SUCCESS && RES >= 0) {
       UInt i;
       struct vki_pollfd* ufds = (struct vki_pollfd *)(Addr)ARG1;
       for (i = 0; i < ARG2; i++)
@@ -4483,7 +4528,11 @@ PRE(sys_setrlimit)
    }
    else if (((struct vki_rlimit *)(Addr)ARG2)->rlim_cur
             > ((struct vki_rlimit *)(Addr)ARG2)->rlim_max) {
+#if defined(VGO_freebsd)
+      SET_STATUS_Failure( VKI_EPERM );
+#else
       SET_STATUS_Failure( VKI_EINVAL );
+#endif
    }
    else if (arg1 == VKI_RLIMIT_NOFILE) {
       if (((struct vki_rlimit *)(Addr)ARG2)->rlim_cur > VG_(fd_hard_limit) ||
@@ -4536,7 +4585,7 @@ PRE(sys_setuid)
    PRE_REG_READ1(long, "setuid", vki_uid_t, uid);
 }
 
-#if !defined(VGP_nanomips_linux)
+#if !defined(VGP_nanomips_linux) && !defined(VGO_freebsd)
 PRE(sys_newstat)
 {
    FUSE_COMPATIBLE_MAY_BLOCK();
@@ -4551,7 +4600,9 @@ POST(sys_newstat)
 {
    POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
 }
+#endif
 
+#if !defined(VGP_nanomips_linux)
 PRE(sys_statfs)
 {
    FUSE_COMPATIBLE_MAY_BLOCK();
@@ -4638,6 +4689,7 @@ PRE(sys_unlink)
    PRE_MEM_RASCIIZ( "unlink(pathname)", ARG1 );
 }
 
+#if !defined(VGO_freebsd)
 PRE(sys_newuname)
 {
    PRINT("sys_newuname ( %#" FMT_REGWORD "x )", ARG1);
@@ -4651,6 +4703,7 @@ POST(sys_newuname)
       POST_MEM_WRITE( ARG1, sizeof(struct vki_new_utsname) );
    }
 }
+#endif
 
 PRE(sys_waitpid)
 {
@@ -4793,7 +4846,7 @@ PRE(sys_sethostname)
 #undef PRE
 #undef POST
 
-#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
+#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
index 1a475422b1dcf8ddadb3a2892e9141eb3a8ff46b..2982e276692fbc5f8e0d9a58a05789df89350000 100644 (file)
    mips64 v0    a0   a1   a2   a3   a4   a5   a6   a7   v0        (== NUM)
    arm64  x8    x0   x1   x2   x3   x4   x5   n/a  n/a  x0 ??     (== ARG1??)
 
+   FreeBSD:
+   x86    eax +4   +8   +12  +16  +20  +24  +28  +32  edx:eax, eflags.c
+   amd64  rax rdi  rsi  rdx  rcx  r8   r9   +8   +16  rdx:rax, rflags.c
+
    On s390x the svc instruction is used for system calls. The system call
    number is encoded in the instruction (8 bit immediate field). Since Linux
    2.6 it is also allowed to use svc 0 with the system call number in r1.
@@ -84,8 +88,8 @@
    x86    eax   +4   +8   +12  +16  +20  +24  +28  +32  edx:eax, eflags.c
    amd64  rax   rdi  rsi  rdx  rcx  r8   r9   +8   +16  rdx:rax, rflags.c
 
-   For x86-darwin, "+N" denotes "in memory at N(%esp)"; ditto
-   amd64-darwin.  Apparently 0(%esp) is some kind of return address
+   For x86-darwin and x86-freebsd, "+N" denotes "in memory at N(%esp)";
+   ditto amd64-darwin/amd64-freebsd.  Apparently 0(%esp) is some kind of return address
    (perhaps for syscalls done with "sysenter"?)  I don't think it is
    relevant for syscalls done with "int $0x80/1/2".
 
      ppc32:  Success(N) ==>  r3 = N, CR0.SO = 0
              Fail(N) ==>     r3 = N, CR0.SO = 1
 
+     FreeBSD:
+     x86:    Success(N) ==>  edx:eax = N, cc = 0
+             Fail(N)    ==>  edx:eax = N, cc = 1
+
+     ditto amd64
+
      Darwin:
      x86:    Success(N) ==>  edx:eax = N, cc = 0
              Fail(N)    ==>  edx:eax = N, cc = 1
 */
 #if defined(VGO_linux)
 extern
+UWord ML_(do_syscall_for_client_WRK)( Word syscallno, 
+                                      void* guest_state,
+                                      const vki_sigset_t *syscall_mask,
+                                      const vki_sigset_t *restore_mask,
+                                      Word sigsetSzB );
+#elif defined(VGO_freebsd)
+extern
 UWord ML_(do_syscall_for_client_WRK)( Word syscallno, 
                                       void* guest_state,
                                       const vki_sigset_t *syscall_mask,
@@ -333,11 +350,25 @@ void do_syscall_for_client ( Int syscallno,
 {
    vki_sigset_t saved;
    UWord err;
+#  if defined(VGO_freebsd)
+   Int real_syscallno;
+#  endif
 #  if defined(VGO_linux)
    err = ML_(do_syscall_for_client_WRK)(
             syscallno, &tst->arch.vex, 
             syscall_mask, &saved, sizeof(vki_sigset_t)
          );
+#  elif defined(VGO_freebsd)
+   if (tst->arch.vex.guest_SC_CLASS == VG_FREEBSD_SYSCALL0)
+      real_syscallno = __NR_syscall;
+   else if (tst->arch.vex.guest_SC_CLASS == VG_FREEBSD_SYSCALL198)
+      real_syscallno = __NR___syscall;
+   else
+      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:
@@ -518,6 +549,80 @@ void getSyscallArgsFromGuestState ( /*OUT*/SyscallArgs*       canonical,
    vg_assert(gst->guest_syscall_flag == SC_FLAG);
 #endif
 
+#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->klass = VG_FREEBSD_SYSCALL0;
+      canonical->sysno = stack[1];
+      stack += 1;
+      break;
+   case __NR___syscall:
+      canonical->klass = VG_FREEBSD_SYSCALL198;
+      canonical->sysno = stack[1];
+      stack += 2;
+      break;
+   default:
+      canonical->klass = 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->klass = VG_FREEBSD_SYSCALL0;
+      canonical->sysno = gst->guest_RDI;
+      break;
+   case __NR___syscall:
+      canonical->klass = VG_FREEBSD_SYSCALL198;
+      canonical->sysno = gst->guest_RDI;
+      break;
+   default:
+      canonical->klass = 0;
+      canonical->sysno = gst->guest_RAX;
+      break;
+   }
+
+   // stack[0] is a (fake) return address
+   if (canonical->klass == VG_FREEBSD_SYSCALL0 || canonical->klass == VG_FREEBSD_SYSCALL198) {
+      // 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];
+   } else {
+      // 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;
@@ -709,7 +814,7 @@ void getSyscallArgsFromGuestState ( /*OUT*/SyscallArgs*       canonical,
       canonical->arg6  = stack[1];
       canonical->arg7  = stack[2];
       canonical->arg8  = stack[3];
-      
       PRINT("SYSCALL[%d,?](0) syscall(%s, ...); please stand by...\n",
             VG_(getpid)(), /*tid,*/
             VG_SYSNUM_STRING(canonical->sysno));
@@ -842,6 +947,74 @@ void putSyscallArgsIntoGuestState ( /*IN*/ SyscallArgs*       canonical,
    gst->guest_GPR8 = canonical->arg6;
    gst->guest_GPR9 = canonical->arg7;
 
+#elif defined(VGP_x86_freebsd)
+   VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
+   UWord *stack = (UWord *)gst->guest_ESP;
+
+   // stack[0] is a (fake) return address
+   switch (canonical->klass) {
+   case VG_FREEBSD_SYSCALL0:
+      gst->guest_EAX = __NR_syscall;
+      stack[1] = canonical->sysno;
+      stack++;
+      break;
+   case VG_FREEBSD_SYSCALL198:
+      gst->guest_EAX = __NR___syscall;
+      stack[1] = canonical->sysno;
+      stack += 2;
+      break;
+   default:
+      gst->guest_EAX = canonical->sysno;
+      break;
+   }
+
+   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_freebsd)
+   VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
+   UWord *stack = (UWord *)gst->guest_RSP;
+
+   // stack[0] is a (fake) return address
+   switch (canonical->klass) {
+   case VG_FREEBSD_SYSCALL0:
+      gst->guest_RAX = __NR_syscall;
+      break;
+   case VG_FREEBSD_SYSCALL198:
+      gst->guest_RAX = __NR___syscall;
+      break;
+   default:
+      gst->guest_RAX = canonical->sysno;
+      break;
+   }
+
+   if (canonical->klass == VG_FREEBSD_SYSCALL0 || canonical->klass == VG_FREEBSD_SYSCALL198) {
+       gst->guest_RDI = canonical->sysno;
+       gst->guest_RSI = canonical->arg1;
+       gst->guest_RDX = canonical->arg2;
+       gst->guest_R10 = canonical->arg3;
+       gst->guest_R8  = canonical->arg4;
+       gst->guest_R9  = canonical->arg5;
+       stack[1]       = canonical->arg6;
+       stack[2]       = canonical->arg7;
+       stack[3]       = canonical->arg8;
+   } else {
+       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;
@@ -1027,6 +1200,15 @@ void getSyscallStatusFromGuestState ( /*OUT*/SyscallStatus*     canonical,
    canonical->sres = VG_(mk_SysRes_ppc64_linux)( gst->guest_GPR3, cr0so, flag );
    canonical->what = SsComplete;
 
+#  elif defined(VGP_x86_freebsd)
+   /* 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_freebsd)(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 );
@@ -1058,6 +1240,13 @@ void getSyscallStatusFromGuestState ( /*OUT*/SyscallStatus*     canonical,
    RegWord  a0 = gst->guest_r4;    // a0
    canonical->sres = VG_(mk_SysRes_nanomips_linux)(a0);
    canonical->what = SsComplete;
+#  elif defined(VGP_amd64_freebsd)
+   /* 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_freebsd)(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 */
@@ -1262,6 +1451,43 @@ void putSyscallStatusIntoGuestState ( /*IN*/ ThreadId tid,
    VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, 
              OFFSET_arm64_X0, sizeof(UWord) );
 
+#elif defined(VGP_x86_freebsd)
+   VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
+   vg_assert(canonical->what == SsComplete);
+   if (sr_isError(canonical->sres)) {
+      gst->guest_EAX = sr_Err(canonical->sres);
+      LibVEX_GuestX86_put_eflag_c(1, gst);
+   } else {
+      gst->guest_EAX = sr_Res(canonical->sres);
+      gst->guest_EDX = sr_ResHI(canonical->sres);
+      LibVEX_GuestX86_put_eflag_c(0, gst);
+   }
+   VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
+      OFFSET_x86_EAX, sizeof(UInt) );
+   VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
+      OFFSET_x86_EDX, sizeof(UInt) );
+   // GrP fixme sets defined for entire eflags, not just bit c
+   VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
+      offsetof(VexGuestX86State, guest_CC_DEP1), sizeof(UInt) );
+#elif defined(VGP_amd64_freebsd)
+   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 {
+      gst->guest_RAX = sr_Res(canonical->sres);
+      gst->guest_RDX = sr_ResHI(canonical->sres);
+      LibVEX_GuestAMD64_put_rflag_c(0, gst);
+   }
+   VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
+      OFFSET_amd64_RAX, sizeof(ULong) );
+   VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
+      OFFSET_amd64_RDX, sizeof(ULong) );
+   // GrP fixme sets defined for entire eflags, not just bit c
+   VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
+      offsetof(VexGuestAMD64State, guest_CC_DEP1), sizeof(ULong) );
 #elif defined(VGP_x86_darwin)
    VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
    SysRes sres = canonical->sres;
@@ -1493,6 +1719,30 @@ void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout )
    layout->o_arg7   = OFFSET_ppc64_GPR9;
    layout->uu_arg8  = -1; /* impossible value */
 
+#elif defined(VGP_x86_freebsd)
+   layout->o_sysno  = OFFSET_x86_EAX;
+   // syscall parameters are on stack in C convention
+   layout->s_arg1   = sizeof(UWord) * 1;
+   layout->s_arg2   = sizeof(UWord) * 2;
+   layout->s_arg3   = sizeof(UWord) * 3;
+   layout->s_arg4   = sizeof(UWord) * 4;
+   layout->s_arg5   = sizeof(UWord) * 5;
+   layout->s_arg6   = sizeof(UWord) * 6;
+   layout->s_arg7   = sizeof(UWord) * 7;
+   layout->s_arg8   = sizeof(UWord) * 8;
+#elif defined(VGP_amd64_freebsd)
+   layout->o_sysno  = OFFSET_amd64_RAX;
+   layout->o_arg1   = OFFSET_amd64_RDI;
+   layout->o_arg2   = OFFSET_amd64_RSI;
+   layout->o_arg3   = OFFSET_amd64_RDX;
+   layout->o_arg4   = OFFSET_amd64_R10;
+   layout->o_arg5   = OFFSET_amd64_R8;
+   layout->o_arg6   = OFFSET_amd64_R9;
+   layout->s_arg7   = sizeof(UWord) * 1;
+   layout->s_arg8   = sizeof(UWord) * 2;
+   layout->arg6_is_reg = True;
+
 #elif defined(VGP_arm_linux)
    layout->o_sysno  = OFFSET_arm_R7;
    layout->o_arg1   = OFFSET_arm_R0;
@@ -1610,6 +1860,24 @@ void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout )
 #endif
 }
 
+#if defined(VGP_amd64_freebsd)
+static
+void getSyscallArgLayout_0_198 ( /*OUT*/SyscallArgLayout* layout )
+{
+   VG_(bzero_inline)(layout, sizeof(*layout));
+   layout->o_sysno  = OFFSET_amd64_RDI;
+   layout->o_arg1   = OFFSET_amd64_RSI;
+   layout->o_arg2   = OFFSET_amd64_RDX;
+   layout->o_arg3   = OFFSET_amd64_R10;
+   layout->o_arg4   = OFFSET_amd64_R8;
+   layout->o_arg5   = OFFSET_amd64_R9;
+   layout->s_arg6   = sizeof(UWord) * 1;
+   layout->s_arg7   = sizeof(UWord) * 2;
+   layout->s_arg8   = sizeof(UWord) * 3;
+   layout->arg6_is_reg = False;
+}
+#endif
+
 
 /* ---------------------------------------------------------------------
    The main driver logic
@@ -1652,6 +1920,9 @@ static const SyscallTableEntry* get_syscall_entry ( Int syscallno )
 #  if defined(VGO_linux)
    sys = ML_(get_linux_syscall_entry)( syscallno );
 
+#  elif defined(VGO_freebsd)
+   sys = ML_(get_freebsd_syscall_entry)( syscallno );
+
 #  elif defined(VGO_darwin)
    Int idx = VG_DARWIN_SYSNO_INDEX(syscallno);
 
@@ -1868,6 +2139,9 @@ void VG_(client_syscall) ( ThreadId tid, UInt trc )
       is interrupted by a signal. */
    sysno = sci->orig_args.sysno;
 
+#  if defined(VGO_freebsd)
+   tst->arch.vex.guest_SC_CLASS = sci->orig_args.klass;
+#  endif
    /* It's sometimes useful, as a crude debugging hack, to get a
       stack trace at each (or selected) syscalls. */
    if (0 && sysno == __NR_ioctl) {
@@ -1907,8 +2181,23 @@ void VG_(client_syscall) ( ThreadId tid, UInt trc )
       action.  This info is needed so that the scalar syscall argument
       checks (PRE_REG_READ calls) know which bits of the guest state
       they need to inspect. */
+#if defined(VGP_amd64_freebsd)
+   // PJF - somewhat unfortunate uglificaton of the code, but the current code handles two
+   // types of syscall with different register use. Mixing them up is not good.
+   // I've avoided modifying the existing function (I could have added
+   // a FreeBSD amd64-only flag to it for this purpose).
+   if (sci->orig_args.klass == VG_FREEBSD_SYSCALL0 || sci->orig_args.klass == VG_FREEBSD_SYSCALL198) {
+       getSyscallArgLayout_0_198( &layout );
+    } else {
+#endif
+
    getSyscallArgLayout( &layout );
 
+#if defined(VGP_amd64_freebsd)
+   }
+#endif
+
+
    /* Make sure the tmp signal mask matches the real signal mask;
       sigsuspend may change this. */
    vg_assert(VG_(iseqsigset)(&tst->sig_mask, &tst->tmp_sig_mask));
@@ -2269,7 +2558,7 @@ void VG_(post_syscall) (ThreadId tid)
 /* These are addresses within ML_(do_syscall_for_client_WRK).  See
    syscall-$PLAT.S for details. 
 */
-#if defined(VGO_linux)
+#if defined(VGO_linux) || defined(VGO_freebsd)
   extern const Addr ML_(blksys_setup);
   extern const Addr ML_(blksys_restart);
   extern const Addr ML_(blksys_complete);
@@ -2450,6 +2739,46 @@ void ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch )
       vg_assert(p[0] == 0x01 && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0xD4);
    }
 
+#elif defined(VGP_x86_freebsd)
+   /* XXX: we support different syscall methods. */
+   arch->vex.guest_EIP -= 2;             // sizeof(int $0x80)
+
+   /* Make sure our caller is actually sane, and we're really backing
+      back over a syscall.
+
+      int $0x80 == CD 80
+   */
+   {
+      UChar *p = (UChar *)arch->vex.guest_EIP;
+      if (p[0] != 0xcd || p[1] != 0x80)
+         VG_(message)(Vg_DebugMsg,
+                      "?! restarting over syscall at %#x %02x %02x\n",
+                      arch->vex.guest_EIP, p[0], p[1]);
+
+      vg_assert(p[0] == 0xcd && p[1] == 0x80);
+   }
+
+#elif defined(VGP_amd64_freebsd)
+   /* XXX: we support different syscall methods. */
+   arch->vex.guest_RIP -= 2;             // sizeof(syscall)
+
+   /* Make sure our caller is actually sane, and we're really backing
+      back over a syscall.
+
+      syscall == 0F 05 
+   */
+   {
+      UChar *p = (UChar *)arch->vex.guest_RIP;
+      if (p[0] != 0x0F || p[1] != 0x05)
+         VG_(message)(Vg_DebugMsg,
+                      "?! restarting over syscall at %#llx %02x %02x\n",
+                      arch->vex.guest_RIP, p[0], p[1]);
+
+      vg_assert(p[0] == 0x0F && p[1] == 0x05);
+   }
+
 #elif defined(VGP_x86_darwin)
    arch->vex.guest_EIP = arch->vex.guest_IP_AT_SYSCALL; 
 
@@ -2700,7 +3029,7 @@ VG_(fixup_guest_state_after_syscall_interrupted)( ThreadId tid,
    th_regs = &tst->arch;
    sci     = & syscallInfo[tid];
 
-#  if defined(VGO_linux)
+#  if defined(VGO_linux) || defined(VGO_freebsd)
    outside_range
       = ip < ML_(blksys_setup) || ip >= ML_(blksys_finished);
    in_setup_to_restart
@@ -2868,6 +3197,24 @@ VG_(fixup_guest_state_after_syscall_interrupted)( ThreadId tid,
       /* Result committed, but the signal mask has not been restored;
          we expect our caller (the signal handler) will have fixed
          this up. */
+/* XXX: needed? */
+#if defined(VGP_x86_freebsd)
+      /* On FreeBSD, the success/fail status is returned to the caller
+        and still has to be fixed up here. */
+      if (!(sci->flags & SfNoWriteResult)) {
+        if (sr_isError(sres))
+           LibVEX_GuestX86_put_eflag_c(1, &th_regs->vex);
+        else
+           LibVEX_GuestX86_put_eflag_c(0, &th_regs->vex);
+      }
+#elif defined(VGP_amd64_freebsd)
+      if (!(sci->flags & SfNoWriteResult)) {
+        if (sr_isError(sres))
+           LibVEX_GuestAMD64_put_rflag_c(1, &th_regs->vex);
+        else
+           LibVEX_GuestAMD64_put_rflag_c(0, &th_regs->vex);
+      }
+#endif
       if (VG_(clo_trace_signals))
          VG_(message)( Vg_DebugMsg,
                        "  completed and committed: nothing to do\n");
index c2d642992ad26ad627cb985108b00fce41675dfc..ad1db3cb9ff9e77a88aaf0c4ca004b4eb41d6ce1 100644 (file)
@@ -851,6 +851,72 @@ VG_(trampoline_stuff_end):
 #      undef UD2_1024
 #      undef UD2_PAGE
         
+/*---------------- x86-freebsd ----------------*/
+#else
+#if defined(VGP_x86_freebsd)
+
+.global VG_(trampoline_stuff_start)
+VG_(trampoline_stuff_start):
+
+.global VG_(x86_freebsd_SUBST_FOR_sigreturn)
+VG_(x86_freebsd_SUBST_FOR_sigreturn):
+       /*
+        * PJF this magic number is fairly flakey
+        * If ever it is wrong sys_fake_sigreturn will fail
+        * the sigreturn will be to some bogus EIP address and
+        * the client will likely terminate with a SIGILL
+        * In this case adding some printfs to sigframe_create
+        * and sys_fake_sigreturn should help debugging to
+        * find the right offset
+        */
+       lea     0x1c(%esp), %eax        /* args to sigreturn(ucontext_t *) */
+       pushl   %eax
+       pushl   %eax                    /* fake return addr */
+/*     movl    0x44(%eax), %gs ; restore %gs, not done by sigreturn */
+        movl    $__NR_fake_sigreturn, %eax
+        int     $0x80
+        ud2
+
+.global VG_(trampoline_stuff_end)
+VG_(trampoline_stuff_end):
+
+#else
+#if defined(VGP_amd64_freebsd)
+
+#      define UD2_16     ud2 ; ud2 ; ud2 ; ud2 ;ud2 ; ud2 ; ud2 ; ud2
+#      define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
+#      define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
+#      define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
+#      define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
+
+       /* a leading page of unexecutable code */
+       UD2_PAGE
+
+.global VG_(trampoline_stuff_start)
+VG_(trampoline_stuff_start):
+
+.global VG_(amd64_freebsd_SUBST_FOR_sigreturn)
+VG_(amd64_freebsd_SUBST_FOR_sigreturn):
+        /* This is a very specific sequence which GDB uses to
+           recognize signal handler frames. */
+        movq    $__NR_fake_sigreturn, %rax
+        movq   %rsp, %rdi
+        addq   $8,%rdi
+        syscall
+        ud2
+
+.global VG_(trampoline_stuff_end)
+VG_(trampoline_stuff_end):
+
+       /* and a trailing page of unexecutable code */
+       UD2_PAGE
+
+#      undef UD2_16
+#      undef UD2_64
+#      undef UD2_256
+#      undef UD2_1024
+#      undef UD2_PAGE
+
 /*---------------- x86-darwin ----------------*/
 #else
 #if defined(VGP_x86_darwin)
@@ -1629,6 +1695,8 @@ VG_(trampoline_stuff_end):
 #endif
 #endif
 #endif
+#endif
+#endif
 
 /* Let the linker know we don't need an executable stack */
 MARK_STACK_NO_EXEC
index 332202a915252926308030dc4156be568777df22..c3f84a9d5b7f68962e79bd53ab749d6a1853a579 100644 (file)
@@ -1688,7 +1688,9 @@ Bool VG_(translate) ( ThreadId tid,
    vex_abiinfo.guest_amd64_assume_fs_is_const = True;
    vex_abiinfo.guest_amd64_assume_gs_is_const = True;
 #  endif
-
+#  if defined(VGP_amd64_freebsd)
+   vex_abiinfo.guest_amd64_assume_fs_is_const = True;
+#  endif
 #  if defined(VGP_amd64_darwin)
    vex_abiinfo.guest_amd64_assume_gs_is_const = True;
 #  endif
index b9ded7ad9d15319fe9e84c6bda7ed5b13adfe3c9..694c71d5bccfdc48ad8324224f28210ed57660ad 100644 (file)
@@ -26,7 +26,7 @@
    The GNU General Public License is contained in the file COPYING.
 */
 
-#if defined(VGO_linux) || defined(VGO_solaris)
+#if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 #include "pub_core_basics.h"
 #include "pub_core_vki.h"
@@ -39,6 +39,7 @@
 #include "pub_core_libcfile.h"      // VG_(open) et al
 #include "pub_core_machine.h"       // VG_ELF_CLASS (XXX: which should be moved)
 #include "pub_core_mallocfree.h"    // VG_(malloc), VG_(free)
+#include "pub_core_vkiscnums.h"
 #include "pub_core_syscall.h"       // VG_(strerror)
 #include "pub_core_ume.h"           // self
 
@@ -642,6 +643,15 @@ Int VG_(load_ELF)(Int fd, const HChar* name, /*MOD*/ExeInfo* info)
          VG_(pread)(fd, buf, ph->p_filesz, ph->p_offset);
          buf[ph->p_filesz] = '\0';
 
+#if defined(VGP_x86_freebsd)
+         sres._isError = True;
+         /* Hack.  FreeBSD's kernel overloads the interpreter name. */
+         if (VG_(strcmp)(buf, "/libexec/ld-elf.so.1") == 0 ||
+             VG_(strcmp)(buf, "/usr/libexec/ld-elf.so.1") == 0) {
+            sres = VG_(open)("/libexec/ld-elf32.so.1", VKI_O_RDONLY, 0);
+         }
+         if (sr_isError(sres))
+#endif
          sres = VG_(open)(buf, VKI_O_RDONLY, 0);
          if (sr_isError(sres)) {
             VG_(printf)("valgrind: m_ume.c: can't open interpreter\n");
@@ -868,7 +878,7 @@ Int VG_(load_ELF)(Int fd, const HChar* name, /*MOD*/ExeInfo* info)
    return 0;
 }
 
-#endif // defined(VGO_linux) || defined(VGO_solaris)
+#endif // defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
index d917fb596895ff8bc47bc3fb214ad59a24e65cc5..49e48d242b8dc357b7db7ee57c13288baf5d4e73 100644 (file)
@@ -49,7 +49,7 @@ typedef struct {
 } ExeHandler;
 
 static ExeHandler exe_handlers[] = {
-#  if defined(VGO_linux) || defined(VGO_solaris)
+#  if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
    { VG_(match_ELF),    VG_(load_ELF) },
 #  elif defined(VGO_darwin)
    { VG_(match_macho),  VG_(load_macho) },
index c9094ed8dc203dc48cddbdda8421323c29332fe4..489fc75229c20fa466061f20d8caaf8623eaceea 100644 (file)
@@ -25,7 +25,7 @@
    The GNU General Public License is contained in the file COPYING.
 */
 
-#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
+#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 #ifndef __PRIV_UME_H
 #define __PRIV_UME_H
@@ -34,7 +34,7 @@
 
 extern Int VG_(do_exec_inner)(const HChar *exe, ExeInfo *info);
 
-#if defined(VGO_linux) || defined(VGO_solaris)
+#if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
 extern Bool VG_(match_ELF) ( const void *hdr, SizeT len );
 extern Int  VG_(load_ELF)  ( Int fd, const HChar *name, ExeInfo *info );
 #elif defined(VGO_darwin)
index 278b12fdec201e315a1b81444f8f949a3043a1eb..0cc1882a1d50f8cb4efbc2ac3ec2c3c65e0c85e7 100644 (file)
@@ -76,7 +76,7 @@ void VG_(vki_do_initial_consistency_checks) ( void )
 
    /* --- Platform-specific checks on signal sets --- */
 
-#  if defined(VGO_linux) || defined(VGO_solaris)
+#  if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
    /* nothing to check */
 #  elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin)
    vg_assert(_VKI_NSIG == NSIG);
@@ -90,7 +90,7 @@ void VG_(vki_do_initial_consistency_checks) ( void )
 
    /* --- Platform-specific checks on sigactions --- */
 
-#  if defined(VGO_linux)
+#  if defined(VGO_linux) || defined(VGO_freebsd)
    /* the toK- and fromK- forms are identical */
    vg_assert( sizeof(vki_sigaction_toK_t) 
               == sizeof(vki_sigaction_fromK_t) );
index a7ffbf7b5152254f2d83837a16fafe763e974d5a..76ae104afd9c081392b2926484cfceb17cef6d6a 100644 (file)
@@ -67,6 +67,17 @@ STATIC_ASSERT(__NR_pipe2 == 5287);
 #endif
 
 //---------------------------------------------------------------------------
+#elif defined(VGO_freebsd)
+//---------------------------------------------------------------------------
+
+const HChar* VG_(sysnum_string)(Word sysnum)
+{
+   static HChar buf[20+1];   // large enough
+
+   VG_(snprintf)(buf, sizeof(buf), "%3ld", sysnum);
+   return buf;
+}
+
 #elif defined(VGO_darwin)
 //---------------------------------------------------------------------------
 
index 0f34782d3fec536d12fb4691bd1d15c9e9106015..aac2a0a321dc6ef77482463e52ca46a21b17a2c3 100644 (file)
@@ -384,6 +384,10 @@ extern Bool VG_(am_search_for_new_segment)(Addr *start, SizeT *size,
                                            UInt *prot);
 #endif
 
+/* For kern.usrstack syscall on FreeBSD */
+extern Word VG_(get_usrstack)(void);
+
+
 #endif   // __PUB_CORE_ASPACEMGR_H
 
 /*--------------------------------------------------------------------*/
index 8f05208ac7c93714aa0b7ccd6273f9b715a99ecc..938ed00cc1b78cefb6649d27323d6c6bec890ddd 100644 (file)
@@ -60,7 +60,7 @@ extern void VG_(di_initialise) ( void );
    released by simply re-opening and closing the same file (even via
    different fd!).
 */
-#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
+#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
 extern ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd );
 
 extern void VG_(di_notify_munmap)( Addr a, SizeT len );
index 9ecf642484746b668cb6052788712937c9020901..844337f9d9294ececbfc7641bc24ae3742773a9b 100644 (file)
@@ -225,6 +225,7 @@ typedef
       int offset_lwpid;
 
       int vgdb_pid;
+      int padding;
    } VgdbShared64;
 
 // The below typedef makes the life of valgrind easier.
index beef7d4c9361172e05019d2e3e16dde0d63bcd22..cfbd41f8b8ffca091748b439dfa7ef8aa91b3f28 100644 (file)
@@ -66,7 +66,7 @@ void VG_(ii_finalise_image)( IIFinaliseImageInfo );
 
 /* ------------------------- Linux ------------------------- */
 
-#if defined(VGO_linux)
+#if defined(VGO_linux) || defined(VGO_freebsd)
 
 struct _IICreateImageInfo {
    /* ------ Mandatory fields ------ */
index 8bf068d5ca99d6fee9605829368b409185ed7daf..29cc2a4494b2a7f13196c7d9ce1526316e720081 100644 (file)
@@ -85,6 +85,13 @@ extern void VG_(do_atfork_pre)    ( ThreadId tid );
 extern void VG_(do_atfork_parent) ( ThreadId tid );
 extern void VG_(do_atfork_child)  ( ThreadId tid );
 
+#if defined(VGO_freebsd)
+// sysctl, modfind
+extern Int VG_(sysctlbyname)(const HChar *name, void *oldp, SizeT *oldlenp, const void *newp, SizeT newlen);
+extern Int VG_(getosreldate)(void);
+extern Bool VG_(is32on64)(void);
+#endif
+
 // icache invalidation
 extern void VG_(invalidate_icache) ( void *ptr, SizeT nbytes );
 
index aa1f13de06f8b78337e1729cb179d27158b4d102..38c9ce99c44d475a83397633d1deff92ac93fb03 100644 (file)
 #include "pub_core_basics.h"      // UnwindStartRegs
 
 // XXX: this is *really* the wrong spot for these things
-#if defined(VGP_x86_linux) || defined(VGP_x86_solaris)
+#if defined(VGP_x86_linux) || defined(VGP_x86_solaris) || defined(VGP_x86_freebsd)
 #  define VG_ELF_DATA2XXX     ELFDATA2LSB
 #  define VG_ELF_MACHINE      EM_386
 #  define VG_ELF_CLASS        ELFCLASS32
 #  undef  VG_PLAT_USES_PPCTOC
-#elif defined(VGP_amd64_linux) || defined(VGP_amd64_solaris)
+#elif defined(VGP_amd64_linux) || defined(VGP_amd64_solaris) || defined(VGP_amd64_freebsd)
 #  define VG_ELF_DATA2XXX     ELFDATA2LSB
 #  define VG_ELF_MACHINE      EM_X86_64
 #  define VG_ELF_CLASS        ELFCLASS64
index 3fd22cdad8ed6eb56e3ecb0981eabfda4a75ea45..b5922ca50123d29a7b70d32d2fd30113529a03f0 100644 (file)
@@ -78,6 +78,8 @@ typedef Int ArenaId;
       defined(VGP_ppc64le_linux)  || \
       defined(VGP_s390x_linux)    || \
       (defined(VGP_mips64_linux) && !defined(VGABI_N32)) || \
+      defined(VGP_x86_freebsd)    || \
+      defined(VGP_amd64_freebsd)  || \
       defined(VGP_x86_darwin)     || \
       defined(VGP_amd64_darwin)   || \
       defined(VGP_arm64_linux)    || \
index 82bb4779ac09deb520b11d2c2970fb43d7414f1c..1b8caeb69b09238416bb72336941e32f328d3c93 100644 (file)
@@ -58,9 +58,13 @@ void VG_(sigframe_create) ( ThreadId tid,
 
 /* Remove a signal frame from thread 'tid's stack, and 
    restore the CPU state from it. */
+#ifdef VGO_freebsd
+extern 
+void VG_(sigframe_destroy)( ThreadId tid );
+#else
 extern 
 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT );
-
+#endif
 #if defined(VGO_solaris)
 extern
 void VG_(sigframe_return)(ThreadId tid, const vki_ucontext_t *uc);
index ddcca3809f24759bcd06cf1a62cfb7127165e112..6c4f825918333c7b4d01ab73725a6c89866f77b0 100644 (file)
@@ -91,6 +91,8 @@ extern SysRes VG_(mk_SysRes_x86_linux)   ( Int  val );
 extern SysRes VG_(mk_SysRes_amd64_linux) ( Long val );
 extern SysRes VG_(mk_SysRes_ppc32_linux) ( UInt  val, UInt  cr0so );
 extern SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so, UInt flag );
+extern SysRes VG_(mk_SysRes_x86_freebsd) ( UInt val, UInt val2, Bool err);
+extern SysRes VG_(mk_SysRes_amd64_freebsd)( ULong val, ULong val2, Bool err );
 extern SysRes VG_(mk_SysRes_arm_linux)   ( Int val );
 extern SysRes VG_(mk_SysRes_arm64_linux) ( Long val );
 extern SysRes VG_(mk_SysRes_x86_darwin)  ( UChar scclass, Bool isErr,
index 9dfa97bbfd16b7490a1241a5d42153b0947a98bd..a17620afc2576ce91968fb42dd005a4cd4053d31 100644 (file)
@@ -99,6 +99,10 @@ extern Bool VG_(setup_client_dataseg)(void);
 extern void VG_(track_client_dataseg)(ThreadId tid);
 #endif
 
+#if defined(VGO_freebsd)
+extern Bool VG_(get_capability_mode)(void);
+#endif
+
 #endif   // __PUB_CORE_SYSWRAP_H
 
 /*--------------------------------------------------------------------*/
index 931a4bcc1970ff8959285c0fbd8ce4dc00a3698b..54c575a7233a9451aca8acc03f370ceeb29182fc 100644 (file)
 extern Addr VG_(trampoline_stuff_start);
 extern Addr VG_(trampoline_stuff_end);
 
+#if defined(VGP_x86_freebsd)
+extern void VG_(x86_freebsd_SUBST_FOR_sigreturn);
+#endif
+
+#if defined(VGP_amd64_freebsd)
+extern void VG_(amd64_freebsd_SUBST_FOR_sigreturn);
+#endif
+
 #if defined(VGP_x86_linux)
 extern Addr VG_(x86_linux_SUBST_FOR_sigreturn);
 extern Addr VG_(x86_linux_SUBST_FOR_rt_sigreturn);
index 39d82c7c2321ae497ce5092ca5c4fc1aca555774..5e2098390847064bd28eee548f22fda415b1dd6c 100644 (file)
@@ -45,7 +45,7 @@
 #include "pub_core_debuginfo.h"  // Needed for pub_core_redir.h
 #include "pub_core_redir.h"      // For VG_NOTIFY_ON_LOAD
 
-#if defined(VGO_linux) || defined(VGO_solaris)
+#if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
 
 /* ---------------------------------------------------------------------
    Hook for running __gnu_cxx::__freeres() and __libc_freeres() once
@@ -207,6 +207,10 @@ void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random_addrandom)(unsigned
     // but don't care if it's initialized
 }
 
+#elif defined(VGO_freebsd)
+
+// nothing specific currently
+
 #elif defined(VGO_solaris)
 
 /* Declare the errno and environ symbols weakly in case the client is not
index 745fe32bc74b717efaaea7ddf1585bb891897dc8..01a88ae18b1172e207da7c6999a468454da6cdf8 100644 (file)
@@ -827,8 +827,10 @@ void close_connection(int to_pid, int from_pid)
             (join,
              "vgdb error pthread_join invoke_gdbserver_in_valgrind_thread\n");
    }
+#if !defined(VGO_freebsd)
    if (close(from_pid) != 0)
       ERROR(errno, "close from_pid\n");
+#endif
 }
 
 /* Relay data between gdb and Valgrind gdbserver, till EOF or an
index f5d48eae741e68f47bdd38ebb36fa513df15f8d6..5f11693cd907b20e3a43d7ca97fa9a98ea61984f 100644 (file)
@@ -70,7 +70,7 @@ extern Int  VG_(system) ( const HChar* cmd );
 extern Int  VG_(spawn)  ( const HChar *filename, const HChar **argv );
 extern Int  VG_(fork)   ( void);
 extern void VG_(execv)  ( const HChar* filename, const HChar** argv );
-extern Int  VG_(sysctl) ( Int *name, UInt namelen, void *oldp, SizeT *oldlenp, void *newp, SizeT newlen );
+extern Int  VG_(sysctl) ( Int *name, UInt namelen, void *oldp, SizeT *oldlenp, const void *newp, SizeT newlen );
 
 /* ---------------------------------------------------------------------
    Resource limits and capabilities