r286672 - [tsan][clang] Introduce a function attribute to disable TSan checking at run time

Anna Zaks via cfe-commits cfe-commits at lists.llvm.org
Fri Nov 11 15:22:45 PST 2016


Author: zaks
Date: Fri Nov 11 17:22:44 2016
New Revision: 286672

URL: http://llvm.org/viewvc/llvm-project?rev=286672&view=rev
Log:
[tsan][clang] Introduce a function attribute to disable TSan checking at run time

This introduces a function annotation that disables TSan checking for the
function at run time. The benefit over attribute((no_sanitize("thread")))
is that the accesses within the callees will also be suppressed.

The motivation for this attribute is a guarantee given by the objective C
language that the calls to the reference count decrement and object
deallocation will be synchronized. To model this properly, we would need to
intercept all ref count decrement calls (which are very common in ObjC due
to use of ARC) and also every single message send. Instead, we propose to
just ignore all accesses made from within dealloc at run time. The main
downside is that this still does not introduce any synchronization, which
means we might still report false positives if the code that relies on this
synchronization is not executed from within dealloc. However, we have not
seen this in practice so far and think these cases will be very rare.

(This problem is similar in nature to https://reviews.llvm.org/D21609;
unfortunately, the same solution does not apply here.)

Differential Revision: https://reviews.llvm.org/D25857

Added:
    cfe/trunk/test/CodeGen/sanitize-thread-no-checking-at-run-time.m
Modified:
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=286672&r1=286671&r2=286672&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Fri Nov 11 17:22:44 2016
@@ -731,6 +731,20 @@ void CodeGenFunction::StartFunction(Glob
   if (SanOpts.has(SanitizerKind::SafeStack))
     Fn->addFnAttr(llvm::Attribute::SafeStack);
 
+  // Ignore TSan memory acesses from within ObjC/ObjC++ dealloc, initialize,
+  // .cxx_destruct and all of their calees at run time.
+  if (SanOpts.has(SanitizerKind::Thread)) {
+    if (const auto *OMD = dyn_cast_or_null<ObjCMethodDecl>(D)) {
+      IdentifierInfo *II = OMD->getSelector().getIdentifierInfoForSlot(0);
+      if (OMD->getMethodFamily() == OMF_dealloc ||
+          OMD->getMethodFamily() == OMF_initialize ||
+          (OMD->getSelector().isUnarySelector() && II->isStr(".cxx_destruct"))) {
+        Fn->addFnAttr("sanitize_thread_no_checking_at_run_time");
+        Fn->removeFnAttr(llvm::Attribute::SanitizeThread);
+      }
+    }
+  }
+
   // Apply xray attributes to the function (as a string, for now)
   if (D && ShouldXRayInstrumentFunction()) {
     if (const auto *XRayAttr = D->getAttr<XRayInstrumentAttr>()) {

Added: cfe/trunk/test/CodeGen/sanitize-thread-no-checking-at-run-time.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/sanitize-thread-no-checking-at-run-time.m?rev=286672&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/sanitize-thread-no-checking-at-run-time.m (added)
+++ cfe/trunk/test/CodeGen/sanitize-thread-no-checking-at-run-time.m Fri Nov 11 17:22:44 2016
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -x objective-c++ -emit-llvm -o - %s | FileCheck -check-prefix=WITHOUT %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -x objective-c++ -emit-llvm -o - %s -fsanitize=thread | FileCheck -check-prefix=TSAN %s
+
+__attribute__((objc_root_class))
+ at interface NSObject
+- (void)dealloc;
+ at end
+
+class NeedCleanup {
+public:
+  ~NeedCleanup() __attribute__((no_sanitize("thread"))) {}
+};
+
+ at interface MyObject : NSObject {
+  NeedCleanup v;
+};
++ (void) initialize;
+- (void) dealloc;
+ at end
+
+ at implementation MyObject
++ (void)initialize {
+}
+- (void)dealloc {
+  [super dealloc];
+}
+ at end
+
+// WITHOUT-NOT: "sanitize_thread_no_checking_at_run_time"
+
+// TSAN: initialize{{.*}}) [[ATTR:#[0-9]+]]
+// TSAN: dealloc{{.*}}) [[ATTR:#[0-9]+]]
+// TSAN: cxx_destruct{{.*}}) [[ATTR:#[0-9]+]]
+// TSAN: attributes [[ATTR]] = { nounwind {{.*}} "sanitize_thread_no_checking_at_run_time" {{.*}} }




More information about the cfe-commits mailing list