diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp --- a/clang/lib/Driver/ToolChains/FreeBSD.cpp +++ b/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; } diff --git a/compiler-rt/lib/asan/asan_mapping.h b/compiler-rt/lib/asan/asan_mapping.h --- a/compiler-rt/lib/asan/asan_mapping.h +++ b/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__) diff --git a/compiler-rt/lib/msan/msan.h b/compiler-rt/lib/msan/msan.h --- a/compiler-rt/lib/msan/msan.h +++ b/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 diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ b/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]; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp +++ b/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(); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc b/compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc --- a/compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc +++ b/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 diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/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); diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp +++ b/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 diff --git a/compiler-rt/test/fuzzer/lit.cfg.py b/compiler-rt/test/fuzzer/lit.cfg.py --- a/compiler-rt/test/fuzzer/lit.cfg.py +++ b/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: diff --git a/compiler-rt/test/sanitizer_common/TestCases/FreeBSD/capsicum.cpp b/compiler-rt/test/sanitizer_common/TestCases/FreeBSD/capsicum.cpp --- a/compiler-rt/test/sanitizer_common/TestCases/FreeBSD/capsicum.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/FreeBSD/capsicum.cpp @@ -11,7 +11,7 @@ #include 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); diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/crypt.cpp b/compiler-rt/test/sanitizer_common/TestCases/Posix/crypt.cpp --- a/compiler-rt/test/sanitizer_common/TestCases/Posix/crypt.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/crypt.cpp @@ -6,7 +6,11 @@ #include #include #include +#ifdef __FreeBSD__ +#include +#else #include +#endif int main (int argc, char** argv) diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/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) { diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/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"); }