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 struct TsanInterceptorContext { 33 ThreadState *thr; 34 const uptr pc; 35 }; 36 37 LibIgnore *libignore(); 38 39 #if !SANITIZER_GO 40 inline bool in_symbolizer() { 41 return UNLIKELY(cur_thread_init()->in_symbolizer); 42 } 43 #endif 44 45 inline bool MustIgnoreInterceptor(ThreadState *thr) { 46 return !thr->is_inited || thr->ignore_interceptors || thr->in_ignored_lib; 47 } 48 49 } // namespace __tsan 50 51 #define SCOPED_INTERCEPTOR_RAW(func, ...) \ 52 ThreadState *thr = cur_thread_init(); \ 53 ScopedInterceptor si(thr, #func, GET_CALLER_PC()); \ 54 UNUSED const uptr pc = GET_CURRENT_PC(); 55 56 #ifdef __powerpc64__ 57 // Debugging of crashes on powerpc after commit: 58 // c80604f7a3 ("tsan: remove real func check from interceptors") 59 // Somehow replacing if with DCHECK leads to strange failures in: 60 // SanitizerCommon-tsan-powerpc64le-Linux :: Linux/ptrace.cpp 61 // https://lab.llvm.org/buildbot/#/builders/105 62 // https://lab.llvm.org/buildbot/#/builders/121 63 // https://lab.llvm.org/buildbot/#/builders/57 64 # define CHECK_REAL_FUNC(func) \ 65 if (REAL(func) == 0) { \ 66 Report("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \ 67 Die(); \ 68 } 69 #else 70 # define CHECK_REAL_FUNC(func) DCHECK(REAL(func)) 71 #endif 72 73 #define SCOPED_TSAN_INTERCEPTOR(func, ...) \ 74 SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \ 75 CHECK_REAL_FUNC(func); \ 76 if (MustIgnoreInterceptor(thr)) \ 77 return REAL(func)(__VA_ARGS__); 78 79 #define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START() \ 80 si.DisableIgnores(); 81 82 #define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END() \ 83 si.EnableIgnores(); 84 85 #define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__) 86 87 #if SANITIZER_FREEBSD 88 # define TSAN_INTERCEPTOR_FREEBSD_ALIAS(ret, func, ...) \ 89 TSAN_INTERCEPTOR(ret, _pthread_##func, __VA_ARGS__) \ 90 ALIAS(WRAP(pthread_##func)); 91 #else 92 # define TSAN_INTERCEPTOR_FREEBSD_ALIAS(ret, func, ...) 93 #endif 94 95 #if SANITIZER_NETBSD 96 # define TSAN_INTERCEPTOR_NETBSD_ALIAS(ret, func, ...) \ 97 TSAN_INTERCEPTOR(ret, __libc_##func, __VA_ARGS__) \ 98 ALIAS(WRAP(pthread_##func)); 99 # define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(ret, func, ...) \ 100 TSAN_INTERCEPTOR(ret, __libc_thr_##func, __VA_ARGS__) \ 101 ALIAS(WRAP(pthread_##func)); 102 # define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(ret, func, func2, ...) \ 103 TSAN_INTERCEPTOR(ret, __libc_thr_##func, __VA_ARGS__) \ 104 ALIAS(WRAP(pthread_##func2)); 105 #else 106 # define TSAN_INTERCEPTOR_NETBSD_ALIAS(ret, func, ...) 107 # define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(ret, func, ...) 108 # define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(ret, func, func2, ...) 109 #endif 110 111 #define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name) 112 113 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED \ 114 (!cur_thread_init()->is_inited) 115 116 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ 117 MemoryAccessRange(((TsanInterceptorContext *)ctx)->thr, \ 118 ((TsanInterceptorContext *)ctx)->pc, (uptr)ptr, size, \ 119 true) 120 121 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \ 122 MemoryAccessRange(((TsanInterceptorContext *) ctx)->thr, \ 123 ((TsanInterceptorContext *) ctx)->pc, (uptr) ptr, size, \ 124 false) 125 126 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ 127 SCOPED_TSAN_INTERCEPTOR(func, __VA_ARGS__); \ 128 TsanInterceptorContext _ctx = {thr, pc}; \ 129 ctx = (void *)&_ctx; \ 130 (void)ctx; 131 132 #endif // TSAN_INTERCEPTORS_H 133