Skip to content

Commit 8300d52

Browse files
[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
1 parent 4554b5b commit 8300d52

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

clang/docs/ThreadSanitizer.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,16 @@ instruments such functions to avoid false positives and provide meaningful stack
100100
traces. This attribute may not be supported by other compilers, so we suggest
101101
to use it together with ``__has_feature(thread_sanitizer)``.
102102

103+
``__attribute__((disable_sanitizer_instrumentation))``
104+
--------------------------------------------------------
105+
106+
The ``disable_sanitizer_instrumentation`` attribute can be applied to functions
107+
to prevent all kinds of instrumentation. As a result, it may introduce false
108+
positives and incorrect stack traces. Therefore, it should be used with care,
109+
and only if absolutely required; for example for certain code that cannot
110+
tolerate any instrumentation and resulting side-effects. This attribute
111+
overrides ``no_sanitize("thread")``.
112+
103113
Ignorelist
104114
----------
105115

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// RUN: %clang -target x86_64-linux-gnu -S -emit-llvm -o - %s | FileCheck -check-prefixes CHECK,WITHOUT %s
2+
// RUN: %clang -target x86_64-linux-gnu -S -emit-llvm -o - %s -fsanitize=thread | FileCheck -check-prefixes CHECK,TSAN %s
3+
4+
#include <stdatomic.h>
5+
6+
// Instrumented function.
7+
// TSan inserts calls to __tsan_func_entry() and __tsan_func_exit() to prologue/epilogue.
8+
// Non-atomic loads are instrumented with __tsan_readXXX(), atomic loads - with
9+
// __tsan_atomicXXX_load().
10+
//
11+
// CHECK-LABEL: @instrumented1
12+
// TSAN: call void @__tsan_func_entry
13+
// WITHOUT-NOT: call void @__tsan_func_entry
14+
// TSAN: call void @__tsan_read4
15+
// WITHOUT-NOT: call void @__tsan_read4
16+
// TSAN: call i32 @__tsan_atomic32_load
17+
// WITHOUT-NOT: call i32 @__tsan_atomic32_load
18+
// TSAN: call void @__tsan_func_exit
19+
// WITHOUT-NOT: call void @__tsan_func_exit
20+
// CHECK: ret i32
21+
int instrumented1(int *a, _Atomic int *b) {
22+
return *a + atomic_load(b);
23+
}
24+
25+
// Function with no_sanitize("thread").
26+
// TSan only inserts instrumentation necessary to prevent false positives: calls are inserted for
27+
// function entry/exit and atomics, but not plain memory accesses.
28+
//
29+
// CHECK-LABEL: @no_false_positives1
30+
// TSAN: call void @__tsan_func_entry
31+
// WITHOUT-NOT: call void @__tsan_func_entry
32+
// TSAN-NOT: call void @__tsan_read4
33+
// WITHOUT-NOT: call void @__tsan_read4
34+
// TSAN: call i32 @__tsan_atomic32_load
35+
// WITHOUT-NOT: call i32 @__tsan_atomic32_load
36+
// TSAN: call void @__tsan_func_exit
37+
// WITHOUT-NOT: call void @__tsan_func_exit
38+
// CHECK: ret i32
39+
__attribute__((no_sanitize("thread"))) int no_false_positives1(int *a, _Atomic int *b) {
40+
return *a + atomic_load(b);
41+
}
42+
43+
// Function with disable_sanitizer_instrumentation: no instrumentation at all.
44+
//
45+
// CHECK-LABEL: @no_instrumentation1
46+
// TSAN-NOT: call void @__tsan_func_entry
47+
// WITHOUT-NOT: call void @__tsan_func_entry
48+
// TSAN-NOT: call void @__tsan_read4
49+
// WITHOUT-NOT: call void @__tsan_read4
50+
// TSAN-NOT: call i32 @__tsan_atomic32_load
51+
// WITHOUT-NOT: call i32 @__tsan_atomic32_load
52+
// TSAN-NOT: call void @__tsan_func_exit
53+
// WITHOUT-NOT: call void @__tsan_func_exit
54+
// CHECK: ret i32
55+
__attribute__((disable_sanitizer_instrumentation)) int no_instrumentation1(int *a, _Atomic int *b) {
56+
return *a + atomic_load(b);
57+
}

llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,12 @@ bool ThreadSanitizer::sanitizeFunction(Function &F,
562562
// all.
563563
if (F.hasFnAttribute(Attribute::Naked))
564564
return false;
565+
566+
// __attribute__(disable_sanitizer_instrumentation) prevents all kinds of
567+
// instrumentation.
568+
if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
569+
return false;
570+
565571
initialize(*F.getParent());
566572
SmallVector<InstructionInfo, 8> AllLoadsAndStores;
567573
SmallVector<Instruction*, 8> LocalLoadsAndStores;

0 commit comments

Comments
 (0)