diff options
author | Martin Liska <mliska@suse.cz> | 2020-10-16 10:03:04 +0200 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2020-10-16 10:57:03 +0200 |
commit | 0b997f6e07771c98178ea09f4a8c4446baaf84da (patch) | |
tree | c3ef933f3fda4195644c6734b2c212e9f77718e3 /libsanitizer/tsan | |
parent | 4a70aa7a627c0b918ce1da75c0dbe088539e420f (diff) | |
download | gcc-0b997f6e07771c98178ea09f4a8c4446baaf84da.zip gcc-0b997f6e07771c98178ea09f4a8c4446baaf84da.tar.gz gcc-0b997f6e07771c98178ea09f4a8c4446baaf84da.tar.bz2 |
libsanitizer: merge from master
Diffstat (limited to 'libsanitizer/tsan')
-rw-r--r-- | libsanitizer/tsan/tsan_dispatch_defs.h | 11 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_external.cpp | 11 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_flags.cpp | 2 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_flags.inc | 2 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_interceptors.h | 2 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_interceptors_libdispatch.cpp | 32 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_interceptors_mach_vm.cpp | 19 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_interceptors_posix.cpp | 30 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_interface.cpp | 13 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_interface_inl.h | 23 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_platform_linux.cpp | 24 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_platform_mac.cpp | 4 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_platform_posix.cpp | 47 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_report.cpp | 3 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_rtl.cpp | 13 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_rtl.h | 10 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_rtl_ppc64.S | 1 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_rtl_report.cpp | 107 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_sync.cpp | 2 |
19 files changed, 186 insertions, 170 deletions
diff --git a/libsanitizer/tsan/tsan_dispatch_defs.h b/libsanitizer/tsan/tsan_dispatch_defs.h index 298297a..94e0b50 100644 --- a/libsanitizer/tsan/tsan_dispatch_defs.h +++ b/libsanitizer/tsan/tsan_dispatch_defs.h @@ -51,11 +51,18 @@ extern const dispatch_block_t _dispatch_data_destructor_munmap; #define DISPATCH_DATA_DESTRUCTOR_MUNMAP _dispatch_data_destructor_munmap #if __has_attribute(noescape) - #define DISPATCH_NOESCAPE __attribute__((__noescape__)) +# define DISPATCH_NOESCAPE __attribute__((__noescape__)) #else - #define DISPATCH_NOESCAPE +# define DISPATCH_NOESCAPE #endif +#if SANITIZER_MAC +# define SANITIZER_WEAK_IMPORT extern "C" __attribute((weak_import)) +#else +# define SANITIZER_WEAK_IMPORT extern "C" __attribute((weak)) +#endif + + // Data types used in dispatch APIs typedef unsigned long size_t; typedef unsigned long uintptr_t; diff --git a/libsanitizer/tsan/tsan_external.cpp b/libsanitizer/tsan/tsan_external.cpp index 0faa1ee..466b2bf 100644 --- a/libsanitizer/tsan/tsan_external.cpp +++ b/libsanitizer/tsan/tsan_external.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "tsan_rtl.h" #include "tsan_interceptors.h" +#include "sanitizer_common/sanitizer_ptrauth.h" namespace __tsan { @@ -57,13 +58,13 @@ uptr TagFromShadowStackFrame(uptr pc) { #if !SANITIZER_GO typedef void(*AccessFunc)(ThreadState *, uptr, uptr, int); -void ExternalAccess(void *addr, void *caller_pc, void *tag, AccessFunc access) { +void ExternalAccess(void *addr, uptr caller_pc, void *tag, AccessFunc access) { CHECK_LT(tag, atomic_load(&used_tags, memory_order_relaxed)); ThreadState *thr = cur_thread(); - if (caller_pc) FuncEntry(thr, (uptr)caller_pc); + if (caller_pc) FuncEntry(thr, caller_pc); InsertShadowStackFrameForTag(thr, (uptr)tag); bool in_ignored_lib; - if (!caller_pc || !libignore()->IsIgnored((uptr)caller_pc, &in_ignored_lib)) { + if (!caller_pc || !libignore()->IsIgnored(caller_pc, &in_ignored_lib)) { access(thr, CALLERPC, (uptr)addr, kSizeLog1); } FuncExit(thr); @@ -110,12 +111,12 @@ void __tsan_external_assign_tag(void *addr, void *tag) { SANITIZER_INTERFACE_ATTRIBUTE void __tsan_external_read(void *addr, void *caller_pc, void *tag) { - ExternalAccess(addr, caller_pc, tag, MemoryRead); + ExternalAccess(addr, STRIP_PC(caller_pc), tag, MemoryRead); } SANITIZER_INTERFACE_ATTRIBUTE void __tsan_external_write(void *addr, void *caller_pc, void *tag) { - ExternalAccess(addr, caller_pc, tag, MemoryWrite); + ExternalAccess(addr, STRIP_PC(caller_pc), tag, MemoryWrite); } } // extern "C" diff --git a/libsanitizer/tsan/tsan_flags.cpp b/libsanitizer/tsan/tsan_flags.cpp index 44bf325..49e4a9c 100644 --- a/libsanitizer/tsan/tsan_flags.cpp +++ b/libsanitizer/tsan/tsan_flags.cpp @@ -87,7 +87,7 @@ void InitializeFlags(Flags *f, const char *env, const char *env_option_name) { // Let a frontend override. parser.ParseString(__tsan_default_options()); #if TSAN_CONTAINS_UBSAN - const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions(); + const char *ubsan_default_options = __ubsan_default_options(); ubsan_parser.ParseString(ubsan_default_options); #endif // Override from command line. diff --git a/libsanitizer/tsan/tsan_flags.inc b/libsanitizer/tsan/tsan_flags.inc index bfb74b6..2105c75 100644 --- a/libsanitizer/tsan/tsan_flags.inc +++ b/libsanitizer/tsan/tsan_flags.inc @@ -76,6 +76,8 @@ TSAN_FLAG(int, io_sync, 1, TSAN_FLAG(bool, die_after_fork, true, "Die after multi-threaded fork if the child creates new threads.") TSAN_FLAG(const char *, suppressions, "", "Suppressions file name.") +TSAN_FLAG(bool, ignore_interceptors_accesses, SANITIZER_MAC ? true : false, + "Ignore reads and writes from all interceptors.") TSAN_FLAG(bool, ignore_noninstrumented_modules, SANITIZER_MAC ? true : false, "Interceptors should only detect races when called from instrumented " "modules.") diff --git a/libsanitizer/tsan/tsan_interceptors.h b/libsanitizer/tsan/tsan_interceptors.h index 88d1edd..29576ea 100644 --- a/libsanitizer/tsan/tsan_interceptors.h +++ b/libsanitizer/tsan/tsan_interceptors.h @@ -22,7 +22,7 @@ class ScopedInterceptor { LibIgnore *libignore(); #if !SANITIZER_GO -INLINE bool in_symbolizer() { +inline bool in_symbolizer() { cur_thread_init(); return UNLIKELY(cur_thread()->in_symbolizer); } diff --git a/libsanitizer/tsan/tsan_interceptors_libdispatch.cpp b/libsanitizer/tsan/tsan_interceptors_libdispatch.cpp index 5dacd32..cbbb7ec 100644 --- a/libsanitizer/tsan/tsan_interceptors_libdispatch.cpp +++ b/libsanitizer/tsan/tsan_interceptors_libdispatch.cpp @@ -19,6 +19,10 @@ #include "BlocksRuntime/Block.h" #include "tsan_dispatch_defs.h" +#if SANITIZER_MAC +# include <Availability.h> +#endif + namespace __tsan { typedef u16 uint16_t; @@ -219,6 +223,30 @@ static void invoke_and_release_block(void *param) { DISPATCH_INTERCEPT(dispatch, false) DISPATCH_INTERCEPT(dispatch_barrier, true) +// dispatch_async_and_wait() and friends were introduced in macOS 10.14. +// Linking of these interceptors fails when using an older SDK. +#if !SANITIZER_MAC || defined(__MAC_10_14) +// macOS 10.14 is greater than our minimal deployment target. To ensure we +// generate a weak reference so the TSan dylib continues to work on older +// systems, we need to forward declare the intercepted functions as "weak +// imports". Note that this file is multi-platform, so we cannot include the +// actual header file (#include <dispatch/dispatch.h>). +SANITIZER_WEAK_IMPORT void dispatch_async_and_wait( + dispatch_queue_t queue, DISPATCH_NOESCAPE dispatch_block_t block); +SANITIZER_WEAK_IMPORT void dispatch_async_and_wait_f( + dispatch_queue_t queue, void *context, dispatch_function_t work); +SANITIZER_WEAK_IMPORT void dispatch_barrier_async_and_wait( + dispatch_queue_t queue, DISPATCH_NOESCAPE dispatch_block_t block); +SANITIZER_WEAK_IMPORT void dispatch_barrier_async_and_wait_f( + dispatch_queue_t queue, void *context, dispatch_function_t work); + +DISPATCH_INTERCEPT_SYNC_F(dispatch_async_and_wait_f, false) +DISPATCH_INTERCEPT_SYNC_B(dispatch_async_and_wait, false) +DISPATCH_INTERCEPT_SYNC_F(dispatch_barrier_async_and_wait_f, true) +DISPATCH_INTERCEPT_SYNC_B(dispatch_barrier_async_and_wait, true) +#endif + + DECLARE_REAL(void, dispatch_after_f, dispatch_time_t when, dispatch_queue_t queue, void *context, dispatch_function_t work) @@ -746,6 +774,10 @@ void InitializeLibdispatchInterceptors() { INTERCEPT_FUNCTION(dispatch_barrier_async_f); INTERCEPT_FUNCTION(dispatch_barrier_sync); INTERCEPT_FUNCTION(dispatch_barrier_sync_f); + INTERCEPT_FUNCTION(dispatch_async_and_wait); + INTERCEPT_FUNCTION(dispatch_async_and_wait_f); + INTERCEPT_FUNCTION(dispatch_barrier_async_and_wait); + INTERCEPT_FUNCTION(dispatch_barrier_async_and_wait_f); INTERCEPT_FUNCTION(dispatch_after); INTERCEPT_FUNCTION(dispatch_after_f); INTERCEPT_FUNCTION(dispatch_once); diff --git a/libsanitizer/tsan/tsan_interceptors_mach_vm.cpp b/libsanitizer/tsan/tsan_interceptors_mach_vm.cpp index cd318f8..6d62ff6 100644 --- a/libsanitizer/tsan/tsan_interceptors_mach_vm.cpp +++ b/libsanitizer/tsan/tsan_interceptors_mach_vm.cpp @@ -19,12 +19,11 @@ namespace __tsan { -static bool intersects_with_shadow(mach_vm_address_t *address, +static bool intersects_with_shadow(mach_vm_address_t address, mach_vm_size_t size, int flags) { // VM_FLAGS_FIXED is 0x0, so we have to test for VM_FLAGS_ANYWHERE. if (flags & VM_FLAGS_ANYWHERE) return false; - uptr ptr = *address; - return !IsAppMem(ptr) || !IsAppMem(ptr + size - 1); + return !IsAppMem(address) || !IsAppMem(address + size - 1); } TSAN_INTERCEPTOR(kern_return_t, mach_vm_allocate, vm_map_t target, @@ -32,12 +31,12 @@ TSAN_INTERCEPTOR(kern_return_t, mach_vm_allocate, vm_map_t target, SCOPED_TSAN_INTERCEPTOR(mach_vm_allocate, target, address, size, flags); if (target != mach_task_self()) return REAL(mach_vm_allocate)(target, address, size, flags); - if (intersects_with_shadow(address, size, flags)) + if (address && intersects_with_shadow(*address, size, flags)) return KERN_NO_SPACE; - kern_return_t res = REAL(mach_vm_allocate)(target, address, size, flags); - if (res == KERN_SUCCESS) + kern_return_t kr = REAL(mach_vm_allocate)(target, address, size, flags); + if (kr == KERN_SUCCESS) MemoryRangeImitateWriteOrResetRange(thr, pc, *address, size); - return res; + return kr; } TSAN_INTERCEPTOR(kern_return_t, mach_vm_deallocate, vm_map_t target, @@ -45,8 +44,10 @@ TSAN_INTERCEPTOR(kern_return_t, mach_vm_deallocate, vm_map_t target, SCOPED_TSAN_INTERCEPTOR(mach_vm_deallocate, target, address, size); if (target != mach_task_self()) return REAL(mach_vm_deallocate)(target, address, size); - UnmapShadow(thr, address, size); - return REAL(mach_vm_deallocate)(target, address, size); + kern_return_t kr = REAL(mach_vm_deallocate)(target, address, size); + if (kr == KERN_SUCCESS && address) + UnmapShadow(thr, address, size); + return kr; } } // namespace __tsan diff --git a/libsanitizer/tsan/tsan_interceptors_posix.cpp b/libsanitizer/tsan/tsan_interceptors_posix.cpp index 718957c..20c2747 100644 --- a/libsanitizer/tsan/tsan_interceptors_posix.cpp +++ b/libsanitizer/tsan/tsan_interceptors_posix.cpp @@ -31,6 +31,8 @@ #include "tsan_mman.h" #include "tsan_fd.h" +#include <stdarg.h> + using namespace __tsan; #if SANITIZER_FREEBSD || SANITIZER_MAC @@ -135,6 +137,7 @@ const int PTHREAD_BARRIER_SERIAL_THREAD = -1; #endif const int MAP_FIXED = 0x10; typedef long long_t; +typedef __sanitizer::u16 mode_t; // From /usr/include/unistd.h # define F_ULOCK 0 /* Unlock a previously locked region. */ @@ -254,7 +257,8 @@ ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname, if (!thr_->ignore_interceptors) FuncEntry(thr, pc); DPrintf("#%d: intercept %s()\n", thr_->tid, fname); ignoring_ = - !thr_->in_ignored_lib && libignore()->IsIgnored(pc, &in_ignored_lib_); + !thr_->in_ignored_lib && (flags()->ignore_interceptors_accesses || + libignore()->IsIgnored(pc, &in_ignored_lib_)); EnableIgnores(); } @@ -1507,20 +1511,28 @@ TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) { #define TSAN_MAYBE_INTERCEPT_FSTAT64 #endif -TSAN_INTERCEPTOR(int, open, const char *name, int flags, int mode) { - SCOPED_TSAN_INTERCEPTOR(open, name, flags, mode); +TSAN_INTERCEPTOR(int, open, const char *name, int oflag, ...) { + va_list ap; + va_start(ap, oflag); + mode_t mode = va_arg(ap, int); + va_end(ap); + SCOPED_TSAN_INTERCEPTOR(open, name, oflag, mode); READ_STRING(thr, pc, name, 0); - int fd = REAL(open)(name, flags, mode); + int fd = REAL(open)(name, oflag, mode); if (fd >= 0) FdFileCreate(thr, pc, fd); return fd; } #if SANITIZER_LINUX -TSAN_INTERCEPTOR(int, open64, const char *name, int flags, int mode) { - SCOPED_TSAN_INTERCEPTOR(open64, name, flags, mode); +TSAN_INTERCEPTOR(int, open64, const char *name, int oflag, ...) { + va_list ap; + va_start(ap, oflag); + mode_t mode = va_arg(ap, int); + va_end(ap); + SCOPED_TSAN_INTERCEPTOR(open64, name, oflag, mode); READ_STRING(thr, pc, name, 0); - int fd = REAL(open64)(name, flags, mode); + int fd = REAL(open64)(name, oflag, mode); if (fd >= 0) FdFileCreate(thr, pc, fd); return fd; @@ -2436,13 +2448,13 @@ static void syscall_access_range(uptr pc, uptr p, uptr s, bool write) { MemoryAccessRange(thr, pc, p, s, write); } -static void syscall_acquire(uptr pc, uptr addr) { +static USED void syscall_acquire(uptr pc, uptr addr) { TSAN_SYSCALL(); Acquire(thr, pc, addr); DPrintf("syscall_acquire(%p)\n", addr); } -static void syscall_release(uptr pc, uptr addr) { +static USED void syscall_release(uptr pc, uptr addr) { TSAN_SYSCALL(); DPrintf("syscall_release(%p)\n", addr); Release(thr, pc, addr); diff --git a/libsanitizer/tsan/tsan_interface.cpp b/libsanitizer/tsan/tsan_interface.cpp index 2b3a088..55f1c98 100644 --- a/libsanitizer/tsan/tsan_interface.cpp +++ b/libsanitizer/tsan/tsan_interface.cpp @@ -14,15 +14,12 @@ #include "tsan_interface_ann.h" #include "tsan_rtl.h" #include "sanitizer_common/sanitizer_internal_defs.h" +#include "sanitizer_common/sanitizer_ptrauth.h" #define CALLERPC ((uptr)__builtin_return_address(0)) using namespace __tsan; -typedef u16 uint16_t; -typedef u32 uint32_t; -typedef u64 uint64_t; - void __tsan_init() { cur_thread_init(); Initialize(cur_thread()); @@ -43,13 +40,13 @@ void __tsan_write16(void *addr) { } void __tsan_read16_pc(void *addr, void *pc) { - MemoryRead(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog8); - MemoryRead(cur_thread(), (uptr)pc, (uptr)addr + 8, kSizeLog8); + MemoryRead(cur_thread(), STRIP_PC(pc), (uptr)addr, kSizeLog8); + MemoryRead(cur_thread(), STRIP_PC(pc), (uptr)addr + 8, kSizeLog8); } void __tsan_write16_pc(void *addr, void *pc) { - MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog8); - MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr + 8, kSizeLog8); + MemoryWrite(cur_thread(), STRIP_PC(pc), (uptr)addr, kSizeLog8); + MemoryWrite(cur_thread(), STRIP_PC(pc), (uptr)addr + 8, kSizeLog8); } // __tsan_unaligned_read/write calls are emitted by compiler. diff --git a/libsanitizer/tsan/tsan_interface_inl.h b/libsanitizer/tsan/tsan_interface_inl.h index f955ddf..f5d743c 100644 --- a/libsanitizer/tsan/tsan_interface_inl.h +++ b/libsanitizer/tsan/tsan_interface_inl.h @@ -12,6 +12,7 @@ #include "tsan_interface.h" #include "tsan_rtl.h" +#include "sanitizer_common/sanitizer_ptrauth.h" #define CALLERPC ((uptr)__builtin_return_address(0)) @@ -50,35 +51,35 @@ void __tsan_write8(void *addr) { } void __tsan_read1_pc(void *addr, void *pc) { - MemoryRead(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog1); + MemoryRead(cur_thread(), STRIP_PC(pc), (uptr)addr, kSizeLog1); } void __tsan_read2_pc(void *addr, void *pc) { - MemoryRead(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog2); + MemoryRead(cur_thread(), STRIP_PC(pc), (uptr)addr, kSizeLog2); } void __tsan_read4_pc(void *addr, void *pc) { - MemoryRead(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog4); + MemoryRead(cur_thread(), STRIP_PC(pc), (uptr)addr, kSizeLog4); } void __tsan_read8_pc(void *addr, void *pc) { - MemoryRead(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog8); + MemoryRead(cur_thread(), STRIP_PC(pc), (uptr)addr, kSizeLog8); } void __tsan_write1_pc(void *addr, void *pc) { - MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog1); + MemoryWrite(cur_thread(), STRIP_PC(pc), (uptr)addr, kSizeLog1); } void __tsan_write2_pc(void *addr, void *pc) { - MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog2); + MemoryWrite(cur_thread(), STRIP_PC(pc), (uptr)addr, kSizeLog2); } void __tsan_write4_pc(void *addr, void *pc) { - MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog4); + MemoryWrite(cur_thread(), STRIP_PC(pc), (uptr)addr, kSizeLog4); } void __tsan_write8_pc(void *addr, void *pc) { - MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog8); + MemoryWrite(cur_thread(), STRIP_PC(pc), (uptr)addr, kSizeLog8); } void __tsan_vptr_update(void **vptr_p, void *new_val) { @@ -100,7 +101,7 @@ void __tsan_vptr_read(void **vptr_p) { } void __tsan_func_entry(void *pc) { - FuncEntry(cur_thread(), (uptr)pc); + FuncEntry(cur_thread(), STRIP_PC(pc)); } void __tsan_func_exit() { @@ -124,9 +125,9 @@ void __tsan_write_range(void *addr, uptr size) { } void __tsan_read_range_pc(void *addr, uptr size, void *pc) { - MemoryAccessRange(cur_thread(), (uptr)pc, (uptr)addr, size, false); + MemoryAccessRange(cur_thread(), STRIP_PC(pc), (uptr)addr, size, false); } void __tsan_write_range_pc(void *addr, uptr size, void *pc) { - MemoryAccessRange(cur_thread(), (uptr)pc, (uptr)addr, size, true); + MemoryAccessRange(cur_thread(), STRIP_PC(pc), (uptr)addr, size, true); } diff --git a/libsanitizer/tsan/tsan_platform_linux.cpp b/libsanitizer/tsan/tsan_platform_linux.cpp index 33fa586..710e7ec 100644 --- a/libsanitizer/tsan/tsan_platform_linux.cpp +++ b/libsanitizer/tsan/tsan_platform_linux.cpp @@ -8,25 +8,26 @@ // // This file is a part of ThreadSanitizer (TSan), a race detector. // -// Linux- and FreeBSD-specific code. +// Linux- and BSD-specific code. //===----------------------------------------------------------------------===// - #include "sanitizer_common/sanitizer_platform.h" -#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD +#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \ + SANITIZER_OPENBSD #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_linux.h" #include "sanitizer_common/sanitizer_platform_limits_netbsd.h" +#include "sanitizer_common/sanitizer_platform_limits_openbsd.h" #include "sanitizer_common/sanitizer_platform_limits_posix.h" #include "sanitizer_common/sanitizer_posix.h" #include "sanitizer_common/sanitizer_procmaps.h" -#include "sanitizer_common/sanitizer_stoptheworld.h" #include "sanitizer_common/sanitizer_stackdepot.h" +#include "sanitizer_common/sanitizer_stoptheworld.h" +#include "tsan_flags.h" #include "tsan_platform.h" #include "tsan_rtl.h" -#include "tsan_flags.h" #include <fcntl.h> #include <pthread.h> @@ -383,12 +384,16 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) { #endif } -#ifdef __powerpc__ +#if SANITIZER_NETBSD +# ifdef __x86_64__ +# define LONG_JMP_SP_ENV_SLOT 6 +# else +# error unsupported +# endif +#elif defined(__powerpc__) # define LONG_JMP_SP_ENV_SLOT 0 #elif SANITIZER_FREEBSD # define LONG_JMP_SP_ENV_SLOT 2 -#elif SANITIZER_NETBSD -# define LONG_JMP_SP_ENV_SLOT 6 #elif SANITIZER_LINUX # ifdef __aarch64__ # define LONG_JMP_SP_ENV_SLOT 13 @@ -512,4 +517,5 @@ void cur_thread_finalize() { } // namespace __tsan -#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD +#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || + // SANITIZER_OPENBSD diff --git a/libsanitizer/tsan/tsan_platform_mac.cpp b/libsanitizer/tsan/tsan_platform_mac.cpp index f92ecc5..eea52a3 100644 --- a/libsanitizer/tsan/tsan_platform_mac.cpp +++ b/libsanitizer/tsan/tsan_platform_mac.cpp @@ -258,7 +258,7 @@ void InitializePlatform() { pthread_introspection_hook_install(&my_pthread_introspection_hook); #endif - if (GetMacosVersion() >= MACOS_VERSION_MOJAVE) { + if (GetMacosAlignedVersion() >= MacosVersion(10, 14)) { // Libsystem currently uses a process-global key; this might change. const unsigned kTLSLongjmpXorKeySlot = 0x7; longjmp_xor_key = (uptr)pthread_getspecific(kTLSLongjmpXorKeySlot); @@ -267,7 +267,7 @@ void InitializePlatform() { #ifdef __aarch64__ # define LONG_JMP_SP_ENV_SLOT \ - ((GetMacosVersion() >= MACOS_VERSION_MOJAVE) ? 12 : 13) + ((GetMacosAlignedVersion() >= MacosVersion(10, 14)) ? 12 : 13) #else # define LONG_JMP_SP_ENV_SLOT 2 #endif diff --git a/libsanitizer/tsan/tsan_platform_posix.cpp b/libsanitizer/tsan/tsan_platform_posix.cpp index 1a0faee..d56b6c3 100644 --- a/libsanitizer/tsan/tsan_platform_posix.cpp +++ b/libsanitizer/tsan/tsan_platform_posix.cpp @@ -29,10 +29,6 @@ static const char kShadowMemoryMappingHint[] = "HINT: if %s is not supported in your environment, you may set " "TSAN_OPTIONS=%s=0\n"; -static void NoHugePagesInShadow(uptr addr, uptr size) { - SetShadowRegionHugePageMode(addr, size); -} - static void DontDumpShadow(uptr addr, uptr size) { if (common_flags()->use_madv_dontdump) if (!DontDumpShadowMemory(addr, size)) { @@ -46,7 +42,8 @@ static void DontDumpShadow(uptr addr, uptr size) { #if !SANITIZER_GO void InitializeShadowMemory() { // Map memory shadow. - if (!MmapFixedNoReserve(ShadowBeg(), ShadowEnd() - ShadowBeg(), "shadow")) { + if (!MmapFixedSuperNoReserve(ShadowBeg(), ShadowEnd() - ShadowBeg(), + "shadow")) { Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n"); Die(); @@ -55,43 +52,6 @@ void InitializeShadowMemory() { // Frequently a thread uses only a small part of stack and similarly // a program uses a small part of large mmap. On some programs // we see 20% memory usage reduction without huge pages for this range. - // FIXME: don't use constants here. -#if defined(__x86_64__) - const uptr kMadviseRangeBeg = 0x7f0000000000ull; - const uptr kMadviseRangeSize = 0x010000000000ull; -#elif defined(__mips64) - const uptr kMadviseRangeBeg = 0xff00000000ull; - const uptr kMadviseRangeSize = 0x0100000000ull; -#elif defined(__aarch64__) && defined(__APPLE__) - uptr kMadviseRangeBeg = LoAppMemBeg(); - uptr kMadviseRangeSize = LoAppMemEnd() - LoAppMemBeg(); -#elif defined(__aarch64__) - uptr kMadviseRangeBeg = 0; - uptr kMadviseRangeSize = 0; - if (vmaSize == 39) { - kMadviseRangeBeg = 0x7d00000000ull; - kMadviseRangeSize = 0x0300000000ull; - } else if (vmaSize == 42) { - kMadviseRangeBeg = 0x3f000000000ull; - kMadviseRangeSize = 0x01000000000ull; - } else { - DCHECK(0); - } -#elif defined(__powerpc64__) - uptr kMadviseRangeBeg = 0; - uptr kMadviseRangeSize = 0; - if (vmaSize == 44) { - kMadviseRangeBeg = 0x0f60000000ull; - kMadviseRangeSize = 0x0010000000ull; - } else if (vmaSize == 46) { - kMadviseRangeBeg = 0x3f0000000000ull; - kMadviseRangeSize = 0x010000000000ull; - } else { - DCHECK(0); - } -#endif - NoHugePagesInShadow(MemToShadow(kMadviseRangeBeg), - kMadviseRangeSize * kShadowMultiplier); DontDumpShadow(ShadowBeg(), ShadowEnd() - ShadowBeg()); DPrintf("memory shadow: %zx-%zx (%zuGB)\n", ShadowBeg(), ShadowEnd(), @@ -100,12 +60,11 @@ void InitializeShadowMemory() { // Map meta shadow. const uptr meta = MetaShadowBeg(); const uptr meta_size = MetaShadowEnd() - meta; - if (!MmapFixedNoReserve(meta, meta_size, "meta shadow")) { + if (!MmapFixedSuperNoReserve(meta, meta_size, "meta shadow")) { Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n"); Die(); } - NoHugePagesInShadow(meta, meta_size); DontDumpShadow(meta, meta_size); DPrintf("meta shadow: %zx-%zx (%zuGB)\n", meta, meta + meta_size, meta_size >> 30); diff --git a/libsanitizer/tsan/tsan_report.cpp b/libsanitizer/tsan/tsan_report.cpp index 368f1ca..4892c44 100644 --- a/libsanitizer/tsan/tsan_report.cpp +++ b/libsanitizer/tsan/tsan_report.cpp @@ -128,7 +128,8 @@ void PrintStack(const ReportStack *ent) { SymbolizedStack *frame = ent->frames; for (int i = 0; frame && frame->info.address; frame = frame->next, i++) { InternalScopedString res(2 * GetPageSizeCached()); - RenderFrame(&res, common_flags()->stack_trace_format, i, frame->info, + RenderFrame(&res, common_flags()->stack_trace_format, i, + frame->info.address, &frame->info, common_flags()->symbolize_vs_style, common_flags()->strip_path_prefix, kInterposedFunctionPrefix); Printf("%s\n", res.data()); diff --git a/libsanitizer/tsan/tsan_rtl.cpp b/libsanitizer/tsan/tsan_rtl.cpp index 13c9b77..7b37ed5 100644 --- a/libsanitizer/tsan/tsan_rtl.cpp +++ b/libsanitizer/tsan/tsan_rtl.cpp @@ -256,7 +256,8 @@ void MapShadow(uptr addr, uptr size) { const uptr kPageSize = GetPageSizeCached(); uptr shadow_begin = RoundDownTo((uptr)MemToShadow(addr), kPageSize); uptr shadow_end = RoundUpTo((uptr)MemToShadow(addr + size), kPageSize); - if (!MmapFixedNoReserve(shadow_begin, shadow_end - shadow_begin, "shadow")) + if (!MmapFixedSuperNoReserve(shadow_begin, shadow_end - shadow_begin, + "shadow")) Die(); // Meta shadow is 2:1, so tread carefully. @@ -269,7 +270,8 @@ void MapShadow(uptr addr, uptr size) { if (!data_mapped) { // First call maps data+bss. data_mapped = true; - if (!MmapFixedNoReserve(meta_begin, meta_end - meta_begin, "meta shadow")) + if (!MmapFixedSuperNoReserve(meta_begin, meta_end - meta_begin, + "meta shadow")) Die(); } else { // Mapping continous heap. @@ -280,7 +282,8 @@ void MapShadow(uptr addr, uptr size) { return; if (meta_begin < mapped_meta_end) meta_begin = mapped_meta_end; - if (!MmapFixedNoReserve(meta_begin, meta_end - meta_begin, "meta shadow")) + if (!MmapFixedSuperNoReserve(meta_begin, meta_end - meta_begin, + "meta shadow")) Die(); mapped_meta_end = meta_end; } @@ -293,7 +296,7 @@ void MapThreadTrace(uptr addr, uptr size, const char *name) { CHECK_GE(addr, TraceMemBeg()); CHECK_LE(addr + size, TraceMemEnd()); CHECK_EQ(addr, addr & ~((64 << 10) - 1)); // windows wants 64K alignment - if (!MmapFixedNoReserve(addr, size, name)) { + if (!MmapFixedSuperNoReserve(addr, size, name)) { Printf("FATAL: ThreadSanitizer can not mmap thread trace (%p/%p)\n", addr, size); Die(); @@ -957,7 +960,7 @@ static void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size, u64 *p1 = p; p = RoundDown(end, kPageSize); UnmapOrDie((void*)p1, (uptr)p - (uptr)p1); - if (!MmapFixedNoReserve((uptr)p1, (uptr)p - (uptr)p1)) + if (!MmapFixedSuperNoReserve((uptr)p1, (uptr)p - (uptr)p1)) Die(); // Set the ending. while (p < end) { diff --git a/libsanitizer/tsan/tsan_rtl.h b/libsanitizer/tsan/tsan_rtl.h index d3bb61f..efdc53a 100644 --- a/libsanitizer/tsan/tsan_rtl.h +++ b/libsanitizer/tsan/tsan_rtl.h @@ -458,22 +458,22 @@ struct ThreadState { ThreadState *cur_thread(); void set_cur_thread(ThreadState *thr); void cur_thread_finalize(); -INLINE void cur_thread_init() { } +inline void cur_thread_init() { } #else __attribute__((tls_model("initial-exec"))) extern THREADLOCAL char cur_thread_placeholder[]; -INLINE ThreadState *cur_thread() { +inline ThreadState *cur_thread() { return reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current; } -INLINE void cur_thread_init() { +inline void cur_thread_init() { ThreadState *thr = reinterpret_cast<ThreadState *>(cur_thread_placeholder); if (UNLIKELY(!thr->current)) thr->current = thr; } -INLINE void set_cur_thread(ThreadState *thr) { +inline void set_cur_thread(ThreadState *thr) { reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current = thr; } -INLINE void cur_thread_finalize() { } +inline void cur_thread_finalize() { } #endif // SANITIZER_MAC || SANITIZER_ANDROID #endif // SANITIZER_GO diff --git a/libsanitizer/tsan/tsan_rtl_ppc64.S b/libsanitizer/tsan/tsan_rtl_ppc64.S index 9e533a7..8285e21 100644 --- a/libsanitizer/tsan/tsan_rtl_ppc64.S +++ b/libsanitizer/tsan/tsan_rtl_ppc64.S @@ -1,6 +1,5 @@ #include "tsan_ppc_regs.h" - .machine altivec .section .text .hidden __tsan_setjmp .globl _setjmp diff --git a/libsanitizer/tsan/tsan_rtl_report.cpp b/libsanitizer/tsan/tsan_rtl_report.cpp index 949beac..208d0df 100644 --- a/libsanitizer/tsan/tsan_rtl_report.cpp +++ b/libsanitizer/tsan/tsan_rtl_report.cpp @@ -439,65 +439,61 @@ void RestoreStack(int tid, const u64 epoch, VarSizeStackTrace *stk, ExtractTagFromStack(stk, tag); } -static bool HandleRacyStacks(ThreadState *thr, VarSizeStackTrace traces[2], - uptr addr_min, uptr addr_max) { - bool equal_stack = false; - RacyStacks hash; - bool equal_address = false; - RacyAddress ra0 = {addr_min, addr_max}; - { - ReadLock lock(&ctx->racy_mtx); - if (flags()->suppress_equal_stacks) { - hash.hash[0] = md5_hash(traces[0].trace, traces[0].size * sizeof(uptr)); - hash.hash[1] = md5_hash(traces[1].trace, traces[1].size * sizeof(uptr)); - for (uptr i = 0; i < ctx->racy_stacks.Size(); i++) { - if (hash == ctx->racy_stacks[i]) { - VPrintf(2, - "ThreadSanitizer: suppressing report as doubled (stack)\n"); - equal_stack = true; - break; - } - } - } - if (flags()->suppress_equal_addresses) { - for (uptr i = 0; i < ctx->racy_addresses.Size(); i++) { - RacyAddress ra2 = ctx->racy_addresses[i]; - uptr maxbeg = max(ra0.addr_min, ra2.addr_min); - uptr minend = min(ra0.addr_max, ra2.addr_max); - if (maxbeg < minend) { - VPrintf(2, "ThreadSanitizer: suppressing report as doubled (addr)\n"); - equal_address = true; - break; - } - } +static bool FindRacyStacks(const RacyStacks &hash) { + for (uptr i = 0; i < ctx->racy_stacks.Size(); i++) { + if (hash == ctx->racy_stacks[i]) { + VPrintf(2, "ThreadSanitizer: suppressing report as doubled (stack)\n"); + return true; } } - if (!equal_stack && !equal_address) + return false; +} + +static bool HandleRacyStacks(ThreadState *thr, VarSizeStackTrace traces[2]) { + if (!flags()->suppress_equal_stacks) return false; - if (!equal_stack) { - Lock lock(&ctx->racy_mtx); - ctx->racy_stacks.PushBack(hash); - } - if (!equal_address) { - Lock lock(&ctx->racy_mtx); - ctx->racy_addresses.PushBack(ra0); + RacyStacks hash; + hash.hash[0] = md5_hash(traces[0].trace, traces[0].size * sizeof(uptr)); + hash.hash[1] = md5_hash(traces[1].trace, traces[1].size * sizeof(uptr)); + { + ReadLock lock(&ctx->racy_mtx); + if (FindRacyStacks(hash)) + return true; } - return true; + Lock lock(&ctx->racy_mtx); + if (FindRacyStacks(hash)) + return true; + ctx->racy_stacks.PushBack(hash); + return false; } -static void AddRacyStacks(ThreadState *thr, VarSizeStackTrace traces[2], - uptr addr_min, uptr addr_max) { - Lock lock(&ctx->racy_mtx); - if (flags()->suppress_equal_stacks) { - RacyStacks hash; - hash.hash[0] = md5_hash(traces[0].trace, traces[0].size * sizeof(uptr)); - hash.hash[1] = md5_hash(traces[1].trace, traces[1].size * sizeof(uptr)); - ctx->racy_stacks.PushBack(hash); +static bool FindRacyAddress(const RacyAddress &ra0) { + for (uptr i = 0; i < ctx->racy_addresses.Size(); i++) { + RacyAddress ra2 = ctx->racy_addresses[i]; + uptr maxbeg = max(ra0.addr_min, ra2.addr_min); + uptr minend = min(ra0.addr_max, ra2.addr_max); + if (maxbeg < minend) { + VPrintf(2, "ThreadSanitizer: suppressing report as doubled (addr)\n"); + return true; + } } - if (flags()->suppress_equal_addresses) { - RacyAddress ra0 = {addr_min, addr_max}; - ctx->racy_addresses.PushBack(ra0); + return false; +} + +static bool HandleRacyAddress(ThreadState *thr, uptr addr_min, uptr addr_max) { + if (!flags()->suppress_equal_addresses) + return false; + RacyAddress ra0 = {addr_min, addr_max}; + { + ReadLock lock(&ctx->racy_mtx); + if (FindRacyAddress(ra0)) + return true; } + Lock lock(&ctx->racy_mtx); + if (FindRacyAddress(ra0)) + return true; + ctx->racy_addresses.PushBack(ra0); + return false; } bool OutputReport(ThreadState *thr, const ScopedReport &srep) { @@ -618,6 +614,8 @@ void ReportRace(ThreadState *thr) { if (IsExpectedReport(addr_min, addr_max - addr_min)) return; } + if (HandleRacyAddress(thr, addr_min, addr_max)) + return; ReportType typ = ReportTypeRace; if (thr->is_vptr_access && freed) @@ -668,7 +666,7 @@ void ReportRace(ThreadState *thr) { if (IsFiredSuppression(ctx, typ, traces[1])) return; - if (HandleRacyStacks(thr, traces, addr_min, addr_max)) + if (HandleRacyStacks(thr, traces)) return; // If any of the accesses has a tag, treat this as an "external" race. @@ -708,10 +706,7 @@ void ReportRace(ThreadState *thr) { } #endif - if (!OutputReport(thr, rep)) - return; - - AddRacyStacks(thr, traces, addr_min, addr_max); + OutputReport(thr, rep); } void PrintCurrentStack(ThreadState *thr, uptr pc) { diff --git a/libsanitizer/tsan/tsan_sync.cpp b/libsanitizer/tsan/tsan_sync.cpp index 7f686dc..17ddd50f 100644 --- a/libsanitizer/tsan/tsan_sync.cpp +++ b/libsanitizer/tsan/tsan_sync.cpp @@ -175,7 +175,7 @@ void MetaMap::ResetRange(Processor *proc, uptr p, uptr sz) { uptr metap = (uptr)MemToMeta(p0); uptr metasz = sz0 / kMetaRatio; UnmapOrDie((void*)metap, metasz); - if (!MmapFixedNoReserve(metap, metasz)) + if (!MmapFixedSuperNoReserve(metap, metasz)) Die(); } |