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