[clang] 8300d52 - [tsan] Add support for disable_sanitizer_instrumentation attribute

Alexander Potapenko via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 23 03:40:37 PDT 2021


Author: Alexander Potapenko
Date: 2021-08-23T12:38:33+02:00
New Revision: 8300d52e8cbf757192d6b66efa537e15376bf756

URL: https://github.com/llvm/llvm-project/commit/8300d52e8cbf757192d6b66efa537e15376bf756
DIFF: https://github.com/llvm/llvm-project/commit/8300d52e8cbf757192d6b66efa537e15376bf756.diff

LOG: [tsan] Add support for disable_sanitizer_instrumentation attribute

Unlike __attribute__((no_sanitize("thread"))), this one will cause TSan
to skip the entire function during instrumentation.

Depends on https://reviews.llvm.org/D108029

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

Added: 
    clang/test/CodeGen/sanitize-thread-disable.c

Modified: 
    clang/docs/ThreadSanitizer.rst
    llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ThreadSanitizer.rst b/clang/docs/ThreadSanitizer.rst
index 92cc9392955cc..98d5307d824f9 100644
--- a/clang/docs/ThreadSanitizer.rst
+++ b/clang/docs/ThreadSanitizer.rst
@@ -100,6 +100,16 @@ instruments such functions to avoid false positives and provide meaningful stack
 traces.  This attribute may not be supported by other compilers, so we suggest
 to use it together with ``__has_feature(thread_sanitizer)``.
 
+``__attribute__((disable_sanitizer_instrumentation))``
+--------------------------------------------------------
+
+The ``disable_sanitizer_instrumentation`` attribute can be applied to functions
+to prevent all kinds of instrumentation. As a result, it may introduce false
+positives and incorrect stack traces. Therefore, it should be used with care,
+and only if absolutely required; for example for certain code that cannot
+tolerate any instrumentation and resulting side-effects. This attribute
+overrides ``no_sanitize("thread")``.
+
 Ignorelist
 ----------
 

diff  --git a/clang/test/CodeGen/sanitize-thread-disable.c b/clang/test/CodeGen/sanitize-thread-disable.c
new file mode 100644
index 0000000000000..d3ec1425e7821
--- /dev/null
+++ b/clang/test/CodeGen/sanitize-thread-disable.c
@@ -0,0 +1,57 @@
+// RUN: %clang -target x86_64-linux-gnu -S -emit-llvm -o - %s | FileCheck -check-prefixes CHECK,WITHOUT %s
+// RUN: %clang -target x86_64-linux-gnu -S -emit-llvm -o - %s -fsanitize=thread | FileCheck -check-prefixes CHECK,TSAN %s
+
+#include <stdatomic.h>
+
+// Instrumented function.
+// TSan inserts calls to __tsan_func_entry() and __tsan_func_exit() to prologue/epilogue.
+// Non-atomic loads are instrumented with __tsan_readXXX(), atomic loads - with
+// __tsan_atomicXXX_load().
+//
+// CHECK-LABEL: @instrumented1
+// TSAN: call void @__tsan_func_entry
+// WITHOUT-NOT: call void @__tsan_func_entry
+// TSAN: call void @__tsan_read4
+// WITHOUT-NOT: call void @__tsan_read4
+// TSAN: call i32 @__tsan_atomic32_load
+// WITHOUT-NOT: call i32 @__tsan_atomic32_load
+// TSAN: call void @__tsan_func_exit
+// WITHOUT-NOT: call void @__tsan_func_exit
+// CHECK: ret i32
+int instrumented1(int *a, _Atomic int *b) {
+  return *a + atomic_load(b);
+}
+
+// Function with no_sanitize("thread").
+// TSan only inserts instrumentation necessary to prevent false positives: calls are inserted for
+// function entry/exit and atomics, but not plain memory accesses.
+//
+// CHECK-LABEL: @no_false_positives1
+// TSAN: call void @__tsan_func_entry
+// WITHOUT-NOT: call void @__tsan_func_entry
+// TSAN-NOT: call void @__tsan_read4
+// WITHOUT-NOT: call void @__tsan_read4
+// TSAN: call i32 @__tsan_atomic32_load
+// WITHOUT-NOT: call i32 @__tsan_atomic32_load
+// TSAN: call void @__tsan_func_exit
+// WITHOUT-NOT: call void @__tsan_func_exit
+// CHECK: ret i32
+__attribute__((no_sanitize("thread"))) int no_false_positives1(int *a, _Atomic int *b) {
+  return *a + atomic_load(b);
+}
+
+// Function with disable_sanitizer_instrumentation: no instrumentation at all.
+//
+// CHECK-LABEL: @no_instrumentation1
+// TSAN-NOT: call void @__tsan_func_entry
+// WITHOUT-NOT: call void @__tsan_func_entry
+// TSAN-NOT: call void @__tsan_read4
+// WITHOUT-NOT: call void @__tsan_read4
+// TSAN-NOT: call i32 @__tsan_atomic32_load
+// WITHOUT-NOT: call i32 @__tsan_atomic32_load
+// TSAN-NOT: call void @__tsan_func_exit
+// WITHOUT-NOT: call void @__tsan_func_exit
+// CHECK: ret i32
+__attribute__((disable_sanitizer_instrumentation)) int no_instrumentation1(int *a, _Atomic int *b) {
+  return *a + atomic_load(b);
+}

diff  --git a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
index 87fdcc9114f44..714e21dc82bb4 100644
--- a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
@@ -562,6 +562,12 @@ bool ThreadSanitizer::sanitizeFunction(Function &F,
   // all.
   if (F.hasFnAttribute(Attribute::Naked))
     return false;
+
+  // __attribute__(disable_sanitizer_instrumentation) prevents all kinds of
+  // instrumentation.
+  if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
+    return false;
+
   initialize(*F.getParent());
   SmallVector<InstructionInfo, 8> AllLoadsAndStores;
   SmallVector<Instruction*, 8> LocalLoadsAndStores;


        


More information about the cfe-commits mailing list