aboutsummaryrefslogtreecommitdiff
path: root/libsanitizer/tsan
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2020-10-16 10:03:04 +0200
committerMartin Liska <mliska@suse.cz>2020-10-16 10:57:03 +0200
commit0b997f6e07771c98178ea09f4a8c4446baaf84da (patch)
treec3ef933f3fda4195644c6734b2c212e9f77718e3 /libsanitizer/tsan
parent4a70aa7a627c0b918ce1da75c0dbe088539e420f (diff)
downloadgcc-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.h11
-rw-r--r--libsanitizer/tsan/tsan_external.cpp11
-rw-r--r--libsanitizer/tsan/tsan_flags.cpp2
-rw-r--r--libsanitizer/tsan/tsan_flags.inc2
-rw-r--r--libsanitizer/tsan/tsan_interceptors.h2
-rw-r--r--libsanitizer/tsan/tsan_interceptors_libdispatch.cpp32
-rw-r--r--libsanitizer/tsan/tsan_interceptors_mach_vm.cpp19
-rw-r--r--libsanitizer/tsan/tsan_interceptors_posix.cpp30
-rw-r--r--libsanitizer/tsan/tsan_interface.cpp13
-rw-r--r--libsanitizer/tsan/tsan_interface_inl.h23
-rw-r--r--libsanitizer/tsan/tsan_platform_linux.cpp24
-rw-r--r--libsanitizer/tsan/tsan_platform_mac.cpp4
-rw-r--r--libsanitizer/tsan/tsan_platform_posix.cpp47
-rw-r--r--libsanitizer/tsan/tsan_report.cpp3
-rw-r--r--libsanitizer/tsan/tsan_rtl.cpp13
-rw-r--r--libsanitizer/tsan/tsan_rtl.h10
-rw-r--r--libsanitizer/tsan/tsan_rtl_ppc64.S1
-rw-r--r--libsanitizer/tsan/tsan_rtl_report.cpp107
-rw-r--r--libsanitizer/tsan/tsan_sync.cpp2
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();
}