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