13cab2bb3Spatrick #ifndef TSAN_INTERCEPTORS_H
23cab2bb3Spatrick #define TSAN_INTERCEPTORS_H
33cab2bb3Spatrick
43cab2bb3Spatrick #include "sanitizer_common/sanitizer_stacktrace.h"
53cab2bb3Spatrick #include "tsan_rtl.h"
63cab2bb3Spatrick
73cab2bb3Spatrick namespace __tsan {
83cab2bb3Spatrick
93cab2bb3Spatrick class ScopedInterceptor {
103cab2bb3Spatrick public:
113cab2bb3Spatrick ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc);
123cab2bb3Spatrick ~ScopedInterceptor();
DisableIgnores()13*810390e3Srobert void DisableIgnores() {
14*810390e3Srobert if (UNLIKELY(ignoring_))
15*810390e3Srobert DisableIgnoresImpl();
16*810390e3Srobert }
EnableIgnores()17*810390e3Srobert void EnableIgnores() {
18*810390e3Srobert if (UNLIKELY(ignoring_))
19*810390e3Srobert EnableIgnoresImpl();
20*810390e3Srobert }
21*810390e3Srobert
223cab2bb3Spatrick private:
233cab2bb3Spatrick ThreadState *const thr_;
24*810390e3Srobert bool in_ignored_lib_ = false;
25*810390e3Srobert bool in_blocking_func_ = false;
26*810390e3Srobert bool ignoring_ = false;
27*810390e3Srobert
28*810390e3Srobert void DisableIgnoresImpl();
29*810390e3Srobert void EnableIgnoresImpl();
303cab2bb3Spatrick };
313cab2bb3Spatrick
323cab2bb3Spatrick LibIgnore *libignore();
333cab2bb3Spatrick
343cab2bb3Spatrick #if !SANITIZER_GO
in_symbolizer()35d89ec533Spatrick inline bool in_symbolizer() {
36*810390e3Srobert return UNLIKELY(cur_thread_init()->in_symbolizer);
373cab2bb3Spatrick }
383cab2bb3Spatrick #endif
393cab2bb3Spatrick
MustIgnoreInterceptor(ThreadState * thr)40*810390e3Srobert inline bool MustIgnoreInterceptor(ThreadState *thr) {
41*810390e3Srobert return !thr->is_inited || thr->ignore_interceptors || thr->in_ignored_lib;
42*810390e3Srobert }
43*810390e3Srobert
443cab2bb3Spatrick } // namespace __tsan
453cab2bb3Spatrick
463cab2bb3Spatrick #define SCOPED_INTERCEPTOR_RAW(func, ...) \
47*810390e3Srobert ThreadState *thr = cur_thread_init(); \
48*810390e3Srobert ScopedInterceptor si(thr, #func, GET_CALLER_PC()); \
49*810390e3Srobert UNUSED const uptr pc = GET_CURRENT_PC();
503cab2bb3Spatrick
51*810390e3Srobert #ifdef __powerpc64__
52*810390e3Srobert // Debugging of crashes on powerpc after commit:
53*810390e3Srobert // c80604f7a3 ("tsan: remove real func check from interceptors")
54*810390e3Srobert // Somehow replacing if with DCHECK leads to strange failures in:
55*810390e3Srobert // SanitizerCommon-tsan-powerpc64le-Linux :: Linux/ptrace.cpp
56*810390e3Srobert // https://lab.llvm.org/buildbot/#/builders/105
57*810390e3Srobert // https://lab.llvm.org/buildbot/#/builders/121
58*810390e3Srobert // https://lab.llvm.org/buildbot/#/builders/57
59*810390e3Srobert # define CHECK_REAL_FUNC(func) \
603cab2bb3Spatrick if (REAL(func) == 0) { \
613cab2bb3Spatrick Report("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \
623cab2bb3Spatrick Die(); \
63*810390e3Srobert }
64*810390e3Srobert #else
65*810390e3Srobert # define CHECK_REAL_FUNC(func) DCHECK(REAL(func))
66*810390e3Srobert #endif
67*810390e3Srobert
68*810390e3Srobert #define SCOPED_TSAN_INTERCEPTOR(func, ...) \
69*810390e3Srobert SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \
70*810390e3Srobert CHECK_REAL_FUNC(func); \
71*810390e3Srobert if (MustIgnoreInterceptor(thr)) \
72*810390e3Srobert return REAL(func)(__VA_ARGS__);
733cab2bb3Spatrick
743cab2bb3Spatrick #define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START() \
753cab2bb3Spatrick si.DisableIgnores();
763cab2bb3Spatrick
773cab2bb3Spatrick #define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END() \
783cab2bb3Spatrick si.EnableIgnores();
793cab2bb3Spatrick
803cab2bb3Spatrick #define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__)
813cab2bb3Spatrick
82*810390e3Srobert #if SANITIZER_FREEBSD
83*810390e3Srobert # define TSAN_INTERCEPTOR_FREEBSD_ALIAS(ret, func, ...) \
84*810390e3Srobert TSAN_INTERCEPTOR(ret, _pthread_##func, __VA_ARGS__) \
85*810390e3Srobert ALIAS(WRAPPER_NAME(pthread_##func));
86*810390e3Srobert #else
87*810390e3Srobert # define TSAN_INTERCEPTOR_FREEBSD_ALIAS(ret, func, ...)
88*810390e3Srobert #endif
89*810390e3Srobert
903cab2bb3Spatrick #if SANITIZER_NETBSD
913cab2bb3Spatrick # define TSAN_INTERCEPTOR_NETBSD_ALIAS(ret, func, ...) \
923cab2bb3Spatrick TSAN_INTERCEPTOR(ret, __libc_##func, __VA_ARGS__) \
933cab2bb3Spatrick ALIAS(WRAPPER_NAME(pthread_##func));
943cab2bb3Spatrick # define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(ret, func, ...) \
953cab2bb3Spatrick TSAN_INTERCEPTOR(ret, __libc_thr_##func, __VA_ARGS__) \
963cab2bb3Spatrick ALIAS(WRAPPER_NAME(pthread_##func));
973cab2bb3Spatrick # define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(ret, func, func2, ...) \
983cab2bb3Spatrick TSAN_INTERCEPTOR(ret, __libc_thr_##func, __VA_ARGS__) \
993cab2bb3Spatrick ALIAS(WRAPPER_NAME(pthread_##func2));
1003cab2bb3Spatrick #else
1013cab2bb3Spatrick # define TSAN_INTERCEPTOR_NETBSD_ALIAS(ret, func, ...)
1023cab2bb3Spatrick # define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(ret, func, ...)
1033cab2bb3Spatrick # define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(ret, func, func2, ...)
1043cab2bb3Spatrick #endif
1053cab2bb3Spatrick
1063cab2bb3Spatrick #endif // TSAN_INTERCEPTORS_H
107