1 | #ifndef TSAN_INTERCEPTORS_H |
2 | #define TSAN_INTERCEPTORS_H |
3 | |
4 | #include "sanitizer_common/sanitizer_stacktrace.h" |
5 | #include "tsan_rtl.h" |
6 | |
7 | namespace __tsan { |
8 | |
9 | class ScopedInterceptor { |
10 | public: |
11 | ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc); |
12 | ~ScopedInterceptor(); |
13 | void DisableIgnores() { |
14 | if (UNLIKELY(ignoring_)) |
15 | DisableIgnoresImpl(); |
16 | } |
17 | void EnableIgnores() { |
18 | if (UNLIKELY(ignoring_)) |
19 | EnableIgnoresImpl(); |
20 | } |
21 | |
22 | private: |
23 | ThreadState *const thr_; |
24 | bool in_ignored_lib_ = false; |
25 | bool in_blocking_func_ = false; |
26 | bool ignoring_ = false; |
27 | |
28 | void DisableIgnoresImpl(); |
29 | void EnableIgnoresImpl(); |
30 | }; |
31 | |
32 | struct TsanInterceptorContext { |
33 | ThreadState *thr; |
34 | const uptr pc; |
35 | }; |
36 | |
37 | LibIgnore *libignore(); |
38 | |
39 | #if !SANITIZER_GO |
40 | inline bool in_symbolizer() { |
41 | return UNLIKELY(cur_thread_init()->in_symbolizer); |
42 | } |
43 | #endif |
44 | |
45 | inline bool MustIgnoreInterceptor(ThreadState *thr) { |
46 | return !thr->is_inited || thr->ignore_interceptors || thr->in_ignored_lib; |
47 | } |
48 | |
49 | } // namespace __tsan |
50 | |
51 | #define SCOPED_INTERCEPTOR_RAW(func, ...) \ |
52 | ThreadState *thr = cur_thread_init(); \ |
53 | ScopedInterceptor si(thr, #func, GET_CALLER_PC()); \ |
54 | UNUSED const uptr pc = GET_CURRENT_PC(); |
55 | |
56 | #ifdef __powerpc64__ |
57 | // Debugging of crashes on powerpc after commit: |
58 | // c80604f7a3 ("tsan: remove real func check from interceptors") |
59 | // Somehow replacing if with DCHECK leads to strange failures in: |
60 | // SanitizerCommon-tsan-powerpc64le-Linux :: Linux/ptrace.cpp |
61 | // https://lab.llvm.org/buildbot/#/builders/105 |
62 | // https://lab.llvm.org/buildbot/#/builders/121 |
63 | // https://lab.llvm.org/buildbot/#/builders/57 |
64 | # define CHECK_REAL_FUNC(func) \ |
65 | if (REAL(func) == 0) { \ |
66 | Report("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \ |
67 | Die(); \ |
68 | } |
69 | #else |
70 | # define CHECK_REAL_FUNC(func) DCHECK(REAL(func)) |
71 | #endif |
72 | |
73 | #define SCOPED_TSAN_INTERCEPTOR(func, ...) \ |
74 | SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \ |
75 | CHECK_REAL_FUNC(func); \ |
76 | if (MustIgnoreInterceptor(thr)) \ |
77 | return REAL(func)(__VA_ARGS__); |
78 | |
79 | #define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START() \ |
80 | si.DisableIgnores(); |
81 | |
82 | #define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END() \ |
83 | si.EnableIgnores(); |
84 | |
85 | #define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__) |
86 | |
87 | #if SANITIZER_FREEBSD |
88 | # define TSAN_INTERCEPTOR_FREEBSD_ALIAS(ret, func, ...) \ |
89 | TSAN_INTERCEPTOR(ret, _pthread_##func, __VA_ARGS__) \ |
90 | ALIAS(WRAP(pthread_##func)); |
91 | #else |
92 | # define TSAN_INTERCEPTOR_FREEBSD_ALIAS(ret, func, ...) |
93 | #endif |
94 | |
95 | #if SANITIZER_NETBSD |
96 | # define TSAN_INTERCEPTOR_NETBSD_ALIAS(ret, func, ...) \ |
97 | TSAN_INTERCEPTOR(ret, __libc_##func, __VA_ARGS__) \ |
98 | ALIAS(WRAP(pthread_##func)); |
99 | # define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(ret, func, ...) \ |
100 | TSAN_INTERCEPTOR(ret, __libc_thr_##func, __VA_ARGS__) \ |
101 | ALIAS(WRAP(pthread_##func)); |
102 | # define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(ret, func, func2, ...) \ |
103 | TSAN_INTERCEPTOR(ret, __libc_thr_##func, __VA_ARGS__) \ |
104 | ALIAS(WRAP(pthread_##func2)); |
105 | #else |
106 | # define TSAN_INTERCEPTOR_NETBSD_ALIAS(ret, func, ...) |
107 | # define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(ret, func, ...) |
108 | # define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(ret, func, func2, ...) |
109 | #endif |
110 | |
111 | #define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name) |
112 | |
113 | #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED \ |
114 | (!cur_thread_init()->is_inited) |
115 | |
116 | #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ |
117 | MemoryAccessRange(((TsanInterceptorContext *)ctx)->thr, \ |
118 | ((TsanInterceptorContext *)ctx)->pc, (uptr)ptr, size, \ |
119 | true) |
120 | |
121 | #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \ |
122 | MemoryAccessRange(((TsanInterceptorContext *) ctx)->thr, \ |
123 | ((TsanInterceptorContext *) ctx)->pc, (uptr) ptr, size, \ |
124 | false) |
125 | |
126 | #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ |
127 | SCOPED_TSAN_INTERCEPTOR(func, __VA_ARGS__); \ |
128 | TsanInterceptorContext _ctx = {thr, pc}; \ |
129 | ctx = (void *)&_ctx; \ |
130 | (void)ctx; |
131 | |
132 | #endif // TSAN_INTERCEPTORS_H |
133 | |