summaryrefslogtreecommitdiff
path: root/test/tsan
diff options
context:
space:
mode:
authorKuba Mracek <mracek@apple.com>2017-04-21 17:18:14 +0000
committerKuba Mracek <mracek@apple.com>2017-04-21 17:18:14 +0000
commit0a039ecbdab95ae1274a6e0ec484c2a1c2419bdd (patch)
tree8d49670ce014215b41871aa11b33948d974f8fda /test/tsan
parentcc599619a08deaae432a0a62212de6cc7dca490d (diff)
[tsan] Ignore memory accesses for libignored modules for "external" races
On Darwin, the setting ignore_noninstrumented_modules is used to suppress false positives in code that users don't have control of. The recently added "external" API (which can be used to detect races on objects provided by system libraries, but the race is actually user's fault) ignores this flag and it can report issues in non-instrumented modules. This patch fixes that. Differential Revision: https://reviews.llvm.org/D31553 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@301000 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/tsan')
-rw-r--r--test/tsan/Darwin/external-ignore-noninstrumented.cc19
-rw-r--r--test/tsan/Darwin/external-lib.cc68
-rw-r--r--test/tsan/Darwin/external-noninstrumented-module.cc27
-rw-r--r--test/tsan/Darwin/external.cc66
4 files changed, 117 insertions, 63 deletions
diff --git a/test/tsan/Darwin/external-ignore-noninstrumented.cc b/test/tsan/Darwin/external-ignore-noninstrumented.cc
new file mode 100644
index 000000000..d2acaf54b
--- /dev/null
+++ b/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 <stdio.h>
+
+extern "C" void NonInstrumentedModule();
+int main(int argc, char *argv[]) {
+ NonInstrumentedModule();
+ fprintf(stderr, "Done.\n");
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer
+// CHECK: Done.
diff --git a/test/tsan/Darwin/external-lib.cc b/test/tsan/Darwin/external-lib.cc
new file mode 100644
index 000000000..f0afdf1dc
--- /dev/null
+++ b/test/tsan/Darwin/external-lib.cc
@@ -0,0 +1,68 @@
+// This file is used from other tests.
+// RUN: true
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+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;
+}
diff --git a/test/tsan/Darwin/external-noninstrumented-module.cc b/test/tsan/Darwin/external-noninstrumented-module.cc
new file mode 100644
index 000000000..ce6597083
--- /dev/null
+++ b/test/tsan/Darwin/external-noninstrumented-module.cc
@@ -0,0 +1,27 @@
+// This file is used from other tests.
+// RUN: true
+
+#include <thread>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+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();
+}
diff --git a/test/tsan/Darwin/external.cc b/test/tsan/Darwin/external.cc
index 2605480d7..66881d3e5 100644
--- a/test/tsan/Darwin/external.cc
+++ b/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 <thread>
-#include <dlfcn.h>
-#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
@@ -38,62 +36,6 @@ extern "C" {
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 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "WW test done\n");
// CHECK: WW test done
}
-
-#endif // defined(SHARED_LIB)