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