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