xref: /freebsd/contrib/llvm-project/compiler-rt/lib/tsan/rtl/tsan_interceptors.h (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
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 LibIgnore *libignore();
33 
34 #if !SANITIZER_GO
35 inline bool in_symbolizer() {
36   return UNLIKELY(cur_thread_init()->in_symbolizer);
37 }
38 #endif
39 
40 inline bool MustIgnoreInterceptor(ThreadState *thr) {
41   return !thr->is_inited || thr->ignore_interceptors || thr->in_ignored_lib;
42 }
43 
44 }  // namespace __tsan
45 
46 #define SCOPED_INTERCEPTOR_RAW(func, ...)            \
47   ThreadState *thr = cur_thread_init();              \
48   ScopedInterceptor si(thr, #func, GET_CALLER_PC()); \
49   UNUSED const uptr pc = GET_CURRENT_PC();
50 
51 #ifdef __powerpc64__
52 // Debugging of crashes on powerpc after commit:
53 // c80604f7a3 ("tsan: remove real func check from interceptors")
54 // Somehow replacing if with DCHECK leads to strange failures in:
55 // SanitizerCommon-tsan-powerpc64le-Linux :: Linux/ptrace.cpp
56 // https://lab.llvm.org/buildbot/#/builders/105
57 // https://lab.llvm.org/buildbot/#/builders/121
58 // https://lab.llvm.org/buildbot/#/builders/57
59 #  define CHECK_REAL_FUNC(func)                                          \
60     if (REAL(func) == 0) {                                               \
61       Report("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \
62       Die();                                                             \
63     }
64 #else
65 #  define CHECK_REAL_FUNC(func) DCHECK(REAL(func))
66 #endif
67 
68 #define SCOPED_TSAN_INTERCEPTOR(func, ...)   \
69   SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \
70   CHECK_REAL_FUNC(func);                     \
71   if (MustIgnoreInterceptor(thr))            \
72     return REAL(func)(__VA_ARGS__);
73 
74 #define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START() \
75     si.DisableIgnores();
76 
77 #define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END() \
78     si.EnableIgnores();
79 
80 #define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__)
81 
82 #if SANITIZER_FREEBSD
83 #  define TSAN_INTERCEPTOR_FREEBSD_ALIAS(ret, func, ...) \
84     TSAN_INTERCEPTOR(ret, _pthread_##func, __VA_ARGS__)  \
85     ALIAS(WRAPPER_NAME(pthread_##func));
86 #else
87 #  define TSAN_INTERCEPTOR_FREEBSD_ALIAS(ret, func, ...)
88 #endif
89 
90 #if SANITIZER_NETBSD
91 # define TSAN_INTERCEPTOR_NETBSD_ALIAS(ret, func, ...) \
92   TSAN_INTERCEPTOR(ret, __libc_##func, __VA_ARGS__) \
93   ALIAS(WRAPPER_NAME(pthread_##func));
94 # define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(ret, func, ...) \
95   TSAN_INTERCEPTOR(ret, __libc_thr_##func, __VA_ARGS__) \
96   ALIAS(WRAPPER_NAME(pthread_##func));
97 # define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(ret, func, func2, ...) \
98   TSAN_INTERCEPTOR(ret, __libc_thr_##func, __VA_ARGS__) \
99   ALIAS(WRAPPER_NAME(pthread_##func2));
100 #else
101 # define TSAN_INTERCEPTOR_NETBSD_ALIAS(ret, func, ...)
102 # define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(ret, func, ...)
103 # define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(ret, func, func2, ...)
104 #endif
105 
106 #endif  // TSAN_INTERCEPTORS_H
107