andrew created this revision.
andrew added a reviewer: Sanitizers.
Herald added subscribers: llvm-commits, cfe-commits, hiraditya, kristof.beyls, 
krytarowski, arichardson, dberris, emaste.
Herald added projects: clang, Sanitizers, LLVM.

Add support for asan, msan, and tsan on FreeBSD on aarch64.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D74765

Files:
  clang/lib/Driver/ToolChains/FreeBSD.cpp
  compiler-rt/lib/asan/asan_mapping.h
  compiler-rt/lib/msan/msan.h
  compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
  compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
  compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc
  compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
  compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
  compiler-rt/test/fuzzer/lit.cfg.py
  compiler-rt/test/sanitizer_common/TestCases/FreeBSD/capsicum.cpp
  compiler-rt/test/sanitizer_common/TestCases/Posix/crypt.cpp
  llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
  llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Index: llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
===================================================================
--- llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -416,6 +416,14 @@
   0x380000000000,  // OriginBase
 };
 
+// aarch64 FreeBSD
+static const MemoryMapParams FreeBSD_AArch64_MemoryMapParams = {
+  0x1800000000000,  // AndMask
+  0x0400000000000,  // XorMask
+  0x0200000000000,  // ShadowBase
+  0x0700000000000,  // OriginBase
+};
+
 // x86_64 NetBSD
 static const MemoryMapParams NetBSD_X86_64_MemoryMapParams = {
   0,               // AndMask
@@ -449,6 +457,12 @@
   &FreeBSD_X86_64_MemoryMapParams,
 };
 
+static const PlatformMemoryMapParams FreeBSD_ARM_MemoryMapParams = {
+  nullptr,
+  &FreeBSD_AArch64_MemoryMapParams,
+};
+
+
 static const PlatformMemoryMapParams NetBSD_X86_MemoryMapParams = {
   nullptr,
   &NetBSD_X86_64_MemoryMapParams,
@@ -895,6 +909,9 @@
           case Triple::x86:
             MapParams = FreeBSD_X86_MemoryMapParams.bits32;
             break;
+          case Triple::aarch64:
+            MapParams = FreeBSD_ARM_MemoryMapParams.bits64;
+            break;
           default:
             report_fatal_error("unsupported architecture");
         }
Index: llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
===================================================================
--- llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -105,6 +105,7 @@
 static const uint64_t kAArch64_ShadowOffset64 = 1ULL << 36;
 static const uint64_t kFreeBSD_ShadowOffset32 = 1ULL << 30;
 static const uint64_t kFreeBSD_ShadowOffset64 = 1ULL << 46;
+static const uint64_t kFreeBSD_AArch64_ShadowOffset64 = 1ULL << 47;
 static const uint64_t kNetBSD_ShadowOffset32 = 1ULL << 30;
 static const uint64_t kNetBSD_ShadowOffset64 = 1ULL << 46;
 static const uint64_t kNetBSDKasan_ShadowOffset64 = 0xdfff900000000000;
@@ -482,6 +483,8 @@
       Mapping.Offset = kPPC64_ShadowOffset64;
     else if (IsSystemZ)
       Mapping.Offset = kSystemZ_ShadowOffset64;
+    else if (IsFreeBSD && IsAArch64)
+      Mapping.Offset = kFreeBSD_AArch64_ShadowOffset64;
     else if (IsFreeBSD && !IsMIPS64)
       Mapping.Offset = kFreeBSD_ShadowOffset64;
     else if (IsNetBSD) {
Index: compiler-rt/test/sanitizer_common/TestCases/Posix/crypt.cpp
===================================================================
--- compiler-rt/test/sanitizer_common/TestCases/Posix/crypt.cpp
+++ compiler-rt/test/sanitizer_common/TestCases/Posix/crypt.cpp
@@ -6,7 +6,11 @@
 #include <assert.h>
 #include <unistd.h>
 #include <cstring>
+#ifdef __FreeBSD__
+#include <unistd.h>
+#else
 #include <crypt.h>
+#endif
 
 int
 main (int argc, char** argv)
Index: compiler-rt/test/sanitizer_common/TestCases/FreeBSD/capsicum.cpp
===================================================================
--- compiler-rt/test/sanitizer_common/TestCases/FreeBSD/capsicum.cpp
+++ compiler-rt/test/sanitizer_common/TestCases/FreeBSD/capsicum.cpp
@@ -11,7 +11,7 @@
 #include <unistd.h>
 
 void test_cap_ioctls() {
-  cap_rights_t rights;
+  cap_rights_t rights = {0};
   unsigned long ncmds[] = {TIOCGETA, TIOCGWINSZ, FIODTYPE};
   unsigned long rcmds = 0;
   cap_rights_t *rptr = cap_rights_init(&rights, CAP_IOCTL, CAP_READ);
Index: compiler-rt/test/fuzzer/lit.cfg.py
===================================================================
--- compiler-rt/test/fuzzer/lit.cfg.py
+++ compiler-rt/test/fuzzer/lit.cfg.py
@@ -27,7 +27,6 @@
 
 # LeakSanitizer is not supported on OSX or Windows right now.
 if (sys.platform.startswith('darwin') or
-    sys.platform.startswith('freebsd') or
     sys.platform.startswith('win')):
   lit_config.note('lsan feature unavailable')
 else:
Index: compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
===================================================================
--- compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
+++ compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
@@ -386,7 +386,11 @@
 #ifdef __powerpc__
 # define LONG_JMP_SP_ENV_SLOT 0
 #elif SANITIZER_FREEBSD
-# define LONG_JMP_SP_ENV_SLOT 2
+# ifdef __aarch64__
+#  define LONG_JMP_SP_ENV_SLOT 1
+# else
+#  define LONG_JMP_SP_ENV_SLOT 2
+#endif
 #elif SANITIZER_NETBSD
 # define LONG_JMP_SP_ENV_SLOT 6
 #elif SANITIZER_LINUX
Index: compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
===================================================================
--- compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
+++ compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
@@ -643,6 +643,18 @@
 #endif
 
 #if !SANITIZER_MAC
+TSAN_INTERCEPTOR(void*, __crt_malloc, uptr size) {
+  if (in_symbolizer())
+    return InternalAlloc(size);
+  void *p = 0;
+  {
+    SCOPED_INTERCEPTOR_RAW(__crt_malloc, size);
+    p = user_alloc(thr, pc, size);
+  }
+  invoke_malloc_hook(p, size);
+  return p;
+}
+
 TSAN_INTERCEPTOR(void*, malloc, uptr size) {
   if (in_symbolizer())
     return InternalAlloc(size);
@@ -660,6 +672,18 @@
   return user_memalign(thr, pc, align, sz);
 }
 
+TSAN_INTERCEPTOR(void*, __crt_calloc, uptr size, uptr n) {
+  if (in_symbolizer())
+    return InternalCalloc(size, n);
+  void *p = 0;
+  {
+    SCOPED_INTERCEPTOR_RAW(__crt_calloc, size, n);
+    p = user_calloc(thr, pc, size, n);
+  }
+  invoke_malloc_hook(p, n * size);
+  return p;
+}
+
 TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) {
   if (in_symbolizer())
     return InternalCalloc(size, n);
@@ -698,6 +722,16 @@
   return p;
 }
 
+TSAN_INTERCEPTOR(void, __crt_free, void *p) {
+  if (p == 0)
+    return;
+  if (in_symbolizer())
+    return InternalFree(p);
+  invoke_free_hook(p);
+  SCOPED_INTERCEPTOR_RAW(__crt_free, p);
+  user_free(thr, pc, p);
+}
+
 TSAN_INTERCEPTOR(void, free, void *p) {
   if (p == 0)
     return;
@@ -2648,6 +2682,9 @@
   TSAN_INTERCEPT(_longjmp);
 #endif
 
+  TSAN_INTERCEPT(__crt_malloc);
+  TSAN_INTERCEPT(__crt_calloc);
+  TSAN_INTERCEPT(__crt_free);
   TSAN_INTERCEPT(malloc);
   TSAN_INTERCEPT(__libc_memalign);
   TSAN_INTERCEPT(calloc);
Index: compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc
===================================================================
--- compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc
+++ compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc
@@ -19,7 +19,7 @@
 # define SYSCALL(name) __NR_ ## name
 #endif
 
-#if defined(__x86_64__) && (SANITIZER_FREEBSD || SANITIZER_MAC)
+#if (defined(__x86_64__) || defined(__aarch64__)) && (SANITIZER_FREEBSD || SANITIZER_MAC)
 # define internal_syscall __syscall
 # else
 # define internal_syscall syscall
Index: compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
===================================================================
--- compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
+++ compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
@@ -381,7 +381,9 @@
 #if SANITIZER_FREEBSD
 static void **ThreadSelfSegbase() {
   void **segbase = 0;
-# if defined(__i386__)
+# if defined(__aarch64__)
+  __asm __volatile("mrs %0, tpidr_el0" : "=r" (segbase));
+# elif defined(__i386__)
   // sysarch(I386_GET_GSBASE, segbase);
   __asm __volatile("mov %%gs:0, %0" : "=r" (segbase));
 # elif defined(__x86_64__)
@@ -406,7 +408,10 @@
 uptr ThreadSelf() {
   return (uptr)ThreadSelfTlsTcb()->tcb_pthread;
 }
+#endif  // SANITIZER_NETBSD
 
+#if SANITIZER_NETBSD || (SANITIZER_FREEBSD && \
+    (defined(__aarch64__) || defined(__mips__)))
 int GetSizeFromHdr(struct dl_phdr_info *info, size_t size, void *data) {
   const Elf_Phdr *hdr = info->dlpi_phdr;
   const Elf_Phdr *last_hdr = hdr + info->dlpi_phnum;
@@ -419,7 +424,8 @@
   }
   return 0;
 }
-#endif  // SANITIZER_NETBSD
+#endif  // SANITIZER_NETBSD || (SANITIZER_FREEBSD && (defined(__aarch64__) ||
+        // defined(__mips__)))
 
 #if !SANITIZER_GO
 static void GetTls(uptr *addr, uptr *size) {
@@ -442,6 +448,22 @@
   *addr = 0;
   *size = 0;
   if (segbase != 0) {
+# if defined(__aarch64__) || defined(__mips__)
+    // Variant I
+    //
+    // dtv = segbase[0];
+    // dtv[2] = base of TLS block of the main program
+    void **dtv = (void**) segbase[0];
+    if ((uptr) dtv[1] >= 2) {
+      // Find size (p_memsz) of TLS block of the main program.
+      dl_iterate_phdr(GetSizeFromHdr, size);
+
+      if (*size != 0)
+        *addr = (uptr) dtv[2];
+    }
+# elif defined(__x86_64__) || defined(__i386__)
+    // Variant II
+    //
     // tcbalign = 16
     // tls_size = round(tls_static_space, tcbalign);
     // dtv = segbase[1];
@@ -449,6 +471,9 @@
     void **dtv = (void**) segbase[1];
     *addr = (uptr) dtv[2];
     *size = (*addr == 0) ? 0 : ((uptr) segbase[0] - (uptr) dtv[2]);
+#else
+#error "unsupported CPU arch"
+#endif
   }
 #elif SANITIZER_NETBSD
   struct tls_tcb * const tcb = ThreadSelfTlsTcb();
Index: compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
===================================================================
--- compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
+++ compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
@@ -1334,7 +1334,7 @@
                        : "memory", "$29" );
   return res;
 }
-#elif defined(__aarch64__)
+#elif defined(__aarch64__) && SANITIZER_LINUX
 uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
                     int *parent_tidptr, void *newtls, int *child_tidptr) {
   long long res;
@@ -1734,7 +1734,7 @@
 void internal_join_thread(void *th) {}
 #endif
 
-#if defined(__aarch64__)
+#if defined(__aarch64__) && SANITIZER_LINUX
 // Android headers in the older NDK releases miss this definition.
 struct __sanitizer_esr_context {
   struct _aarch64_ctx head;
@@ -1833,7 +1833,7 @@
   static const uptr FSR_WRITE = 1U << 11;
   uptr fsr = ucontext->uc_mcontext.error_code;
   return fsr & FSR_WRITE ? WRITE : READ;
-#elif defined(__aarch64__)
+#elif defined(__aarch64__) && SANITIZER_LINUX
   static const u64 ESR_ELx_WNR = 1U << 6;
   u64 esr;
   if (!Aarch64GetESR(ucontext, &esr)) return UNKNOWN;
@@ -1883,10 +1883,17 @@
   *bp = ucontext->uc_mcontext.arm_fp;
   *sp = ucontext->uc_mcontext.arm_sp;
 #elif defined(__aarch64__)
+# if SANITIZER_FREEBSD
+  ucontext_t *ucontext = (ucontext_t*)context;
+  *pc = ucontext->uc_mcontext.mc_gpregs.gp_elr;
+  *bp = ucontext->uc_mcontext.mc_gpregs.gp_x[29];
+  *sp = ucontext->uc_mcontext.mc_gpregs.gp_sp;
+#else
   ucontext_t *ucontext = (ucontext_t*)context;
   *pc = ucontext->uc_mcontext.pc;
   *bp = ucontext->uc_mcontext.regs[29];
   *sp = ucontext->uc_mcontext.sp;
+#endif
 #elif defined(__hppa__)
   ucontext_t *ucontext = (ucontext_t*)context;
   *pc = ucontext->uc_mcontext.sc_iaoq[0];
Index: compiler-rt/lib/msan/msan.h
===================================================================
--- compiler-rt/lib/msan/msan.h
+++ compiler-rt/lib/msan/msan.h
@@ -181,6 +181,27 @@
 #define MEM_TO_SHADOW(mem) (LINEARIZE_MEM((mem)) + 0x080000000000ULL)
 #define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x140000000000ULL)
 
+#elif SANITIZER_FREEBSD && defined(__aarch64__)
+
+// Low memory: main binary, MAP_32BIT mappings and modules
+// High memory: heap, modules and main thread stack
+const MappingDesc kMemoryLayout[] = {
+    {0x000000000000ULL, 0x020000000000ULL, MappingDesc::APP, "low memory"},
+    {0x020000000000ULL, 0x200000000000ULL, MappingDesc::INVALID, "invalid"},
+    {0x200000000000ULL, 0x620000000000ULL, MappingDesc::SHADOW, "shadow"},
+    {0x620000000000ULL, 0x700000000000ULL, MappingDesc::INVALID, "invalid"},
+    {0x700000000000ULL, 0xb20000000000ULL, MappingDesc::ORIGIN, "origin"},
+    {0xb20000000000ULL, 0xc00000000000ULL, MappingDesc::INVALID, "invalid"},
+    {0xc00000000000ULL, 0x1000000000000ULL, MappingDesc::APP, "high memory"}};
+
+// Maps low and high app ranges to contiguous space with zero base:
+//   Low:  0000 0000 0000 -   01ff ffff ffff -> 4000 0000 0000 - 41ff ffff ffff
+//   High: c000 0000 0000 - 1 ffff ffff ffff -> 0000 0000 0000 - 3fff ffff ffff
+#define LINEARIZE_MEM(mem) \
+  (((uptr)(mem) & ~0x1800000000000ULL) ^ 0x400000000000ULL)
+#define MEM_TO_SHADOW(mem) (LINEARIZE_MEM((mem)) + 0x200000000000ULL)
+#define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x500000000000)
+
 #elif SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 64
 
 // Low memory: main binary, MAP_32BIT mappings and modules
Index: compiler-rt/lib/asan/asan_mapping.h
===================================================================
--- compiler-rt/lib/asan/asan_mapping.h
+++ compiler-rt/lib/asan/asan_mapping.h
@@ -168,6 +168,7 @@
 static const u64 kSPARC64_ShadowOffset64 = 1ULL << 43;  // 0x80000000000
 static const u64 kFreeBSD_ShadowOffset32 = 1ULL << 30;  // 0x40000000
 static const u64 kFreeBSD_ShadowOffset64 = 1ULL << 46;  // 0x400000000000
+static const u64 kFreeBSD_AArch64_ShadowOffset64 = 1ULL << 47; // 0x800000000000
 static const u64 kNetBSD_ShadowOffset32 = 1ULL << 30;  // 0x40000000
 static const u64 kNetBSD_ShadowOffset64 = 1ULL << 46;  // 0x400000000000
 static const u64 kWindowsShadowOffset32 = 3ULL << 28;  // 0x30000000
@@ -206,6 +207,8 @@
 #else
 #  if SANITIZER_IOS
 #    define SHADOW_OFFSET __asan_shadow_memory_dynamic_address
+#  elif defined(__aarch64__) && SANITIZER_FREEBSD
+#    define SHADOW_OFFSET kFreeBSD_AArch64_ShadowOffset64
 #  elif defined(__aarch64__)
 #    define SHADOW_OFFSET kAArch64_ShadowOffset64
 #  elif defined(__powerpc64__)
Index: clang/lib/Driver/ToolChains/FreeBSD.cpp
===================================================================
--- clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -454,12 +454,13 @@
   const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
   const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
   const bool IsMIPS64 = getTriple().isMIPS64();
+  const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64;
   SanitizerMask Res = ToolChain::getSupportedSanitizers();
   Res |= SanitizerKind::Address;
   Res |= SanitizerKind::PointerCompare;
   Res |= SanitizerKind::PointerSubtract;
   Res |= SanitizerKind::Vptr;
-  if (IsX86_64 || IsMIPS64) {
+  if (IsX86_64 || IsMIPS64 || IsAArch64) {
     Res |= SanitizerKind::Leak;
     Res |= SanitizerKind::Thread;
   }
@@ -469,7 +470,7 @@
     Res |= SanitizerKind::Fuzzer;
     Res |= SanitizerKind::FuzzerNoLink;
   }
-  if (IsX86_64)
+  if (IsX86_64 || IsAArch64)
     Res |= SanitizerKind::Memory;
   return Res;
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to