14f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov//===-- tsan_interceptors.cc ----------------------------------------------===// 27ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 37ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// The LLVM Compiler Infrastructure 47ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 57ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is distributed under the University of Illinois Open Source 67ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// License. See LICENSE.TXT for details. 77ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 87ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===// 97ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is a part of ThreadSanitizer (TSan), a race detector. 117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 128530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany// FIXME: move as many interceptors as possible into 13edd2821982c058469dca631a3147fdd42045c48aDmitry Vyukov// sanitizer_common/sanitizer_common_interceptors.inc 147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===// 157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 16fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov#include "sanitizer_common/sanitizer_atomic.h" 17230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov#include "sanitizer_common/sanitizer_libc.h" 18b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov#include "sanitizer_common/sanitizer_linux.h" 1947a0f6edc48eb6dc46b2e1f203d6783fd7e07505Alexey Samsonov#include "sanitizer_common/sanitizer_platform_limits_posix.h" 2047b1634df012507799eb39aa17d4022d748ba67bAlexey Samsonov#include "sanitizer_common/sanitizer_placement_new.h" 217eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov#include "sanitizer_common/sanitizer_stacktrace.h" 2236decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov#include "interception/interception.h" 237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_interface.h" 247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_platform.h" 254af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov#include "tsan_suppressions.h" 264f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov#include "tsan_rtl.h" 277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_mman.h" 28c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov#include "tsan_fd.h" 297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyusing namespace __tsan; // NOLINT 317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 326d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if SANITIZER_FREEBSD 336d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define __errno_location __error 346d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define __libc_malloc __malloc 356d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define __libc_realloc __realloc 366d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define __libc_calloc __calloc 376d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define __libc_free __free 386d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define stdout __stdoutp 396d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define stderr __stderrp 406d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 416d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 4286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifdef __mips__ 4386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesconst int kSigCount = 129; 4486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#else 452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesconst int kSigCount = 65; 4686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif 47e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov 48e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukovstruct my_siginfo_t { 494219ea38d733f73c96c8740777ee0bb7061cbe0fDmitry Vyukov // The size is determined by looking at sizeof of real siginfo_t on linux. 50236a098869e35b29e938cbb7bd98d8d5b656d47fDmitry Vyukov u64 opaque[128 / sizeof(u64)]; 51e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov}; 52e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov 5386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifdef __mips__ 5486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstruct ucontext_t { 5586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u64 opaque[768 / sizeof(u64) + 1]; 5686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}; 5786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#else 587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystruct ucontext_t { 594219ea38d733f73c96c8740777ee0bb7061cbe0fDmitry Vyukov // The size is determined by looking at sizeof of real ucontext_t on linux. 60236a098869e35b29e938cbb7bd98d8d5b656d47fDmitry Vyukov u64 opaque[936 / sizeof(u64) + 1]; 617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}; 6286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif 637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_attr_init(void *attr); 657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_attr_destroy(void *attr); 66e236dbb5e558b174609d2d13e80685d488c129d8Evgeniy StepanovDECLARE_REAL(int, pthread_attr_getdetachstate, void *, void *) 677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize); 687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_key_create(unsigned *key, void (*destructor)(void* v)); 697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_setspecific(unsigned key, const void *v); 706a211c5814e25d6745a5058cc0e499e5235d3821Stephen HinesDECLARE_REAL(int, pthread_mutexattr_gettype, void *, void *) 717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int pthread_yield(); 729a949a8909f652b28e9084de785c848743139fd5Evgeniy Stepanovextern "C" int pthread_sigmask(int how, const __sanitizer_sigset_t *set, 739a949a8909f652b28e9084de785c848743139fd5Evgeniy Stepanov __sanitizer_sigset_t *oldset); 749a949a8909f652b28e9084de785c848743139fd5Evgeniy Stepanov// REAL(sigfillset) defined in common interceptors. 759a949a8909f652b28e9084de785c848743139fd5Evgeniy StepanovDECLARE_REAL(int, sigfillset, __sanitizer_sigset_t *set) 762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesDECLARE_REAL(int, fflush, __sanitizer_FILE *fp) 777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void *pthread_self(); 787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void _exit(int status); 797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" int *__errno_location(); 80f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukovextern "C" int fileno_unlocked(void *stream); 8131c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukovextern "C" void *__libc_malloc(uptr size); 8231c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukovextern "C" void *__libc_calloc(uptr size, uptr n); 8331c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukovextern "C" void *__libc_realloc(void *ptr, uptr size); 8431c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukovextern "C" void __libc_free(void *ptr); 8586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesextern "C" int dirfd(void *dirp); 866d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 878e1c769ed84f4d5cf23904dee1abeec6f125f1acDmitry Vyukovextern "C" int mallopt(int param, int value); 886d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesextern __sanitizer_FILE *stdout, *stderr; 907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int PTHREAD_MUTEX_RECURSIVE = 1; 917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int PTHREAD_MUTEX_RECURSIVE_NP = 1; 927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int EINVAL = 22; 937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int EBUSY = 16; 9411f5309ec1bf13430c8a3a16f177d9e8e1190e38Dmitry Vyukovconst int EOWNERDEAD = 130; 957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int EPOLL_CTL_ADD = 1; 96d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst int SIGILL = 4; 97d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst int SIGABRT = 6; 98d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst int SIGFPE = 8; 99d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst int SIGSEGV = 11; 100d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst int SIGPIPE = 13; 1012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesconst int SIGTERM = 15; 10286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifdef __mips__ 10386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesconst int SIGBUS = 10; 10486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesconst int SIGSYS = 12; 10586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#else 106d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst int SIGBUS = 7; 107158ca5237af46076225d5d82a38ae0f733f57f31Dmitry Vyukovconst int SIGSYS = 31; 10886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif 1097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid *const MAP_FAILED = (void*)-1; 1107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int PTHREAD_BARRIER_SERIAL_THREAD = -1; 1117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int MAP_FIXED = 0x10; 1127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanytypedef long long_t; // NOLINT 1137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1140ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko// From /usr/include/unistd.h 1150ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko# define F_ULOCK 0 /* Unlock a previously locked region. */ 1160ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko# define F_LOCK 1 /* Lock a region for exclusive use. */ 1170ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko# define F_TLOCK 2 /* Test and lock a region for exclusive use. */ 1180ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko# define F_TEST 3 /* Test a region for other processes locks. */ 1190ce948e0887e2c23c6510c32a639da9730bbce25Alexander Potapenko 1207a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov#define errno (*__errno_location()) 1217a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov 12286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinestypedef void (*sighandler_t)(int sig); 12386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinestypedef void (*sigactionhandler_t)(int sig, my_siginfo_t *siginfo, void *uctx); 12486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 1257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystruct sigaction_t { 12686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifdef __mips__ 12786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u32 sa_flags; 12886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif 1297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany union { 1307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany sighandler_t sa_handler; 13186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines sigactionhandler_t sa_sigaction; 1327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany }; 1336d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if SANITIZER_FREEBSD 1346d1862363c88c183b0ed7740fca876342cf0474bStephen Hines int sa_flags; 1356d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __sanitizer_sigset_t sa_mask; 1366d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 1379a949a8909f652b28e9084de785c848743139fd5Evgeniy Stepanov __sanitizer_sigset_t sa_mask; 13886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef __mips__ 1397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int sa_flags; 14086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif 1417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void (*sa_restorer)(); 1426d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 1437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}; 1447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst sighandler_t SIG_DFL = (sighandler_t)0; 1467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst sighandler_t SIG_IGN = (sighandler_t)1; 147d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovconst sighandler_t SIG_ERR = (sighandler_t)-1; 1487c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#if SANITIZER_FREEBSD 1497c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarconst int SA_SIGINFO = 0x40; 1507c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarconst int SIG_SETMASK = 3; 1517c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#elif defined(__mips__) 15286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesconst int SA_SIGINFO = 8; 15386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesconst int SIG_SETMASK = 3; 15486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#else 1557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int SA_SIGINFO = 4; 1567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst int SIG_SETMASK = 2; 15786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif 1587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 159909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED \ 160909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar (!cur_thread()->is_inited) 161909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar 1627eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovnamespace std { 1637eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovstruct nothrow_t {}; 1647eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov} // namespace std 1657eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov 1667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic sigaction_t sigactions[kSigCount]; 1677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 168e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukovnamespace __tsan { 169e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukovstruct SignalDesc { 170e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov bool armed; 171e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov bool sigaction; 172e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov my_siginfo_t siginfo; 173e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov ucontext_t ctx; 174e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov}; 175e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov 1767c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarstruct ThreadSignalContext { 177e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov int int_signal_send; 1786d1862363c88c183b0ed7740fca876342cf0474bStephen Hines atomic_uintptr_t in_blocking_func; 1796d1862363c88c183b0ed7740fca876342cf0474bStephen Hines atomic_uintptr_t have_pending_signals; 180e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov SignalDesc pending_signals[kSigCount]; 181e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov}; 182d18865339cebcdaa9fc720a1e960cb452f330835Dmitry Vyukov 1834af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov// The object is 64-byte aligned, because we want hot data to be located in 1844af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov// a single cache line if possible (it's accessed in every interceptor). 1854af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukovstatic ALIGNED(64) char libignore_placeholder[sizeof(LibIgnore)]; 1864af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukovstatic LibIgnore *libignore() { 1874af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov return reinterpret_cast<LibIgnore*>(&libignore_placeholder[0]); 1884af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov} 189d18865339cebcdaa9fc720a1e960cb452f330835Dmitry Vyukov 1904af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukovvoid InitializeLibIgnore() { 19186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines const SuppressionContext &supp = *Suppressions(); 19286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines const uptr n = supp.SuppressionCount(); 19386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines for (uptr i = 0; i < n; i++) { 19486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines const Suppression *s = supp.SuppressionAt(i); 19586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (0 == internal_strcmp(s->type, kSuppressionLib)) 19686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines libignore()->AddIgnoredLibrary(s->templ); 19786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 1983dbbd850cde5728c35aa4c15a279d858604fc6eeDmitry Vyukov libignore()->OnLibraryLoaded(0); 199d18865339cebcdaa9fc720a1e960cb452f330835Dmitry Vyukov} 200d18865339cebcdaa9fc720a1e960cb452f330835Dmitry Vyukov 201ba5e99668e3030cc5bab357a04271a1bdbac209cAlexey Samsonov} // namespace __tsan 202e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov 2037c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarstatic ThreadSignalContext *SigCtx(ThreadState *thr) { 2047c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ThreadSignalContext *ctx = (ThreadSignalContext*)thr->signal_ctx; 2056d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (ctx == 0 && !thr->is_dead) { 2067c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ctx = (ThreadSignalContext*)MmapOrDie(sizeof(*ctx), "ThreadSignalContext"); 207c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov MemoryResetRange(thr, (uptr)&SigCtx, (uptr)ctx, sizeof(*ctx)); 208e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov thr->signal_ctx = ctx; 209e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov } 210e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov return ctx; 211e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov} 212e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov 2137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic unsigned g_thread_finalize_key; 2147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 21536decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukovclass ScopedInterceptor { 21636decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov public: 21736decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc); 21836decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov ~ScopedInterceptor(); 21936decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov private: 22036decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov ThreadState *const thr_; 2212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines const uptr pc_; 2224af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov bool in_ignored_lib_; 22336decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov}; 22436decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov 2254f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey SamsonovScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname, 2264f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov uptr pc) 2274f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov : thr_(thr) 2282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines , pc_(pc) 2294af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov , in_ignored_lib_(false) { 2302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (!thr_->ignore_interceptors) { 2314f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov Initialize(thr); 2324f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov FuncEntry(thr, pc); 2337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines DPrintf("#%d: intercept %s()\n", thr_->tid, fname); 2354af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov if (!thr_->in_ignored_lib && libignore()->IsIgnored(pc)) { 2364af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov in_ignored_lib_ = true; 2374af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov thr_->in_ignored_lib = true; 2382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ThreadIgnoreBegin(thr_, pc_); 2394af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov } 24005906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov} 24105906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov 2424f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey SamsonovScopedInterceptor::~ScopedInterceptor() { 2434af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov if (in_ignored_lib_) { 2444af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov thr_->in_ignored_lib = false; 2452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ThreadIgnoreEnd(thr_, pc_); 2464af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov } 2472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (!thr_->ignore_interceptors) { 248ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov ProcessPendingSignals(thr_); 2492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines FuncExit(thr_); 2506a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines CheckNoLocks(thr_); 2514f0ea398bdc99a4a32402057c23bbcc6d19a8eb4Alexey Samsonov } 25205906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov} 25305906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov 25436decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov#define SCOPED_INTERCEPTOR_RAW(func, ...) \ 25536decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov ThreadState *thr = cur_thread(); \ 25636decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov const uptr caller_pc = GET_CALLER_PC(); \ 25736decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov ScopedInterceptor si(thr, #func, caller_pc); \ 2586d1862363c88c183b0ed7740fca876342cf0474bStephen Hines const uptr pc = StackTrace::GetCurrentPc(); \ 25936decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov (void)pc; \ 26036decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov/**/ 26136decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov 26236decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov#define SCOPED_TSAN_INTERCEPTOR(func, ...) \ 26336decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \ 26436decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov if (REAL(func) == 0) { \ 2652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Report("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \ 26636decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov Die(); \ 2672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } \ 2682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (thr->ignore_interceptors || thr->in_ignored_lib) \ 26936decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov return REAL(func)(__VA_ARGS__); \ 27036decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov/**/ 27136decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov 27236decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov#define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__) 27336decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func) 2746d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if SANITIZER_FREEBSD 2756d1862363c88c183b0ed7740fca876342cf0474bStephen Hines# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION(func) 2766d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 2776d1862363c88c183b0ed7740fca876342cf0474bStephen Hines# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION_VER(func, ver) 2786d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 27936decbf426ea75eef9ce6f6f43b74a66e66795d3Dmitry Vyukov 280909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar#define READ_STRING_OF_LEN(thr, pc, s, len, n) \ 281909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar MemoryAccessRange((thr), (pc), (uptr)(s), \ 282909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar common_flags()->strict_string_checks ? (len) + 1 : (n), false) 283909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar 284909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar#define READ_STRING(thr, pc, s, n) \ 285909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar READ_STRING_OF_LEN((thr), (pc), (s), internal_strlen(s), (n)) 286909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar 287ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov#define BLOCK_REAL(name) (BlockingCall(thr), REAL(name)) 288ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov 289ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukovstruct BlockingCall { 290b717f4d415cafbb8526bb33f737b9c07409a73bbAlexey Samsonov explicit BlockingCall(ThreadState *thr) 2916d1862363c88c183b0ed7740fca876342cf0474bStephen Hines : thr(thr) 2926d1862363c88c183b0ed7740fca876342cf0474bStephen Hines , ctx(SigCtx(thr)) { 2936d1862363c88c183b0ed7740fca876342cf0474bStephen Hines for (;;) { 2946d1862363c88c183b0ed7740fca876342cf0474bStephen Hines atomic_store(&ctx->in_blocking_func, 1, memory_order_relaxed); 2956d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (atomic_load(&ctx->have_pending_signals, memory_order_relaxed) == 0) 2966d1862363c88c183b0ed7740fca876342cf0474bStephen Hines break; 2976d1862363c88c183b0ed7740fca876342cf0474bStephen Hines atomic_store(&ctx->in_blocking_func, 0, memory_order_relaxed); 2986d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ProcessPendingSignals(thr); 2996d1862363c88c183b0ed7740fca876342cf0474bStephen Hines } 3006d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // When we are in a "blocking call", we process signals asynchronously 3016d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // (right when they arrive). In this context we do not expect to be 3026d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // executing any user/runtime code. The known interceptor sequence when 3036d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // this is not true is: pthread_join -> munmap(stack). It's fine 3046d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // to ignore munmap in this case -- we handle stack shadow separately. 3056d1862363c88c183b0ed7740fca876342cf0474bStephen Hines thr->ignore_interceptors++; 306ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov } 307ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov 308ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov ~BlockingCall() { 3096d1862363c88c183b0ed7740fca876342cf0474bStephen Hines thr->ignore_interceptors--; 3106d1862363c88c183b0ed7740fca876342cf0474bStephen Hines atomic_store(&ctx->in_blocking_func, 0, memory_order_relaxed); 311ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov } 312ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov 3136d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ThreadState *thr; 3147c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ThreadSignalContext *ctx; 315ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov}; 316ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov 317848531192777acecf79747dc7c1ffeedf5c1da9fDmitry VyukovTSAN_INTERCEPTOR(unsigned, sleep, unsigned sec) { 318848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov SCOPED_TSAN_INTERCEPTOR(sleep, sec); 319ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov unsigned res = BLOCK_REAL(sleep)(sec); 320848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov AfterSleep(thr, pc); 321848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov return res; 322848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov} 323848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov 324848531192777acecf79747dc7c1ffeedf5c1da9fDmitry VyukovTSAN_INTERCEPTOR(int, usleep, long_t usec) { 325848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov SCOPED_TSAN_INTERCEPTOR(usleep, usec); 326ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov int res = BLOCK_REAL(usleep)(usec); 327848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov AfterSleep(thr, pc); 328848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov return res; 329848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov} 330848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov 331848531192777acecf79747dc7c1ffeedf5c1da9fDmitry VyukovTSAN_INTERCEPTOR(int, nanosleep, void *req, void *rem) { 332848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov SCOPED_TSAN_INTERCEPTOR(nanosleep, req, rem); 333ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov int res = BLOCK_REAL(nanosleep)(req, rem); 334848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov AfterSleep(thr, pc); 335848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov return res; 336848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov} 337848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov 3386d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// The sole reason tsan wraps atexit callbacks is to establish synchronization 3396d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// between callback setup and callback execution. 3406d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesstruct AtExitCtx { 3416d1862363c88c183b0ed7740fca876342cf0474bStephen Hines void (*f)(); 3426d1862363c88c183b0ed7740fca876342cf0474bStephen Hines void *arg; 3437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}; 3447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3456d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesstatic void at_exit_wrapper(void *arg) { 3466d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ThreadState *thr = cur_thread(); 3476d1862363c88c183b0ed7740fca876342cf0474bStephen Hines uptr pc = 0; 3486d1862363c88c183b0ed7740fca876342cf0474bStephen Hines Acquire(thr, pc, (uptr)arg); 3496d1862363c88c183b0ed7740fca876342cf0474bStephen Hines AtExitCtx *ctx = (AtExitCtx*)arg; 3506d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ((void(*)(void *arg))ctx->f)(ctx->arg); 3516d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __libc_free(ctx); 3526d1862363c88c183b0ed7740fca876342cf0474bStephen Hines} 3536d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 3546d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesstatic int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(), 3556d1862363c88c183b0ed7740fca876342cf0474bStephen Hines void *arg, void *dso); 3567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 3577ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, atexit, void (*f)()) { 35831c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov if (cur_thread()->in_symbolizer) 35931c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov return 0; 3602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // We want to setup the atexit callback even if we are in ignored lib 3612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // or after fork. 3622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines SCOPED_INTERCEPTOR_RAW(atexit, f); 3636d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return setup_at_exit_wrapper(thr, pc, (void(*)())f, 0, 0); 36431c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov} 36531c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov 3666d1862363c88c183b0ed7740fca876342cf0474bStephen HinesTSAN_INTERCEPTOR(int, __cxa_atexit, void (*f)(void *a), void *arg, void *dso) { 36731c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov if (cur_thread()->in_symbolizer) 36831c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov return 0; 3696d1862363c88c183b0ed7740fca876342cf0474bStephen Hines SCOPED_TSAN_INTERCEPTOR(__cxa_atexit, f, arg, dso); 3706d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return setup_at_exit_wrapper(thr, pc, (void(*)())f, arg, dso); 37131c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov} 37231c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov 3736d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesstatic int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(), 3746d1862363c88c183b0ed7740fca876342cf0474bStephen Hines void *arg, void *dso) { 3756d1862363c88c183b0ed7740fca876342cf0474bStephen Hines AtExitCtx *ctx = (AtExitCtx*)__libc_malloc(sizeof(AtExitCtx)); 3766d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ctx->f = f; 3776d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ctx->arg = arg; 3786d1862363c88c183b0ed7740fca876342cf0474bStephen Hines Release(thr, pc, (uptr)ctx); 3796d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // Memory allocation in __cxa_atexit will race with free during exit, 3806d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // because we do not see synchronization around atexit callback list. 3816d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ThreadIgnoreBegin(thr, pc); 3826d1862363c88c183b0ed7740fca876342cf0474bStephen Hines int res = REAL(__cxa_atexit)(at_exit_wrapper, ctx, dso); 3836d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ThreadIgnoreEnd(thr, pc); 3846d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return res; 3856d1862363c88c183b0ed7740fca876342cf0474bStephen Hines} 3866d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 3876d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesstatic void on_exit_wrapper(int status, void *arg) { 3886d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ThreadState *thr = cur_thread(); 3896d1862363c88c183b0ed7740fca876342cf0474bStephen Hines uptr pc = 0; 3906d1862363c88c183b0ed7740fca876342cf0474bStephen Hines Acquire(thr, pc, (uptr)arg); 3916d1862363c88c183b0ed7740fca876342cf0474bStephen Hines AtExitCtx *ctx = (AtExitCtx*)arg; 3926d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ((void(*)(int status, void *arg))ctx->f)(status, ctx->arg); 3936d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __libc_free(ctx); 3946d1862363c88c183b0ed7740fca876342cf0474bStephen Hines} 3956d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 3966d1862363c88c183b0ed7740fca876342cf0474bStephen HinesTSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) { 39731c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov if (cur_thread()->in_symbolizer) 39831c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov return 0; 3996d1862363c88c183b0ed7740fca876342cf0474bStephen Hines SCOPED_TSAN_INTERCEPTOR(on_exit, f, arg); 4006d1862363c88c183b0ed7740fca876342cf0474bStephen Hines AtExitCtx *ctx = (AtExitCtx*)__libc_malloc(sizeof(AtExitCtx)); 4016d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ctx->f = (void(*)())f; 4026d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ctx->arg = arg; 4036d1862363c88c183b0ed7740fca876342cf0474bStephen Hines Release(thr, pc, (uptr)ctx); 4046d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // Memory allocation in __cxa_atexit will race with free during exit, 4056d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // because we do not see synchronization around atexit callback list. 4066d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ThreadIgnoreBegin(thr, pc); 4076d1862363c88c183b0ed7740fca876342cf0474bStephen Hines int res = REAL(on_exit)(on_exit_wrapper, ctx); 4086d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ThreadIgnoreEnd(thr, pc); 4096d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return res; 4107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 4117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 4128b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov// Cleanup old bufs. 4138b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukovstatic void JmpBufGarbageCollect(ThreadState *thr, uptr sp) { 4148b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov for (uptr i = 0; i < thr->jmp_bufs.Size(); i++) { 4158b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov JmpBuf *buf = &thr->jmp_bufs[i]; 4168b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov if (buf->sp <= sp) { 4178b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov uptr sz = thr->jmp_bufs.Size(); 4188b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov thr->jmp_bufs[i] = thr->jmp_bufs[sz - 1]; 4198b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov thr->jmp_bufs.PopBack(); 4208b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov i--; 4218b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov } 4228b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov } 423f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov} 424f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov 4258b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukovstatic void SetJmp(ThreadState *thr, uptr sp, uptr mangled_sp) { 4267c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar if (!thr->is_inited) // called from libc guts during bootstrap 4278b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov return; 4288b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov // Cleanup old bufs. 4298b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov JmpBufGarbageCollect(thr, sp); 4308b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov // Remember the buf. 4318b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov JmpBuf *buf = thr->jmp_bufs.PushBack(); 4328b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov buf->sp = sp; 4338b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov buf->mangled_sp = mangled_sp; 4348b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov buf->shadow_stack_pos = thr->shadow_stack_pos; 4357c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ThreadSignalContext *sctx = SigCtx(thr); 4366d1862363c88c183b0ed7740fca876342cf0474bStephen Hines buf->int_signal_send = sctx ? sctx->int_signal_send : 0; 4376d1862363c88c183b0ed7740fca876342cf0474bStephen Hines buf->in_blocking_func = sctx ? 4386d1862363c88c183b0ed7740fca876342cf0474bStephen Hines atomic_load(&sctx->in_blocking_func, memory_order_relaxed) : 4396d1862363c88c183b0ed7740fca876342cf0474bStephen Hines false; 4406d1862363c88c183b0ed7740fca876342cf0474bStephen Hines buf->in_signal_handler = atomic_load(&thr->in_signal_handler, 4416d1862363c88c183b0ed7740fca876342cf0474bStephen Hines memory_order_relaxed); 4428b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov} 4438b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov 4448b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukovstatic void LongJmp(ThreadState *thr, uptr *env) { 4456d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if SANITIZER_FREEBSD 4466d1862363c88c183b0ed7740fca876342cf0474bStephen Hines uptr mangled_sp = env[2]; 4476d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 4488b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov uptr mangled_sp = env[6]; 4496d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif // SANITIZER_FREEBSD 4508b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov // Find the saved buf by mangled_sp. 4518b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov for (uptr i = 0; i < thr->jmp_bufs.Size(); i++) { 4528b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov JmpBuf *buf = &thr->jmp_bufs[i]; 4538b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov if (buf->mangled_sp == mangled_sp) { 4548b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov CHECK_GE(thr->shadow_stack_pos, buf->shadow_stack_pos); 4558b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov // Unwind the stack. 4568b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov while (thr->shadow_stack_pos > buf->shadow_stack_pos) 4578b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov FuncExit(thr); 4587c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ThreadSignalContext *sctx = SigCtx(thr); 4596d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (sctx) { 4606d1862363c88c183b0ed7740fca876342cf0474bStephen Hines sctx->int_signal_send = buf->int_signal_send; 4616d1862363c88c183b0ed7740fca876342cf0474bStephen Hines atomic_store(&sctx->in_blocking_func, buf->in_blocking_func, 4626d1862363c88c183b0ed7740fca876342cf0474bStephen Hines memory_order_relaxed); 4636d1862363c88c183b0ed7740fca876342cf0474bStephen Hines } 4646d1862363c88c183b0ed7740fca876342cf0474bStephen Hines atomic_store(&thr->in_signal_handler, buf->in_signal_handler, 4656d1862363c88c183b0ed7740fca876342cf0474bStephen Hines memory_order_relaxed); 4668b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov JmpBufGarbageCollect(thr, buf->sp - 1); // do not collect buf->sp 4678b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov return; 4688b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov } 4698b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov } 4708b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov Printf("ThreadSanitizer: can't find longjmp buf\n"); 4718b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov CHECK(0); 4728b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov} 4738b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov 474f109267c5320210e69c1b66add801fd5f2e2a452Timur Iskhodzhanov// FIXME: put everything below into a common extern "C" block? 4758b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukovextern "C" void __tsan_setjmp(uptr sp, uptr mangled_sp) { 4768b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov SetJmp(cur_thread(), sp, mangled_sp); 4778b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov} 4788b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov 4798b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov// Not called. Merely to satisfy TSAN_INTERCEPT(). 480f109267c5320210e69c1b66add801fd5f2e2a452Timur Iskhodzhanovextern "C" SANITIZER_INTERFACE_ATTRIBUTE 481f109267c5320210e69c1b66add801fd5f2e2a452Timur Iskhodzhanovint __interceptor_setjmp(void *env); 4828b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukovextern "C" int __interceptor_setjmp(void *env) { 4838b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov CHECK(0); 4848b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov return 0; 4858b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov} 4868b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov 487f109267c5320210e69c1b66add801fd5f2e2a452Timur Iskhodzhanov// FIXME: any reason to have a separate declaration? 488f109267c5320210e69c1b66add801fd5f2e2a452Timur Iskhodzhanovextern "C" SANITIZER_INTERFACE_ATTRIBUTE 489f109267c5320210e69c1b66add801fd5f2e2a452Timur Iskhodzhanovint __interceptor__setjmp(void *env); 4908b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukovextern "C" int __interceptor__setjmp(void *env) { 4918b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov CHECK(0); 4928b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov return 0; 4938b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov} 4948b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov 495f109267c5320210e69c1b66add801fd5f2e2a452Timur Iskhodzhanovextern "C" SANITIZER_INTERFACE_ATTRIBUTE 496f109267c5320210e69c1b66add801fd5f2e2a452Timur Iskhodzhanovint __interceptor_sigsetjmp(void *env); 4978b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukovextern "C" int __interceptor_sigsetjmp(void *env) { 4988b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov CHECK(0); 4998b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov return 0; 5008b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov} 5018b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov 502f109267c5320210e69c1b66add801fd5f2e2a452Timur Iskhodzhanovextern "C" SANITIZER_INTERFACE_ATTRIBUTE 503f109267c5320210e69c1b66add801fd5f2e2a452Timur Iskhodzhanovint __interceptor___sigsetjmp(void *env); 5048b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukovextern "C" int __interceptor___sigsetjmp(void *env) { 5058b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov CHECK(0); 5068b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov return 0; 5078b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov} 5088b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov 5098b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukovextern "C" int setjmp(void *env); 5108b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukovextern "C" int _setjmp(void *env); 5118b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukovextern "C" int sigsetjmp(void *env); 5128b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukovextern "C" int __sigsetjmp(void *env); 5138b30c254a63a7421dd81d13dee086a54c4ca134bDmitry VyukovDEFINE_REAL(int, setjmp, void *env) 5148b30c254a63a7421dd81d13dee086a54c4ca134bDmitry VyukovDEFINE_REAL(int, _setjmp, void *env) 5158b30c254a63a7421dd81d13dee086a54c4ca134bDmitry VyukovDEFINE_REAL(int, sigsetjmp, void *env) 5168b30c254a63a7421dd81d13dee086a54c4ca134bDmitry VyukovDEFINE_REAL(int, __sigsetjmp, void *env) 5178b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov 5188b30c254a63a7421dd81d13dee086a54c4ca134bDmitry VyukovTSAN_INTERCEPTOR(void, longjmp, uptr *env, int val) { 5198b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov { 5208b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov SCOPED_TSAN_INTERCEPTOR(longjmp, env, val); 5218b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov } 5228b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov LongJmp(cur_thread(), env); 5238b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov REAL(longjmp)(env, val); 5248b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov} 5258b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov 5268b30c254a63a7421dd81d13dee086a54c4ca134bDmitry VyukovTSAN_INTERCEPTOR(void, siglongjmp, uptr *env, int val) { 5278b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov { 5288b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov SCOPED_TSAN_INTERCEPTOR(siglongjmp, env, val); 5298b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov } 5308b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov LongJmp(cur_thread(), env); 5318b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov REAL(siglongjmp)(env, val); 532f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov} 533f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov 5347ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, malloc, uptr size) { 5354af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov if (cur_thread()->in_symbolizer) 53631c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov return __libc_malloc(size); 53705906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov void *p = 0; 53805906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov { 53905906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov SCOPED_INTERCEPTOR_RAW(malloc, size); 54005906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov p = user_alloc(thr, pc, size); 54105906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov } 54205906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov invoke_malloc_hook(p, size); 54305906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov return p; 5447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 54607ba8ef44deb54baa9307298fbffe25ddb30c362Dmitry VyukovTSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) { 54707ba8ef44deb54baa9307298fbffe25ddb30c362Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(__libc_memalign, align, sz); 548543b94a5cd102c0795b44d78234d5458eed2c75eDmitry Vyukov return user_alloc(thr, pc, sz, align); 54907ba8ef44deb54baa9307298fbffe25ddb30c362Dmitry Vyukov} 55007ba8ef44deb54baa9307298fbffe25ddb30c362Dmitry Vyukov 5517ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) { 5524af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov if (cur_thread()->in_symbolizer) 55331c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov return __libc_calloc(size, n); 55405906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov void *p = 0; 55505906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov { 55605906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov SCOPED_INTERCEPTOR_RAW(calloc, size, n); 55786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines p = user_calloc(thr, pc, size, n); 55805906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov } 55905906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov invoke_malloc_hook(p, n * size); 5607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return p; 5617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5637ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) { 5644af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov if (cur_thread()->in_symbolizer) 56531c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov return __libc_realloc(p, size); 56605906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov if (p) 56705906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov invoke_free_hook(p); 56805906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov { 56905906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov SCOPED_INTERCEPTOR_RAW(realloc, p, size); 57005906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov p = user_realloc(thr, pc, p, size); 57105906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov } 57205906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov invoke_malloc_hook(p, size); 57305906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov return p; 5747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5767ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void, free, void *p) { 5777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (p == 0) 5787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 5794af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov if (cur_thread()->in_symbolizer) 58031c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov return __libc_free(p); 58105906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov invoke_free_hook(p); 5827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_INTERCEPTOR_RAW(free, p); 5837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany user_free(thr, pc, p); 5847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5867ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void, cfree, void *p) { 5877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (p == 0) 5887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 5894af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov if (cur_thread()->in_symbolizer) 59031c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov return __libc_free(p); 59105906a7a12865b0fb0f5f6d607848cf7b5a1e5e0Dmitry Vyukov invoke_free_hook(p); 5927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_INTERCEPTOR_RAW(cfree, p); 5937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany user_free(thr, pc, p); 5947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 5957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 5968a6b5e551ab8a331f7e7bc4bfcd74926fbffa3f6Alexey SamsonovTSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) { 5978a6b5e551ab8a331f7e7bc4bfcd74926fbffa3f6Alexey Samsonov SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p); 5986a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines return user_alloc_usable_size(p); 5998a6b5e551ab8a331f7e7bc4bfcd74926fbffa3f6Alexey Samsonov} 6008a6b5e551ab8a331f7e7bc4bfcd74926fbffa3f6Alexey Samsonov 6017eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov#define OPERATOR_NEW_BODY(mangled_name) \ 6024af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov if (cur_thread()->in_symbolizer) \ 60331c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov return __libc_malloc(size); \ 6047eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov void *p = 0; \ 6057eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov { \ 6067eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov SCOPED_INTERCEPTOR_RAW(mangled_name, size); \ 6077eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov p = user_alloc(thr, pc, size); \ 6087eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov } \ 6097eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov invoke_malloc_hook(p, size); \ 6107eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov return p; 6117eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov 6123c80c6c574850106481f82b9e23d1c728458d4a9Timur IskhodzhanovSANITIZER_INTERFACE_ATTRIBUTE 6133c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanovvoid *operator new(__sanitizer::uptr size); 6147eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid *operator new(__sanitizer::uptr size) { 6157eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov OPERATOR_NEW_BODY(_Znwm); 6167eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov} 6171dcabd115668f9efba615f7c4e190244a4df361fDmitry Vyukov 6183c80c6c574850106481f82b9e23d1c728458d4a9Timur IskhodzhanovSANITIZER_INTERFACE_ATTRIBUTE 6193c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanovvoid *operator new[](__sanitizer::uptr size); 6207eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid *operator new[](__sanitizer::uptr size) { 6217eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov OPERATOR_NEW_BODY(_Znam); 6227eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov} 6231dcabd115668f9efba615f7c4e190244a4df361fDmitry Vyukov 6243c80c6c574850106481f82b9e23d1c728458d4a9Timur IskhodzhanovSANITIZER_INTERFACE_ATTRIBUTE 6253c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanovvoid *operator new(__sanitizer::uptr size, std::nothrow_t const&); 6267eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid *operator new(__sanitizer::uptr size, std::nothrow_t const&) { 6277eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov OPERATOR_NEW_BODY(_ZnwmRKSt9nothrow_t); 6287eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov} 6291dcabd115668f9efba615f7c4e190244a4df361fDmitry Vyukov 6303c80c6c574850106481f82b9e23d1c728458d4a9Timur IskhodzhanovSANITIZER_INTERFACE_ATTRIBUTE 6313c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanovvoid *operator new[](__sanitizer::uptr size, std::nothrow_t const&); 6327eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid *operator new[](__sanitizer::uptr size, std::nothrow_t const&) { 6337eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov OPERATOR_NEW_BODY(_ZnamRKSt9nothrow_t); 6347eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov} 6357eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov 6367eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov#define OPERATOR_DELETE_BODY(mangled_name) \ 6377eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov if (ptr == 0) return; \ 6384af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov if (cur_thread()->in_symbolizer) \ 63931c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov return __libc_free(ptr); \ 6407eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov invoke_free_hook(ptr); \ 6417eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov SCOPED_INTERCEPTOR_RAW(mangled_name, ptr); \ 6427eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov user_free(thr, pc, ptr); 6437eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov 6443c80c6c574850106481f82b9e23d1c728458d4a9Timur IskhodzhanovSANITIZER_INTERFACE_ATTRIBUTE 6452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid operator delete(void *ptr) throw(); 6462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid operator delete(void *ptr) throw() { 6477eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov OPERATOR_DELETE_BODY(_ZdlPv); 6487eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov} 6491dcabd115668f9efba615f7c4e190244a4df361fDmitry Vyukov 6503c80c6c574850106481f82b9e23d1c728458d4a9Timur IskhodzhanovSANITIZER_INTERFACE_ATTRIBUTE 6512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid operator delete[](void *ptr) throw(); 6522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid operator delete[](void *ptr) throw() { 6532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines OPERATOR_DELETE_BODY(_ZdaPv); 6547eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov} 6551dcabd115668f9efba615f7c4e190244a4df361fDmitry Vyukov 6563c80c6c574850106481f82b9e23d1c728458d4a9Timur IskhodzhanovSANITIZER_INTERFACE_ATTRIBUTE 6573c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanovvoid operator delete(void *ptr, std::nothrow_t const&); 6587eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid operator delete(void *ptr, std::nothrow_t const&) { 6592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines OPERATOR_DELETE_BODY(_ZdlPvRKSt9nothrow_t); 6607eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov} 6611dcabd115668f9efba615f7c4e190244a4df361fDmitry Vyukov 6623c80c6c574850106481f82b9e23d1c728458d4a9Timur IskhodzhanovSANITIZER_INTERFACE_ATTRIBUTE 6633c80c6c574850106481f82b9e23d1c728458d4a9Timur Iskhodzhanovvoid operator delete[](void *ptr, std::nothrow_t const&); 6647eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonovvoid operator delete[](void *ptr, std::nothrow_t const&) { 6657eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov OPERATOR_DELETE_BODY(_ZdaPvRKSt9nothrow_t); 6667eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov} 6677eff311e3e969ae084aadba7d7812591e34d08abAlexey Samsonov 668d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry VyukovTSAN_INTERCEPTOR(uptr, strlen, const char *s) { 6697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(strlen, s); 670d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov uptr len = internal_strlen(s); 6717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany MemoryAccessRange(thr, pc, (uptr)s, len + 1, false); 6727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return len; 6737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 6747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 675065c4ac846589d04436cb7f19f938ff42035313eDmitry VyukovTSAN_INTERCEPTOR(void*, memset, void *dst, int v, uptr size) { 676909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar // On FreeBSD we get here from libthr internals on thread initialization. 677909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar if (!COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) { 678909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar SCOPED_TSAN_INTERCEPTOR(memset, dst, v, size); 679909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar MemoryAccessRange(thr, pc, (uptr)dst, size, true); 680909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar } 681065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov return internal_memset(dst, v, size); 6827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 6837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 684065c4ac846589d04436cb7f19f938ff42035313eDmitry VyukovTSAN_INTERCEPTOR(void*, memcpy, void *dst, const void *src, uptr size) { 6857c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // On FreeBSD we get here from libthr internals on thread initialization. 686909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar if (!COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) { 6877c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar SCOPED_TSAN_INTERCEPTOR(memcpy, dst, src, size); 6887c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar MemoryAccessRange(thr, pc, (uptr)dst, size, true); 6897c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar MemoryAccessRange(thr, pc, (uptr)src, size, false); 6907c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar } 691065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov return internal_memcpy(dst, src, size); 6927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 6937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 694065c4ac846589d04436cb7f19f938ff42035313eDmitry VyukovTSAN_INTERCEPTOR(int, memcmp, const void *s1, const void *s2, uptr n) { 695065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov SCOPED_TSAN_INTERCEPTOR(memcmp, s1, s2, n); 696d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov int res = 0; 697d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov uptr len = 0; 698d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov for (; len < n; len++) { 6996d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if ((res = ((const unsigned char *)s1)[len] - 7006d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ((const unsigned char *)s2)[len])) 701d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov break; 702d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov } 703d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov MemoryAccessRange(thr, pc, (uptr)s1, len < n ? len + 1 : n, false); 704d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov MemoryAccessRange(thr, pc, (uptr)s2, len < n ? len + 1 : n, false); 705d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov return res; 706d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov} 707d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov 7087ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, memmove, void *dst, void *src, uptr n) { 7097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(memmove, dst, src, n); 7107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany MemoryAccessRange(thr, pc, (uptr)dst, n, true); 7117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany MemoryAccessRange(thr, pc, (uptr)src, n, false); 7127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return REAL(memmove)(dst, src, n); 7137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 7147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 715d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry VyukovTSAN_INTERCEPTOR(char*, strchr, char *s, int c) { 7167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(strchr, s, c); 717d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov char *res = REAL(strchr)(s, c); 718909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar uptr len = internal_strlen(s); 719909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar uptr n = res ? (char*)res - (char*)s + 1 : len + 1; 720909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar READ_STRING_OF_LEN(thr, pc, s, len, n); 7217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 7227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 7237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 724d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry VyukovTSAN_INTERCEPTOR(char*, strchrnul, char *s, int c) { 7257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(strchrnul, s, c); 726d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov char *res = REAL(strchrnul)(s, c); 7277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr len = (char*)res - (char*)s + 1; 728909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar READ_STRING(thr, pc, s, len); 7297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 7307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 7317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 732d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry VyukovTSAN_INTERCEPTOR(char*, strrchr, char *s, int c) { 7337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(strrchr, s, c); 734d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov MemoryAccessRange(thr, pc, (uptr)s, internal_strlen(s) + 1, false); 7357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return REAL(strrchr)(s, c); 7367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 7377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 738d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry VyukovTSAN_INTERCEPTOR(char*, strcpy, char *dst, const char *src) { // NOLINT 7397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(strcpy, dst, src); // NOLINT 740d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov uptr srclen = internal_strlen(src); 7417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany MemoryAccessRange(thr, pc, (uptr)dst, srclen + 1, true); 7427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany MemoryAccessRange(thr, pc, (uptr)src, srclen + 1, false); 7437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return REAL(strcpy)(dst, src); // NOLINT 7447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 7457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 746d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry VyukovTSAN_INTERCEPTOR(char*, strncpy, char *dst, char *src, uptr n) { 7477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(strncpy, dst, src, n); 748b93c3d5badc4066120edf3ed1c515cdd516a8776Kostya Serebryany uptr srclen = internal_strnlen(src, n); 7497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany MemoryAccessRange(thr, pc, (uptr)dst, n, true); 7507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany MemoryAccessRange(thr, pc, (uptr)src, min(srclen + 1, n), false); 7517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return REAL(strncpy)(dst, src, n); 7527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 7537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 7547ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(const char*, strstr, const char *s1, const char *s2) { 7557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(strstr, s1, s2); 7567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany const char *res = REAL(strstr)(s1, s2); 757d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov uptr len1 = internal_strlen(s1); 758d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov uptr len2 = internal_strlen(s2); 7597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany MemoryAccessRange(thr, pc, (uptr)s1, len1 + 1, false); 7607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany MemoryAccessRange(thr, pc, (uptr)s2, len2 + 1, false); 7617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 7627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 7637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 76439fa68e4076f6a86765ddc69c44bcecb804f0b53Dmitry VyukovTSAN_INTERCEPTOR(char*, strdup, const char *str) { 76539fa68e4076f6a86765ddc69c44bcecb804f0b53Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(strdup, str); 76639fa68e4076f6a86765ddc69c44bcecb804f0b53Dmitry Vyukov // strdup will call malloc, so no instrumentation is required here. 76739fa68e4076f6a86765ddc69c44bcecb804f0b53Dmitry Vyukov return REAL(strdup)(str); 76839fa68e4076f6a86765ddc69c44bcecb804f0b53Dmitry Vyukov} 76939fa68e4076f6a86765ddc69c44bcecb804f0b53Dmitry Vyukov 7707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic bool fix_mmap_addr(void **addr, long_t sz, int flags) { 7717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (*addr) { 7727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (!IsAppMem((uptr)*addr) || !IsAppMem((uptr)*addr + sz - 1)) { 7737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (flags & MAP_FIXED) { 7747a72b4a0f04f7f043ab86396b0faa552f55aa857Dmitry Vyukov errno = EINVAL; 7757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return false; 7767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else { 7777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany *addr = 0; 7787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 7797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 7807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 7817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return true; 7827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 7837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 7847ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, mmap, void *addr, long_t sz, int prot, 7857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int flags, int fd, unsigned off) { 7867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(mmap, addr, sz, prot, flags, fd, off); 7877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (!fix_mmap_addr(&addr, sz, flags)) 7887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return MAP_FAILED; 7897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void *res = REAL(mmap)(addr, sz, prot, flags, fd, off); 7907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res != MAP_FAILED) { 791c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov if (fd > 0) 792c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov FdAccess(thr, pc, fd); 79374172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov MemoryRangeImitateWrite(thr, pc, (uptr)res, sz); 7947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 7957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 7967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 7977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 7986d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 7997ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, mmap64, void *addr, long_t sz, int prot, 8007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int flags, int fd, u64 off) { 8017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(mmap64, addr, sz, prot, flags, fd, off); 8027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (!fix_mmap_addr(&addr, sz, flags)) 8037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return MAP_FAILED; 8047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void *res = REAL(mmap64)(addr, sz, prot, flags, fd, off); 8057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res != MAP_FAILED) { 806c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov if (fd > 0) 807c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov FdAccess(thr, pc, fd); 80874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov MemoryRangeImitateWrite(thr, pc, (uptr)res, sz); 8097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 8107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 8117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 8126d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_MMAP64 TSAN_INTERCEPT(mmap64) 8136d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 8146d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_MMAP64 8156d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 8167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 8177ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) { 8187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(munmap, addr, sz); 819909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar if (sz != 0) { 820909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar // If sz == 0, munmap will return EINVAL and don't unmap any memory. 821909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar DontNeedShadowFor((uptr)addr, sz); 822909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar ctx->metamap.ResetRange(thr, pc, (uptr)addr, (uptr)sz); 823909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar } 8247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(munmap)(addr, sz); 8257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 8267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 8277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 8286d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 8297ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) { 8304af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov SCOPED_INTERCEPTOR_RAW(memalign, align, sz); 8312e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov return user_alloc(thr, pc, sz, align); 8327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 8336d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_MEMALIGN TSAN_INTERCEPT(memalign) 8346d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 8356d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_MEMALIGN 8366d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 8377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 8386a211c5814e25d6745a5058cc0e499e5235d3821Stephen HinesTSAN_INTERCEPTOR(void*, aligned_alloc, uptr align, uptr sz) { 8396a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines SCOPED_INTERCEPTOR_RAW(memalign, align, sz); 8406a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines return user_alloc(thr, pc, sz, align); 8416a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines} 8426a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines 8437ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, valloc, uptr sz) { 8444af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov SCOPED_INTERCEPTOR_RAW(valloc, sz); 845f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany return user_alloc(thr, pc, sz, GetPageSizeCached()); 8467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 8477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 8486d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 8497ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(void*, pvalloc, uptr sz) { 8504af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov SCOPED_INTERCEPTOR_RAW(pvalloc, sz); 851f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany sz = RoundUp(sz, GetPageSizeCached()); 852f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany return user_alloc(thr, pc, sz, GetPageSizeCached()); 8537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 8546d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_PVALLOC TSAN_INTERCEPT(pvalloc) 8556d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 8566d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_PVALLOC 8576d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 8587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 8597ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) { 8604af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov SCOPED_INTERCEPTOR_RAW(posix_memalign, memptr, align, sz); 8612e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov *memptr = user_alloc(thr, pc, sz, align); 8627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return 0; 8637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 8647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 8657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Used in thread-safe function static initialization. 8661ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukovextern "C" int INTERFACE_ATTRIBUTE __cxa_guard_acquire(atomic_uint32_t *g) { 8671ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov SCOPED_INTERCEPTOR_RAW(__cxa_guard_acquire, g); 8681ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov for (;;) { 8691ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov u32 cmp = atomic_load(g, memory_order_acquire); 8701ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov if (cmp == 0) { 8711ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov if (atomic_compare_exchange_strong(g, &cmp, 1<<16, memory_order_relaxed)) 8721ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov return 1; 8731ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov } else if (cmp == 1) { 8741ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov Acquire(thr, pc, (uptr)g); 8751ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov return 0; 8761ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov } else { 8771ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov internal_sched_yield(); 8781ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov } 8797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 8807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 8817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 8821ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukovextern "C" void INTERFACE_ATTRIBUTE __cxa_guard_release(atomic_uint32_t *g) { 8831ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov SCOPED_INTERCEPTOR_RAW(__cxa_guard_release, g); 8841ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov Release(thr, pc, (uptr)g); 8851ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov atomic_store(g, 1, memory_order_release); 8861ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov} 8871ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov 8881ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukovextern "C" void INTERFACE_ATTRIBUTE __cxa_guard_abort(atomic_uint32_t *g) { 8891ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov SCOPED_INTERCEPTOR_RAW(__cxa_guard_abort, g); 8901ffeded71b960d8a0f018a46a0035203b1484a7aDmitry Vyukov atomic_store(g, 0, memory_order_relaxed); 8917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 8927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 8937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void thread_finalize(void *v) { 8947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr iter = (uptr)v; 8957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (iter > 1) { 8967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) { 897b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("ThreadSanitizer: failed to set thread key\n"); 8987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Die(); 8997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 9007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 9017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 9027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany { 903e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov ThreadState *thr = cur_thread(); 904e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov ThreadFinish(thr); 9057c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ThreadSignalContext *sctx = thr->signal_ctx; 9061fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov if (sctx) { 9071fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov thr->signal_ctx = 0; 908c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov UnmapOrDie(sctx, sizeof(*sctx)); 9091fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov } 9107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 9117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 9127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 9137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 9147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystruct ThreadParam { 9157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void* (*callback)(void *arg); 9167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void *param; 9177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany atomic_uintptr_t tid; 9187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}; 9197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 9207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void *__tsan_thread_start_func(void *arg) { 9217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ThreadParam *p = (ThreadParam*)arg; 9227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void* (*callback)(void *arg) = p->callback; 9237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void *param = p->param; 9247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int tid = 0; 9257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany { 9267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ThreadState *thr = cur_thread(); 9272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Thread-local state is not initialized yet. 9282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ScopedIgnoreInterceptors ignore; 9296d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ThreadIgnoreBegin(thr, 0); 9306eb836f9bd2b96a321ddc7fb5ea08aa65131e61fSergey Matveev if (pthread_setspecific(g_thread_finalize_key, 9316eb836f9bd2b96a321ddc7fb5ea08aa65131e61fSergey Matveev (void *)kPthreadDestructorIterations)) { 932b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("ThreadSanitizer: failed to set thread key\n"); 9337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Die(); 9347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 9356d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ThreadIgnoreEnd(thr, 0); 9367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0) 9377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany pthread_yield(); 9387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany atomic_store(&p->tid, 0, memory_order_release); 9397dccf3f92a867f917ad19f9a6b37bcf93e64b35bDmitry Vyukov ThreadStart(thr, tid, GetTid()); 9407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 9417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void *res = callback(param); 9427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Prevent the callback from being tail called, 9437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // it mixes up stack traces. 9447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany volatile int foo = 42; 9457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany foo++; 9467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 9477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 9487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 9497ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_create, 9507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany void *th, void *attr, void *(*callback)(void*), void * param) { 9514af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov SCOPED_INTERCEPTOR_RAW(pthread_create, th, attr, callback, param); 9522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (ctx->after_multithreaded_fork) { 9532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (flags()->die_after_fork) { 9542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Report("ThreadSanitizer: starting new threads after multi-threaded " 9552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines "fork is not supported. Dying (set die_after_fork=0 to override)\n"); 9562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Die(); 9572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } else { 9582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines VPrintf(1, "ThreadSanitizer: starting new threads after multi-threaded " 9592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines "fork is not supported (pid %d). Continuing because of " 9602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines "die_after_fork=0, but you are on your own\n", internal_getpid()); 9612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 9622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 963f110e356170fbe990b99c0939d77eeaa89b25497Alexey Samsonov __sanitizer_pthread_attr_t myattr; 9647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (attr == 0) { 9657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany pthread_attr_init(&myattr); 9667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany attr = &myattr; 9677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 9687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int detached = 0; 969e236dbb5e558b174609d2d13e80685d488c129d8Evgeniy Stepanov REAL(pthread_attr_getdetachstate)(attr, &detached); 9702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines AdjustStackSize(attr); 971b9bf700ae7fe59e25976e0abe9636150f3a39cd2Evgeniy Stepanov 9727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ThreadParam p; 9737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany p.callback = callback; 9747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany p.param = param; 9757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany atomic_store(&p.tid, 0, memory_order_relaxed); 9762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines int res = -1; 9772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines { 9782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Otherwise we see false positives in pthread stack manipulation. 9792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ScopedIgnoreInterceptors ignore; 9802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ThreadIgnoreBegin(thr, pc); 9812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines res = REAL(pthread_create)(th, attr, __tsan_thread_start_func, &p); 9822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ThreadIgnoreEnd(thr, pc); 9832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 9847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 98564310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov int tid = ThreadCreate(thr, pc, *(uptr*)th, detached); 9867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_NE(tid, 0); 9877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany atomic_store(&p.tid, tid, memory_order_release); 9887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany while (atomic_load(&p.tid, memory_order_acquire) != 0) 9897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany pthread_yield(); 9907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 9917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (attr == &myattr) 9927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany pthread_attr_destroy(&myattr); 9937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 9947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 9957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 9967ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) { 9974af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov SCOPED_INTERCEPTOR_RAW(pthread_join, th, ret); 9987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int tid = ThreadTid(thr, pc, (uptr)th); 9992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ThreadIgnoreBegin(thr, pc); 1000ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov int res = BLOCK_REAL(pthread_join)(th, ret); 10012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ThreadIgnoreEnd(thr, pc); 10027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 100364310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov ThreadJoin(thr, pc, tid); 10047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 10057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 10067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 10077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 100886277eb844c4983c81de62d7c050e92fe7155788Stephen HinesDEFINE_REAL_PTHREAD_FUNCTIONS 100986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 10107ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_detach, void *th) { 10117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_detach, th); 10127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int tid = ThreadTid(thr, pc, (uptr)th); 10137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_detach)(th); 10147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 101564310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov ThreadDetach(thr, pc, tid); 10167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 10177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 10187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 10197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 10202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Problem: 10212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// NPTL implementation of pthread_cond has 2 versions (2.2.5 and 2.3.2). 10222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// pthread_cond_t has different size in the different versions. 10232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// If call new REAL functions for old pthread_cond_t, they will corrupt memory 10242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// after pthread_cond_t (old cond is smaller). 10252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// If we call old REAL functions for new pthread_cond_t, we will lose some 10262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// functionality (e.g. old functions do not support waiting against 10272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// CLOCK_REALTIME). 10282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Proper handling would require to have 2 versions of interceptors as well. 10292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// But this is messy, in particular requires linker scripts when sanitizer 10302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// runtime is linked into a shared library. 10312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Instead we assume we don't have dynamic libraries built against old 10322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// pthread (2.2.5 is dated by 2002). And provide legacy_pthread_cond flag 10332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// that allows to work with old libraries (but this mode does not support 10342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// some features, e.g. pthread_condattr_getpshared). 10352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void *init_cond(void *c, bool force = false) { 10362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // sizeof(pthread_cond_t) >= sizeof(uptr) in both versions. 10372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // So we allocate additional memory on the side large enough to hold 10382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // any pthread_cond_t object. Always call new REAL functions, but pass 10392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // the aux object to them. 10402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Note: the code assumes that PTHREAD_COND_INITIALIZER initializes 10412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // first word of pthread_cond_t to zero. 10422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // It's all relevant only for linux. 10432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (!common_flags()->legacy_pthread_cond) 10442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return c; 10452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines atomic_uintptr_t *p = (atomic_uintptr_t*)c; 10462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr cond = atomic_load(p, memory_order_acquire); 10472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (!force && cond != 0) 10482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return (void*)cond; 10492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void *newcond = WRAP(malloc)(pthread_cond_t_sz); 10502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines internal_memset(newcond, 0, pthread_cond_t_sz); 10512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (atomic_compare_exchange_strong(p, &cond, (uptr)newcond, 10522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines memory_order_acq_rel)) 10532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return newcond; 10542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines WRAP(free)(newcond); 10552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return (void*)cond; 10562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 10572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 10582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstruct CondMutexUnlockCtx { 1059909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar ScopedInterceptor *si; 10602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ThreadState *thr; 10612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr pc; 10622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void *m; 10632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}; 10642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 10652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void cond_mutex_unlock(CondMutexUnlockCtx *arg) { 1066909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar // pthread_cond_wait interceptor has enabled async signal delivery 1067909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar // (see BlockingCall below). Disable async signals since we are running 1068909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar // tsan code. Also ScopedInterceptor and BlockingCall destructors won't run 1069909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar // since the thread is cancelled, so we have to manually execute them 1070909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar // (the thread still can run some user code due to pthread_cleanup_push). 1071909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar ThreadSignalContext *ctx = SigCtx(arg->thr); 1072909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar CHECK_EQ(atomic_load(&ctx->in_blocking_func, memory_order_relaxed), 1); 1073909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar atomic_store(&ctx->in_blocking_func, 0, memory_order_relaxed); 10742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexLock(arg->thr, arg->pc, (uptr)arg->m); 1075909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar // Undo BlockingCall ctor effects. 1076909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar arg->thr->ignore_interceptors--; 1077909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar arg->si->~ScopedInterceptor(); 10782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 10792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 10802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPTOR(int, pthread_cond_init, void *c, void *a) { 10812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void *cond = init_cond(c, true); 10822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines SCOPED_TSAN_INTERCEPTOR(pthread_cond_init, cond, a); 10832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), true); 10842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return REAL(pthread_cond_init)(cond, a); 10852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 10862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 10872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPTOR(int, pthread_cond_wait, void *c, void *m) { 10882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void *cond = init_cond(c); 10892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait, cond, m); 10902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexUnlock(thr, pc, (uptr)m); 10912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false); 1092909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar CondMutexUnlockCtx arg = {&si, thr, pc, m}; 1093909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar int res = 0; 10942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // This ensures that we handle mutex lock even in case of pthread_cancel. 10952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // See test/tsan/cond_cancel.cc. 1096909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar { 1097909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar // Enable signal delivery while the thread is blocked. 1098909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar BlockingCall bc(thr); 1099909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar res = call_pthread_cancel_with_cleanup( 1100909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar (int(*)(void *c, void *m, void *abstime))REAL(pthread_cond_wait), 1101909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar cond, m, 0, (void(*)(void *arg))cond_mutex_unlock, &arg); 1102909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar } 11032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (res == errno_EOWNERDEAD) 11042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexRepair(thr, pc, (uptr)m); 11052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexLock(thr, pc, (uptr)m); 11062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return res; 11072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 11082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 11092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPTOR(int, pthread_cond_timedwait, void *c, void *m, void *abstime) { 11102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void *cond = init_cond(c); 11112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait, cond, m, abstime); 11122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexUnlock(thr, pc, (uptr)m); 11132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false); 1114909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar CondMutexUnlockCtx arg = {&si, thr, pc, m}; 1115909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar int res = 0; 11162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // This ensures that we handle mutex lock even in case of pthread_cancel. 11172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // See test/tsan/cond_cancel.cc. 1118909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar { 1119909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar BlockingCall bc(thr); 1120909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar res = call_pthread_cancel_with_cleanup( 1121909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar REAL(pthread_cond_timedwait), cond, m, abstime, 1122909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar (void(*)(void *arg))cond_mutex_unlock, &arg); 1123909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar } 11242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (res == errno_EOWNERDEAD) 11252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexRepair(thr, pc, (uptr)m); 11262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexLock(thr, pc, (uptr)m); 11272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return res; 11282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 11292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 11302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPTOR(int, pthread_cond_signal, void *c) { 11312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void *cond = init_cond(c); 11322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal, cond); 11332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false); 11342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return REAL(pthread_cond_signal)(cond); 11352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 11362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 11372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPTOR(int, pthread_cond_broadcast, void *c) { 11382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void *cond = init_cond(c); 11392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines SCOPED_TSAN_INTERCEPTOR(pthread_cond_broadcast, cond); 11402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false); 11412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return REAL(pthread_cond_broadcast)(cond); 11422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 11432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 11442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPTOR(int, pthread_cond_destroy, void *c) { 11452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void *cond = init_cond(c); 11462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy, cond); 11472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), true); 11482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines int res = REAL(pthread_cond_destroy)(cond); 11492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (common_flags()->legacy_pthread_cond) { 11502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Free our aux cond and zero the pointer to not leave dangling pointers. 11512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines WRAP(free)(cond); 11522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines atomic_store((atomic_uintptr_t*)c, 0, memory_order_relaxed); 11532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 11542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return res; 11552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 11562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 11577ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_mutex_init, void *m, void *a) { 11587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_mutex_init, m, a); 11597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_mutex_init)(m, a); 11607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 11617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany bool recursive = false; 11627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (a) { 11637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int type = 0; 11646a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines if (REAL(pthread_mutexattr_gettype)(a, &type) == 0) 11657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany recursive = (type == PTHREAD_MUTEX_RECURSIVE 11667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany || type == PTHREAD_MUTEX_RECURSIVE_NP); 11677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1168c20e9ba760a93706c9160133cdcce62194f9694fDmitry Vyukov MutexCreate(thr, pc, (uptr)m, false, recursive, false); 11697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 11707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 11717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 11727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 11737ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_mutex_destroy, void *m) { 11747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_mutex_destroy, m); 11757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_mutex_destroy)(m); 11767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0 || res == EBUSY) { 117764310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov MutexDestroy(thr, pc, (uptr)m); 11787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 11797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 11807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 11817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 11827ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) { 11837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_mutex_trylock, m); 11847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_mutex_trylock)(m); 118511f5309ec1bf13430c8a3a16f177d9e8e1190e38Dmitry Vyukov if (res == EOWNERDEAD) 118611f5309ec1bf13430c8a3a16f177d9e8e1190e38Dmitry Vyukov MutexRepair(thr, pc, (uptr)m); 118711f5309ec1bf13430c8a3a16f177d9e8e1190e38Dmitry Vyukov if (res == 0 || res == EOWNERDEAD) 11882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexLock(thr, pc, (uptr)m, /*rec=*/1, /*try_lock=*/true); 11897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 11907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 11917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 11927ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) { 11937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_mutex_timedlock, m, abstime); 11947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_mutex_timedlock)(m, abstime); 11957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 119664310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov MutexLock(thr, pc, (uptr)m); 11977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 11987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 11997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 12007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 12017ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_spin_init, void *m, int pshared) { 12027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_spin_init, m, pshared); 12037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_spin_init)(m, pshared); 12047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 1205c20e9ba760a93706c9160133cdcce62194f9694fDmitry Vyukov MutexCreate(thr, pc, (uptr)m, false, false, false); 12067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 12077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 12087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 12097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 12107ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_spin_destroy, void *m) { 12117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_spin_destroy, m); 12127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_spin_destroy)(m); 12137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 121464310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov MutexDestroy(thr, pc, (uptr)m); 12157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 12167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 12177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 12187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 12197ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_spin_lock, void *m) { 12207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_spin_lock, m); 12217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_spin_lock)(m); 12227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 122364310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov MutexLock(thr, pc, (uptr)m); 12247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 12257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 12267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 12277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 12287ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_spin_trylock, void *m) { 12297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_spin_trylock, m); 12307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_spin_trylock)(m); 12317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 12322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexLock(thr, pc, (uptr)m, /*rec=*/1, /*try_lock=*/true); 12337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 12347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 12357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 12367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 12377ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_spin_unlock, void *m) { 12387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_spin_unlock, m); 123964310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov MutexUnlock(thr, pc, (uptr)m); 12407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_spin_unlock)(m); 12417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 12427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 12437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 12447ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_init, void *m, void *a) { 12457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_init, m, a); 12467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_rwlock_init)(m, a); 12477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 1248c20e9ba760a93706c9160133cdcce62194f9694fDmitry Vyukov MutexCreate(thr, pc, (uptr)m, true, false, false); 12497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 12507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 12517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 12527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 12537ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_destroy, void *m) { 12547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_destroy, m); 12557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_rwlock_destroy)(m); 12567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 125764310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov MutexDestroy(thr, pc, (uptr)m); 12587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 12597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 12607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 12617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 12627ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_rdlock, void *m) { 12637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_rdlock, m); 12647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_rwlock_rdlock)(m); 12657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 126664310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov MutexReadLock(thr, pc, (uptr)m); 12677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 12687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 12697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 12707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 12717ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_tryrdlock, void *m) { 12727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_tryrdlock, m); 12737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_rwlock_tryrdlock)(m); 12747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 12756a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines MutexReadLock(thr, pc, (uptr)m, /*try_lock=*/true); 12767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 12777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 12787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 12797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 12807ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) { 12817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedrdlock, m, abstime); 12827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_rwlock_timedrdlock)(m, abstime); 12837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 128464310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov MutexReadLock(thr, pc, (uptr)m); 12857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 12867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 12877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 12887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 12897ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_wrlock, void *m) { 12907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_wrlock, m); 12917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_rwlock_wrlock)(m); 12927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 129364310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov MutexLock(thr, pc, (uptr)m); 12947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 12957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 12967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 12977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 12987ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_trywrlock, void *m) { 12997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_trywrlock, m); 13007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_rwlock_trywrlock)(m); 13017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 13022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MutexLock(thr, pc, (uptr)m, /*rec=*/1, /*try_lock=*/true); 13037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 13047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 13057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 13067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 13077ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_timedwrlock, void *m, void *abstime) { 13087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedwrlock, m, abstime); 13097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_rwlock_timedwrlock)(m, abstime); 13107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 131164310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov MutexLock(thr, pc, (uptr)m); 13127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 13137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 13147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 13157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 13167ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) { 13177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_unlock, m); 131864310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov MutexReadOrWriteUnlock(thr, pc, (uptr)m); 13197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_rwlock_unlock)(m); 13207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 13217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 13227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 13237ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_barrier_init, void *b, void *a, unsigned count) { 13247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_barrier_init, b, a, count); 1325334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov MemoryWrite(thr, pc, (uptr)b, kSizeLog1); 13267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_barrier_init)(b, a, count); 13277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 13287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 13297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 13307ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_barrier_destroy, void *b) { 13317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_barrier_destroy, b); 1332334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov MemoryWrite(thr, pc, (uptr)b, kSizeLog1); 13337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_barrier_destroy)(b); 13347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 13357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 13367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 13377ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) { 13387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(pthread_barrier_wait, b); 133964310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov Release(thr, pc, (uptr)b); 1340334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov MemoryRead(thr, pc, (uptr)b, kSizeLog1); 13417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(pthread_barrier_wait)(b); 1342334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov MemoryRead(thr, pc, (uptr)b, kSizeLog1); 13437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0 || res == PTHREAD_BARRIER_SERIAL_THREAD) { 134464310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov Acquire(thr, pc, (uptr)b); 13457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 13467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 13477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 13487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 13497ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) { 13509fe1d5abd472f3357d5888d1f580fe1866a417f8Dmitry Vyukov SCOPED_INTERCEPTOR_RAW(pthread_once, o, f); 13517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (o == 0 || f == 0) 13527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return EINVAL; 13537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany atomic_uint32_t *a = static_cast<atomic_uint32_t*>(o); 13547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u32 v = atomic_load(a, memory_order_acquire); 13557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (v == 0 && atomic_compare_exchange_strong(a, &v, 1, 13567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany memory_order_relaxed)) { 13577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (*f)(); 13589fe1d5abd472f3357d5888d1f580fe1866a417f8Dmitry Vyukov if (!thr->in_ignored_lib) 13599fe1d5abd472f3357d5888d1f580fe1866a417f8Dmitry Vyukov Release(thr, pc, (uptr)o); 13607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany atomic_store(a, 2, memory_order_release); 13617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } else { 13627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany while (v != 2) { 13637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany pthread_yield(); 13647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany v = atomic_load(a, memory_order_acquire); 13657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 13669fe1d5abd472f3357d5888d1f580fe1866a417f8Dmitry Vyukov if (!thr->in_ignored_lib) 13679fe1d5abd472f3357d5888d1f580fe1866a417f8Dmitry Vyukov Acquire(thr, pc, (uptr)o); 13687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 13697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return 0; 13707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 13717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 13727ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_init, void *s, int pshared, unsigned value) { 13737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(sem_init, s, pshared, value); 13747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(sem_init)(s, pshared, value); 13757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 13767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 13777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 13787ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_destroy, void *s) { 13797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(sem_destroy, s); 13807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(sem_destroy)(s); 13817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 13827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 13837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 13847ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_wait, void *s) { 13857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(sem_wait, s); 1386ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov int res = BLOCK_REAL(sem_wait)(s); 13877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 138864310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov Acquire(thr, pc, (uptr)s); 13897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 13907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 13917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 13927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 13937ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_trywait, void *s) { 13947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(sem_trywait, s); 1395ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov int res = BLOCK_REAL(sem_trywait)(s); 13967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 139764310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov Acquire(thr, pc, (uptr)s); 13987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 13997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 14007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 14017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 14027ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_timedwait, void *s, void *abstime) { 14037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(sem_timedwait, s, abstime); 1404ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov int res = BLOCK_REAL(sem_timedwait)(s, abstime); 14057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 140664310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov Acquire(thr, pc, (uptr)s); 14077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 14087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 14097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 14107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 14117ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_post, void *s) { 14127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(sem_post, s); 141364310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov Release(thr, pc, (uptr)s); 14147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(sem_post)(s); 14157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 14167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 14177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 14187ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sem_getvalue, void *s, int *sval) { 14197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(sem_getvalue, s, sval); 14207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(sem_getvalue)(s, sval); 14217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (res == 0) { 142264310b28c4e418573ddfda2dbedd702ccf20a051Dmitry Vyukov Acquire(thr, pc, (uptr)s); 14237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 14247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 14257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 14267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 14276d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 142861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) { 142961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(__xstat, version, path, buf); 1430909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar READ_STRING(thr, pc, path, 0); 143161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov return REAL(__xstat)(version, path, buf); 143261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov} 14336d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT___XSTAT TSAN_INTERCEPT(__xstat) 14346d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 14356d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT___XSTAT 14366d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 143761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov 143861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, stat, const char *path, void *buf) { 14396d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if SANITIZER_FREEBSD 14406d1862363c88c183b0ed7740fca876342cf0474bStephen Hines SCOPED_TSAN_INTERCEPTOR(stat, path, buf); 1441909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar READ_STRING(thr, pc, path, 0); 14426d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return REAL(stat)(path, buf); 14436d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 144461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(__xstat, 0, path, buf); 1445909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar READ_STRING(thr, pc, path, 0); 144661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov return REAL(__xstat)(0, path, buf); 14476d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 144861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov} 144961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov 14506d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 145161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) { 145261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(__xstat64, version, path, buf); 1453909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar READ_STRING(thr, pc, path, 0); 145461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov return REAL(__xstat64)(version, path, buf); 145561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov} 14566d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT___XSTAT64 TSAN_INTERCEPT(__xstat64) 14576d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 14586d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT___XSTAT64 14596d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 146061ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov 14616d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 146261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, stat64, const char *path, void *buf) { 146361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(__xstat64, 0, path, buf); 1464909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar READ_STRING(thr, pc, path, 0); 146561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov return REAL(__xstat64)(0, path, buf); 146661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov} 14676d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_STAT64 TSAN_INTERCEPT(stat64) 14686d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 14696d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_STAT64 14706d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 147161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov 14726d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 147361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) { 147461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(__lxstat, version, path, buf); 1475909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar READ_STRING(thr, pc, path, 0); 147661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov return REAL(__lxstat)(version, path, buf); 147761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov} 14786d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT___LXSTAT TSAN_INTERCEPT(__lxstat) 14796d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 14806d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT___LXSTAT 14816d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 148261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov 148361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, lstat, const char *path, void *buf) { 14846d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if SANITIZER_FREEBSD 14856d1862363c88c183b0ed7740fca876342cf0474bStephen Hines SCOPED_TSAN_INTERCEPTOR(lstat, path, buf); 1486909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar READ_STRING(thr, pc, path, 0); 14876d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return REAL(lstat)(path, buf); 14886d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 148961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(__lxstat, 0, path, buf); 1490909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar READ_STRING(thr, pc, path, 0); 149161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov return REAL(__lxstat)(0, path, buf); 14926d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 149361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov} 149461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov 14956d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 149661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) { 149761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(__lxstat64, version, path, buf); 1498909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar READ_STRING(thr, pc, path, 0); 149961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov return REAL(__lxstat64)(version, path, buf); 150061ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov} 15016d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT___LXSTAT64 TSAN_INTERCEPT(__lxstat64) 15026d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 15036d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT___LXSTAT64 15046d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 150561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov 15066d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 150761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, lstat64, const char *path, void *buf) { 150861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(__lxstat64, 0, path, buf); 1509909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar READ_STRING(thr, pc, path, 0); 151061ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov return REAL(__lxstat64)(0, path, buf); 151161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov} 15126d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_LSTAT64 TSAN_INTERCEPT(lstat64) 15136d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 15146d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_LSTAT64 15156d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 151661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov 15176d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 151861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) { 151961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(__fxstat, version, fd, buf); 1520c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov if (fd > 0) 1521c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov FdAccess(thr, pc, fd); 152261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov return REAL(__fxstat)(version, fd, buf); 152361ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov} 15246d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT___FXSTAT TSAN_INTERCEPT(__fxstat) 15256d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 15266d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT___FXSTAT 15276d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 152861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov 152961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, fstat, int fd, void *buf) { 15306d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if SANITIZER_FREEBSD 15316d1862363c88c183b0ed7740fca876342cf0474bStephen Hines SCOPED_TSAN_INTERCEPTOR(fstat, fd, buf); 15326d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (fd > 0) 15336d1862363c88c183b0ed7740fca876342cf0474bStephen Hines FdAccess(thr, pc, fd); 15346d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return REAL(fstat)(fd, buf); 15356d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 153661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(__fxstat, 0, fd, buf); 1537c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov if (fd > 0) 1538c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov FdAccess(thr, pc, fd); 153961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov return REAL(__fxstat)(0, fd, buf); 15406d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 154161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov} 154261ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov 15436d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 154461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { 154561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf); 1546c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov if (fd > 0) 1547c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov FdAccess(thr, pc, fd); 154861ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov return REAL(__fxstat64)(version, fd, buf); 154961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov} 15506d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT___FXSTAT64 TSAN_INTERCEPT(__fxstat64) 15516d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 15526d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT___FXSTAT64 15536d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 155461ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov 15556d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 155661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry VyukovTSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) { 155761ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf); 1558c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov if (fd > 0) 1559c05cbca0988c296068e0da1556bd6af7edd43c69Dmitry Vyukov FdAccess(thr, pc, fd); 156061ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov return REAL(__fxstat64)(0, fd, buf); 156161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov} 15626d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_FSTAT64 TSAN_INTERCEPT(fstat64) 15636d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 15646d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_FSTAT64 15656d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 156661ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov 1567ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry VyukovTSAN_INTERCEPTOR(int, open, const char *name, int flags, int mode) { 1568ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(open, name, flags, mode); 1569909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar READ_STRING(thr, pc, name, 0); 1570ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov int fd = REAL(open)(name, flags, mode); 1571ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov if (fd >= 0) 157268230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov FdFileCreate(thr, pc, fd); 1573ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov return fd; 1574ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov} 1575ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov 15766d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 1577c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry VyukovTSAN_INTERCEPTOR(int, open64, const char *name, int flags, int mode) { 1578c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov SCOPED_TSAN_INTERCEPTOR(open64, name, flags, mode); 1579909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar READ_STRING(thr, pc, name, 0); 1580c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov int fd = REAL(open64)(name, flags, mode); 1581c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov if (fd >= 0) 1582c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov FdFileCreate(thr, pc, fd); 1583c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov return fd; 1584c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov} 15856d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_OPEN64 TSAN_INTERCEPT(open64) 15866d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 15876d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_OPEN64 15886d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 1589c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov 1590ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry VyukovTSAN_INTERCEPTOR(int, creat, const char *name, int mode) { 1591ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(creat, name, mode); 1592909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar READ_STRING(thr, pc, name, 0); 1593ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov int fd = REAL(creat)(name, mode); 1594ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov if (fd >= 0) 159568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov FdFileCreate(thr, pc, fd); 1596ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov return fd; 1597ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov} 1598ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov 15996d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 1600c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry VyukovTSAN_INTERCEPTOR(int, creat64, const char *name, int mode) { 1601c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov SCOPED_TSAN_INTERCEPTOR(creat64, name, mode); 1602909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar READ_STRING(thr, pc, name, 0); 1603c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov int fd = REAL(creat64)(name, mode); 1604c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov if (fd >= 0) 1605c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov FdFileCreate(thr, pc, fd); 1606c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov return fd; 1607c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov} 16086d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_CREAT64 TSAN_INTERCEPT(creat64) 16096d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 16106d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_CREAT64 16116d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 1612c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov 1613ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry VyukovTSAN_INTERCEPTOR(int, dup, int oldfd) { 1614ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(dup, oldfd); 1615ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov int newfd = REAL(dup)(oldfd); 1616b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov if (oldfd >= 0 && newfd >= 0 && newfd != oldfd) 1617ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov FdDup(thr, pc, oldfd, newfd); 1618ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov return newfd; 1619ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov} 1620ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov 1621ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry VyukovTSAN_INTERCEPTOR(int, dup2, int oldfd, int newfd) { 1622ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(dup2, oldfd, newfd); 1623ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov int newfd2 = REAL(dup2)(oldfd, newfd); 1624b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov if (oldfd >= 0 && newfd2 >= 0 && newfd2 != oldfd) 1625ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov FdDup(thr, pc, oldfd, newfd2); 1626ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov return newfd2; 1627ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov} 1628ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov 1629ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry VyukovTSAN_INTERCEPTOR(int, dup3, int oldfd, int newfd, int flags) { 1630ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(dup3, oldfd, newfd, flags); 1631ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov int newfd2 = REAL(dup3)(oldfd, newfd, flags); 1632b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov if (oldfd >= 0 && newfd2 >= 0 && newfd2 != oldfd) 1633ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov FdDup(thr, pc, oldfd, newfd2); 1634ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov return newfd2; 1635ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov} 1636ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov 16376d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 163868230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, eventfd, unsigned initval, int flags) { 163968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(eventfd, initval, flags); 164068230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov int fd = REAL(eventfd)(initval, flags); 164168230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov if (fd >= 0) 164268230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov FdEventCreate(thr, pc, fd); 164368230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov return fd; 164468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov} 16456d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_EVENTFD TSAN_INTERCEPT(eventfd) 16466d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 16476d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_EVENTFD 16486d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 164968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov 16506d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 165145d4324bf5b0ec282f0a8f96312233e09a882502Dmitry VyukovTSAN_INTERCEPTOR(int, signalfd, int fd, void *mask, int flags) { 165245d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(signalfd, fd, mask, flags); 1653b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov if (fd >= 0) 1654b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov FdClose(thr, pc, fd); 165545d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov fd = REAL(signalfd)(fd, mask, flags); 165645d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov if (fd >= 0) 165745d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov FdSignalCreate(thr, pc, fd); 165845d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov return fd; 165945d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov} 16606d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_SIGNALFD TSAN_INTERCEPT(signalfd) 16616d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 16626d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_SIGNALFD 16636d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 166445d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov 16656d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 1666b75c67b495ca13801cc629b2c2c9dd0010e54739Dmitry VyukovTSAN_INTERCEPTOR(int, inotify_init, int fake) { 1667b75c67b495ca13801cc629b2c2c9dd0010e54739Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(inotify_init, fake); 1668b75c67b495ca13801cc629b2c2c9dd0010e54739Dmitry Vyukov int fd = REAL(inotify_init)(fake); 166945d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov if (fd >= 0) 167045d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov FdInotifyCreate(thr, pc, fd); 167145d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov return fd; 167245d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov} 16736d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT TSAN_INTERCEPT(inotify_init) 16746d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 16756d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT 16766d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 167745d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov 16786d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 167945d4324bf5b0ec282f0a8f96312233e09a882502Dmitry VyukovTSAN_INTERCEPTOR(int, inotify_init1, int flags) { 168045d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(inotify_init1, flags); 168145d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov int fd = REAL(inotify_init1)(flags); 168245d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov if (fd >= 0) 168345d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov FdInotifyCreate(thr, pc, fd); 168445d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov return fd; 168545d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov} 16866d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT1 TSAN_INTERCEPT(inotify_init1) 16876d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 16886d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT1 16896d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 169045d4324bf5b0ec282f0a8f96312233e09a882502Dmitry Vyukov 169168230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, socket, int domain, int type, int protocol) { 169268230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(socket, domain, type, protocol); 169368230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov int fd = REAL(socket)(domain, type, protocol); 169468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov if (fd >= 0) 169568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov FdSocketCreate(thr, pc, fd); 169668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov return fd; 169768230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov} 169868230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov 1699983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry VyukovTSAN_INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int *fd) { 1700983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(socketpair, domain, type, protocol, fd); 1701983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov int res = REAL(socketpair)(domain, type, protocol, fd); 1702983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov if (res == 0 && fd[0] >= 0 && fd[1] >= 0) 1703983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov FdPipeCreate(thr, pc, fd[0], fd[1]); 1704983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov return res; 1705983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov} 1706983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov 170768230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, connect, int fd, void *addr, unsigned addrlen) { 170868230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(connect, fd, addr, addrlen); 1709ed513f69b8017a69214509105e7ec59fec77b468Dmitry Vyukov FdSocketConnecting(thr, pc, fd); 171068230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov int res = REAL(connect)(fd, addr, addrlen); 1711b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov if (res == 0 && fd >= 0) 171268230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov FdSocketConnect(thr, pc, fd); 171368230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov return res; 171468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov} 171568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov 171652c70e5818727521b89f7fc95a2a383df8985ca6Dmitry VyukovTSAN_INTERCEPTOR(int, bind, int fd, void *addr, unsigned addrlen) { 171752c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(bind, fd, addr, addrlen); 171852c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov int res = REAL(bind)(fd, addr, addrlen); 171952c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov if (fd > 0 && res == 0) 172052c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov FdAccess(thr, pc, fd); 172152c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov return res; 172252c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov} 172352c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov 172452c70e5818727521b89f7fc95a2a383df8985ca6Dmitry VyukovTSAN_INTERCEPTOR(int, listen, int fd, int backlog) { 172552c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(listen, fd, backlog); 172652c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov int res = REAL(listen)(fd, backlog); 172752c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov if (fd > 0 && res == 0) 172852c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov FdAccess(thr, pc, fd); 172952c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov return res; 173052c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov} 173152c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov 17326d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 173368230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, epoll_create, int size) { 173468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(epoll_create, size); 173568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov int fd = REAL(epoll_create)(size); 173668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov if (fd >= 0) 173768230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov FdPollCreate(thr, pc, fd); 173868230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov return fd; 173968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov} 17406d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_EPOLL_CREATE TSAN_INTERCEPT(epoll_create) 17416d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 17426d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_EPOLL_CREATE 17436d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 174468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov 17456d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 174668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry VyukovTSAN_INTERCEPTOR(int, epoll_create1, int flags) { 174768230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(epoll_create1, flags); 174868230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov int fd = REAL(epoll_create1)(flags); 174968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov if (fd >= 0) 175068230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov FdPollCreate(thr, pc, fd); 175168230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov return fd; 175268230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov} 17536d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_EPOLL_CREATE1 TSAN_INTERCEPT(epoll_create1) 17546d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 17556d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_EPOLL_CREATE1 17566d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 175768230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov 1758ddeb2c354235818494d86827e88a0c2fa44bebccDmitry VyukovTSAN_INTERCEPTOR(int, close, int fd) { 1759ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov SCOPED_TSAN_INTERCEPTOR(close, fd); 1760c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov if (fd >= 0) 1761c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov FdClose(thr, pc, fd); 1762ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov return REAL(close)(fd); 1763ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov} 1764ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov 17656d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 1766c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry VyukovTSAN_INTERCEPTOR(int, __close, int fd) { 1767c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov SCOPED_TSAN_INTERCEPTOR(__close, fd); 1768c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov if (fd >= 0) 1769c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov FdClose(thr, pc, fd); 1770c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov return REAL(__close)(fd); 1771c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov} 17726d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT___CLOSE TSAN_INTERCEPT(__close) 17736d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 17746d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT___CLOSE 17756d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 1776c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov 177703f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov// glibc guts 17786d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 177903f224835f46801a0e22cc2951d21b67304e0457Dmitry VyukovTSAN_INTERCEPTOR(void, __res_iclose, void *state, bool free_addr) { 178003f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(__res_iclose, state, free_addr); 178103f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov int fds[64]; 178203f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov int cnt = ExtractResolvFDs(state, fds, ARRAY_SIZE(fds)); 178303f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov for (int i = 0; i < cnt; i++) { 178403f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov if (fds[i] > 0) 178503f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov FdClose(thr, pc, fds[i]); 178603f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov } 178703f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov REAL(__res_iclose)(state, free_addr); 178803f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov} 17896d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT___RES_ICLOSE TSAN_INTERCEPT(__res_iclose) 17906d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 17916d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT___RES_ICLOSE 17926d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 179303f224835f46801a0e22cc2951d21b67304e0457Dmitry Vyukov 179401e96987f557524a351b9f2229e7c920cdb96aadDmitry VyukovTSAN_INTERCEPTOR(int, pipe, int *pipefd) { 1795ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov SCOPED_TSAN_INTERCEPTOR(pipe, pipefd); 1796ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov int res = REAL(pipe)(pipefd); 1797b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov if (res == 0 && pipefd[0] >= 0 && pipefd[1] >= 0) 179868230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov FdPipeCreate(thr, pc, pipefd[0], pipefd[1]); 179901e96987f557524a351b9f2229e7c920cdb96aadDmitry Vyukov return res; 1800ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov} 1801ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov 180201e96987f557524a351b9f2229e7c920cdb96aadDmitry VyukovTSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) { 1803ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov SCOPED_TSAN_INTERCEPTOR(pipe2, pipefd, flags); 1804ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov int res = REAL(pipe2)(pipefd, flags); 1805b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov if (res == 0 && pipefd[0] >= 0 && pipefd[1] >= 0) 180668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov FdPipeCreate(thr, pc, pipefd[0], pipefd[1]); 1807ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov return res; 1808ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov} 1809ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov 18107ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, send, int fd, void *buf, long_t len, int flags) { 18117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(send, fd, buf, len, flags); 181267f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov if (fd >= 0) { 181367f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov FdAccess(thr, pc, fd); 1814b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov FdRelease(thr, pc, fd); 181567f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov } 18167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(send)(fd, buf, len, flags); 18177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 18187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 18197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 18207ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, sendmsg, int fd, void *msg, int flags) { 18217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(sendmsg, fd, msg, flags); 182267f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov if (fd >= 0) { 182367f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov FdAccess(thr, pc, fd); 1824b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov FdRelease(thr, pc, fd); 182567f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov } 18267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(sendmsg)(fd, msg, flags); 18277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 18287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 18297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 18307ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(long_t, recv, int fd, void *buf, long_t len, int flags) { 18317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(recv, fd, buf, len, flags); 183267f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov if (fd >= 0) 183367f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov FdAccess(thr, pc, fd); 18347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(recv)(fd, buf, len, flags); 1835b843c1fcc203accc4f37a784cb067904b3e79abeDmitry Vyukov if (res >= 0 && fd >= 0) { 18363f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov FdAcquire(thr, pc, fd); 18377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 18387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 18397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 18407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 18417ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, unlink, char *path) { 18427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(unlink, path); 1843c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov Release(thr, pc, File2addr(path)); 18447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(unlink)(path); 18457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 18467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 18477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 18482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesTSAN_INTERCEPTOR(void*, tmpfile, int fake) { 18492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines SCOPED_TSAN_INTERCEPTOR(tmpfile, fake); 18502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void *res = REAL(tmpfile)(fake); 1851c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov if (res) { 1852f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov int fd = fileno_unlocked(res); 1853c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov if (fd >= 0) 1854c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov FdFileCreate(thr, pc, fd); 1855c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov } 1856c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov return res; 1857c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov} 1858c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov 18596d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 18602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesTSAN_INTERCEPTOR(void*, tmpfile64, int fake) { 18612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines SCOPED_TSAN_INTERCEPTOR(tmpfile64, fake); 18622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void *res = REAL(tmpfile64)(fake); 1863c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov if (res) { 1864f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov int fd = fileno_unlocked(res); 1865c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov if (fd >= 0) 1866c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov FdFileCreate(thr, pc, fd); 1867c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov } 1868c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov return res; 1869c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov} 18706d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_TMPFILE64 TSAN_INTERCEPT(tmpfile64) 18716d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 18726d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_TMPFILE64 18736d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 1874c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov 18757ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(uptr, fread, void *ptr, uptr size, uptr nmemb, void *f) { 18768aa3d18712dec51d771523867305133ee41e006dDmitry Vyukov // libc file streams can call user-supplied functions, see fopencookie. 1877f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov { 1878f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(fread, ptr, size, nmemb, f); 1879f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov MemoryAccessRange(thr, pc, (uptr)ptr, size * nmemb, true); 1880f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov } 18817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return REAL(fread)(ptr, size, nmemb, f); 18827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 18837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 18847ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(uptr, fwrite, const void *p, uptr size, uptr nmemb, void *f) { 18858aa3d18712dec51d771523867305133ee41e006dDmitry Vyukov // libc file streams can call user-supplied functions, see fopencookie. 1886f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov { 1887f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(fwrite, p, size, nmemb, f); 1888f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov MemoryAccessRange(thr, pc, (uptr)p, size * nmemb, false); 1889f17b3822b22751f09549ab563cc5ca61d072b2e8Dmitry Vyukov } 18907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return REAL(fwrite)(p, size, nmemb, f); 18917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 18927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 189386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic void FlushStreams() { 189486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Flushing all the streams here may freeze the process if a child thread is 189586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // performing file stream operations at the same time. 189686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines REAL(fflush)(stdout); 189786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines REAL(fflush)(stderr); 189886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 189986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 19005043f05a633b8d2f19ebd3dda961408c69473718Dmitry VyukovTSAN_INTERCEPTOR(void, abort, int fake) { 19015043f05a633b8d2f19ebd3dda961408c69473718Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(abort, fake); 190286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines FlushStreams(); 19035043f05a633b8d2f19ebd3dda961408c69473718Dmitry Vyukov REAL(abort)(fake); 19045043f05a633b8d2f19ebd3dda961408c69473718Dmitry Vyukov} 19055043f05a633b8d2f19ebd3dda961408c69473718Dmitry Vyukov 19067ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, puts, const char *s) { 19077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(puts, s); 1908d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov MemoryAccessRange(thr, pc, (uptr)s, internal_strlen(s), false); 19097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return REAL(puts)(s); 19107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 19117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 19127ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, rmdir, char *path) { 19137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(rmdir, path); 1914c78839f0288e5af16101b5fd3b455e1a88cc1c5eDmitry Vyukov Release(thr, pc, Dir2addr(path)); 19157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(rmdir)(path); 19167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 19177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 19187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 191986277eb844c4983c81de62d7c050e92fe7155788Stephen HinesTSAN_INTERCEPTOR(int, closedir, void *dirp) { 192086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines SCOPED_TSAN_INTERCEPTOR(closedir, dirp); 192186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines int fd = dirfd(dirp); 192286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines FdClose(thr, pc, fd); 192386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return REAL(closedir)(dirp); 19247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 19257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 19266d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 19277ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) { 19287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(epoll_ctl, epfd, op, fd, ev); 192929cec483b760082e264340072f3245fad37e2255Dmitry Vyukov if (epfd >= 0) 193029cec483b760082e264340072f3245fad37e2255Dmitry Vyukov FdAccess(thr, pc, epfd); 193129cec483b760082e264340072f3245fad37e2255Dmitry Vyukov if (epfd >= 0 && fd >= 0) 193229cec483b760082e264340072f3245fad37e2255Dmitry Vyukov FdAccess(thr, pc, fd); 193329cec483b760082e264340072f3245fad37e2255Dmitry Vyukov if (op == EPOLL_CTL_ADD && epfd >= 0) 19343f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov FdRelease(thr, pc, epfd); 19357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int res = REAL(epoll_ctl)(epfd, op, fd, ev); 19367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 19377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 19386d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_EPOLL_CTL TSAN_INTERCEPT(epoll_ctl) 19396d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 19406d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_EPOLL_CTL 19416d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 19427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 19436d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 19447ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, epoll_wait, int epfd, void *ev, int cnt, int timeout) { 19457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(epoll_wait, epfd, ev, cnt, timeout); 194629cec483b760082e264340072f3245fad37e2255Dmitry Vyukov if (epfd >= 0) 194729cec483b760082e264340072f3245fad37e2255Dmitry Vyukov FdAccess(thr, pc, epfd); 1948ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov int res = BLOCK_REAL(epoll_wait)(epfd, ev, cnt, timeout); 194929cec483b760082e264340072f3245fad37e2255Dmitry Vyukov if (res > 0 && epfd >= 0) 19503f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov FdAcquire(thr, pc, epfd); 19517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 19527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 19536d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_EPOLL_WAIT TSAN_INTERCEPT(epoll_wait) 19546d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#else 19556d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#define TSAN_MAYBE_INTERCEPT_EPOLL_WAIT 19566d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 19577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 19582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesnamespace __tsan { 19592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 19606d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesstatic void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire, 19616d1862363c88c183b0ed7740fca876342cf0474bStephen Hines bool sigact, int sig, my_siginfo_t *info, void *uctx) { 19626d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (acquire) 19636d1862363c88c183b0ed7740fca876342cf0474bStephen Hines Acquire(thr, 0, (uptr)&sigactions[sig]); 19642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Ensure that the handler does not spoil errno. 19652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines const int saved_errno = errno; 19662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines errno = 99; 196786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // This code races with sigaction. Be careful to not read sa_sigaction twice. 196886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Also need to remember pc for reporting before the call, 196986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // because the handler can reset it. 197086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines volatile uptr pc = sigact ? 19712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (uptr)sigactions[sig].sa_sigaction : 19722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (uptr)sigactions[sig].sa_handler; 197386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (pc != (uptr)SIG_DFL && pc != (uptr)SIG_IGN) { 197486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (sigact) 197586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines ((sigactionhandler_t)pc)(sig, info, uctx); 197686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines else 197786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines ((sighandler_t)pc)(sig); 197886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 19792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // We do not detect errno spoiling for SIGTERM, 19802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // because some SIGTERM handlers do spoil errno but reraise SIGTERM, 19812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // tsan reports false positive in such case. 19822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // It's difficult to properly detect this situation (reraise), 19832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // because in async signal processing case (when handler is called directly 19842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // from rtl_generic_sighandler) we have not yet received the reraised 19852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // signal; and it looks too fragile to intercept all ways to reraise a signal. 19862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (flags()->report_bugs && !sync && sig != SIGTERM && errno != 99) { 19876d1862363c88c183b0ed7740fca876342cf0474bStephen Hines VarSizeStackTrace stack; 198886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // StackTrace::GetNestInstructionPc(pc) is used because return address is 198986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // expected, OutputReport() will undo this. 199086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines ObtainCurrentStack(thr, StackTrace::GetNextInstructionPc(pc), &stack); 19912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ThreadRegistryLock l(ctx->thread_registry); 19922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ScopedReport rep(ReportTypeErrnoInSignal); 19932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (!IsFiredSuppression(ctx, rep, stack)) { 19946d1862363c88c183b0ed7740fca876342cf0474bStephen Hines rep.AddStack(stack, true); 19956a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines OutputReport(thr, rep); 19962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 19972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 19982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines errno = saved_errno; 19992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 20002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 20012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid ProcessPendingSignals(ThreadState *thr) { 20027c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ThreadSignalContext *sctx = SigCtx(thr); 20036d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (sctx == 0 || 20046d1862363c88c183b0ed7740fca876342cf0474bStephen Hines atomic_load(&sctx->have_pending_signals, memory_order_relaxed) == 0) 20052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; 20066d1862363c88c183b0ed7740fca876342cf0474bStephen Hines atomic_store(&sctx->have_pending_signals, 0, memory_order_relaxed); 20076d1862363c88c183b0ed7740fca876342cf0474bStephen Hines atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed); 20082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // These are too big for stack. 20092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines static THREADLOCAL __sanitizer_sigset_t emptyset, oldset; 20107c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar CHECK_EQ(0, REAL(sigfillset)(&emptyset)); 20117c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &emptyset, &oldset)); 20122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines for (int sig = 0; sig < kSigCount; sig++) { 20132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines SignalDesc *signal = &sctx->pending_signals[sig]; 20142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (signal->armed) { 20152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines signal->armed = false; 201686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CallUserSignalHandler(thr, false, true, signal->sigaction, sig, 201786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines &signal->siginfo, &signal->ctx); 20182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 20192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 20207c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &oldset, 0)); 20216d1862363c88c183b0ed7740fca876342cf0474bStephen Hines atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed); 20222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 20232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 20242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} // namespace __tsan 20252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 20267c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarstatic bool is_sync_signal(ThreadSignalContext *sctx, int sig) { 20272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return sig == SIGSEGV || sig == SIGBUS || sig == SIGILL || 20282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE || sig == SIGSYS || 20292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // If we are sending signal to ourselves, we must process it now. 20302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (sctx && sig == sctx->int_signal_send); 20312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 20322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2033b157c67e17c3fc8805c8b7cb590668885680608fTimur Iskhodzhanovvoid ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig, 2034d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov my_siginfo_t *info, void *ctx) { 20357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany ThreadState *thr = cur_thread(); 20367c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ThreadSignalContext *sctx = SigCtx(thr); 20372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (sig < 0 || sig >= kSigCount) { 20382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines VPrintf(1, "ThreadSanitizer: ignoring signal %d\n", sig); 20392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; 20402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 2041d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov // Don't mess with synchronous signals. 20422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines const bool sync = is_sync_signal(sctx, sig); 20432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (sync || 20440bf04eab1910cc8bf622c20ba08c339dc25e297eDmitry Vyukov // If we are in blocking function, we can safely process it now 20450bf04eab1910cc8bf622c20ba08c339dc25e297eDmitry Vyukov // (but check if we are in a recursive interceptor, 20460bf04eab1910cc8bf622c20ba08c339dc25e297eDmitry Vyukov // i.e. pthread_join()->munmap()). 20476d1862363c88c183b0ed7740fca876342cf0474bStephen Hines (sctx && atomic_load(&sctx->in_blocking_func, memory_order_relaxed))) { 20486d1862363c88c183b0ed7740fca876342cf0474bStephen Hines atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed); 20496d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (sctx && atomic_load(&sctx->in_blocking_func, memory_order_relaxed)) { 20502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // We ignore interceptors in blocking functions, 20512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // temporary enbled them again while we are calling user function. 20522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines int const i = thr->ignore_interceptors; 20532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines thr->ignore_interceptors = 0; 20546d1862363c88c183b0ed7740fca876342cf0474bStephen Hines atomic_store(&sctx->in_blocking_func, 0, memory_order_relaxed); 20556d1862363c88c183b0ed7740fca876342cf0474bStephen Hines CallUserSignalHandler(thr, sync, true, sigact, sig, info, ctx); 20562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines thr->ignore_interceptors = i; 20576d1862363c88c183b0ed7740fca876342cf0474bStephen Hines atomic_store(&sctx->in_blocking_func, 1, memory_order_relaxed); 20582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } else { 20596d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // Be very conservative with when we do acquire in this case. 20606d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // It's unsafe to do acquire in async handlers, because ThreadState 20616d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // can be in inconsistent state. 20626d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // SIGSYS looks relatively safe -- it's synchronous and can actually 20636d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // need some global state. 20646d1862363c88c183b0ed7740fca876342cf0474bStephen Hines bool acq = (sig == SIGSYS); 20656d1862363c88c183b0ed7740fca876342cf0474bStephen Hines CallUserSignalHandler(thr, sync, acq, sigact, sig, info, ctx); 20662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 20676d1862363c88c183b0ed7740fca876342cf0474bStephen Hines atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed); 2068d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov return; 2069d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov } 2070d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov 20711fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov if (sctx == 0) 20721fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov return; 2073e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov SignalDesc *signal = &sctx->pending_signals[sig]; 20747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (signal->armed == false) { 20757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany signal->armed = true; 2076d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov signal->sigaction = sigact; 2077d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov if (info) 20786e4815579e5b48b48de092afcc3b092dfb97df5cDmitry Vyukov internal_memcpy(&signal->siginfo, info, sizeof(*info)); 2079a5562db12c5331433407ac21602086f34561c25cDmitry Vyukov if (ctx) 20806e4815579e5b48b48de092afcc3b092dfb97df5cDmitry Vyukov internal_memcpy(&signal->ctx, ctx, sizeof(signal->ctx)); 20816d1862363c88c183b0ed7740fca876342cf0474bStephen Hines atomic_store(&sctx->have_pending_signals, 1, memory_order_relaxed); 20827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 20837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 20847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2085d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukovstatic void rtl_sighandler(int sig) { 2086d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov rtl_generic_sighandler(false, sig, 0, 0); 2087d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov} 2088d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov 20897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void rtl_sigaction(int sig, my_siginfo_t *info, void *ctx) { 2090d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov rtl_generic_sighandler(true, sig, info, ctx); 20917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 20927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 20937ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyTSAN_INTERCEPTOR(int, sigaction, int sig, sigaction_t *act, sigaction_t *old) { 20947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany SCOPED_TSAN_INTERCEPTOR(sigaction, sig, act, old); 2095d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov if (old) 20966e4815579e5b48b48de092afcc3b092dfb97df5cDmitry Vyukov internal_memcpy(old, &sigactions[sig], sizeof(*old)); 2097d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov if (act == 0) 2098d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov return 0; 209986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Copy act into sigactions[sig]. 210086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Can't use struct copy, because compiler can emit call to memcpy. 210186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Can't use internal_memcpy, because it copies byte-by-byte, 210286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // and signal handler reads the sa_handler concurrently. It it can read 210386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // some bytes from old value and some bytes from new value. 210486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Use volatile to prevent insertion of memcpy. 210586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines sigactions[sig].sa_handler = *(volatile sighandler_t*)&act->sa_handler; 210686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines sigactions[sig].sa_flags = *(volatile int*)&act->sa_flags; 210786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines internal_memcpy(&sigactions[sig].sa_mask, &act->sa_mask, 210886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines sizeof(sigactions[sig].sa_mask)); 210986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if !SANITIZER_FREEBSD 211086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines sigactions[sig].sa_restorer = act->sa_restorer; 211186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif 21126e4815579e5b48b48de092afcc3b092dfb97df5cDmitry Vyukov sigaction_t newact; 21136e4815579e5b48b48de092afcc3b092dfb97df5cDmitry Vyukov internal_memcpy(&newact, act, sizeof(newact)); 21149a949a8909f652b28e9084de785c848743139fd5Evgeniy Stepanov REAL(sigfillset)(&newact.sa_mask); 2115d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL) { 21167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (newact.sa_flags & SA_SIGINFO) 21177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany newact.sa_sigaction = rtl_sigaction; 21187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else 21197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany newact.sa_handler = rtl_sighandler; 2120d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov } 21216d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ReleaseStore(thr, pc, (uptr)&sigactions[sig]); 2122d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov int res = REAL(sigaction)(sig, &newact, 0); 2123d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov return res; 2124d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov} 2125d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov 2126d91d06794506f10fb7599a2b835222fba29394e0Dmitry VyukovTSAN_INTERCEPTOR(sighandler_t, signal, int sig, sighandler_t h) { 21272135d8a7f4ba30fe35ed02d5e6ffd59a95b26219Alexey Samsonov sigaction_t act; 2128d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov act.sa_handler = h; 212988207ab15125e2f1e9b3d541b735b2b8aba9b6d9Alexey Samsonov REAL(memset)(&act.sa_mask, -1, sizeof(act.sa_mask)); 2130d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov act.sa_flags = 0; 21312135d8a7f4ba30fe35ed02d5e6ffd59a95b26219Alexey Samsonov sigaction_t old; 2132d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov int res = sigaction(sig, &act, &old); 2133d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov if (res) 2134d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov return SIG_ERR; 2135d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov return old.sa_handler; 2136d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov} 2137d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov 21389a949a8909f652b28e9084de785c848743139fd5Evgeniy StepanovTSAN_INTERCEPTOR(int, sigsuspend, const __sanitizer_sigset_t *mask) { 2139fbeab51e1cddbeb73ad0d86d1f650081178c1dd8Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(sigsuspend, mask); 2140fbeab51e1cddbeb73ad0d86d1f650081178c1dd8Dmitry Vyukov return REAL(sigsuspend)(mask); 2141fbeab51e1cddbeb73ad0d86d1f650081178c1dd8Dmitry Vyukov} 2142fbeab51e1cddbeb73ad0d86d1f650081178c1dd8Dmitry Vyukov 2143d91d06794506f10fb7599a2b835222fba29394e0Dmitry VyukovTSAN_INTERCEPTOR(int, raise, int sig) { 2144d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(raise, sig); 21457c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ThreadSignalContext *sctx = SigCtx(thr); 21461fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov CHECK_NE(sctx, 0); 2147e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov int prev = sctx->int_signal_send; 2148e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov sctx->int_signal_send = sig; 2149d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov int res = REAL(raise)(sig); 2150e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov CHECK_EQ(sctx->int_signal_send, sig); 2151e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov sctx->int_signal_send = prev; 2152d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov return res; 2153d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov} 2154d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov 2155d91d06794506f10fb7599a2b835222fba29394e0Dmitry VyukovTSAN_INTERCEPTOR(int, kill, int pid, int sig) { 2156d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(kill, pid, sig); 21577c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ThreadSignalContext *sctx = SigCtx(thr); 21581fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov CHECK_NE(sctx, 0); 2159e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov int prev = sctx->int_signal_send; 21600b694fcab9b2f33bdd6691cbea4e80a5c27191b1Peter Collingbourne if (pid == (int)internal_getpid()) { 2161e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov sctx->int_signal_send = sig; 2162d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov } 2163d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov int res = REAL(kill)(pid, sig); 21640b694fcab9b2f33bdd6691cbea4e80a5c27191b1Peter Collingbourne if (pid == (int)internal_getpid()) { 2165e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov CHECK_EQ(sctx->int_signal_send, sig); 2166e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov sctx->int_signal_send = prev; 2167d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov } 2168d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov return res; 2169d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov} 2170d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov 2171d91d06794506f10fb7599a2b835222fba29394e0Dmitry VyukovTSAN_INTERCEPTOR(int, pthread_kill, void *tid, int sig) { 2172d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(pthread_kill, tid, sig); 21737c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ThreadSignalContext *sctx = SigCtx(thr); 21741fc03d50a87302689482efa24b045a393097b6c3Dmitry Vyukov CHECK_NE(sctx, 0); 2175e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov int prev = sctx->int_signal_send; 2176d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov if (tid == pthread_self()) { 2177e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov sctx->int_signal_send = sig; 2178d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov } 2179d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov int res = REAL(pthread_kill)(tid, sig); 2180d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov if (tid == pthread_self()) { 2181e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov CHECK_EQ(sctx->int_signal_send, sig); 2182e96366613372e616fc6f2209b81b776f931a2c58Dmitry Vyukov sctx->int_signal_send = prev; 21837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 21847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return res; 21857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 21867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2187ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry VyukovTSAN_INTERCEPTOR(int, gettimeofday, void *tv, void *tz) { 2188ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(gettimeofday, tv, tz); 2189ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov // It's intercepted merely to process pending signals. 2190ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov return REAL(gettimeofday)(tv, tz); 2191ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov} 2192ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov 2193cf878fd3e01cd141ad1e095764d64c410c0ce763Dmitry VyukovTSAN_INTERCEPTOR(int, getaddrinfo, void *node, void *service, 2194cf878fd3e01cd141ad1e095764d64c410c0ce763Dmitry Vyukov void *hints, void *rv) { 2195cf878fd3e01cd141ad1e095764d64c410c0ce763Dmitry Vyukov SCOPED_TSAN_INTERCEPTOR(getaddrinfo, node, service, hints, rv); 2196cf878fd3e01cd141ad1e095764d64c410c0ce763Dmitry Vyukov // We miss atomic synchronization in getaddrinfo, 2197cf878fd3e01cd141ad1e095764d64c410c0ce763Dmitry Vyukov // and can report false race between malloc and free 2198cf878fd3e01cd141ad1e095764d64c410c0ce763Dmitry Vyukov // inside of getaddrinfo. So ignore memory accesses. 21992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ThreadIgnoreBegin(thr, pc); 2200cf878fd3e01cd141ad1e095764d64c410c0ce763Dmitry Vyukov int res = REAL(getaddrinfo)(node, service, hints, rv); 22012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ThreadIgnoreEnd(thr, pc); 2202cf878fd3e01cd141ad1e095764d64c410c0ce763Dmitry Vyukov return res; 2203cf878fd3e01cd141ad1e095764d64c410c0ce763Dmitry Vyukov} 2204cf878fd3e01cd141ad1e095764d64c410c0ce763Dmitry Vyukov 2205b75c67b495ca13801cc629b2c2c9dd0010e54739Dmitry VyukovTSAN_INTERCEPTOR(int, fork, int fake) { 22062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (cur_thread()->in_symbolizer) 22072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return REAL(fork)(fake); 22084af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov SCOPED_INTERCEPTOR_RAW(fork, fake); 22092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ForkBefore(thr, pc); 2210b75c67b495ca13801cc629b2c2c9dd0010e54739Dmitry Vyukov int pid = REAL(fork)(fake); 22114554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov if (pid == 0) { 22124554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov // child 22132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ForkChildAfter(thr, pc); 22144554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov FdOnFork(thr, pc); 22154554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov } else if (pid > 0) { 22164554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov // parent 22172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ForkParentAfter(thr, pc); 22182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } else { 22192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // error 22202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ForkParentAfter(thr, pc); 22214554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov } 22224554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov return pid; 22234554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov} 22244554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov 22252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesTSAN_INTERCEPTOR(int, vfork, int fake) { 22262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Some programs (e.g. openjdk) call close for all file descriptors 22272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // in the child process. Under tsan it leads to false positives, because 22282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // address space is shared, so the parent process also thinks that 22292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // the descriptors are closed (while they are actually not). 22302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // This leads to false positives due to missed synchronization. 22312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Strictly saying this is undefined behavior, because vfork child is not 22322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // allowed to call any functions other than exec/exit. But this is what 22332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // openjdk does, so we want to handle it. 22342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // We could disable interceptors in the child process. But it's not possible 22352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // to simply intercept and wrap vfork, because vfork child is not allowed 22362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // to return from the function that calls vfork, and that's exactly what 22372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // we would do. So this would require some assembly trickery as well. 22382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Instead we simply turn vfork into fork. 22392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return WRAP(fork)(fake); 22402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 22412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 224214dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukovstatic int OnExit(ThreadState *thr) { 224314dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukov int status = Finalize(thr); 224486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines FlushStreams(); 224514dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukov return status; 224614dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukov} 224714dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukov 2248996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanovstruct TsanInterceptorContext { 2249996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov ThreadState *thr; 2250996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov const uptr caller_pc; 2251996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov const uptr pc; 2252996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov}; 2253996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov 22542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void HandleRecvmsg(ThreadState *thr, uptr pc, 22552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines __sanitizer_msghdr *msg) { 22562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines int fds[64]; 22572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines int cnt = ExtractRecvmsgFDs(msg, fds, ARRAY_SIZE(fds)); 22582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines for (int i = 0; i < cnt; i++) 22592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines FdEventCreate(thr, pc, fds[i]); 22602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 22612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2262edd2821982c058469dca631a3147fdd42045c48aDmitry Vyukov#include "sanitizer_common/sanitizer_platform_interceptors.h" 2263917f62eaa5c2839155f703dee114a767ff81cca5Dmitry Vyukov// Causes interceptor recursion (getaddrinfo() and fopen()) 2264917f62eaa5c2839155f703dee114a767ff81cca5Dmitry Vyukov#undef SANITIZER_INTERCEPT_GETADDRINFO 22656d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// There interceptors do not seem to be strictly necessary for tsan. 22666d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// But we see cases where the interceptors consume 70% of execution time. 22676d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// Memory blocks passed to fgetgrent_r are "written to" by tsan several times. 22686d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// First, there is some recursion (getgrnam_r calls fgetgrent_r), and each 22696d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// function "writes to" the buffer. Then, the same memory is "written to" 22706d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// twice, first as buf and then as pwbufp (both of them refer to the same 22716d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// addresses). 22726d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#undef SANITIZER_INTERCEPT_GETPWENT 22736d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#undef SANITIZER_INTERCEPT_GETPWENT_R 22746d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#undef SANITIZER_INTERCEPT_FGETPWENT 22756d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#undef SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS 22766d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#undef SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS 227786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// __tls_get_addr can be called with mis-aligned stack due to: 227886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066 227986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// There are two potential issues: 228086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// 1. Sanitizer code contains a MOVDQA spill (it does not seem to be the case 228186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// right now). or 2. ProcessPendingSignal calls user handler which contains 228286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// MOVDQA spill (this happens right now). 228386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Since the interceptor only initializes memory for msan, the simplest solution 228486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// is to disable the interceptor in tsan (other sanitizers do not call 228586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// signal handlers from COMMON_INTERCEPTOR_ENTER). 228686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#undef SANITIZER_INTERCEPT_TLS_GET_ADDR 2287edd2821982c058469dca631a3147fdd42045c48aDmitry Vyukov 2288a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name) 22895cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov 22903fa122e6a8e12db6583793861f6cf776fe1c98a0Evgeniy Stepanov#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ 22913fa122e6a8e12db6583793861f6cf776fe1c98a0Evgeniy Stepanov MemoryAccessRange(((TsanInterceptorContext *)ctx)->thr, \ 22923fa122e6a8e12db6583793861f6cf776fe1c98a0Evgeniy Stepanov ((TsanInterceptorContext *)ctx)->pc, (uptr)ptr, size, \ 22939d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov true) 22945cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov 22959d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \ 22969d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov MemoryAccessRange(((TsanInterceptorContext *) ctx)->thr, \ 22979d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov ((TsanInterceptorContext *) ctx)->pc, (uptr) ptr, size, \ 22989d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov false) 22995cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov 23009d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ 23019d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov SCOPED_TSAN_INTERCEPTOR(func, __VA_ARGS__); \ 23029d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov TsanInterceptorContext _ctx = {thr, caller_pc, pc}; \ 23039d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov ctx = (void *)&_ctx; \ 23049d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov (void) ctx; 23055cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov 23062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, func, ...) \ 23072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \ 23082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines TsanInterceptorContext _ctx = {thr, caller_pc, pc}; \ 23092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ctx = (void *)&_ctx; \ 23102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (void) ctx; 23112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 23122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) \ 23132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Acquire(thr, pc, File2addr(path)); \ 23142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (file) { \ 23152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines int fd = fileno_unlocked(file); \ 23162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (fd >= 0) FdFileCreate(thr, pc, fd); \ 23172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 23182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 23192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) \ 23202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (file) { \ 23212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines int fd = fileno_unlocked(file); \ 23222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (fd >= 0) FdClose(thr, pc, fd); \ 23232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 23242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 232586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \ 23262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines libignore()->OnLibraryLoaded(filename) 23272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 23282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() \ 23292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines libignore()->OnLibraryUnloaded() 23302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 233186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \ 233286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines Acquire(((TsanInterceptorContext *) ctx)->thr, pc, Dir2addr(path)) 233386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 2334996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \ 23359d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov FdAcquire(((TsanInterceptorContext *) ctx)->thr, pc, fd) 23365cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov 2337996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \ 23389d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov FdRelease(((TsanInterceptorContext *) ctx)->thr, pc, fd) 23395cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov 234067f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) \ 234167f5544391c338411b0006bda7dc1b852bbdd4fbDmitry Vyukov FdAccess(((TsanInterceptorContext *) ctx)->thr, pc, fd) 23425cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov 23439d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \ 23449d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov FdSocketAccept(((TsanInterceptorContext *) ctx)->thr, pc, fd, newfd) 23455cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov 2346996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \ 23479d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov ThreadSetName(((TsanInterceptorContext *) ctx)->thr, name) 23485cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov 23495cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \ 23502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines __tsan::ctx->thread_registry->SetThreadNameByUserId(thread, name) 23515cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov 2352e18e3f07802c420eb4b2da407e148084b75cecc9Evgeniy Stepanov#define COMMON_INTERCEPTOR_BLOCK_REAL(name) BLOCK_REAL(name) 23535cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov 235414dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukov#define COMMON_INTERCEPTOR_ON_EXIT(ctx) \ 235514dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukov OnExit(((TsanInterceptorContext *) ctx)->thr) 23565cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov 23575e2d3776a314629680921abd1d55d89d95a2da90Alexey Samsonov#define COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m) \ 23585e2d3776a314629680921abd1d55d89d95a2da90Alexey Samsonov MutexLock(((TsanInterceptorContext *)ctx)->thr, \ 23595e2d3776a314629680921abd1d55d89d95a2da90Alexey Samsonov ((TsanInterceptorContext *)ctx)->pc, (uptr)m) 23605cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov 23615e2d3776a314629680921abd1d55d89d95a2da90Alexey Samsonov#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) \ 23625e2d3776a314629680921abd1d55d89d95a2da90Alexey Samsonov MutexUnlock(((TsanInterceptorContext *)ctx)->thr, \ 23635e2d3776a314629680921abd1d55d89d95a2da90Alexey Samsonov ((TsanInterceptorContext *)ctx)->pc, (uptr)m) 23645cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov 236511f5309ec1bf13430c8a3a16f177d9e8e1190e38Dmitry Vyukov#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) \ 236611f5309ec1bf13430c8a3a16f177d9e8e1190e38Dmitry Vyukov MutexRepair(((TsanInterceptorContext *)ctx)->thr, \ 236711f5309ec1bf13430c8a3a16f177d9e8e1190e38Dmitry Vyukov ((TsanInterceptorContext *)ctx)->pc, (uptr)m) 236811f5309ec1bf13430c8a3a16f177d9e8e1190e38Dmitry Vyukov 23692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) \ 23702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines HandleRecvmsg(((TsanInterceptorContext *)ctx)->thr, \ 23712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ((TsanInterceptorContext *)ctx)->pc, msg) 23722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 23734f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov#include "sanitizer_common/sanitizer_common_interceptors.inc" 2374c8033193376c3326478a345c4ae6633d4d2862c6Kostya Serebryany 23756c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov#define TSAN_SYSCALL() \ 23766c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov ThreadState *thr = cur_thread(); \ 23772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (thr->ignore_interceptors) \ 23782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; \ 23796c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov ScopedSyscall scoped_syscall(thr) \ 23806c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov/**/ 23816c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov 23826c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukovstruct ScopedSyscall { 23836c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov ThreadState *thr; 23846c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov 23856c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov explicit ScopedSyscall(ThreadState *thr) 23866c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov : thr(thr) { 23872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Initialize(thr); 23886c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov } 23896c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov 23906c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov ~ScopedSyscall() { 23912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ProcessPendingSignals(thr); 23926c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov } 23936c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov}; 23946c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov 2395eb0be61dee155f501bb249287b17d364fedf3507Dmitry Vyukovstatic void syscall_access_range(uptr pc, uptr p, uptr s, bool write) { 23966c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov TSAN_SYSCALL(); 2397eb0be61dee155f501bb249287b17d364fedf3507Dmitry Vyukov MemoryAccessRange(thr, pc, p, s, write); 2398eb0be61dee155f501bb249287b17d364fedf3507Dmitry Vyukov} 2399eb0be61dee155f501bb249287b17d364fedf3507Dmitry Vyukov 24002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void syscall_acquire(uptr pc, uptr addr) { 24012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines TSAN_SYSCALL(); 24022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Acquire(thr, pc, addr); 24032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines DPrintf("syscall_acquire(%p)\n", addr); 24042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 24052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 24062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void syscall_release(uptr pc, uptr addr) { 24072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines TSAN_SYSCALL(); 24082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines DPrintf("syscall_release(%p)\n", addr); 24092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Release(thr, pc, addr); 24102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 24112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2412b47d41f310d9069f68135b7b8cc92b09f7436c4dDmitry Vyukovstatic void syscall_fd_close(uptr pc, int fd) { 24136c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov TSAN_SYSCALL(); 24142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines FdClose(thr, pc, fd); 24152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 24162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 24172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic USED void syscall_fd_acquire(uptr pc, int fd) { 24182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines TSAN_SYSCALL(); 24192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines FdAcquire(thr, pc, fd); 24202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines DPrintf("syscall_fd_acquire(%p)\n", fd); 24212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 24222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 24232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic USED void syscall_fd_release(uptr pc, int fd) { 24242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines TSAN_SYSCALL(); 24252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines DPrintf("syscall_fd_release(%p)\n", fd); 24262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines FdRelease(thr, pc, fd); 24276c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov} 24286c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov 24296c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukovstatic void syscall_pre_fork(uptr pc) { 24306c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov TSAN_SYSCALL(); 24312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ForkBefore(thr, pc); 24326c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov} 24336c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov 24342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void syscall_post_fork(uptr pc, int pid) { 24356c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov TSAN_SYSCALL(); 24362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (pid == 0) { 24376c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov // child 24382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ForkChildAfter(thr, pc); 24396c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov FdOnFork(thr, pc); 24402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } else if (pid > 0) { 24416c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov // parent 24422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ForkParentAfter(thr, pc); 24432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } else { 24442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // error 24452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines ForkParentAfter(thr, pc); 24466c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov } 2447b47d41f310d9069f68135b7b8cc92b09f7436c4dDmitry Vyukov} 2448b47d41f310d9069f68135b7b8cc92b09f7436c4dDmitry Vyukov 2449c09250fce4e017c8da696a7f01abc125ba2288adAlexey Samsonov#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) \ 2450eb0be61dee155f501bb249287b17d364fedf3507Dmitry Vyukov syscall_access_range(GET_CALLER_PC(), (uptr)(p), (uptr)(s), false) 24512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2452c09250fce4e017c8da696a7f01abc125ba2288adAlexey Samsonov#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \ 2453eb0be61dee155f501bb249287b17d364fedf3507Dmitry Vyukov syscall_access_range(GET_CALLER_PC(), (uptr)(p), (uptr)(s), true) 24542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2455c09250fce4e017c8da696a7f01abc125ba2288adAlexey Samsonov#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \ 24560b76578bf5bf04a0674ac5a27ade01e3da26a0c9Evgeniy Stepanov do { \ 24570b76578bf5bf04a0674ac5a27ade01e3da26a0c9Evgeniy Stepanov (void)(p); \ 24580b76578bf5bf04a0674ac5a27ade01e3da26a0c9Evgeniy Stepanov (void)(s); \ 24590b76578bf5bf04a0674ac5a27ade01e3da26a0c9Evgeniy Stepanov } while (false) 24602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2461c09250fce4e017c8da696a7f01abc125ba2288adAlexey Samsonov#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \ 24620b76578bf5bf04a0674ac5a27ade01e3da26a0c9Evgeniy Stepanov do { \ 24630b76578bf5bf04a0674ac5a27ade01e3da26a0c9Evgeniy Stepanov (void)(p); \ 24640b76578bf5bf04a0674ac5a27ade01e3da26a0c9Evgeniy Stepanov (void)(s); \ 24650b76578bf5bf04a0674ac5a27ade01e3da26a0c9Evgeniy Stepanov } while (false) 24662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 24672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define COMMON_SYSCALL_ACQUIRE(addr) \ 24682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines syscall_acquire(GET_CALLER_PC(), (uptr)(addr)) 24692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 24702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define COMMON_SYSCALL_RELEASE(addr) \ 24712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines syscall_release(GET_CALLER_PC(), (uptr)(addr)) 24722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 24730b76578bf5bf04a0674ac5a27ade01e3da26a0c9Evgeniy Stepanov#define COMMON_SYSCALL_FD_CLOSE(fd) syscall_fd_close(GET_CALLER_PC(), fd) 24742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 24752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define COMMON_SYSCALL_FD_ACQUIRE(fd) syscall_fd_acquire(GET_CALLER_PC(), fd) 24762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 24772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define COMMON_SYSCALL_FD_RELEASE(fd) syscall_fd_release(GET_CALLER_PC(), fd) 24782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 24796c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov#define COMMON_SYSCALL_PRE_FORK() \ 24806c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov syscall_pre_fork(GET_CALLER_PC()) 24812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 24826c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov#define COMMON_SYSCALL_POST_FORK(res) \ 24836c21e11b36bb5ebf625463ca6724cf936ef0dc39Dmitry Vyukov syscall_post_fork(GET_CALLER_PC(), res) 24842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2485881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov#include "sanitizer_common/sanitizer_common_syscalls.inc" 2486881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov 2487ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukovnamespace __tsan { 2488ee8ee2437b28ab8bf6f48af15b8b446fb5d55e90Dmitry Vyukov 2489c78140f0bd5d6b44a2a30d82879480c592f10d52Dmitry Vyukovstatic void finalize(void *arg) { 249014dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukov ThreadState *thr = cur_thread(); 2491c78140f0bd5d6b44a2a30d82879480c592f10d52Dmitry Vyukov int status = Finalize(thr); 24922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // Make sure the output is not lost. 249386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines FlushStreams(); 2494c78140f0bd5d6b44a2a30d82879480c592f10d52Dmitry Vyukov if (status) 2495c78140f0bd5d6b44a2a30d82879480c592f10d52Dmitry Vyukov REAL(_exit)(status); 2496c78140f0bd5d6b44a2a30d82879480c592f10d52Dmitry Vyukov} 2497c78140f0bd5d6b44a2a30d82879480c592f10d52Dmitry Vyukov 249891ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukovstatic void unreachable() { 24992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines Report("FATAL: ThreadSanitizer: unreachable called\n"); 250091ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov Die(); 250191ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov} 250291ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov 25037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid InitializeInterceptors() { 25047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // We need to setup it early, because functions like dlsym() can call it. 2505065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov REAL(memset) = internal_memset; 2506065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov REAL(memcpy) = internal_memcpy; 2507065c4ac846589d04436cb7f19f938ff42035313eDmitry Vyukov REAL(memcmp) = internal_memcmp; 25087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 25098e1c769ed84f4d5cf23904dee1abeec6f125f1acDmitry Vyukov // Instruct libc malloc to consume less memory. 25106d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#if !SANITIZER_FREEBSD 25118e1c769ed84f4d5cf23904dee1abeec6f125f1acDmitry Vyukov mallopt(1, 0); // M_MXFAST 25128e1c769ed84f4d5cf23904dee1abeec6f125f1acDmitry Vyukov mallopt(-3, 32*1024); // M_MMAP_THRESHOLD 25136d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#endif 25148e1c769ed84f4d5cf23904dee1abeec6f125f1acDmitry Vyukov 25152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines InitializeCommonInterceptors(); 25162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 25172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // We can not use TSAN_INTERCEPT to get setjmp addr, 25182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // because it does &setjmp and setjmp is not present in some versions of libc. 25192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines using __interception::GetRealFunctionAddress; 25202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines GetRealFunctionAddress("setjmp", (uptr*)&REAL(setjmp), 0, 0); 25212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines GetRealFunctionAddress("_setjmp", (uptr*)&REAL(_setjmp), 0, 0); 25222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines GetRealFunctionAddress("sigsetjmp", (uptr*)&REAL(sigsetjmp), 0, 0); 25232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines GetRealFunctionAddress("__sigsetjmp", (uptr*)&REAL(__sigsetjmp), 0, 0); 2524c8033193376c3326478a345c4ae6633d4d2862c6Kostya Serebryany 2525f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov TSAN_INTERCEPT(longjmp); 2526f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov TSAN_INTERCEPT(siglongjmp); 2527f037f565b2e02878ceb6e7b49647e814e2990ef5Dmitry Vyukov 25287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(malloc); 252907ba8ef44deb54baa9307298fbffe25ddb30c362Dmitry Vyukov TSAN_INTERCEPT(__libc_memalign); 25307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(calloc); 25317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(realloc); 25327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(free); 25337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(cfree); 25347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(mmap); 25356d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT_MMAP64; 25367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(munmap); 25376d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT_MEMALIGN; 25387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(valloc); 25396d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT_PVALLOC; 25407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(posix_memalign); 25417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 25427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(strlen); 25437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(memset); 25447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(memcpy); 25457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(memmove); 25467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(memcmp); 25477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(strchr); 25487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(strchrnul); 25497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(strrchr); 25507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(strcpy); // NOLINT 25517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(strncpy); 25527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(strstr); 255339fa68e4076f6a86765ddc69c44bcecb804f0b53Dmitry Vyukov TSAN_INTERCEPT(strdup); 25547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 25557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_create); 25567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_join); 25577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_detach); 25587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 25592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines TSAN_INTERCEPT_VER(pthread_cond_init, "GLIBC_2.3.2"); 25602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines TSAN_INTERCEPT_VER(pthread_cond_signal, "GLIBC_2.3.2"); 25612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines TSAN_INTERCEPT_VER(pthread_cond_broadcast, "GLIBC_2.3.2"); 25622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines TSAN_INTERCEPT_VER(pthread_cond_wait, "GLIBC_2.3.2"); 25632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines TSAN_INTERCEPT_VER(pthread_cond_timedwait, "GLIBC_2.3.2"); 25642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines TSAN_INTERCEPT_VER(pthread_cond_destroy, "GLIBC_2.3.2"); 25652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 25667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_mutex_init); 25677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_mutex_destroy); 25687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_mutex_trylock); 25697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_mutex_timedlock); 25707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 25717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_spin_init); 25727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_spin_destroy); 25737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_spin_lock); 25747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_spin_trylock); 25757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_spin_unlock); 25767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 25777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_rwlock_init); 25787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_rwlock_destroy); 25797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_rwlock_rdlock); 25807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_rwlock_tryrdlock); 25817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_rwlock_timedrdlock); 25827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_rwlock_wrlock); 25837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_rwlock_trywrlock); 25847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_rwlock_timedwrlock); 25857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_rwlock_unlock); 25867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 25877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_barrier_init); 25887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_barrier_destroy); 25897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_barrier_wait); 25907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 25917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(pthread_once); 25927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 25937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(sem_init); 25947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(sem_destroy); 25957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(sem_wait); 25967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(sem_trywait); 25977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(sem_timedwait); 25987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(sem_post); 25997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(sem_getvalue); 26007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 260161ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov TSAN_INTERCEPT(stat); 26026d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT___XSTAT; 26036d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT_STAT64; 26046d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT___XSTAT64; 260561ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov TSAN_INTERCEPT(lstat); 26066d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT___LXSTAT; 26076d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT_LSTAT64; 26086d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT___LXSTAT64; 260961ba1b5df34614e0647f5f80d462f6485e817fa5Dmitry Vyukov TSAN_INTERCEPT(fstat); 26106d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT___FXSTAT; 26116d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT_FSTAT64; 26126d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT___FXSTAT64; 2613ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov TSAN_INTERCEPT(open); 26146d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT_OPEN64; 2615ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov TSAN_INTERCEPT(creat); 26166d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT_CREAT64; 2617ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov TSAN_INTERCEPT(dup); 2618ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov TSAN_INTERCEPT(dup2); 2619ba3ae356e0827bfdb17feaff53e17c3934470404Dmitry Vyukov TSAN_INTERCEPT(dup3); 26206d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT_EVENTFD; 26216d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT_SIGNALFD; 26226d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT_INOTIFY_INIT; 26236d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT_INOTIFY_INIT1; 262468230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov TSAN_INTERCEPT(socket); 2625983518e360a179d92bdbddebe05a87db3c6cc3c0Dmitry Vyukov TSAN_INTERCEPT(socketpair); 262668230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov TSAN_INTERCEPT(connect); 262752c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov TSAN_INTERCEPT(bind); 262852c70e5818727521b89f7fc95a2a383df8985ca6Dmitry Vyukov TSAN_INTERCEPT(listen); 26296d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT_EPOLL_CREATE; 26306d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT_EPOLL_CREATE1; 2631ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov TSAN_INTERCEPT(close); 26326d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT___CLOSE; 26336d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT___RES_ICLOSE; 2634ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov TSAN_INTERCEPT(pipe); 2635ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov TSAN_INTERCEPT(pipe2); 2636ddeb2c354235818494d86827e88a0c2fa44bebccDmitry Vyukov 26377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(send); 26387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(sendmsg); 26397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(recv); 26407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 26417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(unlink); 26422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines TSAN_INTERCEPT(tmpfile); 26436d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT_TMPFILE64; 26447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(fread); 26457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(fwrite); 26465043f05a633b8d2f19ebd3dda961408c69473718Dmitry Vyukov TSAN_INTERCEPT(abort); 26477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(puts); 26487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(rmdir); 264986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines TSAN_INTERCEPT(closedir); 26507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 26516d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT_EPOLL_CTL; 26526d1862363c88c183b0ed7740fca876342cf0474bStephen Hines TSAN_MAYBE_INTERCEPT_EPOLL_WAIT; 26537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 26547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany TSAN_INTERCEPT(sigaction); 2655d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov TSAN_INTERCEPT(signal); 2656fbeab51e1cddbeb73ad0d86d1f650081178c1dd8Dmitry Vyukov TSAN_INTERCEPT(sigsuspend); 2657d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov TSAN_INTERCEPT(raise); 2658d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov TSAN_INTERCEPT(kill); 2659d91d06794506f10fb7599a2b835222fba29394e0Dmitry Vyukov TSAN_INTERCEPT(pthread_kill); 2660848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov TSAN_INTERCEPT(sleep); 2661848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov TSAN_INTERCEPT(usleep); 2662848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov TSAN_INTERCEPT(nanosleep); 2663aad173b2f1dae9f88bbffd217ebd46ed1f020bcbDmitry Vyukov TSAN_INTERCEPT(gettimeofday); 2664cf878fd3e01cd141ad1e095764d64c410c0ce763Dmitry Vyukov TSAN_INTERCEPT(getaddrinfo); 26657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 26664554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov TSAN_INTERCEPT(fork); 26672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines TSAN_INTERCEPT(vfork); 266831c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov TSAN_INTERCEPT(on_exit); 266931c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov TSAN_INTERCEPT(__cxa_atexit); 2670c78140f0bd5d6b44a2a30d82879480c592f10d52Dmitry Vyukov TSAN_INTERCEPT(_exit); 26714554b7a7b345cd50ff8138b3cda8dd1135b965faDmitry Vyukov 267291ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov // Need to setup it, because interceptors check that the function is resolved. 267391ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov // But atexit is emitted directly into the module, so can't be resolved. 267491ac008b435b879bb366bcf9516c53f2d07c30b1Dmitry Vyukov REAL(atexit) = (int(*)(void(*)()))unreachable; 267531c05ea4d508a476403ba30c1f60ef6190eb46b6Dmitry Vyukov if (REAL(__cxa_atexit)(&finalize, 0, 0)) { 2676b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("ThreadSanitizer: failed to setup atexit callback\n"); 26777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Die(); 26787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 26797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 26807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) { 2681b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("ThreadSanitizer: failed to create thread key\n"); 26827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Die(); 26837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 26843f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov 26853f4e6d9b75fb3f7f2674a31008738cfda9cda9edDmitry Vyukov FdInit(); 26867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 26877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 26887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} // namespace __tsan 2689