tsan_interceptors.cc revision a09507c38cf9dd9119e5aa9bd6d91383514f857b
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===-- tsan_interceptors.cc ----------------------------------------------===//
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//                     The LLVM Compiler Infrastructure
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// License. See LICENSE.TXT for details.
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===//
9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch//
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// This file is a part of ThreadSanitizer (TSan), a race detector.
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// FIXME: move as many interceptors as possible into
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// sanitizer_common/sanitizer_common_interceptors.inc
1423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)//===----------------------------------------------------------------------===//
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sanitizer_common/sanitizer_atomic.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sanitizer_common/sanitizer_libc.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sanitizer_common/sanitizer_linux.h"
19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "sanitizer_common/sanitizer_platform_limits_posix.h"
20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "sanitizer_common/sanitizer_placement_new.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sanitizer_common/sanitizer_stacktrace.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "interception/interception.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "tsan_interface.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "tsan_platform.h"
25558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "tsan_rtl.h"
2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "tsan_mman.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "tsan_fd.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using namespace __tsan;  // NOLINT
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const int kSigCount = 64;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)struct my_siginfo_t {
34558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // The size is determined by looking at sizeof of real siginfo_t on linux.
3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  u64 opaque[128 / sizeof(u64)];
36558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch};
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct sigset_t {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The size is determined by looking at sizeof of real sigset_t on linux.
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  u64 val[128 / sizeof(u64)];
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct ucontext_t {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The size is determined by looking at sizeof of real ucontext_t on linux.
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  u64 opaque[936 / sizeof(u64) + 1];
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int pthread_attr_init(void *attr);
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int pthread_attr_destroy(void *attr);
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int pthread_attr_getdetachstate(void *attr, int *v);
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize);
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int pthread_attr_getstacksize(void *attr, uptr *stacksize);
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int pthread_key_create(unsigned *key, void (*destructor)(void* v));
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int pthread_setspecific(unsigned key, const void *v);
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)extern "C" int pthread_mutexattr_gettype(void *a, int *type);
5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)extern "C" int pthread_yield();
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int sigfillset(sigset_t *set);
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" void *pthread_self();
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" void _exit(int status);
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int *__errno_location();
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int fileno_unlocked(void *stream);
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" void *__libc_malloc(uptr size);
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" void *__libc_calloc(uptr size, uptr n);
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" void *__libc_realloc(void *ptr, uptr size);
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" void __libc_free(void *ptr);
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int mallopt(int param, int value);
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int PTHREAD_MUTEX_RECURSIVE = 1;
6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int PTHREAD_MUTEX_RECURSIVE_NP = 1;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int EINVAL = 22;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int EBUSY = 16;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int EPOLL_CTL_ADD = 1;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int SIGILL = 4;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int SIGABRT = 6;
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int SIGFPE = 8;
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int SIGSEGV = 11;
7723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)const int SIGPIPE = 13;
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int SIGBUS = 7;
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int SIGSYS = 31;
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void *const MAP_FAILED = (void*)-1;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int PTHREAD_BARRIER_SERIAL_THREAD = -1;
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int MAP_FIXED = 0x10;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef long long_t;  // NOLINT
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// From /usr/include/unistd.h
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# define F_ULOCK 0      /* Unlock a previously locked region.  */
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# define F_LOCK  1      /* Lock a region for exclusive use.  */
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# define F_TLOCK 2      /* Test and lock a region for exclusive use.  */
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# define F_TEST  3      /* Test a region for other processes locks.  */
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef void (*sighandler_t)(int sig);
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define errno (*__errno_location())
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct sigaction_t {
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  union {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sighandler_t sa_handler;
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void (*sa_sigaction)(int sig, my_siginfo_t *siginfo, void *uctx);
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sigset_t sa_mask;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int sa_flags;
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void (*sa_restorer)();
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const sighandler_t SIG_DFL = (sighandler_t)0;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const sighandler_t SIG_IGN = (sighandler_t)1;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const sighandler_t SIG_ERR = (sighandler_t)-1;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int SA_SIGINFO = 4;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int SIG_SETMASK = 2;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace std {
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct nothrow_t {};
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace std
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static sigaction_t sigactions[kSigCount];
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace __tsan {
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct SignalDesc {
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool armed;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool sigaction;
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  my_siginfo_t siginfo;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ucontext_t ctx;
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct SignalContext {
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int in_blocking_func;
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int int_signal_send;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int pending_signal_count;
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SignalDesc pending_signals[kSigCount];
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace __tsan
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static SignalContext *SigCtx(ThreadState *thr) {
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SignalContext *ctx = (SignalContext*)thr->signal_ctx;
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ctx == 0 && thr->is_alive) {
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ScopedInRtl in_rtl;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ctx = (SignalContext*)MmapOrDie(sizeof(*ctx), "SignalContext");
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MemoryResetRange(thr, (uptr)&SigCtx, (uptr)ctx, sizeof(*ctx));
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    thr->signal_ctx = ctx;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ctx;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static unsigned g_thread_finalize_key;
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ScopedInterceptor {
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc);
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~ScopedInterceptor();
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ThreadState *const thr_;
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int in_rtl_;
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname,
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     uptr pc)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : thr_(thr)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    , in_rtl_(thr->in_rtl) {
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (thr_->in_rtl == 0) {
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Initialize(thr);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FuncEntry(thr, pc);
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    thr_->in_rtl++;
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DPrintf("#%d: intercept %s()\n", thr_->tid, fname);
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    thr_->in_rtl++;
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ScopedInterceptor::~ScopedInterceptor() {
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  thr_->in_rtl--;
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (thr_->in_rtl == 0) {
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FuncExit(thr_);
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ProcessPendingSignals(thr_);
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK_EQ(in_rtl_, thr_->in_rtl);
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define SCOPED_INTERCEPTOR_RAW(func, ...) \
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ThreadState *thr = cur_thread(); \
18023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    StatInc(thr, StatInterceptor); \
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StatInc(thr, StatInt_##func); \
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const uptr caller_pc = GET_CALLER_PC(); \
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ScopedInterceptor si(thr, #func, caller_pc); \
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (void)pc; \
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/**/
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define SCOPED_TSAN_INTERCEPTOR(func, ...) \
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (REAL(func) == 0) { \
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Printf("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Die(); \
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } \
194c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (thr->in_rtl > 1) \
195c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return REAL(func)(__VA_ARGS__); \
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/**/
197c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define BLOCK_REAL(name) (BlockingCall(thr), REAL(name))
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct BlockingCall {
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit BlockingCall(ThreadState *thr)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : ctx(SigCtx(thr)) {
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ctx->in_blocking_func++;
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
208c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
209c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ~BlockingCall() {
210c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ctx->in_blocking_func--;
211c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SignalContext *ctx;
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(unsigned, sleep, unsigned sec) {
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(sleep, sec);
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned res = BLOCK_REAL(sleep)(sec);
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AfterSleep(thr, pc);
220c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return res;
221c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, usleep, long_t usec) {
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(usleep, usec);
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = BLOCK_REAL(usleep)(usec);
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AfterSleep(thr, pc);
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, nanosleep, void *req, void *rem) {
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(nanosleep, req, rem);
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int res = BLOCK_REAL(nanosleep)(req, rem);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AfterSleep(thr, pc);
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass AtExitContext {
238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public:
239c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  AtExitContext()
240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    : mtx_(MutexTypeAtExit, StatMtxAtExit)
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    , pos_() {
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef void(*atexit_t)();
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int atexit(ThreadState *thr, uptr pc, bool is_on_exit,
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             atexit_t f, void *arg) {
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Lock l(&mtx_);
249c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (pos_ == kMaxAtExit)
250c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return 1;
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Release(thr, pc, (uptr)this);
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    stack_[pos_] = f;
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    args_[pos_] = arg;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    is_on_exits_[pos_] = is_on_exit;
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pos_++;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void exit(ThreadState *thr, uptr pc) {
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK_EQ(thr->in_rtl, 0);
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (;;) {
262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      atexit_t f = 0;
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      void *arg = 0;
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool is_on_exit = false;
2655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      {
2665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        Lock l(&mtx_);
2675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        if (pos_) {
2685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          pos_--;
2695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          f = stack_[pos_];
2705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          arg = args_[pos_];
2715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          is_on_exit = is_on_exits_[pos_];
2725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          ScopedInRtl in_rtl;
2735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          Acquire(thr, pc, (uptr)this);
2745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        }
2755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      }
2765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (f == 0)
2775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        break;
2785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      DPrintf("#%d: executing atexit func %p\n", thr->tid, f);
2795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      CHECK_EQ(thr->in_rtl, 0);
2805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (is_on_exit)
2815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        ((void(*)(int status, void *arg))f)(0, arg);
2825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      else
2835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        ((void(*)(void *arg, void *dso))f)(arg, 0);
2845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
2855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
2865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private:
2885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  static const int kMaxAtExit = 128;
2895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  Mutex mtx_;
2905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  atexit_t stack_[kMaxAtExit];
2915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void *args_[kMaxAtExit];
2925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool is_on_exits_[kMaxAtExit];
2935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  int pos_;
2945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
2955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic AtExitContext *atexit_ctx;
2975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTSAN_INTERCEPTOR(int, atexit, void (*f)()) {
2995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (cur_thread()->in_symbolizer)
3005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return 0;
3015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SCOPED_TSAN_INTERCEPTOR(atexit, f);
3025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return atexit_ctx->atexit(thr, pc, false, (void(*)())f, 0);
3035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
3045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) {
3065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (cur_thread()->in_symbolizer)
3075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return 0;
3085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SCOPED_TSAN_INTERCEPTOR(on_exit, f, arg);
3095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return atexit_ctx->atexit(thr, pc, true, (void(*)())f, arg);
3105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
3115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTSAN_INTERCEPTOR(int, __cxa_atexit, void (*f)(void *a), void *arg, void *dso) {
3135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (cur_thread()->in_symbolizer)
3145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return 0;
3155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SCOPED_TSAN_INTERCEPTOR(__cxa_atexit, f, arg, dso);
3165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (dso)
3175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return REAL(__cxa_atexit)(f, arg, dso);
3185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return atexit_ctx->atexit(thr, pc, false, (void(*)())f, arg);
3195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
3205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Cleanup old bufs.
3225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic void JmpBufGarbageCollect(ThreadState *thr, uptr sp) {
3235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (uptr i = 0; i < thr->jmp_bufs.Size(); i++) {
3245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    JmpBuf *buf = &thr->jmp_bufs[i];
3255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (buf->sp <= sp) {
3265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      uptr sz = thr->jmp_bufs.Size();
3275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      thr->jmp_bufs[i] = thr->jmp_bufs[sz - 1];
3285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      thr->jmp_bufs.PopBack();
3295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      i--;
3305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
3315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
3325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
3335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic void SetJmp(ThreadState *thr, uptr sp, uptr mangled_sp) {
3355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (thr->shadow_stack_pos == 0)  // called from libc guts during bootstrap
3365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
3375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Cleanup old bufs.
3385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  JmpBufGarbageCollect(thr, sp);
3395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Remember the buf.
3405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  JmpBuf *buf = thr->jmp_bufs.PushBack();
3415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  buf->sp = sp;
3425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  buf->mangled_sp = mangled_sp;
3435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  buf->shadow_stack_pos = thr->shadow_stack_pos;
3445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
3455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic void LongJmp(ThreadState *thr, uptr *env) {
3475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  uptr mangled_sp = env[6];
3485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Find the saved buf by mangled_sp.
3495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (uptr i = 0; i < thr->jmp_bufs.Size(); i++) {
3505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    JmpBuf *buf = &thr->jmp_bufs[i];
3515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (buf->mangled_sp == mangled_sp) {
3525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      CHECK_GE(thr->shadow_stack_pos, buf->shadow_stack_pos);
3535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // Unwind the stack.
3545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      while (thr->shadow_stack_pos > buf->shadow_stack_pos)
3555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        FuncExit(thr);
3565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      JmpBufGarbageCollect(thr, buf->sp - 1);  // do not collect buf->sp
3575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return;
3585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Printf("ThreadSanitizer: can't find longjmp buf\n");
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(0);
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// FIXME: put everything below into a common extern "C" block?
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" void __tsan_setjmp(uptr sp, uptr mangled_sp) {
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedInRtl in_rtl;
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetJmp(cur_thread(), sp, mangled_sp);
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Not called.  Merely to satisfy TSAN_INTERCEPT().
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" SANITIZER_INTERFACE_ATTRIBUTE
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int __interceptor_setjmp(void *env);
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int __interceptor_setjmp(void *env) {
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(0);
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
376c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
377c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
378c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// FIXME: any reason to have a separate declaration?
379c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochextern "C" SANITIZER_INTERFACE_ATTRIBUTE
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int __interceptor__setjmp(void *env);
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int __interceptor__setjmp(void *env) {
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(0);
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" SANITIZER_INTERFACE_ATTRIBUTE
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int __interceptor_sigsetjmp(void *env);
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int __interceptor_sigsetjmp(void *env) {
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(0);
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" SANITIZER_INTERFACE_ATTRIBUTE
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int __interceptor___sigsetjmp(void *env);
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int __interceptor___sigsetjmp(void *env) {
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(0);
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
399c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int setjmp(void *env);
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int _setjmp(void *env);
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int sigsetjmp(void *env);
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int __sigsetjmp(void *env);
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DEFINE_REAL(int, setjmp, void *env)
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DEFINE_REAL(int, _setjmp, void *env)
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DEFINE_REAL(int, sigsetjmp, void *env)
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DEFINE_REAL(int, __sigsetjmp, void *env)
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(void, longjmp, uptr *env, int val) {
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SCOPED_TSAN_INTERCEPTOR(longjmp, env, val);
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LongJmp(cur_thread(), env);
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  REAL(longjmp)(env, val);
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
41646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
41746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TSAN_INTERCEPTOR(void, siglongjmp, uptr *env, int val) {
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SCOPED_TSAN_INTERCEPTOR(siglongjmp, env, val);
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LongJmp(cur_thread(), env);
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  REAL(siglongjmp)(env, val);
423c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
424c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
425c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTSAN_INTERCEPTOR(void*, malloc, uptr size) {
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cur_thread()->in_symbolizer)
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return __libc_malloc(size);
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void *p = 0;
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SCOPED_INTERCEPTOR_RAW(malloc, size);
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    p = user_alloc(thr, pc, size);
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invoke_malloc_hook(p, size);
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return p;
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
43758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) {
43858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(__libc_memalign, align, sz);
439c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return user_alloc(thr, pc, sz, align);
440c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
44258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) {
443c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (cur_thread()->in_symbolizer)
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return __libc_calloc(size, n);
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (__sanitizer::CallocShouldReturnNullDueToOverflow(size, n))
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return AllocatorReturnNull();
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void *p = 0;
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SCOPED_INTERCEPTOR_RAW(calloc, size, n);
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    p = user_alloc(thr, pc, n * size);
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (p)
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      internal_memset(p, 0, n * size);
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invoke_malloc_hook(p, n * size);
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return p;
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cur_thread()->in_symbolizer)
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return __libc_realloc(p, size);
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (p)
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    invoke_free_hook(p);
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SCOPED_INTERCEPTOR_RAW(realloc, p, size);
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    p = user_realloc(thr, pc, p, size);
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invoke_malloc_hook(p, size);
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return p;
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(void, free, void *p) {
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (p == 0)
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cur_thread()->in_symbolizer)
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return __libc_free(p);
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invoke_free_hook(p);
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_INTERCEPTOR_RAW(free, p);
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  user_free(thr, pc, p);
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(void, cfree, void *p) {
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (p == 0)
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cur_thread()->in_symbolizer)
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return __libc_free(p);
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invoke_free_hook(p);
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_INTERCEPTOR_RAW(cfree, p);
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  user_free(thr, pc, p);
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
490c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
491c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) {
492c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p);
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return user_alloc_usable_size(thr, pc, p);
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define OPERATOR_NEW_BODY(mangled_name) \
497b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (cur_thread()->in_symbolizer) \
498b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return __libc_malloc(size); \
499b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  void *p = 0; \
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {  \
501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SCOPED_INTERCEPTOR_RAW(mangled_name, size); \
502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    p = user_alloc(thr, pc, size); \
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }  \
504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  invoke_malloc_hook(p, size);  \
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return p;
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SANITIZER_INTERFACE_ATTRIBUTE
508b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void *operator new(__sanitizer::uptr size);
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void *operator new(__sanitizer::uptr size) {
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OPERATOR_NEW_BODY(_Znwm);
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SANITIZER_INTERFACE_ATTRIBUTE
5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void *operator new[](__sanitizer::uptr size);
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void *operator new[](__sanitizer::uptr size) {
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OPERATOR_NEW_BODY(_Znam);
517b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
518b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
519c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochSANITIZER_INTERFACE_ATTRIBUTE
520c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid *operator new(__sanitizer::uptr size, std::nothrow_t const&);
521c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid *operator new(__sanitizer::uptr size, std::nothrow_t const&) {
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OPERATOR_NEW_BODY(_ZnwmRKSt9nothrow_t);
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SANITIZER_INTERFACE_ATTRIBUTE
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void *operator new[](__sanitizer::uptr size, std::nothrow_t const&);
527c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid *operator new[](__sanitizer::uptr size, std::nothrow_t const&) {
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OPERATOR_NEW_BODY(_ZnamRKSt9nothrow_t);
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define OPERATOR_DELETE_BODY(mangled_name) \
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ptr == 0) return;  \
533c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (cur_thread()->in_symbolizer) \
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return __libc_free(ptr); \
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invoke_free_hook(ptr);  \
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_INTERCEPTOR_RAW(mangled_name, ptr);  \
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  user_free(thr, pc, ptr);
538cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
539cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SANITIZER_INTERFACE_ATTRIBUTE
54068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void operator delete(void *ptr);
54168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void operator delete(void *ptr) {
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OPERATOR_DELETE_BODY(_ZdlPv);
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
54568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)SANITIZER_INTERFACE_ATTRIBUTE
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void operator delete[](void *ptr);
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void operator delete[](void *ptr) {
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OPERATOR_DELETE_BODY(_ZdlPvRKSt9nothrow_t);
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
551c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochSANITIZER_INTERFACE_ATTRIBUTE
552c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid operator delete(void *ptr, std::nothrow_t const&);
553c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid operator delete(void *ptr, std::nothrow_t const&) {
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OPERATOR_DELETE_BODY(_ZdaPv);
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
557c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochSANITIZER_INTERFACE_ATTRIBUTE
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void operator delete[](void *ptr, std::nothrow_t const&);
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void operator delete[](void *ptr, std::nothrow_t const&) {
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OPERATOR_DELETE_BODY(_ZdaPvRKSt9nothrow_t);
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(uptr, strlen, const char *s) {
564c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SCOPED_TSAN_INTERCEPTOR(strlen, s);
565c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  uptr len = internal_strlen(s);
566c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  MemoryAccessRange(thr, pc, (uptr)s, len + 1, false);
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return len;
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(void*, memset, void *dst, int v, uptr size) {
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(memset, dst, v, size);
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryAccessRange(thr, pc, (uptr)dst, size, true);
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return internal_memset(dst, v, size);
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(void*, memcpy, void *dst, const void *src, uptr size) {
577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SCOPED_TSAN_INTERCEPTOR(memcpy, dst, src, size);
578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MemoryAccessRange(thr, pc, (uptr)dst, size, true);
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryAccessRange(thr, pc, (uptr)src, size, false);
580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return internal_memcpy(dst, src, size);
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, memcmp, const void *s1, const void *s2, uptr n) {
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(memcmp, s1, s2, n);
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = 0;
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uptr len = 0;
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (; len < n; len++) {
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((res = ((unsigned char*)s1)[len] - ((unsigned char*)s2)[len]))
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MemoryAccessRange(thr, pc, (uptr)s1, len < n ? len + 1 : n, false);
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryAccessRange(thr, pc, (uptr)s2, len < n ? len + 1 : n, false);
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
594c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
595c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(void*, memchr, void *s, int c, uptr n) {
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(memchr, s, c, n);
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void *res = REAL(memchr)(s, c, n);
599c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  uptr len = res ? (char*)res - (char*)s + 1 : n;
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryAccessRange(thr, pc, (uptr)s, len, false);
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(void*, memrchr, char *s, int c, uptr n) {
605c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SCOPED_TSAN_INTERCEPTOR(memrchr, s, c, n);
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryAccessRange(thr, pc, (uptr)s, n, false);
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return REAL(memrchr)(s, c, n);
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(void*, memmove, void *dst, void *src, uptr n) {
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(memmove, dst, src, n);
6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MemoryAccessRange(thr, pc, (uptr)dst, n, true);
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryAccessRange(thr, pc, (uptr)src, n, false);
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return REAL(memmove)(dst, src, n);
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(char*, strchr, char *s, int c) {
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(strchr, s, c);
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char *res = REAL(strchr)(s, c);
620c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  uptr len = res ? (char*)res - (char*)s + 1 : internal_strlen(s) + 1;
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryAccessRange(thr, pc, (uptr)s, len, false);
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(char*, strchrnul, char *s, int c) {
626c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SCOPED_TSAN_INTERCEPTOR(strchrnul, s, c);
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char *res = REAL(strchrnul)(s, c);
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uptr len = (char*)res - (char*)s + 1;
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryAccessRange(thr, pc, (uptr)s, len, false);
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(char*, strrchr, char *s, int c) {
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(strrchr, s, c);
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryAccessRange(thr, pc, (uptr)s, internal_strlen(s) + 1, false);
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return REAL(strrchr)(s, c);
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
638c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(char*, strcpy, char *dst, const char *src) {  // NOLINT
640c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SCOPED_TSAN_INTERCEPTOR(strcpy, dst, src);  // NOLINT
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uptr srclen = internal_strlen(src);
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryAccessRange(thr, pc, (uptr)dst, srclen + 1, true);
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryAccessRange(thr, pc, (uptr)src, srclen + 1, false);
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return REAL(strcpy)(dst, src);  // NOLINT
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(char*, strncpy, char *dst, char *src, uptr n) {
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(strncpy, dst, src, n);
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uptr srclen = internal_strnlen(src, n);
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryAccessRange(thr, pc, (uptr)dst, n, true);
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryAccessRange(thr, pc, (uptr)src, min(srclen + 1, n), false);
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return REAL(strncpy)(dst, src, n);
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
654c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(const char*, strstr, const char *s1, const char *s2) {
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(strstr, s1, s2);
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char *res = REAL(strstr)(s1, s2);
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uptr len1 = internal_strlen(s1);
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uptr len2 = internal_strlen(s2);
660c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  MemoryAccessRange(thr, pc, (uptr)s1, len1 + 1, false);
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryAccessRange(thr, pc, (uptr)s2, len2 + 1, false);
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static bool fix_mmap_addr(void **addr, long_t sz, int flags) {
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (*addr) {
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!IsAppMem((uptr)*addr) || !IsAppMem((uptr)*addr + sz - 1)) {
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (flags & MAP_FIXED) {
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        errno = EINVAL;
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return false;
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
672c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        *addr = 0;
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
674c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(void*, mmap, void *addr, long_t sz, int prot,
6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         int flags, int fd, unsigned off) {
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(mmap, addr, sz, prot, flags, fd, off);
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!fix_mmap_addr(&addr, sz, flags))
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return MAP_FAILED;
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void *res = REAL(mmap)(addr, sz, prot, flags, fd, off);
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res != MAP_FAILED) {
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (fd > 0)
687c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      FdAccess(thr, pc, fd);
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MemoryRangeImitateWrite(thr, pc, (uptr)res, sz);
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
693c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTSAN_INTERCEPTOR(void*, mmap64, void *addr, long_t sz, int prot,
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           int flags, int fd, u64 off) {
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(mmap64, addr, sz, prot, flags, fd, off);
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!fix_mmap_addr(&addr, sz, flags))
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return MAP_FAILED;
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void *res = REAL(mmap64)(addr, sz, prot, flags, fd, off);
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res != MAP_FAILED) {
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (fd > 0)
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FdAccess(thr, pc, fd);
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MemoryRangeImitateWrite(thr, pc, (uptr)res, sz);
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) {
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(munmap, addr, sz);
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DontNeedShadowFor((uptr)addr, sz);
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(munmap)(addr, sz);
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) {
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(memalign, align, sz);
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return user_alloc(thr, pc, sz, align);
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
718c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
719c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTSAN_INTERCEPTOR(void*, valloc, uptr sz) {
720c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SCOPED_TSAN_INTERCEPTOR(valloc, sz);
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return user_alloc(thr, pc, sz, GetPageSizeCached());
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(void*, pvalloc, uptr sz) {
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pvalloc, sz);
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sz = RoundUp(sz, GetPageSizeCached());
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return user_alloc(thr, pc, sz, GetPageSizeCached());
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) {
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(posix_memalign, memptr, align, sz);
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *memptr = user_alloc(thr, pc, sz, align);
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Used in thread-safe function static initialization.
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" int INTERFACE_ATTRIBUTE __cxa_guard_acquire(atomic_uint32_t *g) {
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_INTERCEPTOR_RAW(__cxa_guard_acquire, g);
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (;;) {
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    u32 cmp = atomic_load(g, memory_order_acquire);
741c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (cmp == 0) {
742c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      if (atomic_compare_exchange_strong(g, &cmp, 1<<16, memory_order_relaxed))
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return 1;
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (cmp == 1) {
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Acquire(thr, pc, (uptr)g);
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      internal_sched_yield();
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" void INTERFACE_ATTRIBUTE __cxa_guard_release(atomic_uint32_t *g) {
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_INTERCEPTOR_RAW(__cxa_guard_release, g);
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Release(thr, pc, (uptr)g);
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  atomic_store(g, 1, memory_order_release);
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" void INTERFACE_ATTRIBUTE __cxa_guard_abort(atomic_uint32_t *g) {
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_INTERCEPTOR_RAW(__cxa_guard_abort, g);
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  atomic_store(g, 0, memory_order_relaxed);
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void thread_finalize(void *v) {
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uptr iter = (uptr)v;
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter > 1) {
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) {
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Printf("ThreadSanitizer: failed to set thread key\n");
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Die();
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
773c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  {
774c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ScopedInRtl in_rtl;
775c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ThreadState *thr = cur_thread();
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ThreadFinish(thr);
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SignalContext *sctx = thr->signal_ctx;
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (sctx) {
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      thr->signal_ctx = 0;
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UnmapOrDie(sctx, sizeof(*sctx));
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct ThreadParam {
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void* (*callback)(void *arg);
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void *param;
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  atomic_uintptr_t tid;
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)extern "C" void *__tsan_thread_start_func(void *arg) {
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ThreadParam *p = (ThreadParam*)arg;
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void* (*callback)(void *arg) = p->callback;
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void *param = p->param;
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int tid = 0;
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
798c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ThreadState *thr = cur_thread();
799c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ScopedInRtl in_rtl;
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (pthread_setspecific(g_thread_finalize_key, (void*)4)) {
8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Printf("ThreadSanitizer: failed to set thread key\n");
8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Die();
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
804c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
805c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      pthread_yield();
806c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    atomic_store(&p->tid, 0, memory_order_release);
807c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ThreadStart(thr, tid, GetTid());
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK_EQ(thr->in_rtl, 1);
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void *res = callback(param);
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Prevent the callback from being tail called,
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // it mixes up stack traces.
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  volatile int foo = 42;
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  foo++;
815c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return res;
816c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_create,
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void *th, void *attr, void *(*callback)(void*), void * param) {
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_create, th, attr, callback, param);
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  __sanitizer_pthread_attr_t myattr;
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (attr == 0) {
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pthread_attr_init(&myattr);
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    attr = &myattr;
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int detached = 0;
827c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  pthread_attr_getdetachstate(attr, &detached);
828c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(TSAN_DEBUG_OUTPUT)
8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int verbosity = (TSAN_DEBUG_OUTPUT);
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int verbosity = 0;
833c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#endif
8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AdjustStackSizeLinux(attr, verbosity);
835c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ThreadParam p;
8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  p.callback = callback;
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  p.param = param;
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  atomic_store(&p.tid, 0, memory_order_relaxed);
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_create)(th, attr, __tsan_thread_start_func, &p);
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int tid = ThreadCreate(thr, pc, *(uptr*)th, detached);
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK_NE(tid, 0);
844c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    atomic_store(&p.tid, tid, memory_order_release);
845c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    while (atomic_load(&p.tid, memory_order_acquire) != 0)
846c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      pthread_yield();
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (attr == &myattr)
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pthread_attr_destroy(&myattr);
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) {
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_join, th, ret);
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int tid = ThreadTid(thr, pc, (uptr)th);
8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = BLOCK_REAL(pthread_join)(th, ret);
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ThreadJoin(thr, pc, tid);
8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
860c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return res;
861c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_detach, void *th) {
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_detach, th);
8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int tid = ThreadTid(thr, pc, (uptr)th);
8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_detach)(th);
8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ThreadDetach(thr, pc, tid);
8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
873c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTSAN_INTERCEPTOR(int, pthread_mutex_init, void *m, void *a) {
874c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_init, m, a);
8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_mutex_init)(m, a);
8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool recursive = false;
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (a) {
879c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      int type = 0;
880c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      if (pthread_mutexattr_gettype(a, &type) == 0)
8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        recursive = (type == PTHREAD_MUTEX_RECURSIVE
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            || type == PTHREAD_MUTEX_RECURSIVE_NP);
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MutexCreate(thr, pc, (uptr)m, false, recursive, false);
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_mutex_destroy, void *m) {
890eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_destroy, m);
891eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int res = REAL(pthread_mutex_destroy)(m);
892eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (res == 0 || res == EBUSY) {
893eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MutexDestroy(thr, pc, (uptr)m);
8942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
897c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
898c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTSAN_INTERCEPTOR(int, pthread_mutex_lock, void *m) {
8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_lock, m);
9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_mutex_lock)(m);
9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MutexLock(thr, pc, (uptr)m);
9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) {
9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_trylock, m);
909c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int res = REAL(pthread_mutex_trylock)(m);
910c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (res == 0) {
9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MutexLock(thr, pc, (uptr)m);
9122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
914c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
915c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
916c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) {
917c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_timedlock, m, abstime);
9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_mutex_timedlock)(m, abstime);
9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MutexLock(thr, pc, (uptr)m);
9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
923c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
924c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_mutex_unlock, void *m) {
9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_mutex_unlock, m);
9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MutexUnlock(thr, pc, (uptr)m);
9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_mutex_unlock)(m);
9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_spin_init, void *m, int pshared) {
9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_spin_init, m, pshared);
9342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_spin_init)(m, pshared);
9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
9362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MutexCreate(thr, pc, (uptr)m, false, false, false);
9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
939c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
940c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_spin_destroy, void *m) {
9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_spin_destroy, m);
9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_spin_destroy)(m);
9442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
9452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MutexDestroy(thr, pc, (uptr)m);
9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
9482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_spin_lock, void *m) {
9512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_spin_lock, m);
9522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_spin_lock)(m);
9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MutexLock(thr, pc, (uptr)m);
9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_spin_trylock, void *m) {
9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_spin_trylock, m);
9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_spin_trylock)(m);
9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MutexLock(thr, pc, (uptr)m);
9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
968c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTSAN_INTERCEPTOR(int, pthread_spin_unlock, void *m) {
969c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SCOPED_TSAN_INTERCEPTOR(pthread_spin_unlock, m);
970c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  MutexUnlock(thr, pc, (uptr)m);
971c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int res = REAL(pthread_spin_unlock)(m);
9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_rwlock_init, void *m, void *a) {
9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_init, m, a);
977c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int res = REAL(pthread_rwlock_init)(m, a);
978c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (res == 0) {
9792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MutexCreate(thr, pc, (uptr)m, true, false, false);
9802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
9822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_rwlock_destroy, void *m) {
9852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_destroy, m);
9862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_rwlock_destroy)(m);
9872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
9882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MutexDestroy(thr, pc, (uptr)m);
9892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
9912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_rwlock_rdlock, void *m) {
9942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_rdlock, m);
9952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_rwlock_rdlock)(m);
9962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
9972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MutexReadLock(thr, pc, (uptr)m);
9982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
10002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_rwlock_tryrdlock, void *m) {
10032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_tryrdlock, m);
10042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_rwlock_tryrdlock)(m);
10052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
10062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MutexReadLock(thr, pc, (uptr)m);
1007c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
1008c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return res;
10092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) {
10122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedrdlock, m, abstime);
10135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int res = REAL(pthread_rwlock_timedrdlock)(m, abstime);
10142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
10152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MutexReadLock(thr, pc, (uptr)m);
10162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
10182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_rwlock_wrlock, void *m) {
10212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_wrlock, m);
10222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_rwlock_wrlock)(m);
10232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
10242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MutexLock(thr, pc, (uptr)m);
10252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
10272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_rwlock_trywrlock, void *m) {
10302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_trywrlock, m);
10312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_rwlock_trywrlock)(m);
10322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
10332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MutexLock(thr, pc, (uptr)m);
10342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
10362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_rwlock_timedwrlock, void *m, void *abstime) {
10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedwrlock, m, abstime);
10402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_rwlock_timedwrlock)(m, abstime);
10412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
10422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MutexLock(thr, pc, (uptr)m);
10432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
10452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) {
10482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_unlock, m);
10492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MutexReadOrWriteUnlock(thr, pc, (uptr)m);
10502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_rwlock_unlock)(m);
10512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
10522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_cond_init_2_3_2, void *c, void *a) {
10552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_cond_init_2_3_2, c, a);
10562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryWrite(thr, pc, (uptr)c, kSizeLog1);
10572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_cond_init_2_3_2)(c, a);
10582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
10592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_cond_destroy_2_3_2, void *c) {
1062c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy_2_3_2, c);
1063c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  MemoryWrite(thr, pc, (uptr)c, kSizeLog1);
1064c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int res = REAL(pthread_cond_destroy_2_3_2)(c);
1065c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return res;
1066c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1067c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
10682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_cond_signal_2_3_2, void *c) {
10692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal_2_3_2, c);
10702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryRead(thr, pc, (uptr)c, kSizeLog1);
1071c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int res = REAL(pthread_cond_signal_2_3_2)(c);
1072c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return res;
1073c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1074c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
10752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_cond_broadcast_2_3_2, void *c) {
10762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_cond_broadcast_2_3_2, c);
10772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryRead(thr, pc, (uptr)c, kSizeLog1);
10782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_cond_broadcast_2_3_2)(c);
10792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
10802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_cond_wait_2_3_2, void *c, void *m) {
10832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait_2_3_2, c, m);
10842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MutexUnlock(thr, pc, (uptr)m);
10852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryRead(thr, pc, (uptr)c, kSizeLog1);
10862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_cond_wait_2_3_2)(c, m);
10872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MutexLock(thr, pc, (uptr)m);
10882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
10892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_cond_timedwait_2_3_2, void *c, void *m,
10922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void *abstime) {
10932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait_2_3_2, c, m, abstime);
10942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MutexUnlock(thr, pc, (uptr)m);
10952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryRead(thr, pc, (uptr)c, kSizeLog1);
10962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_cond_timedwait_2_3_2)(c, m, abstime);
1097c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  MutexLock(thr, pc, (uptr)m);
1098c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return res;
1099c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTSAN_INTERCEPTOR(int, pthread_barrier_init, void *b, void *a, unsigned count) {
1102c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SCOPED_TSAN_INTERCEPTOR(pthread_barrier_init, b, a, count);
1103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
11042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_barrier_init)(b, a, count);
11052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
11062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_barrier_destroy, void *b) {
11092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_barrier_destroy, b);
11102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
11112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_barrier_destroy)(b);
11122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
11132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) {
11162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_barrier_wait, b);
11172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Release(thr, pc, (uptr)b);
11182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryRead(thr, pc, (uptr)b, kSizeLog1);
11192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(pthread_barrier_wait)(b);
11202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MemoryRead(thr, pc, (uptr)b, kSizeLog1);
1121c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (res == 0 || res == PTHREAD_BARRIER_SERIAL_THREAD) {
1122c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    Acquire(thr, pc, (uptr)b);
1123c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
11242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
11252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) {
11282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(pthread_once, o, f);
11292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (o == 0 || f == 0)
11302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return EINVAL;
11312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  atomic_uint32_t *a = static_cast<atomic_uint32_t*>(o);
11322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  u32 v = atomic_load(a, memory_order_acquire);
11332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (v == 0 && atomic_compare_exchange_strong(a, &v, 1,
11342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                               memory_order_relaxed)) {
11352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const int old_in_rtl = thr->in_rtl;
11362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    thr->in_rtl = 0;
11372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (*f)();
11382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK_EQ(thr->in_rtl, 0);
11392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    thr->in_rtl = old_in_rtl;
11402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Release(thr, pc, (uptr)o);
11412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    atomic_store(a, 2, memory_order_release);
11422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
11432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    while (v != 2) {
11442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pthread_yield();
11452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      v = atomic_load(a, memory_order_acquire);
11462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
11472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Acquire(thr, pc, (uptr)o);
11482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
11492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
11502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, sem_init, void *s, int pshared, unsigned value) {
11532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(sem_init, s, pshared, value);
11542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(sem_init)(s, pshared, value);
11552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
11562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, sem_destroy, void *s) {
11592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(sem_destroy, s);
11602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(sem_destroy)(s);
11612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
11622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, sem_wait, void *s) {
11652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(sem_wait, s);
11665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int res = BLOCK_REAL(sem_wait)(s);
11672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
1168c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    Acquire(thr, pc, (uptr)s);
1169c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
1170c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return res;
11712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, sem_trywait, void *s) {
11742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(sem_trywait, s);
11752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = BLOCK_REAL(sem_trywait)(s);
11762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
11772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Acquire(thr, pc, (uptr)s);
11782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
11792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
11802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, sem_timedwait, void *s, void *abstime) {
11832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(sem_timedwait, s, abstime);
11842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = BLOCK_REAL(sem_timedwait)(s, abstime);
11852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
11862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Acquire(thr, pc, (uptr)s);
11872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
11882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
11892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
11912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, sem_post, void *s) {
11922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(sem_post, s);
11932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Release(thr, pc, (uptr)s);
11942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(sem_post)(s);
11952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
11962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, sem_getvalue, void *s, int *sval) {
11992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(sem_getvalue, s, sval);
12002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(sem_getvalue)(s, sval);
12012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0) {
12022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Acquire(thr, pc, (uptr)s);
12032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
12042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
12052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) {
12082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(__xstat, version, path, buf);
12092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return REAL(__xstat)(version, path, buf);
12102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, stat, const char *path, void *buf) {
12132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(__xstat, 0, path, buf);
1214c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return REAL(__xstat)(0, path, buf);
12152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) {
12182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(__xstat64, version, path, buf);
12192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return REAL(__xstat64)(version, path, buf);
12202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, stat64, const char *path, void *buf) {
12232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(__xstat64, 0, path, buf);
12242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return REAL(__xstat64)(0, path, buf);
12252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) {
12282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(__lxstat, version, path, buf);
12292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return REAL(__lxstat)(version, path, buf);
12302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, lstat, const char *path, void *buf) {
12332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(__lxstat, 0, path, buf);
12342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return REAL(__lxstat)(0, path, buf);
12352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) {
12382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(__lxstat64, version, path, buf);
12392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return REAL(__lxstat64)(version, path, buf);
12402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, lstat64, const char *path, void *buf) {
12432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(__lxstat64, 0, path, buf);
12442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return REAL(__lxstat64)(0, path, buf);
12452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) {
12482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(__fxstat, version, fd, buf);
12492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fd > 0)
12502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FdAccess(thr, pc, fd);
12512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return REAL(__fxstat)(version, fd, buf);
12522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) {
12552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(__fxstat, 0, fd, buf);
12562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fd > 0)
12572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FdAccess(thr, pc, fd);
12582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return REAL(__fxstat)(0, fd, buf);
12592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1261c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) {
1262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf);
1263c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (fd > 0)
1264c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    FdAccess(thr, pc, fd);
12652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return REAL(__fxstat64)(version, fd, buf);
12662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1267c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
12682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) {
12692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf);
12702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fd > 0)
12712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FdAccess(thr, pc, fd);
12722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return REAL(__fxstat64)(0, fd, buf);
12732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, open, const char *name, int flags, int mode) {
12762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(open, name, flags, mode);
12772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = REAL(open)(name, flags, mode);
12782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fd >= 0)
12792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FdFileCreate(thr, pc, fd);
12802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return fd;
12812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1283c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTSAN_INTERCEPTOR(int, open64, const char *name, int flags, int mode) {
12842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(open64, name, flags, mode);
12852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = REAL(open64)(name, flags, mode);
128646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (fd >= 0)
12872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FdFileCreate(thr, pc, fd);
12882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return fd;
12892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, creat, const char *name, int mode) {
12922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(creat, name, mode);
12932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = REAL(creat)(name, mode);
12942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fd >= 0)
129546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    FdFileCreate(thr, pc, fd);
129646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return fd;
12972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
129846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
129946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TSAN_INTERCEPTOR(int, creat64, const char *name, int mode) {
13002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(creat64, name, mode);
13012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = REAL(creat64)(name, mode);
13022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fd >= 0)
13032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FdFileCreate(thr, pc, fd);
13042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return fd;
13052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
130746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TSAN_INTERCEPTOR(int, dup, int oldfd) {
130846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(dup, oldfd);
13092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int newfd = REAL(dup)(oldfd);
13102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (oldfd >= 0 && newfd >= 0 && newfd != oldfd)
13112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FdDup(thr, pc, oldfd, newfd);
13122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return newfd;
13132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, dup2, int oldfd, int newfd) {
13162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(dup2, oldfd, newfd);
13172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int newfd2 = REAL(dup2)(oldfd, newfd);
13182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (oldfd >= 0 && newfd2 >= 0 && newfd2 != oldfd)
13192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FdDup(thr, pc, oldfd, newfd2);
13202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return newfd2;
132146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
13222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, dup3, int oldfd, int newfd, int flags) {
13242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(dup3, oldfd, newfd, flags);
13252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int newfd2 = REAL(dup3)(oldfd, newfd, flags);
13262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (oldfd >= 0 && newfd2 >= 0 && newfd2 != oldfd)
13272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FdDup(thr, pc, oldfd, newfd2);
13282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return newfd2;
13292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, eventfd, unsigned initval, int flags) {
13322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(eventfd, initval, flags);
13332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = REAL(eventfd)(initval, flags);
13342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fd >= 0)
13352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FdEventCreate(thr, pc, fd);
13362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return fd;
13372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, signalfd, int fd, void *mask, int flags) {
1340c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SCOPED_TSAN_INTERCEPTOR(signalfd, fd, mask, flags);
1341c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (fd >= 0)
1342c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    FdClose(thr, pc, fd);
13432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fd = REAL(signalfd)(fd, mask, flags);
13442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fd >= 0)
1345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FdSignalCreate(thr, pc, fd);
13462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return fd;
13472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TSAN_INTERCEPTOR(int, inotify_init, int fake) {
1350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(inotify_init, fake);
13512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = REAL(inotify_init)(fake);
13522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fd >= 0)
13535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FdInotifyCreate(thr, pc, fd);
1354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return fd;
1355c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
13562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1357c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTSAN_INTERCEPTOR(int, inotify_init1, int flags) {
1358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(inotify_init1, flags);
1359c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int fd = REAL(inotify_init1)(flags);
1360c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (fd >= 0)
1361c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    FdInotifyCreate(thr, pc, fd);
13622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return fd;
1363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
13652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, socket, int domain, int type, int protocol) {
13662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(socket, domain, type, protocol);
1367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int fd = REAL(socket)(domain, type, protocol);
1368c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (fd >= 0)
13692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FdSocketCreate(thr, pc, fd);
13702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return fd;
1371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1372c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
13732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int *fd) {
13742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(socketpair, domain, type, protocol, fd);
13752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(socketpair)(domain, type, protocol, fd);
13762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (res == 0 && fd[0] >= 0 && fd[1] >= 0)
13772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FdPipeCreate(thr, pc, fd[0], fd[1]);
13782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
13792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, connect, int fd, void *addr, unsigned addrlen) {
13822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(connect, fd, addr, addrlen);
13832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FdSocketConnecting(thr, pc, fd);
1384ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int res = REAL(connect)(fd, addr, addrlen);
1385ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (res == 0 && fd >= 0)
13862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FdSocketConnect(thr, pc, fd);
1387ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return res;
13882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, bind, int fd, void *addr, unsigned addrlen) {
13912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(bind, fd, addr, addrlen);
139268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int res = REAL(bind)(fd, addr, addrlen);
13932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fd > 0 && res == 0)
1394c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    FdAccess(thr, pc, fd);
1395c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return res;
13962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, listen, int fd, int backlog) {
13992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(listen, fd, backlog);
14002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int res = REAL(listen)(fd, backlog);
14012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fd > 0 && res == 0)
14022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FdAccess(thr, pc, fd);
14032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return res;
14042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
14052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1406c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTSAN_INTERCEPTOR(int, epoll_create, int size) {
14072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(epoll_create, size);
14082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = REAL(epoll_create)(size);
14092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fd >= 0)
1410c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    FdPollCreate(thr, pc, fd);
1411c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return fd;
1412c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
14132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, epoll_create1, int flags) {
14152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(epoll_create1, flags);
14165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int fd = REAL(epoll_create1)(flags);
14172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fd >= 0)
14182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FdPollCreate(thr, pc, fd);
14192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return fd;
1420c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1421c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
14222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, close, int fd) {
14232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(close, fd);
14242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fd >= 0)
14252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FdClose(thr, pc, fd);
14262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return REAL(close)(fd);
14272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
14282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(int, __close, int fd) {
14302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SCOPED_TSAN_INTERCEPTOR(__close, fd);
14312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fd >= 0)
14322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FdClose(thr, pc, fd);
14332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return REAL(__close)(fd);
14342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
14352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// glibc guts
14372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TSAN_INTERCEPTOR(void, __res_iclose, void *state, bool free_addr) {
1438c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SCOPED_TSAN_INTERCEPTOR(__res_iclose, state, free_addr);
1439c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int fds[64];
1440c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int cnt = ExtractResolvFDs(state, fds, ARRAY_SIZE(fds));
1441c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  for (int i = 0; i < cnt; i++) {
1442c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (fds[i] > 0)
1443c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      FdClose(thr, pc, fds[i]);
1444c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
1445c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  REAL(__res_iclose)(state, free_addr);
1446c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1447c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1448c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTSAN_INTERCEPTOR(int, pipe, int *pipefd) {
1449c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SCOPED_TSAN_INTERCEPTOR(pipe, pipefd);
1450c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int res = REAL(pipe)(pipefd);
1451c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (res == 0 && pipefd[0] >= 0 && pipefd[1] >= 0)
1452c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    FdPipeCreate(thr, pc, pipefd[0], pipefd[1]);
1453c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return res;
1454c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1455c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1456c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) {
1457c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SCOPED_TSAN_INTERCEPTOR(pipe2, pipefd, flags);
1458c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int res = REAL(pipe2)(pipefd, flags);
1459c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (res == 0 && pipefd[0] >= 0 && pipefd[1] >= 0)
1460c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    FdPipeCreate(thr, pc, pipefd[0], pipefd[1]);
1461c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return res;
1462c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1463c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1464c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTSAN_INTERCEPTOR(long_t, send, int fd, void *buf, long_t len, int flags) {
1465c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SCOPED_TSAN_INTERCEPTOR(send, fd, buf, len, flags);
1466c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (fd >= 0)
1467c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    FdRelease(thr, pc, fd);
1468c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int res = REAL(send)(fd, buf, len, flags);
1469c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return res;
14702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
14712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1472TSAN_INTERCEPTOR(long_t, sendmsg, int fd, void *msg, int flags) {
1473  SCOPED_TSAN_INTERCEPTOR(sendmsg, fd, msg, flags);
1474  if (fd >= 0)
1475    FdRelease(thr, pc, fd);
1476  int res = REAL(sendmsg)(fd, msg, flags);
1477  return res;
1478}
1479
1480TSAN_INTERCEPTOR(long_t, recv, int fd, void *buf, long_t len, int flags) {
1481  SCOPED_TSAN_INTERCEPTOR(recv, fd, buf, len, flags);
1482  int res = REAL(recv)(fd, buf, len, flags);
1483  if (res >= 0 && fd >= 0) {
1484    FdAcquire(thr, pc, fd);
1485  }
1486  return res;
1487}
1488
1489TSAN_INTERCEPTOR(int, unlink, char *path) {
1490  SCOPED_TSAN_INTERCEPTOR(unlink, path);
1491  Release(thr, pc, File2addr(path));
1492  int res = REAL(unlink)(path);
1493  return res;
1494}
1495
1496TSAN_INTERCEPTOR(void*, fopen, char *path, char *mode) {
1497  SCOPED_TSAN_INTERCEPTOR(fopen, path, mode);
1498  void *res = REAL(fopen)(path, mode);
1499  Acquire(thr, pc, File2addr(path));
1500  if (res) {
1501    int fd = fileno_unlocked(res);
1502    if (fd >= 0)
1503      FdFileCreate(thr, pc, fd);
1504  }
1505  return res;
1506}
1507
1508TSAN_INTERCEPTOR(void*, freopen, char *path, char *mode, void *stream) {
1509  SCOPED_TSAN_INTERCEPTOR(freopen, path, mode, stream);
1510  if (stream) {
1511    int fd = fileno_unlocked(stream);
1512    if (fd >= 0)
1513      FdClose(thr, pc, fd);
1514  }
1515  void *res = REAL(freopen)(path, mode, stream);
1516  Acquire(thr, pc, File2addr(path));
1517  if (res) {
1518    int fd = fileno_unlocked(res);
1519    if (fd >= 0)
1520      FdFileCreate(thr, pc, fd);
1521  }
1522  return res;
1523}
1524
1525TSAN_INTERCEPTOR(int, fclose, void *stream) {
1526  {
1527    SCOPED_TSAN_INTERCEPTOR(fclose, stream);
1528    if (stream) {
1529      int fd = fileno_unlocked(stream);
1530      if (fd >= 0)
1531        FdClose(thr, pc, fd);
1532    }
1533  }
1534  return REAL(fclose)(stream);
1535}
1536
1537TSAN_INTERCEPTOR(uptr, fread, void *ptr, uptr size, uptr nmemb, void *f) {
1538  {
1539    SCOPED_TSAN_INTERCEPTOR(fread, ptr, size, nmemb, f);
1540    MemoryAccessRange(thr, pc, (uptr)ptr, size * nmemb, true);
1541  }
1542  return REAL(fread)(ptr, size, nmemb, f);
1543}
1544
1545TSAN_INTERCEPTOR(uptr, fwrite, const void *p, uptr size, uptr nmemb, void *f) {
1546  {
1547    SCOPED_TSAN_INTERCEPTOR(fwrite, p, size, nmemb, f);
1548    MemoryAccessRange(thr, pc, (uptr)p, size * nmemb, false);
1549  }
1550  return REAL(fwrite)(p, size, nmemb, f);
1551}
1552
1553TSAN_INTERCEPTOR(int, fflush, void *stream) {
1554  SCOPED_TSAN_INTERCEPTOR(fflush, stream);
1555  return REAL(fflush)(stream);
1556}
1557
1558TSAN_INTERCEPTOR(void, abort, int fake) {
1559  SCOPED_TSAN_INTERCEPTOR(abort, fake);
1560  REAL(fflush)(0);
1561  REAL(abort)(fake);
1562}
1563
1564TSAN_INTERCEPTOR(int, puts, const char *s) {
1565  SCOPED_TSAN_INTERCEPTOR(puts, s);
1566  MemoryAccessRange(thr, pc, (uptr)s, internal_strlen(s), false);
1567  return REAL(puts)(s);
1568}
1569
1570TSAN_INTERCEPTOR(int, rmdir, char *path) {
1571  SCOPED_TSAN_INTERCEPTOR(rmdir, path);
1572  Release(thr, pc, Dir2addr(path));
1573  int res = REAL(rmdir)(path);
1574  return res;
1575}
1576
1577TSAN_INTERCEPTOR(void*, opendir, char *path) {
1578  SCOPED_TSAN_INTERCEPTOR(opendir, path);
1579  void *res = REAL(opendir)(path);
1580  if (res != 0)
1581    Acquire(thr, pc, Dir2addr(path));
1582  return res;
1583}
1584
1585TSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) {
1586  SCOPED_TSAN_INTERCEPTOR(epoll_ctl, epfd, op, fd, ev);
1587  if (op == EPOLL_CTL_ADD && epfd >= 0) {
1588    FdRelease(thr, pc, epfd);
1589  }
1590  int res = REAL(epoll_ctl)(epfd, op, fd, ev);
1591  if (fd >= 0)
1592    FdAccess(thr, pc, fd);
1593  return res;
1594}
1595
1596TSAN_INTERCEPTOR(int, epoll_wait, int epfd, void *ev, int cnt, int timeout) {
1597  SCOPED_TSAN_INTERCEPTOR(epoll_wait, epfd, ev, cnt, timeout);
1598  int res = BLOCK_REAL(epoll_wait)(epfd, ev, cnt, timeout);
1599  if (res > 0 && epfd >= 0) {
1600    FdAcquire(thr, pc, epfd);
1601  }
1602  return res;
1603}
1604
1605void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
1606    my_siginfo_t *info, void *ctx) {
1607  ThreadState *thr = cur_thread();
1608  SignalContext *sctx = SigCtx(thr);
1609  // Don't mess with synchronous signals.
1610  if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
1611      sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE || sig == SIGSYS ||
1612      // If we are sending signal to ourselves, we must process it now.
1613      (sctx && sig == sctx->int_signal_send) ||
1614      // If we are in blocking function, we can safely process it now
1615      // (but check if we are in a recursive interceptor,
1616      // i.e. pthread_join()->munmap()).
1617      (sctx && sctx->in_blocking_func == 1 && thr->in_rtl == 1)) {
1618    int in_rtl = thr->in_rtl;
1619    thr->in_rtl = 0;
1620    CHECK_EQ(thr->in_signal_handler, false);
1621    thr->in_signal_handler = true;
1622    if (sigact)
1623      sigactions[sig].sa_sigaction(sig, info, ctx);
1624    else
1625      sigactions[sig].sa_handler(sig);
1626    CHECK_EQ(thr->in_signal_handler, true);
1627    thr->in_signal_handler = false;
1628    thr->in_rtl = in_rtl;
1629    return;
1630  }
1631
1632  if (sctx == 0)
1633    return;
1634  SignalDesc *signal = &sctx->pending_signals[sig];
1635  if (signal->armed == false) {
1636    signal->armed = true;
1637    signal->sigaction = sigact;
1638    if (info)
1639      internal_memcpy(&signal->siginfo, info, sizeof(*info));
1640    if (ctx)
1641      internal_memcpy(&signal->ctx, ctx, sizeof(signal->ctx));
1642    sctx->pending_signal_count++;
1643  }
1644}
1645
1646static void rtl_sighandler(int sig) {
1647  rtl_generic_sighandler(false, sig, 0, 0);
1648}
1649
1650static void rtl_sigaction(int sig, my_siginfo_t *info, void *ctx) {
1651  rtl_generic_sighandler(true, sig, info, ctx);
1652}
1653
1654TSAN_INTERCEPTOR(int, sigaction, int sig, sigaction_t *act, sigaction_t *old) {
1655  SCOPED_TSAN_INTERCEPTOR(sigaction, sig, act, old);
1656  if (old)
1657    internal_memcpy(old, &sigactions[sig], sizeof(*old));
1658  if (act == 0)
1659    return 0;
1660  internal_memcpy(&sigactions[sig], act, sizeof(*act));
1661  sigaction_t newact;
1662  internal_memcpy(&newact, act, sizeof(newact));
1663  sigfillset(&newact.sa_mask);
1664  if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL) {
1665    if (newact.sa_flags & SA_SIGINFO)
1666      newact.sa_sigaction = rtl_sigaction;
1667    else
1668      newact.sa_handler = rtl_sighandler;
1669  }
1670  int res = REAL(sigaction)(sig, &newact, 0);
1671  return res;
1672}
1673
1674TSAN_INTERCEPTOR(sighandler_t, signal, int sig, sighandler_t h) {
1675  sigaction_t act;
1676  act.sa_handler = h;
1677  REAL(memset)(&act.sa_mask, -1, sizeof(act.sa_mask));
1678  act.sa_flags = 0;
1679  sigaction_t old;
1680  int res = sigaction(sig, &act, &old);
1681  if (res)
1682    return SIG_ERR;
1683  return old.sa_handler;
1684}
1685
1686TSAN_INTERCEPTOR(int, sigsuspend, const sigset_t *mask) {
1687  SCOPED_TSAN_INTERCEPTOR(sigsuspend, mask);
1688  return REAL(sigsuspend)(mask);
1689}
1690
1691TSAN_INTERCEPTOR(int, raise, int sig) {
1692  SCOPED_TSAN_INTERCEPTOR(raise, sig);
1693  SignalContext *sctx = SigCtx(thr);
1694  CHECK_NE(sctx, 0);
1695  int prev = sctx->int_signal_send;
1696  sctx->int_signal_send = sig;
1697  int res = REAL(raise)(sig);
1698  CHECK_EQ(sctx->int_signal_send, sig);
1699  sctx->int_signal_send = prev;
1700  return res;
1701}
1702
1703TSAN_INTERCEPTOR(int, kill, int pid, int sig) {
1704  SCOPED_TSAN_INTERCEPTOR(kill, pid, sig);
1705  SignalContext *sctx = SigCtx(thr);
1706  CHECK_NE(sctx, 0);
1707  int prev = sctx->int_signal_send;
1708  if (pid == (int)internal_getpid()) {
1709    sctx->int_signal_send = sig;
1710  }
1711  int res = REAL(kill)(pid, sig);
1712  if (pid == (int)internal_getpid()) {
1713    CHECK_EQ(sctx->int_signal_send, sig);
1714    sctx->int_signal_send = prev;
1715  }
1716  return res;
1717}
1718
1719TSAN_INTERCEPTOR(int, pthread_kill, void *tid, int sig) {
1720  SCOPED_TSAN_INTERCEPTOR(pthread_kill, tid, sig);
1721  SignalContext *sctx = SigCtx(thr);
1722  CHECK_NE(sctx, 0);
1723  int prev = sctx->int_signal_send;
1724  if (tid == pthread_self()) {
1725    sctx->int_signal_send = sig;
1726  }
1727  int res = REAL(pthread_kill)(tid, sig);
1728  if (tid == pthread_self()) {
1729    CHECK_EQ(sctx->int_signal_send, sig);
1730    sctx->int_signal_send = prev;
1731  }
1732  return res;
1733}
1734
1735TSAN_INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
1736  SCOPED_TSAN_INTERCEPTOR(gettimeofday, tv, tz);
1737  // It's intercepted merely to process pending signals.
1738  return REAL(gettimeofday)(tv, tz);
1739}
1740
1741TSAN_INTERCEPTOR(int, getaddrinfo, void *node, void *service,
1742    void *hints, void *rv) {
1743  SCOPED_TSAN_INTERCEPTOR(getaddrinfo, node, service, hints, rv);
1744  // We miss atomic synchronization in getaddrinfo,
1745  // and can report false race between malloc and free
1746  // inside of getaddrinfo. So ignore memory accesses.
1747  IgnoreCtl(thr, true, true);
1748  IgnoreCtl(thr, false, true);
1749  int res = REAL(getaddrinfo)(node, service, hints, rv);
1750  IgnoreCtl(thr, true, false);
1751  IgnoreCtl(thr, false, false);
1752  return res;
1753}
1754
1755// Linux kernel has a bug that leads to kernel deadlock if a process
1756// maps TBs of memory and then calls mlock().
1757static void MlockIsUnsupported() {
1758  static atomic_uint8_t printed;
1759  if (atomic_exchange(&printed, 1, memory_order_relaxed))
1760    return;
1761  if (flags()->verbosity > 0)
1762    Printf("INFO: ThreadSanitizer ignores mlock/mlockall/munlock/munlockall\n");
1763}
1764
1765TSAN_INTERCEPTOR(int, mlock, const void *addr, uptr len) {
1766  MlockIsUnsupported();
1767  return 0;
1768}
1769
1770TSAN_INTERCEPTOR(int, munlock, const void *addr, uptr len) {
1771  MlockIsUnsupported();
1772  return 0;
1773}
1774
1775TSAN_INTERCEPTOR(int, mlockall, int flags) {
1776  MlockIsUnsupported();
1777  return 0;
1778}
1779
1780TSAN_INTERCEPTOR(int, munlockall, void) {
1781  MlockIsUnsupported();
1782  return 0;
1783}
1784
1785TSAN_INTERCEPTOR(int, fork, int fake) {
1786  SCOPED_TSAN_INTERCEPTOR(fork, fake);
1787  // It's intercepted merely to process pending signals.
1788  int pid = REAL(fork)(fake);
1789  if (pid == 0) {
1790    // child
1791    FdOnFork(thr, pc);
1792  } else if (pid > 0) {
1793    // parent
1794  }
1795  return pid;
1796}
1797
1798struct TsanInterceptorContext {
1799  ThreadState *thr;
1800  const uptr caller_pc;
1801  const uptr pc;
1802};
1803
1804#include "sanitizer_common/sanitizer_platform_interceptors.h"
1805// Causes interceptor recursion (getpwuid_r() calls fopen())
1806#undef SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
1807#undef SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
1808// Causes interceptor recursion (getaddrinfo() and fopen())
1809#undef SANITIZER_INTERCEPT_GETADDRINFO
1810#undef SANITIZER_INTERCEPT_GETNAMEINFO
1811// Causes interceptor recursion (glob64() calls lstat64())
1812#undef SANITIZER_INTERCEPT_GLOB
1813
1814#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count) \
1815  do {                                                \
1816  } while (false)
1817#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size)                    \
1818  MemoryAccessRange(((TsanInterceptorContext *)ctx)->thr,                 \
1819                    ((TsanInterceptorContext *)ctx)->pc, (uptr)ptr, size, \
1820                    true)
1821#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size)                       \
1822  MemoryAccessRange(((TsanInterceptorContext *) ctx)->thr,                  \
1823                    ((TsanInterceptorContext *) ctx)->pc, (uptr) ptr, size, \
1824                    false)
1825#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)      \
1826  SCOPED_TSAN_INTERCEPTOR(func, __VA_ARGS__);         \
1827  TsanInterceptorContext _ctx = {thr, caller_pc, pc}; \
1828  ctx = (void *)&_ctx;                                \
1829  (void) ctx;
1830#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
1831  FdAcquire(((TsanInterceptorContext *) ctx)->thr, pc, fd)
1832#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
1833  FdRelease(((TsanInterceptorContext *) ctx)->thr, pc, fd)
1834#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
1835  FdSocketAccept(((TsanInterceptorContext *) ctx)->thr, pc, fd, newfd)
1836#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
1837  ThreadSetName(((TsanInterceptorContext *) ctx)->thr, name)
1838#define COMMON_INTERCEPTOR_BLOCK_REAL(name) BLOCK_REAL(name)
1839#include "sanitizer_common/sanitizer_common_interceptors.inc"
1840
1841// FIXME: Implement these with MemoryAccessRange().
1842#define COMMON_SYSCALL_PRE_READ_RANGE(p, s)
1843#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s)
1844#define COMMON_SYSCALL_POST_READ_RANGE(p, s)
1845#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s)
1846#include "sanitizer_common/sanitizer_common_syscalls.inc"
1847
1848namespace __tsan {
1849
1850void ProcessPendingSignals(ThreadState *thr) {
1851  CHECK_EQ(thr->in_rtl, 0);
1852  SignalContext *sctx = SigCtx(thr);
1853  if (sctx == 0 || sctx->pending_signal_count == 0 || thr->in_signal_handler)
1854    return;
1855  Context *ctx = CTX();
1856  thr->in_signal_handler = true;
1857  sctx->pending_signal_count = 0;
1858  // These are too big for stack.
1859  static THREADLOCAL sigset_t emptyset, oldset;
1860  sigfillset(&emptyset);
1861  pthread_sigmask(SIG_SETMASK, &emptyset, &oldset);
1862  for (int sig = 0; sig < kSigCount; sig++) {
1863    SignalDesc *signal = &sctx->pending_signals[sig];
1864    if (signal->armed) {
1865      signal->armed = false;
1866      if (sigactions[sig].sa_handler != SIG_DFL
1867          && sigactions[sig].sa_handler != SIG_IGN) {
1868        // Insure that the handler does not spoil errno.
1869        const int saved_errno = errno;
1870        errno = 0;
1871        if (signal->sigaction)
1872          sigactions[sig].sa_sigaction(sig, &signal->siginfo, &signal->ctx);
1873        else
1874          sigactions[sig].sa_handler(sig);
1875        if (flags()->report_bugs && errno != 0) {
1876          ScopedInRtl in_rtl;
1877          __tsan::StackTrace stack;
1878          uptr pc = signal->sigaction ?
1879              (uptr)sigactions[sig].sa_sigaction :
1880              (uptr)sigactions[sig].sa_handler;
1881          pc += 1;  // return address is expected, OutputReport() will undo this
1882          stack.Init(&pc, 1);
1883          ThreadRegistryLock l(ctx->thread_registry);
1884          ScopedReport rep(ReportTypeErrnoInSignal);
1885          if (!IsFiredSuppression(ctx, rep, stack)) {
1886            rep.AddStack(&stack);
1887            OutputReport(ctx, rep, rep.GetReport()->stacks[0]);
1888          }
1889        }
1890        errno = saved_errno;
1891      }
1892    }
1893  }
1894  pthread_sigmask(SIG_SETMASK, &oldset, 0);
1895  CHECK_EQ(thr->in_signal_handler, true);
1896  thr->in_signal_handler = false;
1897}
1898
1899static void finalize(void *arg) {
1900  ThreadState * thr = cur_thread();
1901  uptr pc = 0;
1902  atexit_ctx->exit(thr, pc);
1903  int status = Finalize(cur_thread());
1904  REAL(fflush)(0);
1905  if (status)
1906    _exit(status);
1907}
1908
1909static void unreachable() {
1910  Printf("FATAL: ThreadSanitizer: unreachable called\n");
1911  Die();
1912}
1913
1914void InitializeInterceptors() {
1915  CHECK_GT(cur_thread()->in_rtl, 0);
1916
1917  // We need to setup it early, because functions like dlsym() can call it.
1918  REAL(memset) = internal_memset;
1919  REAL(memcpy) = internal_memcpy;
1920  REAL(memcmp) = internal_memcmp;
1921
1922  // Instruct libc malloc to consume less memory.
1923  mallopt(1, 0);  // M_MXFAST
1924  mallopt(-3, 32*1024);  // M_MMAP_THRESHOLD
1925
1926  SANITIZER_COMMON_INTERCEPTORS_INIT;
1927
1928  TSAN_INTERCEPT(setjmp);
1929  TSAN_INTERCEPT(_setjmp);
1930  TSAN_INTERCEPT(sigsetjmp);
1931  TSAN_INTERCEPT(__sigsetjmp);
1932  TSAN_INTERCEPT(longjmp);
1933  TSAN_INTERCEPT(siglongjmp);
1934
1935  TSAN_INTERCEPT(malloc);
1936  TSAN_INTERCEPT(__libc_memalign);
1937  TSAN_INTERCEPT(calloc);
1938  TSAN_INTERCEPT(realloc);
1939  TSAN_INTERCEPT(free);
1940  TSAN_INTERCEPT(cfree);
1941  TSAN_INTERCEPT(mmap);
1942  TSAN_INTERCEPT(mmap64);
1943  TSAN_INTERCEPT(munmap);
1944  TSAN_INTERCEPT(memalign);
1945  TSAN_INTERCEPT(valloc);
1946  TSAN_INTERCEPT(pvalloc);
1947  TSAN_INTERCEPT(posix_memalign);
1948
1949  TSAN_INTERCEPT(strlen);
1950  TSAN_INTERCEPT(memset);
1951  TSAN_INTERCEPT(memcpy);
1952  TSAN_INTERCEPT(memchr);
1953  TSAN_INTERCEPT(memrchr);
1954  TSAN_INTERCEPT(memmove);
1955  TSAN_INTERCEPT(memcmp);
1956  TSAN_INTERCEPT(strchr);
1957  TSAN_INTERCEPT(strchrnul);
1958  TSAN_INTERCEPT(strrchr);
1959  TSAN_INTERCEPT(strcpy);  // NOLINT
1960  TSAN_INTERCEPT(strncpy);
1961  TSAN_INTERCEPT(strstr);
1962
1963  TSAN_INTERCEPT(pthread_create);
1964  TSAN_INTERCEPT(pthread_join);
1965  TSAN_INTERCEPT(pthread_detach);
1966
1967  TSAN_INTERCEPT(pthread_mutex_init);
1968  TSAN_INTERCEPT(pthread_mutex_destroy);
1969  TSAN_INTERCEPT(pthread_mutex_lock);
1970  TSAN_INTERCEPT(pthread_mutex_trylock);
1971  TSAN_INTERCEPT(pthread_mutex_timedlock);
1972  TSAN_INTERCEPT(pthread_mutex_unlock);
1973
1974  TSAN_INTERCEPT(pthread_spin_init);
1975  TSAN_INTERCEPT(pthread_spin_destroy);
1976  TSAN_INTERCEPT(pthread_spin_lock);
1977  TSAN_INTERCEPT(pthread_spin_trylock);
1978  TSAN_INTERCEPT(pthread_spin_unlock);
1979
1980  TSAN_INTERCEPT(pthread_rwlock_init);
1981  TSAN_INTERCEPT(pthread_rwlock_destroy);
1982  TSAN_INTERCEPT(pthread_rwlock_rdlock);
1983  TSAN_INTERCEPT(pthread_rwlock_tryrdlock);
1984  TSAN_INTERCEPT(pthread_rwlock_timedrdlock);
1985  TSAN_INTERCEPT(pthread_rwlock_wrlock);
1986  TSAN_INTERCEPT(pthread_rwlock_trywrlock);
1987  TSAN_INTERCEPT(pthread_rwlock_timedwrlock);
1988  TSAN_INTERCEPT(pthread_rwlock_unlock);
1989
1990  INTERCEPT_FUNCTION_VER(pthread_cond_init, pthread_cond_init_2_3_2,
1991      GLIBC_2.3.2);
1992  INTERCEPT_FUNCTION_VER(pthread_cond_destroy, pthread_cond_destroy_2_3_2,
1993      GLIBC_2.3.2);
1994  INTERCEPT_FUNCTION_VER(pthread_cond_signal, pthread_cond_signal_2_3_2,
1995      GLIBC_2.3.2);
1996  INTERCEPT_FUNCTION_VER(pthread_cond_broadcast, pthread_cond_broadcast_2_3_2,
1997      GLIBC_2.3.2);
1998  INTERCEPT_FUNCTION_VER(pthread_cond_wait, pthread_cond_wait_2_3_2,
1999      GLIBC_2.3.2);
2000  INTERCEPT_FUNCTION_VER(pthread_cond_timedwait, pthread_cond_timedwait_2_3_2,
2001      GLIBC_2.3.2);
2002
2003  TSAN_INTERCEPT(pthread_barrier_init);
2004  TSAN_INTERCEPT(pthread_barrier_destroy);
2005  TSAN_INTERCEPT(pthread_barrier_wait);
2006
2007  TSAN_INTERCEPT(pthread_once);
2008
2009  TSAN_INTERCEPT(sem_init);
2010  TSAN_INTERCEPT(sem_destroy);
2011  TSAN_INTERCEPT(sem_wait);
2012  TSAN_INTERCEPT(sem_trywait);
2013  TSAN_INTERCEPT(sem_timedwait);
2014  TSAN_INTERCEPT(sem_post);
2015  TSAN_INTERCEPT(sem_getvalue);
2016
2017  TSAN_INTERCEPT(stat);
2018  TSAN_INTERCEPT(__xstat);
2019  TSAN_INTERCEPT(stat64);
2020  TSAN_INTERCEPT(__xstat64);
2021  TSAN_INTERCEPT(lstat);
2022  TSAN_INTERCEPT(__lxstat);
2023  TSAN_INTERCEPT(lstat64);
2024  TSAN_INTERCEPT(__lxstat64);
2025  TSAN_INTERCEPT(fstat);
2026  TSAN_INTERCEPT(__fxstat);
2027  TSAN_INTERCEPT(fstat64);
2028  TSAN_INTERCEPT(__fxstat64);
2029  TSAN_INTERCEPT(open);
2030  TSAN_INTERCEPT(open64);
2031  TSAN_INTERCEPT(creat);
2032  TSAN_INTERCEPT(creat64);
2033  TSAN_INTERCEPT(dup);
2034  TSAN_INTERCEPT(dup2);
2035  TSAN_INTERCEPT(dup3);
2036  TSAN_INTERCEPT(eventfd);
2037  TSAN_INTERCEPT(signalfd);
2038  TSAN_INTERCEPT(inotify_init);
2039  TSAN_INTERCEPT(inotify_init1);
2040  TSAN_INTERCEPT(socket);
2041  TSAN_INTERCEPT(socketpair);
2042  TSAN_INTERCEPT(connect);
2043  TSAN_INTERCEPT(bind);
2044  TSAN_INTERCEPT(listen);
2045  TSAN_INTERCEPT(epoll_create);
2046  TSAN_INTERCEPT(epoll_create1);
2047  TSAN_INTERCEPT(close);
2048  TSAN_INTERCEPT(__close);
2049  TSAN_INTERCEPT(__res_iclose);
2050  TSAN_INTERCEPT(pipe);
2051  TSAN_INTERCEPT(pipe2);
2052
2053  TSAN_INTERCEPT(send);
2054  TSAN_INTERCEPT(sendmsg);
2055  TSAN_INTERCEPT(recv);
2056
2057  TSAN_INTERCEPT(unlink);
2058  TSAN_INTERCEPT(fopen);
2059  TSAN_INTERCEPT(freopen);
2060  TSAN_INTERCEPT(fclose);
2061  TSAN_INTERCEPT(fread);
2062  TSAN_INTERCEPT(fwrite);
2063  TSAN_INTERCEPT(fflush);
2064  TSAN_INTERCEPT(abort);
2065  TSAN_INTERCEPT(puts);
2066  TSAN_INTERCEPT(rmdir);
2067  TSAN_INTERCEPT(opendir);
2068
2069  TSAN_INTERCEPT(epoll_ctl);
2070  TSAN_INTERCEPT(epoll_wait);
2071
2072  TSAN_INTERCEPT(sigaction);
2073  TSAN_INTERCEPT(signal);
2074  TSAN_INTERCEPT(sigsuspend);
2075  TSAN_INTERCEPT(raise);
2076  TSAN_INTERCEPT(kill);
2077  TSAN_INTERCEPT(pthread_kill);
2078  TSAN_INTERCEPT(sleep);
2079  TSAN_INTERCEPT(usleep);
2080  TSAN_INTERCEPT(nanosleep);
2081  TSAN_INTERCEPT(gettimeofday);
2082  TSAN_INTERCEPT(getaddrinfo);
2083
2084  TSAN_INTERCEPT(mlock);
2085  TSAN_INTERCEPT(munlock);
2086  TSAN_INTERCEPT(mlockall);
2087  TSAN_INTERCEPT(munlockall);
2088
2089  TSAN_INTERCEPT(fork);
2090  TSAN_INTERCEPT(on_exit);
2091  TSAN_INTERCEPT(__cxa_atexit);
2092
2093  // Need to setup it, because interceptors check that the function is resolved.
2094  // But atexit is emitted directly into the module, so can't be resolved.
2095  REAL(atexit) = (int(*)(void(*)()))unreachable;
2096  atexit_ctx = new(internal_alloc(MBlockAtExit, sizeof(AtExitContext)))
2097      AtExitContext();
2098
2099  if (REAL(__cxa_atexit)(&finalize, 0, 0)) {
2100    Printf("ThreadSanitizer: failed to setup atexit callback\n");
2101    Die();
2102  }
2103
2104  if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
2105    Printf("ThreadSanitizer: failed to create thread key\n");
2106    Die();
2107  }
2108
2109  FdInit();
2110}
2111
2112void internal_start_thread(void(*func)(void *arg), void *arg) {
2113  void *th;
2114  REAL(pthread_create)(&th, 0, (void*(*)(void *arg))func, arg);
2115  REAL(pthread_detach)(th);
2116}
2117
2118}  // namespace __tsan
2119