17ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev//=-- lsan_interceptors.cc ------------------------------------------------===//
27ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev//
37ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev//                     The LLVM Compiler Infrastructure
47ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev//
57ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev// This file is distributed under the University of Illinois Open Source
67ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev// License. See LICENSE.TXT for details.
77ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev//
87ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev//===----------------------------------------------------------------------===//
97ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev//
107ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev// This file is a part of LeakSanitizer.
117ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev// Interceptors for standalone LSan.
127ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev//
137ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev//===----------------------------------------------------------------------===//
147ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
156d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#include "interception/interception.h"
167ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev#include "sanitizer_common/sanitizer_allocator.h"
177ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev#include "sanitizer_common/sanitizer_atomic.h"
187ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev#include "sanitizer_common/sanitizer_common.h"
197ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev#include "sanitizer_common/sanitizer_flags.h"
207ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev#include "sanitizer_common/sanitizer_internal_defs.h"
217ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev#include "sanitizer_common/sanitizer_linux.h"
227ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev#include "sanitizer_common/sanitizer_platform_limits_posix.h"
237ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev#include "lsan.h"
247ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev#include "lsan_allocator.h"
257ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev#include "lsan_thread.h"
267ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
277ea7d20ea31f2146817967512356652cc1f72004Sergey Matveevusing namespace __lsan;
287ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
297ea7d20ea31f2146817967512356652cc1f72004Sergey Matveevextern "C" {
307ea7d20ea31f2146817967512356652cc1f72004Sergey Matveevint pthread_attr_init(void *attr);
317ea7d20ea31f2146817967512356652cc1f72004Sergey Matveevint pthread_attr_destroy(void *attr);
327ea7d20ea31f2146817967512356652cc1f72004Sergey Matveevint pthread_attr_getdetachstate(void *attr, int *v);
337ea7d20ea31f2146817967512356652cc1f72004Sergey Matveevint pthread_key_create(unsigned *key, void (*destructor)(void* v));
347ea7d20ea31f2146817967512356652cc1f72004Sergey Matveevint pthread_setspecific(unsigned key, const void *v);
357ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev}
367ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
3774c88796a4024922144660ed1ade519af5008fe2Sergey Matveev#define ENSURE_LSAN_INITED do {   \
3874c88796a4024922144660ed1ade519af5008fe2Sergey Matveev  CHECK(!lsan_init_is_running);   \
3974c88796a4024922144660ed1ade519af5008fe2Sergey Matveev  if (!lsan_inited)               \
4074c88796a4024922144660ed1ade519af5008fe2Sergey Matveev    __lsan_init();                \
4174c88796a4024922144660ed1ade519af5008fe2Sergey Matveev} while (0)
4274c88796a4024922144660ed1ade519af5008fe2Sergey Matveev
437ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev///// Malloc/free interceptors. /////
447ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
45d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveevconst bool kAlwaysClearMemory = true;
46d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev
477ea7d20ea31f2146817967512356652cc1f72004Sergey Matveevnamespace std {
487ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  struct nothrow_t;
497ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev}
507ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
517ea7d20ea31f2146817967512356652cc1f72004Sergey MatveevINTERCEPTOR(void*, malloc, uptr size) {
5274c88796a4024922144660ed1ade519af5008fe2Sergey Matveev  ENSURE_LSAN_INITED;
536d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  GET_STACK_TRACE_MALLOC;
54d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev  return Allocate(stack, size, 1, kAlwaysClearMemory);
557ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev}
567ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
577ea7d20ea31f2146817967512356652cc1f72004Sergey MatveevINTERCEPTOR(void, free, void *p) {
5874c88796a4024922144660ed1ade519af5008fe2Sergey Matveev  ENSURE_LSAN_INITED;
597ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  Deallocate(p);
607ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev}
617ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
627ea7d20ea31f2146817967512356652cc1f72004Sergey MatveevINTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
6374c88796a4024922144660ed1ade519af5008fe2Sergey Matveev  if (lsan_init_is_running) {
6474c88796a4024922144660ed1ade519af5008fe2Sergey Matveev    // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
6574c88796a4024922144660ed1ade519af5008fe2Sergey Matveev    const uptr kCallocPoolSize = 1024;
6674c88796a4024922144660ed1ade519af5008fe2Sergey Matveev    static uptr calloc_memory_for_dlsym[kCallocPoolSize];
6774c88796a4024922144660ed1ade519af5008fe2Sergey Matveev    static uptr allocated;
6874c88796a4024922144660ed1ade519af5008fe2Sergey Matveev    uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
6974c88796a4024922144660ed1ade519af5008fe2Sergey Matveev    void *mem = (void*)&calloc_memory_for_dlsym[allocated];
7074c88796a4024922144660ed1ade519af5008fe2Sergey Matveev    allocated += size_in_words;
7174c88796a4024922144660ed1ade519af5008fe2Sergey Matveev    CHECK(allocated < kCallocPoolSize);
7274c88796a4024922144660ed1ade519af5008fe2Sergey Matveev    return mem;
7374c88796a4024922144660ed1ade519af5008fe2Sergey Matveev  }
747ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  if (CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0;
7574c88796a4024922144660ed1ade519af5008fe2Sergey Matveev  ENSURE_LSAN_INITED;
766d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  GET_STACK_TRACE_MALLOC;
777ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  size *= nmemb;
787ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  return Allocate(stack, size, 1, true);
797ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev}
807ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
817ea7d20ea31f2146817967512356652cc1f72004Sergey MatveevINTERCEPTOR(void*, realloc, void *q, uptr size) {
8274c88796a4024922144660ed1ade519af5008fe2Sergey Matveev  ENSURE_LSAN_INITED;
836d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  GET_STACK_TRACE_MALLOC;
847ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  return Reallocate(stack, q, size, 1);
857ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev}
867ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
877ea7d20ea31f2146817967512356652cc1f72004Sergey MatveevINTERCEPTOR(void*, memalign, uptr alignment, uptr size) {
8874c88796a4024922144660ed1ade519af5008fe2Sergey Matveev  ENSURE_LSAN_INITED;
896d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  GET_STACK_TRACE_MALLOC;
90d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev  return Allocate(stack, size, alignment, kAlwaysClearMemory);
917ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev}
927ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
936a211c5814e25d6745a5058cc0e499e5235d3821Stephen HinesINTERCEPTOR(void*, aligned_alloc, uptr alignment, uptr size) {
946a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  ENSURE_LSAN_INITED;
956d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  GET_STACK_TRACE_MALLOC;
966a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  return Allocate(stack, size, alignment, kAlwaysClearMemory);
976a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines}
986a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
997ea7d20ea31f2146817967512356652cc1f72004Sergey MatveevINTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
10074c88796a4024922144660ed1ade519af5008fe2Sergey Matveev  ENSURE_LSAN_INITED;
1016d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  GET_STACK_TRACE_MALLOC;
102d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev  *memptr = Allocate(stack, size, alignment, kAlwaysClearMemory);
1037ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  // FIXME: Return ENOMEM if user requested more than max alloc size.
1047ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  return 0;
1057ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev}
1067ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
1077ea7d20ea31f2146817967512356652cc1f72004Sergey MatveevINTERCEPTOR(void*, valloc, uptr size) {
10874c88796a4024922144660ed1ade519af5008fe2Sergey Matveev  ENSURE_LSAN_INITED;
1096d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  GET_STACK_TRACE_MALLOC;
1107ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  if (size == 0)
1117ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev    size = GetPageSizeCached();
112d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev  return Allocate(stack, size, GetPageSizeCached(), kAlwaysClearMemory);
1137ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev}
1147ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
1157ea7d20ea31f2146817967512356652cc1f72004Sergey MatveevINTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
11674c88796a4024922144660ed1ade519af5008fe2Sergey Matveev  ENSURE_LSAN_INITED;
1177ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  return GetMallocUsableSize(ptr);
1187ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev}
1197ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
1207ea7d20ea31f2146817967512356652cc1f72004Sergey Matveevstruct fake_mallinfo {
1217ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  int x[10];
1227ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev};
1237ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
1247ea7d20ea31f2146817967512356652cc1f72004Sergey MatveevINTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
1257ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  struct fake_mallinfo res;
1267ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  internal_memset(&res, 0, sizeof(res));
1277ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  return res;
1287ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev}
1297ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
1307ea7d20ea31f2146817967512356652cc1f72004Sergey MatveevINTERCEPTOR(int, mallopt, int cmd, int value) {
1317ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  return -1;
1327ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev}
1337ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
134d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey MatveevINTERCEPTOR(void*, pvalloc, uptr size) {
13574c88796a4024922144660ed1ade519af5008fe2Sergey Matveev  ENSURE_LSAN_INITED;
1366d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  GET_STACK_TRACE_MALLOC;
137d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev  uptr PageSize = GetPageSizeCached();
138d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev  size = RoundUpTo(size, PageSize);
139d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev  if (size == 0) {
140d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev    // pvalloc(0) should allocate one page.
141d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev    size = PageSize;
142d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev  }
143d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev  return Allocate(stack, size, GetPageSizeCached(), kAlwaysClearMemory);
144d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev}
145d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev
1462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPTOR(void, cfree, void *p) ALIAS(WRAPPER_NAME(free));
147d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev
148d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev#define OPERATOR_NEW_BODY                              \
14974c88796a4024922144660ed1ade519af5008fe2Sergey Matveev  ENSURE_LSAN_INITED;                                  \
1506d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  GET_STACK_TRACE_MALLOC;                              \
151d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev  return Allocate(stack, size, 1, kAlwaysClearMemory);
152d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev
153d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey MatveevINTERCEPTOR_ATTRIBUTE
154d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveevvoid *operator new(uptr size) { OPERATOR_NEW_BODY; }
155d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey MatveevINTERCEPTOR_ATTRIBUTE
156d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveevvoid *operator new[](uptr size) { OPERATOR_NEW_BODY; }
157d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey MatveevINTERCEPTOR_ATTRIBUTE
158d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveevvoid *operator new(uptr size, std::nothrow_t const&) { OPERATOR_NEW_BODY; }
159d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey MatveevINTERCEPTOR_ATTRIBUTE
160d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveevvoid *operator new[](uptr size, std::nothrow_t const&) { OPERATOR_NEW_BODY; }
161d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev
162d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev#define OPERATOR_DELETE_BODY \
16374c88796a4024922144660ed1ade519af5008fe2Sergey Matveev  ENSURE_LSAN_INITED;        \
164d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev  Deallocate(ptr);
165d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev
166d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey MatveevINTERCEPTOR_ATTRIBUTE
1672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid operator delete(void *ptr) throw() { OPERATOR_DELETE_BODY; }
168d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey MatveevINTERCEPTOR_ATTRIBUTE
1692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid operator delete[](void *ptr) throw() { OPERATOR_DELETE_BODY; }
170d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey MatveevINTERCEPTOR_ATTRIBUTE
171d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveevvoid operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; }
172d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey MatveevINTERCEPTOR_ATTRIBUTE
173d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveevvoid operator delete[](void *ptr, std::nothrow_t const &) {
174d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev  OPERATOR_DELETE_BODY;
175d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev}
1767ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
1777ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev// We need this to intercept the __libc_memalign calls that are used to
1787ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev// allocate dynamic TLS space in ld-linux.so.
1792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPTOR(void *, __libc_memalign, uptr align, uptr s)
1802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    ALIAS(WRAPPER_NAME(memalign));
1817ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
1827ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev///// Thread initialization and finalization. /////
1837ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
1847ea7d20ea31f2146817967512356652cc1f72004Sergey Matveevstatic unsigned g_thread_finalize_key;
1857ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
1867ea7d20ea31f2146817967512356652cc1f72004Sergey Matveevstatic void thread_finalize(void *v) {
1877ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  uptr iter = (uptr)v;
1887ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  if (iter > 1) {
1897ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev    if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) {
1907ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev      Report("LeakSanitizer: failed to set thread key.\n");
1917ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev      Die();
1927ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev    }
1937ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev    return;
1947ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  }
1957ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  ThreadFinish();
1967ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev}
1977ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
1987ea7d20ea31f2146817967512356652cc1f72004Sergey Matveevstruct ThreadParam {
1997ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  void *(*callback)(void *arg);
2007ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  void *param;
2017ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  atomic_uintptr_t tid;
2027ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev};
2037ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
2047ea7d20ea31f2146817967512356652cc1f72004Sergey Matveevextern "C" void *__lsan_thread_start_func(void *arg) {
2057ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  ThreadParam *p = (ThreadParam*)arg;
2067ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  void* (*callback)(void *arg) = p->callback;
2077ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  void *param = p->param;
2087ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  // Wait until the last iteration to maximize the chance that we are the last
2097ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  // destructor to run.
2107ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  if (pthread_setspecific(g_thread_finalize_key,
2117ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev                          (void*)kPthreadDestructorIterations)) {
2127ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev    Report("LeakSanitizer: failed to set thread key.\n");
2137ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev    Die();
2147ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  }
2157ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  int tid = 0;
2167ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
2177ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev    internal_sched_yield();
2187ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  SetCurrentThread(tid);
2197ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  ThreadStart(tid, GetTid());
22086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  atomic_store(&p->tid, 0, memory_order_release);
2217ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  return callback(param);
2227ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev}
2237ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
224fc1a61203fec6797060744c5c6754b0ae924f5b2Sergey MatveevINTERCEPTOR(int, pthread_create, void *th, void *attr,
225fc1a61203fec6797060744c5c6754b0ae924f5b2Sergey Matveev            void *(*callback)(void *), void *param) {
22674c88796a4024922144660ed1ade519af5008fe2Sergey Matveev  ENSURE_LSAN_INITED;
227c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev  EnsureMainThreadIDIsCorrect();
2287ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  __sanitizer_pthread_attr_t myattr;
2297ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  if (attr == 0) {
2307ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev    pthread_attr_init(&myattr);
2317ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev    attr = &myattr;
2327ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  }
2332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  AdjustStackSize(attr);
2347ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  int detached = 0;
2357ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  pthread_attr_getdetachstate(attr, &detached);
2367ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  ThreadParam p;
2377ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  p.callback = callback;
2387ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  p.param = param;
2397ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  atomic_store(&p.tid, 0, memory_order_relaxed);
2407ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  int res = REAL(pthread_create)(th, attr, __lsan_thread_start_func, &p);
2417ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  if (res == 0) {
2427ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev    int tid = ThreadCreate(GetCurrentThread(), *(uptr *)th, detached);
2437ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev    CHECK_NE(tid, 0);
2447ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev    atomic_store(&p.tid, tid, memory_order_release);
2457ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev    while (atomic_load(&p.tid, memory_order_acquire) != 0)
2467ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev      internal_sched_yield();
2477ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  }
2487ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  if (attr == &myattr)
2497ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev    pthread_attr_destroy(&myattr);
2507ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  return res;
2517ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev}
2527ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
2537ea7d20ea31f2146817967512356652cc1f72004Sergey MatveevINTERCEPTOR(int, pthread_join, void *th, void **ret) {
25474c88796a4024922144660ed1ade519af5008fe2Sergey Matveev  ENSURE_LSAN_INITED;
2557ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  int tid = ThreadTid((uptr)th);
2567ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  int res = REAL(pthread_join)(th, ret);
2577ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  if (res == 0)
2587ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev    ThreadJoin(tid);
2597ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  return res;
2607ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev}
2617ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
2627ea7d20ea31f2146817967512356652cc1f72004Sergey Matveevnamespace __lsan {
2637ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
2647ea7d20ea31f2146817967512356652cc1f72004Sergey Matveevvoid InitializeInterceptors() {
2657ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  INTERCEPT_FUNCTION(malloc);
2667ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  INTERCEPT_FUNCTION(free);
267d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev  INTERCEPT_FUNCTION(cfree);
2687ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  INTERCEPT_FUNCTION(calloc);
2697ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  INTERCEPT_FUNCTION(realloc);
2707ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  INTERCEPT_FUNCTION(memalign);
2717ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  INTERCEPT_FUNCTION(posix_memalign);
272d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev  INTERCEPT_FUNCTION(__libc_memalign);
2737ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  INTERCEPT_FUNCTION(valloc);
274d16d7233510f4ebb3b5bcafdee2db373c53c5c56Sergey Matveev  INTERCEPT_FUNCTION(pvalloc);
2757ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  INTERCEPT_FUNCTION(malloc_usable_size);
2767ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  INTERCEPT_FUNCTION(mallinfo);
2777ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  INTERCEPT_FUNCTION(mallopt);
2787ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  INTERCEPT_FUNCTION(pthread_create);
2797ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  INTERCEPT_FUNCTION(pthread_join);
2807ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
2817ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
2827ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev    Report("LeakSanitizer: failed to create thread key.\n");
2837ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev    Die();
2847ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev  }
2857ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev}
2867ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev
2877ea7d20ea31f2146817967512356652cc1f72004Sergey Matveev}  // namespace __lsan
288