Index: lib/tsan/rtl/tsan_external.cc =================================================================== --- lib/tsan/rtl/tsan_external.cc +++ lib/tsan/rtl/tsan_external.cc @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// #include "tsan_rtl.h" +#include "tsan_interceptors.h" namespace __tsan { @@ -57,9 +58,12 @@ CHECK_LT(tag, atomic_load(&used_tags, memory_order_relaxed)); ThreadState *thr = cur_thread(); thr->external_tag = (uptr)tag; - FuncEntry(thr, (uptr)caller_pc); - MemoryRead(thr, CALLERPC, (uptr)addr, kSizeLog8); - FuncExit(thr); + if (caller_pc) FuncEntry(thr, (uptr)caller_pc); + bool in_ignored_lib; + if (!caller_pc || !libignore()->IsIgnored((uptr)caller_pc, &in_ignored_lib)) { + MemoryRead(thr, CALLERPC, (uptr)addr, kSizeLog8); + } + if (caller_pc) FuncExit(thr); thr->external_tag = 0; } @@ -68,9 +72,12 @@ CHECK_LT(tag, atomic_load(&used_tags, memory_order_relaxed)); ThreadState *thr = cur_thread(); thr->external_tag = (uptr)tag; - FuncEntry(thr, (uptr)caller_pc); - MemoryWrite(thr, CALLERPC, (uptr)addr, kSizeLog8); - FuncExit(thr); + if (caller_pc) FuncEntry(thr, (uptr)caller_pc); + bool in_ignored_lib; + if (!caller_pc || !libignore()->IsIgnored((uptr)caller_pc, &in_ignored_lib)) { + MemoryWrite(thr, CALLERPC, (uptr)addr, kSizeLog8); + } + if (caller_pc) FuncExit(thr); thr->external_tag = 0; } } // extern "C" Index: lib/tsan/rtl/tsan_interceptors.h =================================================================== --- lib/tsan/rtl/tsan_interceptors.h +++ lib/tsan/rtl/tsan_interceptors.h @@ -19,6 +19,8 @@ bool ignoring_; }; +LibIgnore *libignore(); + } // namespace __tsan #define SCOPED_INTERCEPTOR_RAW(func, ...) \ Index: lib/tsan/rtl/tsan_interceptors.cc =================================================================== --- lib/tsan/rtl/tsan_interceptors.cc +++ lib/tsan/rtl/tsan_interceptors.cc @@ -219,7 +219,7 @@ // The object is 64-byte aligned, because we want hot data to be located in // a single cache line if possible (it's accessed in every interceptor). static ALIGNED(64) char libignore_placeholder[sizeof(LibIgnore)]; -static LibIgnore *libignore() { +LibIgnore *libignore() { return reinterpret_cast(&libignore_placeholder[0]); } Index: test/tsan/Darwin/external-ignore-noninstrumented.cc =================================================================== --- test/tsan/Darwin/external-ignore-noninstrumented.cc +++ test/tsan/Darwin/external-ignore-noninstrumented.cc @@ -0,0 +1,19 @@ +// RUN: %clangxx_tsan -shared %p/external-lib.cc -fno-sanitize=thread -DUSE_TSAN_CALLBACKS \ +// RUN: -o %t-lib.dylib -install_name @rpath/`basename %t-lib.dylib` + +// RUN: %clangxx_tsan -shared %p/external-noninstrumented-module.cc %t-lib.dylib -fno-sanitize=thread \ +// RUN: -o %t-module.dylib -install_name @rpath/`basename %t-module.dylib` + +// RUN: %clangxx_tsan %s %t-module.dylib -o %t +// RUN: %run %t 2>&1 | FileCheck %s + +#include + +extern "C" void NonInstrumentedModule(); +int main(int argc, char *argv[]) { + NonInstrumentedModule(); + fprintf(stderr, "Done.\n"); +} + +// CHECK-NOT: WARNING: ThreadSanitizer +// CHECK: Done. Index: test/tsan/Darwin/external-lib.cc =================================================================== --- test/tsan/Darwin/external-lib.cc +++ test/tsan/Darwin/external-lib.cc @@ -0,0 +1,68 @@ +// This file is used from other tests. +// RUN: true + +#include +#include +#include + +struct MyObject; +typedef MyObject *MyObjectRef; +extern "C" { + void InitializeLibrary(); + MyObject *ObjectCreate(); + long ObjectRead(MyObject *); + void ObjectWrite(MyObject *, long); + void ObjectWriteAnother(MyObject *, long); +} + +struct MyObject { + long _val; + long _another; +}; + +#if defined(USE_TSAN_CALLBACKS) +static void *tag; +void *(*callback_register_tag)(const char *object_type); +void *(*callback_assign_tag)(void *addr, void *tag); +void (*callback_read)(void *addr, void *caller_pc, void *tag); +void (*callback_write)(void *addr, void *caller_pc, void *tag); +#endif + +void InitializeLibrary() { +#if defined(USE_TSAN_CALLBACKS) + callback_register_tag = (decltype(callback_register_tag))dlsym(RTLD_DEFAULT, "__tsan_external_register_tag"); + callback_assign_tag = (decltype(callback_assign_tag))dlsym(RTLD_DEFAULT, "__tsan_external_assign_tag"); + callback_read = (decltype(callback_read))dlsym(RTLD_DEFAULT, "__tsan_external_read"); + callback_write = (decltype(callback_write))dlsym(RTLD_DEFAULT, "__tsan_external_write"); + tag = callback_register_tag("MyLibrary::MyObject"); +#endif +} + +MyObject *ObjectCreate() { + MyObject *ref = (MyObject *)malloc(sizeof(MyObject)); +#if defined(USE_TSAN_CALLBACKS) + callback_assign_tag(ref, tag); +#endif + return ref; +} + +long ObjectRead(MyObject *ref) { +#if defined(USE_TSAN_CALLBACKS) + callback_read(ref, __builtin_return_address(0), tag); +#endif + return ref->_val; +} + +void ObjectWrite(MyObject *ref, long val) { +#if defined(USE_TSAN_CALLBACKS) + callback_write(ref, __builtin_return_address(0), tag); +#endif + ref->_val = val; +} + +void ObjectWriteAnother(MyObject *ref, long val) { +#if defined(USE_TSAN_CALLBACKS) + callback_write(ref, __builtin_return_address(0), tag); +#endif + ref->_another = val; +} Index: test/tsan/Darwin/external-noninstrumented-module.cc =================================================================== --- test/tsan/Darwin/external-noninstrumented-module.cc +++ test/tsan/Darwin/external-noninstrumented-module.cc @@ -0,0 +1,27 @@ +// This file is used from other tests. +// RUN: true + +#include + +#include +#include + +struct MyObject; +typedef MyObject *MyObjectRef; +extern "C" { + void InitializeLibrary(); + MyObject *ObjectCreate(); + long ObjectRead(MyObject *); + void ObjectWrite(MyObject *, long); + void ObjectWriteAnother(MyObject *, long); +} + +extern "C" void NonInstrumentedModule() { + InitializeLibrary(); + + MyObjectRef ref = ObjectCreate(); + std::thread t1([ref]{ ObjectWrite(ref, 42); }); + std::thread t2([ref]{ ObjectWrite(ref, 43); }); + t1.join(); + t2.join(); +} Index: test/tsan/Darwin/external.cc =================================================================== --- test/tsan/Darwin/external.cc +++ test/tsan/Darwin/external.cc @@ -1,12 +1,12 @@ -// RUN: %clangxx_tsan %s -shared -DSHARED_LIB \ +// RUN: %clangxx_tsan %p/external-lib.cc -shared \ // RUN: -o %t-lib-instrumented.dylib \ // RUN: -install_name @rpath/`basename %t-lib-instrumented.dylib` -// RUN: %clangxx_tsan %s -shared -DSHARED_LIB -fno-sanitize=thread \ +// RUN: %clangxx_tsan %p/external-lib.cc -shared -fno-sanitize=thread \ // RUN: -o %t-lib-noninstrumented.dylib \ // RUN: -install_name @rpath/`basename %t-lib-noninstrumented.dylib` -// RUN: %clangxx_tsan %s -shared -DSHARED_LIB -fno-sanitize=thread -DUSE_TSAN_CALLBACKS \ +// RUN: %clangxx_tsan %p/external-lib.cc -shared -fno-sanitize=thread -DUSE_TSAN_CALLBACKS \ // RUN: -o %t-lib-noninstrumented-callbacks.dylib \ // RUN: -install_name @rpath/`basename %t-lib-noninstrumented-callbacks.dylib` @@ -23,8 +23,6 @@ #include -#include -#include #include #include @@ -38,62 +36,6 @@ void ObjectWriteAnother(MyObject *, long); } -#if defined(SHARED_LIB) - -struct MyObject { - long _val; - long _another; -}; - -#if defined(USE_TSAN_CALLBACKS) -static void *tag; -void *(*callback_register_tag)(const char *object_type); -void *(*callback_assign_tag)(void *addr, void *tag); -void (*callback_read)(void *addr, void *caller_pc, void *tag); -void (*callback_write)(void *addr, void *caller_pc, void *tag); -#endif - -void InitializeLibrary() { -#if defined(USE_TSAN_CALLBACKS) - callback_register_tag = (decltype(callback_register_tag))dlsym(RTLD_DEFAULT, "__tsan_external_register_tag"); - callback_assign_tag = (decltype(callback_assign_tag))dlsym(RTLD_DEFAULT, "__tsan_external_assign_tag"); - callback_read = (decltype(callback_read))dlsym(RTLD_DEFAULT, "__tsan_external_read"); - callback_write = (decltype(callback_write))dlsym(RTLD_DEFAULT, "__tsan_external_write"); - tag = callback_register_tag("MyLibrary::MyObject"); -#endif -} - -MyObject *ObjectCreate() { - MyObject *ref = (MyObject *)malloc(sizeof(MyObject)); -#if defined(USE_TSAN_CALLBACKS) - callback_assign_tag(ref, tag); -#endif - return ref; -} - -long ObjectRead(MyObject *ref) { -#if defined(USE_TSAN_CALLBACKS) - callback_read(ref, __builtin_return_address(0), tag); -#endif - return ref->_val; -} - -void ObjectWrite(MyObject *ref, long val) { -#if defined(USE_TSAN_CALLBACKS) - callback_write(ref, __builtin_return_address(0), tag); -#endif - ref->_val = val; -} - -void ObjectWriteAnother(MyObject *ref, long val) { -#if defined(USE_TSAN_CALLBACKS) - callback_write(ref, __builtin_return_address(0), tag); -#endif - ref->_another = val; -} - -#else // defined(SHARED_LIB) - int main(int argc, char *argv[]) { InitializeLibrary(); @@ -159,5 +101,3 @@ fprintf(stderr, "WW test done\n"); // CHECK: WW test done } - -#endif // defined(SHARED_LIB)