[compiler-rt] r301000 - [tsan] Ignore memory accesses for libignored modules for "external" races

Kuba Mracek via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 21 10:18:15 PDT 2017


Author: kuba.brecka
Date: Fri Apr 21 12:18:14 2017
New Revision: 301000

URL: http://llvm.org/viewvc/llvm-project?rev=301000&view=rev
Log:
[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


Added:
    compiler-rt/trunk/test/tsan/Darwin/external-ignore-noninstrumented.cc
    compiler-rt/trunk/test/tsan/Darwin/external-lib.cc
    compiler-rt/trunk/test/tsan/Darwin/external-noninstrumented-module.cc
Modified:
    compiler-rt/trunk/lib/tsan/rtl/tsan_external.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.h
    compiler-rt/trunk/test/tsan/Darwin/external.cc

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_external.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_external.cc?rev=301000&r1=300999&r2=301000&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_external.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_external.cc Fri Apr 21 12:18:14 2017
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 #include "tsan_rtl.h"
+#include "tsan_interceptors.h"
 
 namespace __tsan {
 
@@ -57,9 +58,12 @@ void __tsan_external_read(void *addr, vo
   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 @@ void __tsan_external_write(void *addr, v
   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"

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=301000&r1=300999&r2=301000&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Fri Apr 21 12:18:14 2017
@@ -210,7 +210,7 @@ struct ThreadSignalContext {
 // 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*>(&libignore_placeholder[0]);
 }
 

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.h?rev=301000&r1=300999&r2=301000&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.h Fri Apr 21 12:18:14 2017
@@ -19,6 +19,8 @@ class ScopedInterceptor {
   bool ignoring_;
 };
 
+LibIgnore *libignore();
+
 }  // namespace __tsan
 
 #define SCOPED_INTERCEPTOR_RAW(func, ...) \

Added: compiler-rt/trunk/test/tsan/Darwin/external-ignore-noninstrumented.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/Darwin/external-ignore-noninstrumented.cc?rev=301000&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/Darwin/external-ignore-noninstrumented.cc (added)
+++ compiler-rt/trunk/test/tsan/Darwin/external-ignore-noninstrumented.cc Fri Apr 21 12:18:14 2017
@@ -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.

Added: compiler-rt/trunk/test/tsan/Darwin/external-lib.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/Darwin/external-lib.cc?rev=301000&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/Darwin/external-lib.cc (added)
+++ compiler-rt/trunk/test/tsan/Darwin/external-lib.cc Fri Apr 21 12:18:14 2017
@@ -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;
+}

Added: compiler-rt/trunk/test/tsan/Darwin/external-noninstrumented-module.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/Darwin/external-noninstrumented-module.cc?rev=301000&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/Darwin/external-noninstrumented-module.cc (added)
+++ compiler-rt/trunk/test/tsan/Darwin/external-noninstrumented-module.cc Fri Apr 21 12:18:14 2017
@@ -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();
+}

Modified: compiler-rt/trunk/test/tsan/Darwin/external.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/Darwin/external.cc?rev=301000&r1=300999&r2=301000&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/Darwin/external.cc (original)
+++ compiler-rt/trunk/test/tsan/Darwin/external.cc Fri Apr 21 12:18:14 2017
@@ -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)




More information about the llvm-commits mailing list