summaryrefslogtreecommitdiff
path: root/lib/tsan/rtl/tsan_platform_mac.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tsan/rtl/tsan_platform_mac.cc')
-rw-r--r--lib/tsan/rtl/tsan_platform_mac.cc67
1 files changed, 39 insertions, 28 deletions
diff --git a/lib/tsan/rtl/tsan_platform_mac.cc b/lib/tsan/rtl/tsan_platform_mac.cc
index 7e3a47387b6d..0c2d2aa9338e 100644
--- a/lib/tsan/rtl/tsan_platform_mac.cc
+++ b/lib/tsan/rtl/tsan_platform_mac.cc
@@ -1,9 +1,8 @@
//===-- tsan_platform_mac.cc ----------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -74,22 +73,22 @@ static void *SignalSafeGetOrAllocate(uptr *dst, uptr size) {
// shadow memory is set up.
static uptr main_thread_identity = 0;
ALIGNED(64) static char main_thread_state[sizeof(ThreadState)];
+static ThreadState *main_thread_state_loc = (ThreadState *)main_thread_state;
-ThreadState **cur_thread_location() {
- ThreadState **thread_identity = (ThreadState **)pthread_self();
- return ((uptr)thread_identity == main_thread_identity) ? nullptr
- : thread_identity;
+static ThreadState **cur_thread_location() {
+ uptr thread_identity = (uptr)pthread_self();
+ if (thread_identity == main_thread_identity || main_thread_identity == 0)
+ return &main_thread_state_loc;
+ return (ThreadState **)MemToShadow(thread_identity);
}
ThreadState *cur_thread() {
- ThreadState **thr_state_loc = cur_thread_location();
- if (thr_state_loc == nullptr || main_thread_identity == 0) {
- return (ThreadState *)&main_thread_state;
- }
- ThreadState **fake_tls = (ThreadState **)MemToShadow((uptr)thr_state_loc);
- ThreadState *thr = (ThreadState *)SignalSafeGetOrAllocate(
- (uptr *)fake_tls, sizeof(ThreadState));
- return thr;
+ return (ThreadState *)SignalSafeGetOrAllocate(
+ (uptr *)cur_thread_location(), sizeof(ThreadState));
+}
+
+void set_cur_thread(ThreadState *thr) {
+ *cur_thread_location() = thr;
}
// TODO(kuba.brecka): This is not async-signal-safe. In particular, we call
@@ -97,14 +96,13 @@ ThreadState *cur_thread() {
// handler will try to access the unmapped ThreadState.
void cur_thread_finalize() {
ThreadState **thr_state_loc = cur_thread_location();
- if (thr_state_loc == nullptr) {
+ if (thr_state_loc == &main_thread_state_loc) {
// Calling dispatch_main() or xpc_main() actually invokes pthread_exit to
// exit the main thread. Let's keep the main thread's ThreadState.
return;
}
- ThreadState **fake_tls = (ThreadState **)MemToShadow((uptr)thr_state_loc);
- internal_munmap(*fake_tls, sizeof(ThreadState));
- *fake_tls = nullptr;
+ internal_munmap(*thr_state_loc, sizeof(ThreadState));
+ *thr_state_loc = nullptr;
}
#endif
@@ -213,7 +211,7 @@ static void my_pthread_introspection_hook(unsigned int event, pthread_t thread,
ThreadState *parent_thread_state = nullptr; // No parent.
int tid = ThreadCreate(parent_thread_state, 0, (uptr)thread, true);
CHECK_NE(tid, 0);
- ThreadStart(thr, tid, GetTid(), /*workerthread*/ true);
+ ThreadStart(thr, tid, GetTid(), ThreadType::Worker);
}
} else if (event == PTHREAD_INTROSPECTION_THREAD_TERMINATE) {
if (thread == pthread_self()) {
@@ -240,8 +238,7 @@ void InitializePlatformEarly() {
#endif
}
-static const uptr kPthreadSetjmpXorKeySlot = 0x7;
-extern "C" uptr __tsan_darwin_setjmp_xor_key = 0;
+static uptr longjmp_xor_key = 0;
void InitializePlatform() {
DisableCoreDumperIfNecessary();
@@ -256,21 +253,35 @@ void InitializePlatform() {
#endif
if (GetMacosVersion() >= MACOS_VERSION_MOJAVE) {
- __tsan_darwin_setjmp_xor_key =
- (uptr)pthread_getspecific(kPthreadSetjmpXorKeySlot);
+ // Libsystem currently uses a process-global key; this might change.
+ const unsigned kTLSLongjmpXorKeySlot = 0x7;
+ longjmp_xor_key = (uptr)pthread_getspecific(kTLSLongjmpXorKeySlot);
}
}
+#ifdef __aarch64__
+# define LONG_JMP_SP_ENV_SLOT \
+ ((GetMacosVersion() >= MACOS_VERSION_MOJAVE) ? 12 : 13)
+#else
+# define LONG_JMP_SP_ENV_SLOT 2
+#endif
+
+uptr ExtractLongJmpSp(uptr *env) {
+ uptr mangled_sp = env[LONG_JMP_SP_ENV_SLOT];
+ uptr sp = mangled_sp ^ longjmp_xor_key;
+ return sp;
+}
+
#if !SANITIZER_GO
void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) {
// The pointer to the ThreadState object is stored in the shadow memory
// of the tls.
uptr tls_end = tls_addr + tls_size;
- ThreadState **thr_state_loc = cur_thread_location();
- if (thr_state_loc == nullptr) {
+ uptr thread_identity = (uptr)pthread_self();
+ if (thread_identity == main_thread_identity) {
MemoryRangeImitateWrite(thr, /*pc=*/2, tls_addr, tls_size);
} else {
- uptr thr_state_start = (uptr)thr_state_loc;
+ uptr thr_state_start = thread_identity;
uptr thr_state_end = thr_state_start + sizeof(uptr);
CHECK_GE(thr_state_start, tls_addr);
CHECK_LE(thr_state_start, tls_addr + tls_size);