diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-12-24 01:00:33 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-12-24 01:00:33 +0000 |
commit | 46d7550315cd1db7e0cdf313e2702222751d8a24 (patch) | |
tree | 7c8ad1d503cf19120d55ce098d2f8bd1534fa721 /lib | |
parent | cdf4f3055e964bb585f294cf77cb549ead82783f (diff) |
Diffstat (limited to 'lib')
-rw-r--r-- | lib/asan/CMakeLists.txt | 5 | ||||
-rwxr-xr-x | lib/asan/scripts/asan_symbolize.py | 4 | ||||
-rw-r--r-- | lib/builtins/CMakeLists.txt | 6 | ||||
-rw-r--r-- | lib/builtins/aarch64/chkstk.S | 34 | ||||
-rw-r--r-- | lib/fuzzer/FuzzerTracePC.h | 1 | ||||
-rw-r--r-- | lib/hwasan/hwasan.cc | 118 | ||||
-rw-r--r-- | lib/hwasan/hwasan_interface_internal.h | 26 | ||||
-rw-r--r-- | lib/hwasan/hwasan_linux.cc | 10 | ||||
-rw-r--r-- | lib/msan/msan_new_delete.cc | 44 | ||||
-rw-r--r-- | lib/profile/InstrProfilingUtil.c | 1 | ||||
-rw-r--r-- | lib/sanitizer_common/CMakeLists.txt | 38 | ||||
-rw-r--r-- | lib/sanitizer_common/sancov_begin.S | 5 | ||||
-rw-r--r-- | lib/sanitizer_common/sancov_end.S | 5 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_atomic_clang.h | 17 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_atomic_clang_mips.h | 118 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_atomic_clang_other.h | 63 | ||||
-rwxr-xr-x | lib/sanitizer_common/scripts/gen_dynamic_list.py | 20 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_new_delete.cc | 97 | ||||
-rw-r--r-- | lib/ubsan/ubsan_handlers.cc | 2 |
19 files changed, 510 insertions, 104 deletions
diff --git a/lib/asan/CMakeLists.txt b/lib/asan/CMakeLists.txt index da82e485b5819..fbd72f69298f6 100644 --- a/lib/asan/CMakeLists.txt +++ b/lib/asan/CMakeLists.txt @@ -175,6 +175,11 @@ else() EXTRA asan.syms.extra) set(VERSION_SCRIPT_FLAG -Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/clang_rt.asan-dynamic-${arch}.vers) + # The Solaris 11.4 linker supports a subset of GNU ld version scripts, + # but requires a special option to enable it. + if (OS_NAME MATCHES "SunOS") + list(APPEND VERSION_SCRIPT_FLAG -Wl,-z,gnu-version-script-compat) + endif() set_property(SOURCE ${CMAKE_CURRENT_BINARY_DIR}/dummy.cc APPEND PROPERTY diff --git a/lib/asan/scripts/asan_symbolize.py b/lib/asan/scripts/asan_symbolize.py index cd5d89ba2219a..68b6f093b533f 100755 --- a/lib/asan/scripts/asan_symbolize.py +++ b/lib/asan/scripts/asan_symbolize.py @@ -280,7 +280,7 @@ def BreakpadSymbolizerFactory(binary): def SystemSymbolizerFactory(system, addr, binary, arch): if system == 'Darwin': return DarwinSymbolizer(addr, binary, arch) - elif system in ['Linux', 'FreeBSD', 'NetBSD']: + elif system in ['Linux', 'FreeBSD', 'NetBSD', 'SunOS']: return Addr2LineSymbolizer(binary) @@ -370,7 +370,7 @@ class SymbolizationLoop(object): self.binary_name_filter = binary_name_filter self.dsym_hint_producer = dsym_hint_producer self.system = os.uname()[0] - if self.system not in ['Linux', 'Darwin', 'FreeBSD', 'NetBSD']: + if self.system not in ['Linux', 'Darwin', 'FreeBSD', 'NetBSD','SunOS']: raise Exception('Unknown system') self.llvm_symbolizers = {} self.last_llvm_symbolizer = None diff --git a/lib/builtins/CMakeLists.txt b/lib/builtins/CMakeLists.txt index 6fa9583191219..6a0faf8ebf0ef 100644 --- a/lib/builtins/CMakeLists.txt +++ b/lib/builtins/CMakeLists.txt @@ -446,6 +446,12 @@ set(aarch64_SOURCES ${GENERIC_TF_SOURCES} ${GENERIC_SOURCES}) +if (MINGW) + set(aarch64_SOURCES + ${aarch64_SOURCES} + aarch64/chkstk.S) +endif() + set(armhf_SOURCES ${arm_SOURCES}) set(armv7_SOURCES ${arm_SOURCES}) set(armv7s_SOURCES ${arm_SOURCES}) diff --git a/lib/builtins/aarch64/chkstk.S b/lib/builtins/aarch64/chkstk.S new file mode 100644 index 0000000000000..89ec90b08a13f --- /dev/null +++ b/lib/builtins/aarch64/chkstk.S @@ -0,0 +1,34 @@ +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. + +#include "../assembly.h" + +// __chkstk routine +// This routine is windows specific. +// http://msdn.microsoft.com/en-us/library/ms648426.aspx + +// This clobbers registers x16 and x17. +// Does not modify any memory or the stack pointer. + +// mov x15, #256 // Number of bytes of stack, in units of 16 byte +// bl __chkstk +// sub sp, sp, x15, lsl #4 + +#ifdef __aarch64__ + +#define PAGE_SIZE 4096 + + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__chkstk) + lsl x16, x15, #4 + mov x17, sp +1: + sub x17, x17, #PAGE_SIZE + subs x16, x16, #PAGE_SIZE + ldr xzr, [x17] + b.gt 1b + + ret +END_COMPILERRT_FUNCTION(__chkstk) + +#endif // __aarch64__ diff --git a/lib/fuzzer/FuzzerTracePC.h b/lib/fuzzer/FuzzerTracePC.h index dc65cd72091ab..c3f241b905b1d 100644 --- a/lib/fuzzer/FuzzerTracePC.h +++ b/lib/fuzzer/FuzzerTracePC.h @@ -276,6 +276,7 @@ void TracePC::CollectFeatures(Callback HandleFeature) const { // Step function, grows similar to 8 * Log_2(A). auto StackDepthStepFunction = [](uint32_t A) -> uint32_t { + if (!A) return A; uint32_t Log2 = Log(A); if (Log2 < 3) return A; Log2 -= 3; diff --git a/lib/hwasan/hwasan.cc b/lib/hwasan/hwasan.cc index fcc40eb901829..8b1e5a7846af5 100644 --- a/lib/hwasan/hwasan.cc +++ b/lib/hwasan/hwasan.cc @@ -252,40 +252,112 @@ static void SigIll() { // __builtin_unreachable(); } -template<bool IsStore, unsigned LogSize> -__attribute__((always_inline, nodebug)) -static void CheckAddress(uptr p) { +enum class ErrorAction { Abort, Recover }; +enum class AccessType { Load, Store }; + +template <ErrorAction EA, AccessType AT, unsigned LogSize> +__attribute__((always_inline, nodebug)) static void CheckAddress(uptr p) { tag_t ptr_tag = GetTagFromPointer(p); uptr ptr_raw = p & ~kAddressTagMask; tag_t mem_tag = *(tag_t *)MEM_TO_SHADOW(ptr_raw); - if (UNLIKELY(ptr_tag != mem_tag)) SigIll<0x100 + 0x10 * IsStore + LogSize>(); + if (UNLIKELY(ptr_tag != mem_tag)) { + SigIll<0x100 + 0x20 * (EA == ErrorAction::Recover) + + 0x10 * (AT == AccessType::Store) + LogSize>(); + if (EA == ErrorAction::Abort) __builtin_unreachable(); + } } -template<bool IsStore> -__attribute__((always_inline, nodebug)) -static void CheckAddressSized(uptr p, uptr sz) { +template <ErrorAction EA, AccessType AT> +__attribute__((always_inline, nodebug)) static void CheckAddressSized(uptr p, + uptr sz) { CHECK_NE(0, sz); tag_t ptr_tag = GetTagFromPointer(p); uptr ptr_raw = p & ~kAddressTagMask; tag_t *shadow_first = (tag_t *)MEM_TO_SHADOW(ptr_raw); tag_t *shadow_last = (tag_t *)MEM_TO_SHADOW(ptr_raw + sz - 1); for (tag_t *t = shadow_first; t <= shadow_last; ++t) - if (UNLIKELY(ptr_tag != *t)) SigIll<0x100 + 0x10 * IsStore + 0xf>(); -} - -void __hwasan_load(uptr p, uptr sz) { CheckAddressSized<false>(p, sz); } -void __hwasan_load1(uptr p) { CheckAddress<false, 0>(p); } -void __hwasan_load2(uptr p) { CheckAddress<false, 1>(p); } -void __hwasan_load4(uptr p) { CheckAddress<false, 2>(p); } -void __hwasan_load8(uptr p) { CheckAddress<false, 3>(p); } -void __hwasan_load16(uptr p) { CheckAddress<false, 4>(p); } - -void __hwasan_store(uptr p, uptr sz) { CheckAddressSized<true>(p, sz); } -void __hwasan_store1(uptr p) { CheckAddress<true, 0>(p); } -void __hwasan_store2(uptr p) { CheckAddress<true, 1>(p); } -void __hwasan_store4(uptr p) { CheckAddress<true, 2>(p); } -void __hwasan_store8(uptr p) { CheckAddress<true, 3>(p); } -void __hwasan_store16(uptr p) { CheckAddress<true, 4>(p); } + if (UNLIKELY(ptr_tag != *t)) { + SigIll<0x100 + 0x20 * (EA == ErrorAction::Recover) + + 0x10 * (AT == AccessType::Store) + 0xf>(); + if (EA == ErrorAction::Abort) __builtin_unreachable(); + } +} + +void __hwasan_load(uptr p, uptr sz) { + CheckAddressSized<ErrorAction::Abort, AccessType::Load>(p, sz); +} +void __hwasan_load1(uptr p) { + CheckAddress<ErrorAction::Abort, AccessType::Load, 0>(p); +} +void __hwasan_load2(uptr p) { + CheckAddress<ErrorAction::Abort, AccessType::Load, 1>(p); +} +void __hwasan_load4(uptr p) { + CheckAddress<ErrorAction::Abort, AccessType::Load, 2>(p); +} +void __hwasan_load8(uptr p) { + CheckAddress<ErrorAction::Abort, AccessType::Load, 3>(p); +} +void __hwasan_load16(uptr p) { + CheckAddress<ErrorAction::Abort, AccessType::Load, 4>(p); +} + +void __hwasan_load_noabort(uptr p, uptr sz) { + CheckAddressSized<ErrorAction::Recover, AccessType::Load>(p, sz); +} +void __hwasan_load1_noabort(uptr p) { + CheckAddress<ErrorAction::Recover, AccessType::Load, 0>(p); +} +void __hwasan_load2_noabort(uptr p) { + CheckAddress<ErrorAction::Recover, AccessType::Load, 1>(p); +} +void __hwasan_load4_noabort(uptr p) { + CheckAddress<ErrorAction::Recover, AccessType::Load, 2>(p); +} +void __hwasan_load8_noabort(uptr p) { + CheckAddress<ErrorAction::Recover, AccessType::Load, 3>(p); +} +void __hwasan_load16_noabort(uptr p) { + CheckAddress<ErrorAction::Recover, AccessType::Load, 4>(p); +} + +void __hwasan_store(uptr p, uptr sz) { + CheckAddressSized<ErrorAction::Abort, AccessType::Store>(p, sz); +} +void __hwasan_store1(uptr p) { + CheckAddress<ErrorAction::Abort, AccessType::Store, 0>(p); +} +void __hwasan_store2(uptr p) { + CheckAddress<ErrorAction::Abort, AccessType::Store, 1>(p); +} +void __hwasan_store4(uptr p) { + CheckAddress<ErrorAction::Abort, AccessType::Store, 2>(p); +} +void __hwasan_store8(uptr p) { + CheckAddress<ErrorAction::Abort, AccessType::Store, 3>(p); +} +void __hwasan_store16(uptr p) { + CheckAddress<ErrorAction::Abort, AccessType::Store, 4>(p); +} + +void __hwasan_store_noabort(uptr p, uptr sz) { + CheckAddressSized<ErrorAction::Recover, AccessType::Store>(p, sz); +} +void __hwasan_store1_noabort(uptr p) { + CheckAddress<ErrorAction::Recover, AccessType::Store, 0>(p); +} +void __hwasan_store2_noabort(uptr p) { + CheckAddress<ErrorAction::Recover, AccessType::Store, 1>(p); +} +void __hwasan_store4_noabort(uptr p) { + CheckAddress<ErrorAction::Recover, AccessType::Store, 2>(p); +} +void __hwasan_store8_noabort(uptr p) { + CheckAddress<ErrorAction::Recover, AccessType::Store, 3>(p); +} +void __hwasan_store16_noabort(uptr p) { + CheckAddress<ErrorAction::Recover, AccessType::Store, 4>(p); +} #if !SANITIZER_SUPPORTS_WEAK_HOOKS extern "C" { diff --git a/lib/hwasan/hwasan_interface_internal.h b/lib/hwasan/hwasan_interface_internal.h index 08b77534e0ae3..7e95271ac0af7 100644 --- a/lib/hwasan/hwasan_interface_internal.h +++ b/lib/hwasan/hwasan_interface_internal.h @@ -45,6 +45,19 @@ SANITIZER_INTERFACE_ATTRIBUTE void __hwasan_load16(uptr); SANITIZER_INTERFACE_ATTRIBUTE +void __hwasan_load_noabort(uptr, uptr); +SANITIZER_INTERFACE_ATTRIBUTE +void __hwasan_load1_noabort(uptr); +SANITIZER_INTERFACE_ATTRIBUTE +void __hwasan_load2_noabort(uptr); +SANITIZER_INTERFACE_ATTRIBUTE +void __hwasan_load4_noabort(uptr); +SANITIZER_INTERFACE_ATTRIBUTE +void __hwasan_load8_noabort(uptr); +SANITIZER_INTERFACE_ATTRIBUTE +void __hwasan_load16_noabort(uptr); + +SANITIZER_INTERFACE_ATTRIBUTE void __hwasan_store(uptr, uptr); SANITIZER_INTERFACE_ATTRIBUTE void __hwasan_store1(uptr); @@ -57,6 +70,19 @@ void __hwasan_store8(uptr); SANITIZER_INTERFACE_ATTRIBUTE void __hwasan_store16(uptr); +SANITIZER_INTERFACE_ATTRIBUTE +void __hwasan_store_noabort(uptr, uptr); +SANITIZER_INTERFACE_ATTRIBUTE +void __hwasan_store1_noabort(uptr); +SANITIZER_INTERFACE_ATTRIBUTE +void __hwasan_store2_noabort(uptr); +SANITIZER_INTERFACE_ATTRIBUTE +void __hwasan_store4_noabort(uptr); +SANITIZER_INTERFACE_ATTRIBUTE +void __hwasan_store8_noabort(uptr); +SANITIZER_INTERFACE_ATTRIBUTE +void __hwasan_store16_noabort(uptr); + // Returns the offset of the first tag mismatch or -1 if the whole range is // good. SANITIZER_INTERFACE_ATTRIBUTE diff --git a/lib/hwasan/hwasan_linux.cc b/lib/hwasan/hwasan_linux.cc index 9b8613171cbdb..48dea8eb6ff46 100644 --- a/lib/hwasan/hwasan_linux.cc +++ b/lib/hwasan/hwasan_linux.cc @@ -174,12 +174,14 @@ struct AccessInfo { uptr size; bool is_store; bool is_load; + bool recover; }; #if defined(__aarch64__) static AccessInfo GetAccessInfo(siginfo_t *info, ucontext_t *uc) { // Access type is encoded in HLT immediate as 0x1XY, - // where X is 1 for store, 0 for load. + // where X&1 is 1 for store, 0 for load, + // and X&2 is 1 if the error is recoverable. // Valid values of Y are 0 to 4, which are interpreted as log2(access_size), // and 0xF, which means that access size is stored in X1 register. // Access address is always in X0 register. @@ -189,7 +191,8 @@ static AccessInfo GetAccessInfo(siginfo_t *info, ucontext_t *uc) { if ((code & 0xff00) != 0x100) return AccessInfo{0, 0, false, false}; // Not ours. bool is_store = code & 0x10; - unsigned size_log = code & 0xff; + bool recover = code & 0x20; + unsigned size_log = code & 0xf; if (size_log > 4 && size_log != 0xf) return AccessInfo{0, 0, false, false}; // Not ours. @@ -200,6 +203,7 @@ static AccessInfo GetAccessInfo(siginfo_t *info, ucontext_t *uc) { ai.size = uc->uc_mcontext.regs[1]; else ai.size = 1U << size_log; + ai.recover = recover; return ai; } #else @@ -223,7 +227,7 @@ static bool HwasanOnSIGILL(int signo, siginfo_t *info, ucontext_t *uc) { ReportTagMismatch(stack, ai.addr, ai.size, ai.is_store); ++hwasan_report_count; - if (flags()->halt_on_error) + if (flags()->halt_on_error || !ai.recover) Die(); uc->uc_mcontext.pc += 4; diff --git a/lib/msan/msan_new_delete.cc b/lib/msan/msan_new_delete.cc index 721926791029e..5cc76e4bc08c3 100644 --- a/lib/msan/msan_new_delete.cc +++ b/lib/msan/msan_new_delete.cc @@ -22,9 +22,10 @@ using namespace __msan; // NOLINT -// Fake std::nothrow_t to avoid including <new>. +// Fake std::nothrow_t and std::align_val_t to avoid including <new>. namespace std { struct nothrow_t {}; + enum class align_val_t: size_t {}; } // namespace std @@ -34,6 +35,11 @@ namespace std { void *res = msan_malloc(size, &stack);\ if (!nothrow && UNLIKELY(!res)) DieOnFailure::OnOOM();\ return res +#define OPERATOR_NEW_BODY_ALIGN(nothrow) \ + GET_MALLOC_STACK_TRACE;\ + void *res = msan_memalign((uptr)align, size, &stack);\ + if (!nothrow && UNLIKELY(!res)) DieOnFailure::OnOOM();\ + return res; INTERCEPTOR_ATTRIBUTE void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } @@ -47,6 +53,18 @@ INTERCEPTOR_ATTRIBUTE void *operator new[](size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY(true /*nothrow*/); } +INTERCEPTOR_ATTRIBUTE +void *operator new(size_t size, std::align_val_t align) +{ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); } +INTERCEPTOR_ATTRIBUTE +void *operator new[](size_t size, std::align_val_t align) +{ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); } +INTERCEPTOR_ATTRIBUTE +void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&) +{ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); } +INTERCEPTOR_ATTRIBUTE +void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&) +{ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); } #define OPERATOR_DELETE_BODY \ GET_MALLOC_STACK_TRACE; \ @@ -62,5 +80,29 @@ INTERCEPTOR_ATTRIBUTE void operator delete[](void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; } +INTERCEPTOR_ATTRIBUTE +void operator delete(void *ptr, size_t size) NOEXCEPT { OPERATOR_DELETE_BODY; } +INTERCEPTOR_ATTRIBUTE +void operator delete[](void *ptr, size_t size) NOEXCEPT +{ OPERATOR_DELETE_BODY; } +INTERCEPTOR_ATTRIBUTE +void operator delete(void *ptr, std::align_val_t align) NOEXCEPT +{ OPERATOR_DELETE_BODY; } +INTERCEPTOR_ATTRIBUTE +void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT +{ OPERATOR_DELETE_BODY; } +INTERCEPTOR_ATTRIBUTE +void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&) +{ OPERATOR_DELETE_BODY; } +INTERCEPTOR_ATTRIBUTE +void operator delete[](void *ptr, std::align_val_t align, std::nothrow_t const&) +{ OPERATOR_DELETE_BODY; } +INTERCEPTOR_ATTRIBUTE +void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT +{ OPERATOR_DELETE_BODY; } +INTERCEPTOR_ATTRIBUTE +void operator delete[](void *ptr, size_t size, std::align_val_t align) NOEXCEPT +{ OPERATOR_DELETE_BODY; } + #endif // MSAN_REPLACE_OPERATORS_NEW_AND_DELETE diff --git a/lib/profile/InstrProfilingUtil.c b/lib/profile/InstrProfilingUtil.c index 1105623834129..7f49d0f9fae11 100644 --- a/lib/profile/InstrProfilingUtil.c +++ b/lib/profile/InstrProfilingUtil.c @@ -9,6 +9,7 @@ #ifdef _WIN32 #include <direct.h> +#include <process.h> #include <windows.h> #include "WindowsMMap.h" #else diff --git a/lib/sanitizer_common/CMakeLists.txt b/lib/sanitizer_common/CMakeLists.txt index 60caa5c4ffc90..e0226ae4975f9 100644 --- a/lib/sanitizer_common/CMakeLists.txt +++ b/lib/sanitizer_common/CMakeLists.txt @@ -20,12 +20,15 @@ set(SANITIZER_SOURCES_NOTERMINATION sanitizer_platform_limits_linux.cc sanitizer_platform_limits_netbsd.cc sanitizer_platform_limits_posix.cc + sanitizer_platform_limits_solaris.cc sanitizer_posix.cc sanitizer_printf.cc sanitizer_procmaps_common.cc sanitizer_procmaps_freebsd.cc sanitizer_procmaps_linux.cc sanitizer_procmaps_mac.cc + sanitizer_procmaps_solaris.cc + sanitizer_solaris.cc sanitizer_stackdepot.cc sanitizer_stacktrace.cc sanitizer_stacktrace_printer.cc @@ -40,7 +43,7 @@ set(SANITIZER_SOURCES_NOTERMINATION sanitizer_thread_registry.cc sanitizer_win.cc) -if(UNIX AND NOT APPLE) +if(UNIX AND NOT APPLE AND NOT OS_NAME MATCHES "SunOS") list(APPEND SANITIZER_SOURCES_NOTERMINATION sanitizer_linux_x86_64.S) list(APPEND SANITIZER_SOURCES_NOTERMINATION @@ -122,6 +125,7 @@ set(SANITIZER_HEADERS sanitizer_platform_interceptors.h sanitizer_platform_limits_netbsd.h sanitizer_platform_limits_posix.h + sanitizer_platform_limits_solaris.h sanitizer_posix.h sanitizer_procmaps.h sanitizer_quarantine.h @@ -216,6 +220,38 @@ add_compiler_rt_object_libraries(RTSanitizerCommonLibcNoHooks CFLAGS ${SANITIZER_NO_WEAK_HOOKS_CFLAGS} DEFS ${SANITIZER_COMMON_DEFINITIONS}) +if(OS_NAME MATCHES "SunOS") + # Solaris ld doesn't support the non-standard GNU ld extension of adding + # __start_SECNAME and __stop_SECNAME labels to sections whose names are + # valid C identifiers. Instead we add our own definitions for the + # __sancov_guards section. + add_compiler_rt_object_libraries(SancovBegin + ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} + SOURCES sancov_begin.S + CFLAGS ${SANITIZER_CFLAGS} + DEFS ${SANITIZER_COMMON_DEFINITIONS}) + + add_compiler_rt_runtime(clang_rt.sancov_begin + STATIC + ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} + OBJECT_LIBS SancovBegin + CFLAGS ${SANITIZER_CFLAGS} + DEFS ${SANITIZER_COMMON_DEFINITIONS}) + + add_compiler_rt_object_libraries(SancovEnd + ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} + SOURCES sancov_end.S + CFLAGS ${SANITIZER_CFLAGS} + DEFS ${SANITIZER_COMMON_DEFINITIONS}) + + add_compiler_rt_runtime(clang_rt.sancov_end + STATIC + ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} + OBJECT_LIBS SancovEnd + CFLAGS ${SANITIZER_CFLAGS} + DEFS ${SANITIZER_COMMON_DEFINITIONS}) +endif() + if(WIN32) add_compiler_rt_object_libraries(SanitizerCommonWeakInterception ${SANITIZER_COMMON_SUPPORTED_OS} diff --git a/lib/sanitizer_common/sancov_begin.S b/lib/sanitizer_common/sancov_begin.S new file mode 100644 index 0000000000000..c8ad0a0bcb5c5 --- /dev/null +++ b/lib/sanitizer_common/sancov_begin.S @@ -0,0 +1,5 @@ + .type __start___sancov_guards,@object + .globl __start___sancov_guards + .section __sancov_guards,"aw",@progbits + .p2align 2 +__start___sancov_guards: diff --git a/lib/sanitizer_common/sancov_end.S b/lib/sanitizer_common/sancov_end.S new file mode 100644 index 0000000000000..31117b1c0b561 --- /dev/null +++ b/lib/sanitizer_common/sancov_end.S @@ -0,0 +1,5 @@ + .type __stop___sancov_guards,@object + .globl __stop___sancov_guards + .section __sancov_guards,"aw",@progbits + .p2align 2 +__stop___sancov_guards: diff --git a/lib/sanitizer_common/sanitizer_atomic_clang.h b/lib/sanitizer_common/sanitizer_atomic_clang.h index 65b3a38f0d515..cd41c920f1b1d 100644 --- a/lib/sanitizer_common/sanitizer_atomic_clang.h +++ b/lib/sanitizer_common/sanitizer_atomic_clang.h @@ -78,17 +78,7 @@ INLINE bool atomic_compare_exchange_strong(volatile T *a, typename T::Type *cmp, typedef typename T::Type Type; Type cmpv = *cmp; Type prev; -#if defined(_MIPS_SIM) && _MIPS_SIM == _ABIO32 - if (sizeof(*a) == 8) { - Type volatile *val_ptr = const_cast<Type volatile *>(&a->val_dont_use); - prev = __mips_sync_val_compare_and_swap<u64>( - reinterpret_cast<u64 volatile *>(val_ptr), (u64)cmpv, (u64)xchg); - } else { - prev = __sync_val_compare_and_swap(&a->val_dont_use, cmpv, xchg); - } -#else prev = __sync_val_compare_and_swap(&a->val_dont_use, cmpv, xchg); -#endif if (prev == cmpv) return true; *cmp = prev; return false; @@ -104,6 +94,13 @@ INLINE bool atomic_compare_exchange_weak(volatile T *a, } // namespace __sanitizer +// This include provides explicit template instantiations for atomic_uint64_t +// on MIPS32, which does not directly support 8 byte atomics. It has to +// proceed the template definitions above. +#if defined(_MIPS_SIM) && defined(_ABIO32) + #include "sanitizer_atomic_clang_mips.h" +#endif + #undef ATOMIC_ORDER #endif // SANITIZER_ATOMIC_CLANG_H diff --git a/lib/sanitizer_common/sanitizer_atomic_clang_mips.h b/lib/sanitizer_common/sanitizer_atomic_clang_mips.h new file mode 100644 index 0000000000000..c64e6e5427984 --- /dev/null +++ b/lib/sanitizer_common/sanitizer_atomic_clang_mips.h @@ -0,0 +1,118 @@ +//===-- sanitizer_atomic_clang_mips.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer/AddressSanitizer runtime. +// Not intended for direct inclusion. Include sanitizer_atomic.h. +// +//===----------------------------------------------------------------------===// + +#ifndef SANITIZER_ATOMIC_CLANG_MIPS_H +#define SANITIZER_ATOMIC_CLANG_MIPS_H + +namespace __sanitizer { + +// MIPS32 does not support atomics > 4 bytes. To address this lack of +// functionality, the sanitizer library provides helper methods which use an +// internal spin lock mechanism to emulate atomic oprations when the size is +// 8 bytes. +static void __spin_lock(volatile int *lock) { + while (__sync_lock_test_and_set(lock, 1)) + while (*lock) { + } +} + +static void __spin_unlock(volatile int *lock) { __sync_lock_release(lock); } + +// Make sure the lock is on its own cache line to prevent false sharing. +// Put it inside a struct that is aligned and padded to the typical MIPS +// cacheline which is 32 bytes. +static struct { + int lock; + char pad[32 - sizeof(int)]; +} __attribute__((aligned(32))) lock = {0, {0}}; + +template <> +INLINE atomic_uint64_t::Type atomic_fetch_add(volatile atomic_uint64_t *ptr, + atomic_uint64_t::Type val, + memory_order mo) { + DCHECK(mo & + (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst)); + DCHECK(!((uptr)ptr % sizeof(*ptr))); + + atomic_uint64_t::Type ret; + + __spin_lock(&lock.lock); + ret = *(const_cast<atomic_uint64_t::Type volatile *>(&ptr->val_dont_use)); + ptr->val_dont_use = ret + val; + __spin_unlock(&lock.lock); + + return ret; +} + +template <> +INLINE atomic_uint64_t::Type atomic_fetch_sub(volatile atomic_uint64_t *ptr, + atomic_uint64_t::Type val, + memory_order mo) { + return atomic_fetch_add(ptr, -val, mo); +} + +template <> +INLINE bool atomic_compare_exchange_strong(volatile atomic_uint64_t *ptr, + atomic_uint64_t::Type *cmp, + atomic_uint64_t::Type xchg, + memory_order mo) { + DCHECK(mo & + (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst)); + DCHECK(!((uptr)ptr % sizeof(*ptr))); + + typedef atomic_uint64_t::Type Type; + Type cmpv = *cmp; + Type prev; + bool ret = false; + + __spin_lock(&lock.lock); + prev = *(const_cast<Type volatile *>(&ptr->val_dont_use)); + if (prev == cmpv) { + ret = true; + ptr->val_dont_use = xchg; + } + __spin_unlock(&lock.lock); + + return ret; +} + +template <> +INLINE atomic_uint64_t::Type atomic_load(const volatile atomic_uint64_t *ptr, + memory_order mo) { + DCHECK(mo & + (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst)); + DCHECK(!((uptr)ptr % sizeof(*ptr))); + + atomic_uint64_t::Type zero = 0; + volatile atomic_uint64_t *Newptr = + const_cast<volatile atomic_uint64_t *>(ptr); + return atomic_fetch_add(Newptr, zero, mo); +} + +template <> +INLINE void atomic_store(volatile atomic_uint64_t *ptr, atomic_uint64_t::Type v, + memory_order mo) { + DCHECK(mo & + (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst)); + DCHECK(!((uptr)ptr % sizeof(*ptr))); + + __spin_lock(&lock.lock); + ptr->val_dont_use = v; + __spin_unlock(&lock.lock); +} + +} // namespace __sanitizer + +#endif // SANITIZER_ATOMIC_CLANG_MIPS_H + diff --git a/lib/sanitizer_common/sanitizer_atomic_clang_other.h b/lib/sanitizer_common/sanitizer_atomic_clang_other.h index d2acc311bf7da..35e2d007eda86 100644 --- a/lib/sanitizer_common/sanitizer_atomic_clang_other.h +++ b/lib/sanitizer_common/sanitizer_atomic_clang_other.h @@ -17,55 +17,6 @@ namespace __sanitizer { -// MIPS32 does not support atomic > 4 bytes. To address this lack of -// functionality, the sanitizer library provides helper methods which use an -// internal spin lock mechanism to emulate atomic oprations when the size is -// 8 bytes. -#if defined(_MIPS_SIM) && _MIPS_SIM == _ABIO32 -static void __spin_lock(volatile int *lock) { - while (__sync_lock_test_and_set(lock, 1)) - while (*lock) { - } -} - -static void __spin_unlock(volatile int *lock) { __sync_lock_release(lock); } - - -// Make sure the lock is on its own cache line to prevent false sharing. -// Put it inside a struct that is aligned and padded to the typical MIPS -// cacheline which is 32 bytes. -static struct { - int lock; - char pad[32 - sizeof(int)]; -} __attribute__((aligned(32))) lock = {0}; - -template <class T> -T __mips_sync_fetch_and_add(volatile T *ptr, T val) { - T ret; - - __spin_lock(&lock.lock); - - ret = *ptr; - *ptr = ret + val; - - __spin_unlock(&lock.lock); - - return ret; -} - -template <class T> -T __mips_sync_val_compare_and_swap(volatile T *ptr, T oldval, T newval) { - T ret; - __spin_lock(&lock.lock); - - ret = *ptr; - if (ret == oldval) *ptr = newval; - - __spin_unlock(&lock.lock); - - return ret; -} -#endif INLINE void proc_yield(int cnt) { __asm__ __volatile__("" ::: "memory"); @@ -103,15 +54,8 @@ INLINE typename T::Type atomic_load( // 64-bit load on 32-bit platform. // Gross, but simple and reliable. // Assume that it is not in read-only memory. -#if defined(_MIPS_SIM) && _MIPS_SIM == _ABIO32 - typename T::Type volatile *val_ptr = - const_cast<typename T::Type volatile *>(&a->val_dont_use); - v = __mips_sync_fetch_and_add<u64>( - reinterpret_cast<u64 volatile *>(val_ptr), 0); -#else v = __sync_fetch_and_add( const_cast<typename T::Type volatile *>(&a->val_dont_use), 0); -#endif } return v; } @@ -141,14 +85,7 @@ INLINE void atomic_store(volatile T *a, typename T::Type v, memory_order mo) { typename T::Type cmp = a->val_dont_use; typename T::Type cur; for (;;) { -#if defined(_MIPS_SIM) && _MIPS_SIM == _ABIO32 - typename T::Type volatile *val_ptr = - const_cast<typename T::Type volatile *>(&a->val_dont_use); - cur = __mips_sync_val_compare_and_swap<u64>( - reinterpret_cast<u64 volatile *>(val_ptr), (u64)cmp, (u64)v); -#else cur = __sync_val_compare_and_swap(&a->val_dont_use, cmp, v); -#endif if (cmp == v) break; cmp = cur; diff --git a/lib/sanitizer_common/scripts/gen_dynamic_list.py b/lib/sanitizer_common/scripts/gen_dynamic_list.py index 1d4230607b924..25632ed77b946 100755 --- a/lib/sanitizer_common/scripts/gen_dynamic_list.py +++ b/lib/sanitizer_common/scripts/gen_dynamic_list.py @@ -26,12 +26,32 @@ new_delete = set([ '_Znwm', '_ZnwmRKSt9nothrow_t', # operator new(unsigned long) '_Znaj', '_ZnajRKSt9nothrow_t', # operator new[](unsigned int) '_Znwj', '_ZnwjRKSt9nothrow_t', # operator new(unsigned int) + # operator new(unsigned long, std::align_val_t) + '_ZnwmSt11align_val_t', '_ZnwmSt11align_val_tRKSt9nothrow_t', + # operator new(unsigned int, std::align_val_t) + '_ZnwjSt11align_val_t', '_ZnwjSt11align_val_tRKSt9nothrow_t', + # operator new[](unsigned long, std::align_val_t) + '_ZnamSt11align_val_t', '_ZnamSt11align_val_tRKSt9nothrow_t', + # operator new[](unsigned int, std::align_val_t) + '_ZnajSt11align_val_t', '_ZnajSt11align_val_tRKSt9nothrow_t', '_ZdaPv', '_ZdaPvRKSt9nothrow_t', # operator delete[](void *) '_ZdlPv', '_ZdlPvRKSt9nothrow_t', # operator delete(void *) '_ZdaPvm', # operator delete[](void*, unsigned long) '_ZdlPvm', # operator delete(void*, unsigned long) '_ZdaPvj', # operator delete[](void*, unsigned int) '_ZdlPvj', # operator delete(void*, unsigned int) + # operator delete(void*, std::align_val_t) + '_ZdlPvSt11align_val_t', '_ZdlPvSt11align_val_tRKSt9nothrow_t', + # operator delete[](void*, std::align_val_t) + '_ZdaPvSt11align_val_t', '_ZdaPvSt11align_val_tRKSt9nothrow_t', + # operator delete(void*, unsigned long, std::align_val_t) + '_ZdlPvmSt11align_val_t', + # operator delete[](void*, unsigned long, std::align_val_t) + '_ZdaPvmSt11align_val_t', + # operator delete(void*, unsigned int, std::align_val_t) + '_ZdlPvjSt11align_val_t', + # operator delete[](void*, unsigned int, std::align_val_t) + '_ZdaPvjSt11align_val_t', ]) versioned_functions = set(['memcpy', 'pthread_attr_getaffinity_np', diff --git a/lib/tsan/rtl/tsan_new_delete.cc b/lib/tsan/rtl/tsan_new_delete.cc index 4d03145c16ad5..a1bb22690e0f4 100644 --- a/lib/tsan/rtl/tsan_new_delete.cc +++ b/lib/tsan/rtl/tsan_new_delete.cc @@ -20,6 +20,7 @@ using namespace __tsan; // NOLINT namespace std { struct nothrow_t {}; +enum class align_val_t: __sanitizer::uptr {}; } // namespace std DECLARE_REAL(void *, malloc, uptr size) @@ -38,6 +39,18 @@ DECLARE_REAL(void, free, void *ptr) invoke_malloc_hook(p, size); \ return p; +#define OPERATOR_NEW_BODY_ALIGN(mangled_name, nothrow) \ + if (cur_thread()->in_symbolizer) \ + return InternalAlloc(size, nullptr, (uptr)align); \ + void *p = 0; \ + { \ + SCOPED_INTERCEPTOR_RAW(mangled_name, size); \ + p = user_memalign(thr, pc, (uptr)align, size); \ + if (!nothrow && UNLIKELY(!p)) DieOnFailure::OnOOM(); \ + } \ + invoke_malloc_hook(p, size); \ + return p; + SANITIZER_INTERFACE_ATTRIBUTE void *operator new(__sanitizer::uptr size); void *operator new(__sanitizer::uptr size) { @@ -62,6 +75,36 @@ void *operator new[](__sanitizer::uptr size, std::nothrow_t const&) { OPERATOR_NEW_BODY(_ZnamRKSt9nothrow_t, true /*nothrow*/); } +SANITIZER_INTERFACE_ATTRIBUTE +void *operator new(__sanitizer::uptr size, std::align_val_t align); +void *operator new(__sanitizer::uptr size, std::align_val_t align) { + OPERATOR_NEW_BODY_ALIGN(_ZnwmSt11align_val_t, false /*nothrow*/); +} + +SANITIZER_INTERFACE_ATTRIBUTE +void *operator new[](__sanitizer::uptr size, std::align_val_t align); +void *operator new[](__sanitizer::uptr size, std::align_val_t align) { + OPERATOR_NEW_BODY_ALIGN(_ZnamSt11align_val_t, false /*nothrow*/); +} + +SANITIZER_INTERFACE_ATTRIBUTE +void *operator new(__sanitizer::uptr size, std::align_val_t align, + std::nothrow_t const&); +void *operator new(__sanitizer::uptr size, std::align_val_t align, + std::nothrow_t const&) { + OPERATOR_NEW_BODY_ALIGN(_ZnwmSt11align_val_tRKSt9nothrow_t, + true /*nothrow*/); +} + +SANITIZER_INTERFACE_ATTRIBUTE +void *operator new[](__sanitizer::uptr size, std::align_val_t align, + std::nothrow_t const&); +void *operator new[](__sanitizer::uptr size, std::align_val_t align, + std::nothrow_t const&) { + OPERATOR_NEW_BODY_ALIGN(_ZnamSt11align_val_tRKSt9nothrow_t, + true /*nothrow*/); +} + #define OPERATOR_DELETE_BODY(mangled_name) \ if (ptr == 0) return; \ if (cur_thread()->in_symbolizer) \ @@ -93,3 +136,57 @@ void operator delete[](void *ptr, std::nothrow_t const&); void operator delete[](void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY(_ZdaPvRKSt9nothrow_t); } + +SANITIZER_INTERFACE_ATTRIBUTE +void operator delete(void *ptr, __sanitizer::uptr size) NOEXCEPT; +void operator delete(void *ptr, __sanitizer::uptr size) NOEXCEPT { + OPERATOR_DELETE_BODY(_ZdlPvm); +} + +SANITIZER_INTERFACE_ATTRIBUTE +void operator delete[](void *ptr, __sanitizer::uptr size) NOEXCEPT; +void operator delete[](void *ptr, __sanitizer::uptr size) NOEXCEPT { + OPERATOR_DELETE_BODY(_ZdaPvm); +} + +SANITIZER_INTERFACE_ATTRIBUTE +void operator delete(void *ptr, std::align_val_t align) NOEXCEPT; +void operator delete(void *ptr, std::align_val_t align) NOEXCEPT { + OPERATOR_DELETE_BODY(_ZdlPvSt11align_val_t); +} + +SANITIZER_INTERFACE_ATTRIBUTE +void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT; +void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT { + OPERATOR_DELETE_BODY(_ZdaPvSt11align_val_t); +} + +SANITIZER_INTERFACE_ATTRIBUTE +void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&); +void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&) { + OPERATOR_DELETE_BODY(_ZdlPvSt11align_val_tRKSt9nothrow_t); +} + +SANITIZER_INTERFACE_ATTRIBUTE +void operator delete[](void *ptr, std::align_val_t align, + std::nothrow_t const&); +void operator delete[](void *ptr, std::align_val_t align, + std::nothrow_t const&) { + OPERATOR_DELETE_BODY(_ZdaPvSt11align_val_tRKSt9nothrow_t); +} + +SANITIZER_INTERFACE_ATTRIBUTE +void operator delete(void *ptr, __sanitizer::uptr size, + std::align_val_t align) NOEXCEPT; +void operator delete(void *ptr, __sanitizer::uptr size, + std::align_val_t align) NOEXCEPT { + OPERATOR_DELETE_BODY(_ZdlPvmSt11align_val_t); +} + +SANITIZER_INTERFACE_ATTRIBUTE +void operator delete[](void *ptr, __sanitizer::uptr size, + std::align_val_t align) NOEXCEPT; +void operator delete[](void *ptr, __sanitizer::uptr size, + std::align_val_t align) NOEXCEPT { + OPERATOR_DELETE_BODY(_ZdaPvmSt11align_val_t); +} diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc index 1112ce1cc5ffa..f674c027cd912 100644 --- a/lib/ubsan/ubsan_handlers.cc +++ b/lib/ubsan/ubsan_handlers.cc @@ -297,7 +297,7 @@ void __ubsan::__ubsan_handle_out_of_bounds_abort(OutOfBoundsData *Data, static void handleBuiltinUnreachableImpl(UnreachableData *Data, ReportOptions Opts) { ScopedReport R(Opts, Data->Loc, ErrorType::UnreachableCall); - Diag(Data->Loc, DL_Error, "execution reached a __builtin_unreachable() call"); + Diag(Data->Loc, DL_Error, "execution reached an unreachable program point"); } void __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) { |