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