diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp @@ -55,6 +55,26 @@ #ifdef TSAN_EXTERNAL_HOOKS bool OnFinalize(bool failed); void OnInitialize(); +#elif SANITIZER_MAC +#include +// On Darwin, strong definitions overriding weak ones is only guaranteed within +// a linkage unit (e.g., when linking .o files). There is just one case where +// strong in one linkage unit overrides a weak in another. That is when the +// strong dylib/exe was built, it linked against a dylib with a weak-def +// (__tsan_default_options() relies on this). We want to use these hooks from +// other libraries (i.e., the Swift runtime) so we need to use dlsym() to look +// them up. +static bool OnFinalize(bool failed) { + if (auto ptr = dlsym(RTLD_DEFAULT, "_ZN6__tsan10OnFinalizeEb")) { + return reinterpret_cast(ptr)(failed); + } + return failed; +} +static void OnInitialize() { + if (auto ptr = dlsym(RTLD_DEFAULT, "_ZN6__tsan12OnInitializeEv")) { + return reinterpret_cast(ptr)(); + } +} #else SANITIZER_WEAK_CXX_DEFAULT_IMPL bool OnFinalize(bool failed) { diff --git a/compiler-rt/test/tsan/on_initialize_finalize_hooks.cpp b/compiler-rt/test/tsan/on_initialize_finalize_hooks.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/tsan/on_initialize_finalize_hooks.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_tsan -O1 %s -o %t.lib -fno-sanitize=thread -shared -DBUILD_LIB=1 +// RUN: %clang_tsan -O1 %s %t.lib -o %t +// RUN: %run %t | FileCheck %s + +// Test that initialization/finalization hooks are called, even when they are +// not defined in the main executable, but by another another library that +// doesn't directly link against the TSan runtime. + +#include + +#if BUILD_LIB +namespace __tsan { +void OnInitialize() { + printf("__tsan_on_initialize()\n"); +} + +bool OnFinalize(bool failed) { + printf("__tsan_on_finalize()\n"); + return failed; +} +} +#else // BUILD_LIB + +int main() { + printf("main()\n"); + return 0; +} + +#endif // BUILD_LIB + +// CHECK: __tsan_on_initialize() +// CHECK: main() +// CHECK: __tsan_on_finalize()