11844Swollman//=-- lsan_interceptors.cpp -----------------------------------------------===// 250476Speter// 31844Swollman// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41638Srgrimes// See https://llvm.org/LICENSE.txt for license information. 594940Sru// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61638Srgrimes// 742915Sjdp//===----------------------------------------------------------------------===// 842915Sjdp// 942915Sjdp// This file is a part of LeakSanitizer. 1042915Sjdp// Interceptors for standalone LSan. 1142915Sjdp// 1242915Sjdp//===----------------------------------------------------------------------===// 1342915Sjdp 1442915Sjdp#include "interception/interception.h" 1542915Sjdp#include "sanitizer_common/sanitizer_allocator.h" 1699362Sru#include "sanitizer_common/sanitizer_allocator_dlsym.h" 1742915Sjdp#include "sanitizer_common/sanitizer_allocator_report.h" 1842915Sjdp#include "sanitizer_common/sanitizer_atomic.h" 1929141Speter#include "sanitizer_common/sanitizer_common.h" 2042915Sjdp#include "sanitizer_common/sanitizer_flags.h" 2142915Sjdp#include "sanitizer_common/sanitizer_internal_defs.h" 2242915Sjdp#include "sanitizer_common/sanitizer_linux.h" 2342915Sjdp#include "sanitizer_common/sanitizer_platform_interceptors.h" 2442915Sjdp#include "sanitizer_common/sanitizer_platform_limits_netbsd.h" 2542915Sjdp#include "sanitizer_common/sanitizer_platform_limits_posix.h" 2642915Sjdp#if SANITIZER_POSIX 2729141Speter#include "sanitizer_common/sanitizer_posix.h" 282827Sjkh#endif 292827Sjkh#include "sanitizer_common/sanitizer_tls_get_addr.h" 302827Sjkh#include "lsan.h" 312827Sjkh#include "lsan_allocator.h" 322827Sjkh#include "lsan_common.h" 331638Srgrimes#include "lsan_thread.h" 342827Sjkh 351638Srgrimes#include <stddef.h> 3643055Sjdp 3718529Sbdeusing namespace __lsan; 3831809Sbde 3918529Sbdeextern "C" { 401638Srgrimesint pthread_attr_init(void *attr); 4142450Sjdpint pthread_attr_destroy(void *attr); 421638Srgrimesint pthread_attr_getdetachstate(void *attr, int *v); 4395064Sobrienint pthread_key_create(unsigned *key, void (*destructor)(void* v)); 441638Srgrimesint pthread_setspecific(unsigned key, const void *v); 4596512Sru} 4696512Sru 4796512Srustruct DlsymAlloc : DlSymAllocator<DlsymAlloc> { 4896512Sru static bool UseImpl() { return lsan_init_is_running; } 4996512Sru static void OnAllocate(const void *ptr, uptr size) { 5096512Sru#if CAN_SANITIZE_LEAKS 5196512Sru // Suppress leaks from dlerror(). Previously dlsym hack on global array was 5296512Sru // used by leak sanitizer as a root region. 5392491Smarkm __lsan_register_root_region(ptr, size); 5492491Smarkm#endif 5592553Sru } 5692491Smarkm static void OnFree(const void *ptr, uptr size) { 5792491Smarkm#if CAN_SANITIZE_LEAKS 5892553Sru __lsan_unregister_root_region(ptr, size); 5992553Sru#endif 6092491Smarkm } 611638Srgrimes}; 621844Swollman 6338186Speter///// Malloc/free interceptors. ///// 6438186Speter 651638Srgrimesnamespace std { 661638Srgrimes struct nothrow_t; 6724761Sjdp enum class align_val_t: size_t; 6838186Speter} 6938186Speter 701638Srgrimes#if !SANITIZER_MAC 7142450SjdpINTERCEPTOR(void*, malloc, uptr size) { 721844Swollman if (DlsymAlloc::Use()) 7396258Sobrien return DlsymAlloc::Allocate(size); 7438186Speter ENSURE_LSAN_INITED; 751844Swollman GET_STACK_TRACE_MALLOC; 7636673Sdt return lsan_malloc(size, stack); 771844Swollman} 7838186Speter 7938186SpeterINTERCEPTOR(void, free, void *p) { 801844Swollman if (DlsymAlloc::PointerIsMine(p)) 8136673Sdt return DlsymAlloc::Free(p); 8224761Sjdp ENSURE_LSAN_INITED; 8338186Speter lsan_free(p); 8438186Speter} 851844Swollman 8642450SjdpINTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { 871844Swollman if (DlsymAlloc::Use()) 8896258Sobrien return DlsymAlloc::Callocate(nmemb, size); 8938186Speter ENSURE_LSAN_INITED; 901844Swollman GET_STACK_TRACE_MALLOC; 911844Swollman return lsan_calloc(nmemb, size, stack); 921844Swollman} 9338186Speter 9438186SpeterINTERCEPTOR(void *, realloc, void *ptr, uptr size) { 951844Swollman if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr)) 961844Swollman return DlsymAlloc::Realloc(ptr, size); 9724761Sjdp ENSURE_LSAN_INITED; 9838186Speter GET_STACK_TRACE_MALLOC; 9938186Speter return lsan_realloc(ptr, size, stack); 1001844Swollman} 10142450Sjdp 1021844SwollmanINTERCEPTOR(void*, reallocarray, void *q, uptr nmemb, uptr size) { 10396258Sobrien ENSURE_LSAN_INITED; 10438186Speter GET_STACK_TRACE_MALLOC; 1051844Swollman return lsan_reallocarray(q, nmemb, size, stack); 10636054Sbde} 10736054Sbde 10838186SpeterINTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { 10938186Speter ENSURE_LSAN_INITED; 11036054Sbde GET_STACK_TRACE_MALLOC; 11136054Sbde return lsan_posix_memalign(memptr, alignment, size, stack); 11236054Sbde} 11338186Speter 11438186SpeterINTERCEPTOR(void*, valloc, uptr size) { 11536054Sbde ENSURE_LSAN_INITED; 11642450Sjdp GET_STACK_TRACE_MALLOC; 11736054Sbde return lsan_valloc(size, stack); 11896258Sobrien} 11938186Speter#endif // !SANITIZER_MAC 12036054Sbde 12195251Sru#if SANITIZER_INTERCEPT_MEMALIGN 12297101SruINTERCEPTOR(void*, memalign, uptr alignment, uptr size) { 12317510Speter ENSURE_LSAN_INITED; 12496258Sobrien GET_STACK_TRACE_MALLOC; 12538186Speter return lsan_memalign(alignment, size, stack); 1261638Srgrimes} 12795251Sru#define LSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign) 12897101Sru#else 12917510Speter#define LSAN_MAYBE_INTERCEPT_MEMALIGN 13096258Sobrien#endif // SANITIZER_INTERCEPT_MEMALIGN 13138186Speter 1321638Srgrimes#if SANITIZER_INTERCEPT___LIBC_MEMALIGN 13395251SruINTERCEPTOR(void *, __libc_memalign, uptr alignment, uptr size) { 13497101Sru ENSURE_LSAN_INITED; 13595216Smarkm GET_STACK_TRACE_MALLOC; 13638186Speter void *res = lsan_memalign(alignment, size, stack); 13738186Speter DTLS_on_libc_memalign(res, size); 1381638Srgrimes return res; 1391844Swollman} 14097101Sru#define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign) 14196258Sobrien#else 14238186Speter#define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN 1431844Swollman#endif // SANITIZER_INTERCEPT___LIBC_MEMALIGN 1441844Swollman 14597101Sru#if SANITIZER_INTERCEPT_ALIGNED_ALLOC 14696258SobrienINTERCEPTOR(void*, aligned_alloc, uptr alignment, uptr size) { 14738186Speter ENSURE_LSAN_INITED; 1481844Swollman GET_STACK_TRACE_MALLOC; 14942450Sjdp return lsan_aligned_alloc(alignment, size, stack); 15097101Sru} 15195216Smarkm#define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC INTERCEPT_FUNCTION(aligned_alloc) 15238186Speter#else 15338186Speter#define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC 1541844Swollman#endif 15596512Sru 1561638Srgrimes#if SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE 15799362SruINTERCEPTOR(uptr, malloc_usable_size, void *ptr) { 15899362Sru ENSURE_LSAN_INITED; 15999362Sru return GetMallocUsableSize(ptr); 16099362Sru} 16196512Sru#define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE \ 16296512Sru INTERCEPT_FUNCTION(malloc_usable_size) 1631638Srgrimes#else 16496512Sru#define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE 16596512Sru#endif 16696512Sru 16796512Sru#if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 16896512Srustruct fake_mallinfo { 16999362Sru int x[10]; 1701638Srgrimes}; 17196512Sru 17295114SobrienINTERCEPTOR(struct fake_mallinfo, mallinfo, void) { 17399362Sru struct fake_mallinfo res; 17496512Sru internal_memset(&res, 0, sizeof(res)); 17596512Sru return res; 17695306Sru} 17796512Sru#define LSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo) 17896512Sru 17996512SruINTERCEPTOR(int, mallopt, int cmd, int value) { 18096512Sru return 0; 18196512Sru} 18274805Sru#define LSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt) 1831844Swollman#else 18499362Sru#define LSAN_MAYBE_INTERCEPT_MALLINFO 18599362Sru#define LSAN_MAYBE_INTERCEPT_MALLOPT 18696512Sru#endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 18799362Sru 1881844Swollman#if SANITIZER_INTERCEPT_PVALLOC 18996512SruINTERCEPTOR(void*, pvalloc, uptr size) { 19096512Sru ENSURE_LSAN_INITED; 1911638Srgrimes GET_STACK_TRACE_MALLOC; 19242915Sjdp return lsan_pvalloc(size, stack); 19342915Sjdp} 19496512Sru#define LSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc) 19542915Sjdp#else 19696512Sru#define LSAN_MAYBE_INTERCEPT_PVALLOC 19742915Sjdp#endif // SANITIZER_INTERCEPT_PVALLOC 19838655Sjb 19991011Sru#if SANITIZER_INTERCEPT_CFREE 20096512SruINTERCEPTOR(void, cfree, void *p) ALIAS(WRAPPER_NAME(free)); 20191011Sru#define LSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree) 20228945Speter#else 20396343Sobrien#define LSAN_MAYBE_INTERCEPT_CFREE 20496512Sru#endif // SANITIZER_INTERCEPT_CFREE 20591011Sru 20628945Speter#if SANITIZER_INTERCEPT_MCHECK_MPROBE 20742915SjdpINTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) { 2081844Swollman return 0; 20999362Sru} 21096512Sru 21196512SruINTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) { 21296512Sru return 0; 2132353Sbde} 21496512Sru 21596512SruINTERCEPTOR(int, mprobe, void *ptr) { 21696512Sru return 0; 2173859Sbde} 2181844Swollman#endif // SANITIZER_INTERCEPT_MCHECK_MPROBE 21999362Sru 22096512Sru 22196512Sru// TODO(alekseys): throw std::bad_alloc instead of dying on OOM. 22296512Sru#define OPERATOR_NEW_BODY(nothrow)\ 22396512Sru ENSURE_LSAN_INITED;\ 22492491Smarkm GET_STACK_TRACE_MALLOC;\ 22596512Sru void *res = lsan_malloc(size, stack);\ 22696512Sru if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\ 22792491Smarkm return res; 22892491Smarkm#define OPERATOR_NEW_BODY_ALIGN(nothrow)\ 2291638Srgrimes ENSURE_LSAN_INITED;\ 23096512Sru GET_STACK_TRACE_MALLOC;\ 23196512Sru void *res = lsan_memalign((uptr)align, size, stack);\ 23296512Sru if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\ 23396512Sru return res; 23496512Sru 23596512Sru#define OPERATOR_DELETE_BODY\ 2361638Srgrimes ENSURE_LSAN_INITED;\ 2371638Srgrimes lsan_free(ptr); 23896529Sru 23996529Sru// On OS X it's not enough to just provide our own 'operator new' and 24098870Sjmallett// 'operator delete' implementations, because they're going to be in the runtime 24196529Sru// dylib, and the main executable will depend on both the runtime dylib and 24298870Sjmallett// libstdc++, each of has its implementation of new and delete. 24396529Sru// To make sure that C++ allocation/deallocation operators are overridden on 24496529Sru// OS X we need to intercept them using their mangled names. 24599362Sru#if !SANITIZER_MAC 24696529Sru 24799362SruINTERCEPTOR_ATTRIBUTE 24896529Sruvoid *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } 24996529SruINTERCEPTOR_ATTRIBUTE 25099362Sruvoid *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } 25199362SruINTERCEPTOR_ATTRIBUTE 25296529Sruvoid *operator new(size_t size, std::nothrow_t const&) 25399362Sru{ OPERATOR_NEW_BODY(true /*nothrow*/); } 25496529SruINTERCEPTOR_ATTRIBUTE 25599362Sruvoid *operator new[](size_t size, std::nothrow_t const&) 25699362Sru{ OPERATOR_NEW_BODY(true /*nothrow*/); } 25796529SruINTERCEPTOR_ATTRIBUTE 25899362Sruvoid *operator new(size_t size, std::align_val_t align) 25999362Sru{ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); } 26099362SruINTERCEPTOR_ATTRIBUTE 26199362Sruvoid *operator new[](size_t size, std::align_val_t align) 26299362Sru{ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); } 26396529SruINTERCEPTOR_ATTRIBUTE 26496529Sruvoid *operator new(size_t size, std::align_val_t align, std::nothrow_t const&) 26596529Sru{ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); } 26699362SruINTERCEPTOR_ATTRIBUTE 26796529Sruvoid *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&) 26899362Sru{ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); } 26996529Sru 27096529SruINTERCEPTOR_ATTRIBUTE 27196529Sruvoid operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } 27296529SruINTERCEPTOR_ATTRIBUTE 27396529Sruvoid operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } 27434179SbdeINTERCEPTOR_ATTRIBUTE 27524750Sbdevoid operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; } 27642450SjdpINTERCEPTOR_ATTRIBUTE 27724750Sbdevoid operator delete[](void *ptr, std::nothrow_t const &) 27824750Sbde{ OPERATOR_DELETE_BODY; } 27942915SjdpINTERCEPTOR_ATTRIBUTE 28038655Sjbvoid operator delete(void *ptr, size_t size) NOEXCEPT 28142915Sjdp{ OPERATOR_DELETE_BODY; } 28291011SruINTERCEPTOR_ATTRIBUTE 28325468Sjdpvoid operator delete[](void *ptr, size_t size) NOEXCEPT 28428945Speter{ OPERATOR_DELETE_BODY; } 28531809SbdeINTERCEPTOR_ATTRIBUTE 28642915Sjdpvoid operator delete(void *ptr, std::align_val_t) NOEXCEPT 28727910Sasami{ OPERATOR_DELETE_BODY; } 28828945SpeterINTERCEPTOR_ATTRIBUTE 28928945Spetervoid operator delete[](void *ptr, std::align_val_t) NOEXCEPT 2901638Srgrimes{ OPERATOR_DELETE_BODY; } 2911638SrgrimesINTERCEPTOR_ATTRIBUTE 2921638Srgrimesvoid operator delete(void *ptr, std::align_val_t, std::nothrow_t const&) 29348204Sjmg{ OPERATOR_DELETE_BODY; } 2942298SwollmanINTERCEPTOR_ATTRIBUTE 2952298Swollmanvoid operator delete[](void *ptr, std::align_val_t, std::nothrow_t const&) 2962298Swollman{ OPERATOR_DELETE_BODY; } 29749328ShoekINTERCEPTOR_ATTRIBUTE 29849328Shoekvoid operator delete(void *ptr, size_t size, std::align_val_t) NOEXCEPT 29949328Shoek{ OPERATOR_DELETE_BODY; } 30049328ShoekINTERCEPTOR_ATTRIBUTE 30156971Sruvoid operator delete[](void *ptr, size_t size, std::align_val_t) NOEXCEPT 30249328Shoek{ OPERATOR_DELETE_BODY; } 30349328Shoek 30449328Shoek#else // SANITIZER_MAC 30549328Shoek 30699362SruINTERCEPTOR(void *, _Znwm, size_t size) 30795306Sru{ OPERATOR_NEW_BODY(false /*nothrow*/); } 30899343SruINTERCEPTOR(void *, _Znam, size_t size) 30995306Sru{ OPERATOR_NEW_BODY(false /*nothrow*/); } 31099362SruINTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) 31192980Sdes{ OPERATOR_NEW_BODY(true /*nothrow*/); } 31249328ShoekINTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) 31396512Sru{ OPERATOR_NEW_BODY(true /*nothrow*/); } 31499362Sru 31592980SdesINTERCEPTOR(void, _ZdlPv, void *ptr) 31649328Shoek{ OPERATOR_DELETE_BODY; } 3171638SrgrimesINTERCEPTOR(void, _ZdaPv, void *ptr) 31842915Sjdp{ OPERATOR_DELETE_BODY; } 31948204SjmgINTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) 32049328Shoek{ OPERATOR_DELETE_BODY; } 32142915SjdpINTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) 32242915Sjdp{ OPERATOR_DELETE_BODY; } 32396512Sru 3241844Swollman#endif // !SANITIZER_MAC 32528945Speter 32699362Sru 3271844Swollman///// Thread initialization and finalization. ///// 32849328Shoek 3291844Swollman#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD && !SANITIZER_FUCHSIA 33099362Srustatic unsigned g_thread_finalize_key; 33196462Sru 33296462Srustatic void thread_finalize(void *v) { 33396462Sru uptr iter = (uptr)v; 33499362Sru if (iter > 1) { 33596462Sru if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) { 33697769Sru Report("LeakSanitizer: failed to set thread key.\n"); 33796668Sru Die(); 33899256Sru } 33996462Sru return; 34096162Sru } 34196164Sru ThreadFinish(); 34299343Sru} 34396162Sru#endif 34496162Sru 3451638Srgrimes#if SANITIZER_NETBSD 3461638SrgrimesINTERCEPTOR(void, _lwp_exit) { 3471638Srgrimes ENSURE_LSAN_INITED; 34895306Sru ThreadFinish(); 34992553Sru REAL(_lwp_exit)(); 3501638Srgrimes} 3511638Srgrimes#define LSAN_MAYBE_INTERCEPT__LWP_EXIT INTERCEPT_FUNCTION(_lwp_exit) 3521844Swollman#else 3531638Srgrimes#define LSAN_MAYBE_INTERCEPT__LWP_EXIT 35474842Sru#endif 3551844Swollman 3561844Swollman#if SANITIZER_INTERCEPT_THR_EXIT 35734092SbdeINTERCEPTOR(void, thr_exit, tid_t *state) { 35899362Sru ENSURE_LSAN_INITED; 35996512Sru ThreadFinish(); 36099362Sru REAL(thr_exit)(state); 36134092Sbde} 36299362Sru#define LSAN_MAYBE_INTERCEPT_THR_EXIT INTERCEPT_FUNCTION(thr_exit) 36399362Sru#else 36499362Sru#define LSAN_MAYBE_INTERCEPT_THR_EXIT 36596512Sru#endif 36699362Sru 36734092Sbde#if SANITIZER_INTERCEPT___CXA_ATEXIT 36816663SjkhINTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, 36976861Skris void *dso_handle) { 37076861Skris __lsan::ScopedInterceptorDisabler disabler; 371 return REAL(__cxa_atexit)(func, arg, dso_handle); 372} 373#define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT INTERCEPT_FUNCTION(__cxa_atexit) 374#else 375#define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT 376#endif 377 378#if SANITIZER_INTERCEPT_ATEXIT 379INTERCEPTOR(int, atexit, void (*f)()) { 380 __lsan::ScopedInterceptorDisabler disabler; 381 return REAL(__cxa_atexit)((void (*)(void *a))f, 0, 0); 382} 383#define LSAN_MAYBE_INTERCEPT_ATEXIT INTERCEPT_FUNCTION(atexit) 384#else 385#define LSAN_MAYBE_INTERCEPT_ATEXIT 386#endif 387 388#if SANITIZER_INTERCEPT_PTHREAD_ATFORK 389extern "C" { 390extern int _pthread_atfork(void (*prepare)(), void (*parent)(), 391 void (*child)()); 392}; 393 394INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(), 395 void (*child)()) { 396 __lsan::ScopedInterceptorDisabler disabler; 397 // REAL(pthread_atfork) cannot be called due to symbol indirections at least 398 // on NetBSD 399 return _pthread_atfork(prepare, parent, child); 400} 401#define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK INTERCEPT_FUNCTION(pthread_atfork) 402#else 403#define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK 404#endif 405 406#if SANITIZER_INTERCEPT_STRERROR 407INTERCEPTOR(char *, strerror, int errnum) { 408 __lsan::ScopedInterceptorDisabler disabler; 409 return REAL(strerror)(errnum); 410} 411#define LSAN_MAYBE_INTERCEPT_STRERROR INTERCEPT_FUNCTION(strerror) 412#else 413#define LSAN_MAYBE_INTERCEPT_STRERROR 414#endif 415 416#if SANITIZER_POSIX 417 418struct ThreadParam { 419 void *(*callback)(void *arg); 420 void *param; 421 atomic_uintptr_t tid; 422}; 423 424extern "C" void *__lsan_thread_start_func(void *arg) { 425 ThreadParam *p = (ThreadParam*)arg; 426 void* (*callback)(void *arg) = p->callback; 427 void *param = p->param; 428 // Wait until the last iteration to maximize the chance that we are the last 429 // destructor to run. 430#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD 431 if (pthread_setspecific(g_thread_finalize_key, 432 (void*)GetPthreadDestructorIterations())) { 433 Report("LeakSanitizer: failed to set thread key.\n"); 434 Die(); 435 } 436#endif 437 int tid = 0; 438 while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0) 439 internal_sched_yield(); 440 ThreadStart(tid, GetTid()); 441 atomic_store(&p->tid, 0, memory_order_release); 442 return callback(param); 443} 444 445INTERCEPTOR(int, pthread_create, void *th, void *attr, 446 void *(*callback)(void *), void *param) { 447 ENSURE_LSAN_INITED; 448 EnsureMainThreadIDIsCorrect(); 449 __sanitizer_pthread_attr_t myattr; 450 if (!attr) { 451 pthread_attr_init(&myattr); 452 attr = &myattr; 453 } 454 AdjustStackSize(attr); 455 int detached = 0; 456 pthread_attr_getdetachstate(attr, &detached); 457 ThreadParam p; 458 p.callback = callback; 459 p.param = param; 460 atomic_store(&p.tid, 0, memory_order_relaxed); 461 int res; 462 { 463 // Ignore all allocations made by pthread_create: thread stack/TLS may be 464 // stored by pthread for future reuse even after thread destruction, and 465 // the linked list it's stored in doesn't even hold valid pointers to the 466 // objects, the latter are calculated by obscure pointer arithmetic. 467 ScopedInterceptorDisabler disabler; 468 res = REAL(pthread_create)(th, attr, __lsan_thread_start_func, &p); 469 } 470 if (res == 0) { 471 int tid = ThreadCreate(GetCurrentThread(), *(uptr *)th, 472 IsStateDetached(detached)); 473 CHECK_NE(tid, kMainTid); 474 atomic_store(&p.tid, tid, memory_order_release); 475 while (atomic_load(&p.tid, memory_order_acquire) != 0) 476 internal_sched_yield(); 477 } 478 if (attr == &myattr) 479 pthread_attr_destroy(&myattr); 480 return res; 481} 482 483INTERCEPTOR(int, pthread_join, void *th, void **ret) { 484 ENSURE_LSAN_INITED; 485 int tid = ThreadTid((uptr)th); 486 int res = REAL(pthread_join)(th, ret); 487 if (res == 0) 488 ThreadJoin(tid); 489 return res; 490} 491 492INTERCEPTOR(int, pthread_detach, void *th) { 493 ENSURE_LSAN_INITED; 494 int tid = ThreadTid((uptr)th); 495 int res = REAL(pthread_detach)(th); 496 if (res == 0) 497 ThreadDetach(tid); 498 return res; 499} 500 501INTERCEPTOR(void, _exit, int status) { 502 if (status == 0 && HasReportedLeaks()) status = common_flags()->exitcode; 503 REAL(_exit)(status); 504} 505 506#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name) 507#include "sanitizer_common/sanitizer_signal_interceptors.inc" 508 509#endif // SANITIZER_POSIX 510 511namespace __lsan { 512 513void InitializeInterceptors() { 514 // Fuchsia doesn't use interceptors that require any setup. 515#if !SANITIZER_FUCHSIA 516 InitializeSignalInterceptors(); 517 518 INTERCEPT_FUNCTION(malloc); 519 INTERCEPT_FUNCTION(free); 520 LSAN_MAYBE_INTERCEPT_CFREE; 521 INTERCEPT_FUNCTION(calloc); 522 INTERCEPT_FUNCTION(realloc); 523 LSAN_MAYBE_INTERCEPT_MEMALIGN; 524 LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN; 525 LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC; 526 INTERCEPT_FUNCTION(posix_memalign); 527 INTERCEPT_FUNCTION(valloc); 528 LSAN_MAYBE_INTERCEPT_PVALLOC; 529 LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE; 530 LSAN_MAYBE_INTERCEPT_MALLINFO; 531 LSAN_MAYBE_INTERCEPT_MALLOPT; 532 INTERCEPT_FUNCTION(pthread_create); 533 INTERCEPT_FUNCTION(pthread_detach); 534 INTERCEPT_FUNCTION(pthread_join); 535 INTERCEPT_FUNCTION(_exit); 536 537 LSAN_MAYBE_INTERCEPT__LWP_EXIT; 538 LSAN_MAYBE_INTERCEPT_THR_EXIT; 539 540 LSAN_MAYBE_INTERCEPT___CXA_ATEXIT; 541 LSAN_MAYBE_INTERCEPT_ATEXIT; 542 LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK; 543 544 LSAN_MAYBE_INTERCEPT_STRERROR; 545 546#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD 547 if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) { 548 Report("LeakSanitizer: failed to create thread key.\n"); 549 Die(); 550 } 551#endif 552 553#endif // !SANITIZER_FUCHSIA 554} 555 556} // namespace __lsan 557