master
  1#ifndef TSAN_INTERCEPTORS_H
  2#define TSAN_INTERCEPTORS_H
  3
  4#include "sanitizer_common/sanitizer_stacktrace.h"
  5#include "tsan_rtl.h"
  6
  7namespace __tsan {
  8
  9class 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
 32struct TsanInterceptorContext {
 33  ThreadState *thr;
 34  const uptr pc;
 35};
 36
 37LibIgnore *libignore();
 38
 39#if !SANITIZER_GO
 40inline bool in_symbolizer() {
 41  return UNLIKELY(cur_thread_init()->in_symbolizer);
 42}
 43#endif
 44
 45inline 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