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