168d75effSDimitry Andric //=-- lsan_interceptors.cpp -----------------------------------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is a part of LeakSanitizer. 1068d75effSDimitry Andric // Interceptors for standalone LSan. 1168d75effSDimitry Andric // 1268d75effSDimitry Andric //===----------------------------------------------------------------------===// 1368d75effSDimitry Andric 1468d75effSDimitry Andric #include "interception/interception.h" 1568d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator.h" 16349cc55cSDimitry Andric #include "sanitizer_common/sanitizer_allocator_dlsym.h" 1768d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_report.h" 1868d75effSDimitry Andric #include "sanitizer_common/sanitizer_atomic.h" 1968d75effSDimitry Andric #include "sanitizer_common/sanitizer_common.h" 2068d75effSDimitry Andric #include "sanitizer_common/sanitizer_flags.h" 2168d75effSDimitry Andric #include "sanitizer_common/sanitizer_internal_defs.h" 2268d75effSDimitry Andric #include "sanitizer_common/sanitizer_linux.h" 2368d75effSDimitry Andric #include "sanitizer_common/sanitizer_platform_interceptors.h" 2468d75effSDimitry Andric #include "sanitizer_common/sanitizer_platform_limits_netbsd.h" 2568d75effSDimitry Andric #include "sanitizer_common/sanitizer_platform_limits_posix.h" 265ffd83dbSDimitry Andric #if SANITIZER_POSIX 2768d75effSDimitry Andric #include "sanitizer_common/sanitizer_posix.h" 285ffd83dbSDimitry Andric #endif 2968d75effSDimitry Andric #include "sanitizer_common/sanitizer_tls_get_addr.h" 3068d75effSDimitry Andric #include "lsan.h" 3168d75effSDimitry Andric #include "lsan_allocator.h" 3268d75effSDimitry Andric #include "lsan_common.h" 3368d75effSDimitry Andric #include "lsan_thread.h" 3468d75effSDimitry Andric 3568d75effSDimitry Andric #include <stddef.h> 3668d75effSDimitry Andric 3768d75effSDimitry Andric using namespace __lsan; 3868d75effSDimitry Andric 3968d75effSDimitry Andric extern "C" { 4068d75effSDimitry Andric int pthread_attr_init(void *attr); 4168d75effSDimitry Andric int pthread_attr_destroy(void *attr); 4268d75effSDimitry Andric int pthread_attr_getdetachstate(void *attr, int *v); 4368d75effSDimitry Andric int pthread_key_create(unsigned *key, void (*destructor)(void* v)); 4468d75effSDimitry Andric int pthread_setspecific(unsigned key, const void *v); 4568d75effSDimitry Andric } 4668d75effSDimitry Andric 47349cc55cSDimitry Andric struct DlsymAlloc : DlSymAllocator<DlsymAlloc> { 48349cc55cSDimitry Andric static bool UseImpl() { return lsan_init_is_running; } 49349cc55cSDimitry Andric static void OnAllocate(const void *ptr, uptr size) { 50349cc55cSDimitry Andric #if CAN_SANITIZE_LEAKS 51349cc55cSDimitry Andric // Suppress leaks from dlerror(). Previously dlsym hack on global array was 52349cc55cSDimitry Andric // used by leak sanitizer as a root region. 53349cc55cSDimitry Andric __lsan_register_root_region(ptr, size); 54349cc55cSDimitry Andric #endif 55349cc55cSDimitry Andric } 56349cc55cSDimitry Andric static void OnFree(const void *ptr, uptr size) { 57349cc55cSDimitry Andric #if CAN_SANITIZE_LEAKS 58349cc55cSDimitry Andric __lsan_unregister_root_region(ptr, size); 59349cc55cSDimitry Andric #endif 60349cc55cSDimitry Andric } 61349cc55cSDimitry Andric }; 62349cc55cSDimitry Andric 6368d75effSDimitry Andric ///// Malloc/free interceptors. ///// 6468d75effSDimitry Andric 6568d75effSDimitry Andric namespace std { 6668d75effSDimitry Andric struct nothrow_t; 6768d75effSDimitry Andric enum class align_val_t: size_t; 6868d75effSDimitry Andric } 6968d75effSDimitry Andric 7068d75effSDimitry Andric #if !SANITIZER_MAC 7168d75effSDimitry Andric INTERCEPTOR(void*, malloc, uptr size) { 72349cc55cSDimitry Andric if (DlsymAlloc::Use()) 73349cc55cSDimitry Andric return DlsymAlloc::Allocate(size); 7468d75effSDimitry Andric ENSURE_LSAN_INITED; 7568d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 7668d75effSDimitry Andric return lsan_malloc(size, stack); 7768d75effSDimitry Andric } 7868d75effSDimitry Andric 7968d75effSDimitry Andric INTERCEPTOR(void, free, void *p) { 80349cc55cSDimitry Andric if (DlsymAlloc::PointerIsMine(p)) 81349cc55cSDimitry Andric return DlsymAlloc::Free(p); 8268d75effSDimitry Andric ENSURE_LSAN_INITED; 8368d75effSDimitry Andric lsan_free(p); 8468d75effSDimitry Andric } 8568d75effSDimitry Andric 8668d75effSDimitry Andric INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { 87349cc55cSDimitry Andric if (DlsymAlloc::Use()) 88349cc55cSDimitry Andric return DlsymAlloc::Callocate(nmemb, size); 8968d75effSDimitry Andric ENSURE_LSAN_INITED; 9068d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 9168d75effSDimitry Andric return lsan_calloc(nmemb, size, stack); 9268d75effSDimitry Andric } 9368d75effSDimitry Andric 94349cc55cSDimitry Andric INTERCEPTOR(void *, realloc, void *ptr, uptr size) { 95349cc55cSDimitry Andric if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr)) 96349cc55cSDimitry Andric return DlsymAlloc::Realloc(ptr, size); 9768d75effSDimitry Andric ENSURE_LSAN_INITED; 9868d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 99349cc55cSDimitry Andric return lsan_realloc(ptr, size, stack); 10068d75effSDimitry Andric } 10168d75effSDimitry Andric 10268d75effSDimitry Andric INTERCEPTOR(void*, reallocarray, void *q, uptr nmemb, uptr size) { 10368d75effSDimitry Andric ENSURE_LSAN_INITED; 10468d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 10568d75effSDimitry Andric return lsan_reallocarray(q, nmemb, size, stack); 10668d75effSDimitry Andric } 10768d75effSDimitry Andric 10868d75effSDimitry Andric INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { 10968d75effSDimitry Andric ENSURE_LSAN_INITED; 11068d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 11168d75effSDimitry Andric return lsan_posix_memalign(memptr, alignment, size, stack); 11268d75effSDimitry Andric } 11368d75effSDimitry Andric 11468d75effSDimitry Andric INTERCEPTOR(void*, valloc, uptr size) { 11568d75effSDimitry Andric ENSURE_LSAN_INITED; 11668d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 11768d75effSDimitry Andric return lsan_valloc(size, stack); 11868d75effSDimitry Andric } 1195ffd83dbSDimitry Andric #endif // !SANITIZER_MAC 12068d75effSDimitry Andric 12168d75effSDimitry Andric #if SANITIZER_INTERCEPT_MEMALIGN 12268d75effSDimitry Andric INTERCEPTOR(void*, memalign, uptr alignment, uptr size) { 12368d75effSDimitry Andric ENSURE_LSAN_INITED; 12468d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 12568d75effSDimitry Andric return lsan_memalign(alignment, size, stack); 12668d75effSDimitry Andric } 12768d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign) 128e8d8bef9SDimitry Andric #else 129e8d8bef9SDimitry Andric #define LSAN_MAYBE_INTERCEPT_MEMALIGN 130e8d8bef9SDimitry Andric #endif // SANITIZER_INTERCEPT_MEMALIGN 13168d75effSDimitry Andric 132e8d8bef9SDimitry Andric #if SANITIZER_INTERCEPT___LIBC_MEMALIGN 13368d75effSDimitry Andric INTERCEPTOR(void *, __libc_memalign, uptr alignment, uptr size) { 13468d75effSDimitry Andric ENSURE_LSAN_INITED; 13568d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 13668d75effSDimitry Andric void *res = lsan_memalign(alignment, size, stack); 13768d75effSDimitry Andric DTLS_on_libc_memalign(res, size); 13868d75effSDimitry Andric return res; 13968d75effSDimitry Andric } 14068d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign) 14168d75effSDimitry Andric #else 14268d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN 143e8d8bef9SDimitry Andric #endif // SANITIZER_INTERCEPT___LIBC_MEMALIGN 14468d75effSDimitry Andric 14568d75effSDimitry Andric #if SANITIZER_INTERCEPT_ALIGNED_ALLOC 14668d75effSDimitry Andric INTERCEPTOR(void*, aligned_alloc, uptr alignment, uptr size) { 14768d75effSDimitry Andric ENSURE_LSAN_INITED; 14868d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 14968d75effSDimitry Andric return lsan_aligned_alloc(alignment, size, stack); 15068d75effSDimitry Andric } 15168d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC INTERCEPT_FUNCTION(aligned_alloc) 15268d75effSDimitry Andric #else 15368d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC 15468d75effSDimitry Andric #endif 15568d75effSDimitry Andric 15668d75effSDimitry Andric #if SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE 15768d75effSDimitry Andric INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { 15868d75effSDimitry Andric ENSURE_LSAN_INITED; 15968d75effSDimitry Andric return GetMallocUsableSize(ptr); 16068d75effSDimitry Andric } 16168d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE \ 16268d75effSDimitry Andric INTERCEPT_FUNCTION(malloc_usable_size) 16368d75effSDimitry Andric #else 16468d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE 16568d75effSDimitry Andric #endif 16668d75effSDimitry Andric 16768d75effSDimitry Andric #if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 16868d75effSDimitry Andric struct fake_mallinfo { 16968d75effSDimitry Andric int x[10]; 17068d75effSDimitry Andric }; 17168d75effSDimitry Andric 17268d75effSDimitry Andric INTERCEPTOR(struct fake_mallinfo, mallinfo, void) { 17368d75effSDimitry Andric struct fake_mallinfo res; 17468d75effSDimitry Andric internal_memset(&res, 0, sizeof(res)); 17568d75effSDimitry Andric return res; 17668d75effSDimitry Andric } 17768d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo) 17868d75effSDimitry Andric 17968d75effSDimitry Andric INTERCEPTOR(int, mallopt, int cmd, int value) { 18068d75effSDimitry Andric return 0; 18168d75effSDimitry Andric } 18268d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt) 18368d75effSDimitry Andric #else 18468d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_MALLINFO 18568d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_MALLOPT 18668d75effSDimitry Andric #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 18768d75effSDimitry Andric 18868d75effSDimitry Andric #if SANITIZER_INTERCEPT_PVALLOC 18968d75effSDimitry Andric INTERCEPTOR(void*, pvalloc, uptr size) { 19068d75effSDimitry Andric ENSURE_LSAN_INITED; 19168d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 19268d75effSDimitry Andric return lsan_pvalloc(size, stack); 19368d75effSDimitry Andric } 19468d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc) 19568d75effSDimitry Andric #else 19668d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_PVALLOC 19768d75effSDimitry Andric #endif // SANITIZER_INTERCEPT_PVALLOC 19868d75effSDimitry Andric 19968d75effSDimitry Andric #if SANITIZER_INTERCEPT_CFREE 20068d75effSDimitry Andric INTERCEPTOR(void, cfree, void *p) ALIAS(WRAPPER_NAME(free)); 20168d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree) 20268d75effSDimitry Andric #else 20368d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_CFREE 20468d75effSDimitry Andric #endif // SANITIZER_INTERCEPT_CFREE 20568d75effSDimitry Andric 20668d75effSDimitry Andric #if SANITIZER_INTERCEPT_MCHECK_MPROBE 20768d75effSDimitry Andric INTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) { 20868d75effSDimitry Andric return 0; 20968d75effSDimitry Andric } 21068d75effSDimitry Andric 21168d75effSDimitry Andric INTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) { 21268d75effSDimitry Andric return 0; 21368d75effSDimitry Andric } 21468d75effSDimitry Andric 21568d75effSDimitry Andric INTERCEPTOR(int, mprobe, void *ptr) { 21668d75effSDimitry Andric return 0; 21768d75effSDimitry Andric } 21868d75effSDimitry Andric #endif // SANITIZER_INTERCEPT_MCHECK_MPROBE 21968d75effSDimitry Andric 22068d75effSDimitry Andric 22168d75effSDimitry Andric // TODO(alekseys): throw std::bad_alloc instead of dying on OOM. 22268d75effSDimitry Andric #define OPERATOR_NEW_BODY(nothrow)\ 22368d75effSDimitry Andric ENSURE_LSAN_INITED;\ 22468d75effSDimitry Andric GET_STACK_TRACE_MALLOC;\ 22568d75effSDimitry Andric void *res = lsan_malloc(size, stack);\ 22668d75effSDimitry Andric if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\ 22768d75effSDimitry Andric return res; 22868d75effSDimitry Andric #define OPERATOR_NEW_BODY_ALIGN(nothrow)\ 22968d75effSDimitry Andric ENSURE_LSAN_INITED;\ 23068d75effSDimitry Andric GET_STACK_TRACE_MALLOC;\ 23168d75effSDimitry Andric void *res = lsan_memalign((uptr)align, size, stack);\ 23268d75effSDimitry Andric if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\ 23368d75effSDimitry Andric return res; 23468d75effSDimitry Andric 23568d75effSDimitry Andric #define OPERATOR_DELETE_BODY\ 23668d75effSDimitry Andric ENSURE_LSAN_INITED;\ 23768d75effSDimitry Andric lsan_free(ptr); 23868d75effSDimitry Andric 23968d75effSDimitry Andric // On OS X it's not enough to just provide our own 'operator new' and 24068d75effSDimitry Andric // 'operator delete' implementations, because they're going to be in the runtime 24168d75effSDimitry Andric // dylib, and the main executable will depend on both the runtime dylib and 24268d75effSDimitry Andric // libstdc++, each of has its implementation of new and delete. 24368d75effSDimitry Andric // To make sure that C++ allocation/deallocation operators are overridden on 24468d75effSDimitry Andric // OS X we need to intercept them using their mangled names. 24568d75effSDimitry Andric #if !SANITIZER_MAC 24668d75effSDimitry Andric 24768d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 24868d75effSDimitry Andric void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } 24968d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 25068d75effSDimitry Andric void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } 25168d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 25268d75effSDimitry Andric void *operator new(size_t size, std::nothrow_t const&) 25368d75effSDimitry Andric { OPERATOR_NEW_BODY(true /*nothrow*/); } 25468d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 25568d75effSDimitry Andric void *operator new[](size_t size, std::nothrow_t const&) 25668d75effSDimitry Andric { OPERATOR_NEW_BODY(true /*nothrow*/); } 25768d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 25868d75effSDimitry Andric void *operator new(size_t size, std::align_val_t align) 25968d75effSDimitry Andric { OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); } 26068d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 26168d75effSDimitry Andric void *operator new[](size_t size, std::align_val_t align) 26268d75effSDimitry Andric { OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); } 26368d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 26468d75effSDimitry Andric void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&) 26568d75effSDimitry Andric { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); } 26668d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 26768d75effSDimitry Andric void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&) 26868d75effSDimitry Andric { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); } 26968d75effSDimitry Andric 27068d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 27168d75effSDimitry Andric void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } 27268d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 27368d75effSDimitry Andric void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } 27468d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 27568d75effSDimitry Andric void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; } 27668d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 27768d75effSDimitry Andric void operator delete[](void *ptr, std::nothrow_t const &) 27868d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 27968d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 28068d75effSDimitry Andric void operator delete(void *ptr, size_t size) NOEXCEPT 28168d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 28268d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 28368d75effSDimitry Andric void operator delete[](void *ptr, size_t size) NOEXCEPT 28468d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 28568d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 28668d75effSDimitry Andric void operator delete(void *ptr, std::align_val_t) NOEXCEPT 28768d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 28868d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 28968d75effSDimitry Andric void operator delete[](void *ptr, std::align_val_t) NOEXCEPT 29068d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 29168d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 29268d75effSDimitry Andric void operator delete(void *ptr, std::align_val_t, std::nothrow_t const&) 29368d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 29468d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 29568d75effSDimitry Andric void operator delete[](void *ptr, std::align_val_t, std::nothrow_t const&) 29668d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 29768d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 29868d75effSDimitry Andric void operator delete(void *ptr, size_t size, std::align_val_t) NOEXCEPT 29968d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 30068d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 30168d75effSDimitry Andric void operator delete[](void *ptr, size_t size, std::align_val_t) NOEXCEPT 30268d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 30368d75effSDimitry Andric 30468d75effSDimitry Andric #else // SANITIZER_MAC 30568d75effSDimitry Andric 30668d75effSDimitry Andric INTERCEPTOR(void *, _Znwm, size_t size) 30768d75effSDimitry Andric { OPERATOR_NEW_BODY(false /*nothrow*/); } 30868d75effSDimitry Andric INTERCEPTOR(void *, _Znam, size_t size) 30968d75effSDimitry Andric { OPERATOR_NEW_BODY(false /*nothrow*/); } 31068d75effSDimitry Andric INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) 31168d75effSDimitry Andric { OPERATOR_NEW_BODY(true /*nothrow*/); } 31268d75effSDimitry Andric INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) 31368d75effSDimitry Andric { OPERATOR_NEW_BODY(true /*nothrow*/); } 31468d75effSDimitry Andric 31568d75effSDimitry Andric INTERCEPTOR(void, _ZdlPv, void *ptr) 31668d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 31768d75effSDimitry Andric INTERCEPTOR(void, _ZdaPv, void *ptr) 31868d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 31968d75effSDimitry Andric INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) 32068d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 32168d75effSDimitry Andric INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) 32268d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 32368d75effSDimitry Andric 32468d75effSDimitry Andric #endif // !SANITIZER_MAC 32568d75effSDimitry Andric 32668d75effSDimitry Andric 32768d75effSDimitry Andric ///// Thread initialization and finalization. ///// 32868d75effSDimitry Andric 3295ffd83dbSDimitry Andric #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD && !SANITIZER_FUCHSIA 33068d75effSDimitry Andric static unsigned g_thread_finalize_key; 33168d75effSDimitry Andric 33268d75effSDimitry Andric static void thread_finalize(void *v) { 33368d75effSDimitry Andric uptr iter = (uptr)v; 33468d75effSDimitry Andric if (iter > 1) { 33568d75effSDimitry Andric if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) { 33668d75effSDimitry Andric Report("LeakSanitizer: failed to set thread key.\n"); 33768d75effSDimitry Andric Die(); 33868d75effSDimitry Andric } 33968d75effSDimitry Andric return; 34068d75effSDimitry Andric } 34168d75effSDimitry Andric ThreadFinish(); 34268d75effSDimitry Andric } 34368d75effSDimitry Andric #endif 34468d75effSDimitry Andric 34568d75effSDimitry Andric #if SANITIZER_NETBSD 34668d75effSDimitry Andric INTERCEPTOR(void, _lwp_exit) { 34768d75effSDimitry Andric ENSURE_LSAN_INITED; 34868d75effSDimitry Andric ThreadFinish(); 34968d75effSDimitry Andric REAL(_lwp_exit)(); 35068d75effSDimitry Andric } 35168d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT__LWP_EXIT INTERCEPT_FUNCTION(_lwp_exit) 35268d75effSDimitry Andric #else 35368d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT__LWP_EXIT 35468d75effSDimitry Andric #endif 35568d75effSDimitry Andric 35668d75effSDimitry Andric #if SANITIZER_INTERCEPT_THR_EXIT 35768d75effSDimitry Andric INTERCEPTOR(void, thr_exit, tid_t *state) { 35868d75effSDimitry Andric ENSURE_LSAN_INITED; 35968d75effSDimitry Andric ThreadFinish(); 36068d75effSDimitry Andric REAL(thr_exit)(state); 36168d75effSDimitry Andric } 36268d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_THR_EXIT INTERCEPT_FUNCTION(thr_exit) 36368d75effSDimitry Andric #else 36468d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_THR_EXIT 36568d75effSDimitry Andric #endif 36668d75effSDimitry Andric 36768d75effSDimitry Andric #if SANITIZER_INTERCEPT___CXA_ATEXIT 36868d75effSDimitry Andric INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, 36968d75effSDimitry Andric void *dso_handle) { 37068d75effSDimitry Andric __lsan::ScopedInterceptorDisabler disabler; 37168d75effSDimitry Andric return REAL(__cxa_atexit)(func, arg, dso_handle); 37268d75effSDimitry Andric } 37368d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT INTERCEPT_FUNCTION(__cxa_atexit) 37468d75effSDimitry Andric #else 37568d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT 37668d75effSDimitry Andric #endif 37768d75effSDimitry Andric 37868d75effSDimitry Andric #if SANITIZER_INTERCEPT_ATEXIT 37968d75effSDimitry Andric INTERCEPTOR(int, atexit, void (*f)()) { 38068d75effSDimitry Andric __lsan::ScopedInterceptorDisabler disabler; 38168d75effSDimitry Andric return REAL(__cxa_atexit)((void (*)(void *a))f, 0, 0); 38268d75effSDimitry Andric } 38368d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_ATEXIT INTERCEPT_FUNCTION(atexit) 38468d75effSDimitry Andric #else 38568d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_ATEXIT 38668d75effSDimitry Andric #endif 38768d75effSDimitry Andric 38868d75effSDimitry Andric #if SANITIZER_INTERCEPT_PTHREAD_ATFORK 38968d75effSDimitry Andric extern "C" { 39068d75effSDimitry Andric extern int _pthread_atfork(void (*prepare)(), void (*parent)(), 39168d75effSDimitry Andric void (*child)()); 39268d75effSDimitry Andric }; 39368d75effSDimitry Andric 39468d75effSDimitry Andric INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(), 39568d75effSDimitry Andric void (*child)()) { 39668d75effSDimitry Andric __lsan::ScopedInterceptorDisabler disabler; 39768d75effSDimitry Andric // REAL(pthread_atfork) cannot be called due to symbol indirections at least 39868d75effSDimitry Andric // on NetBSD 39968d75effSDimitry Andric return _pthread_atfork(prepare, parent, child); 40068d75effSDimitry Andric } 40168d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK INTERCEPT_FUNCTION(pthread_atfork) 40268d75effSDimitry Andric #else 40368d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK 40468d75effSDimitry Andric #endif 40568d75effSDimitry Andric 40668d75effSDimitry Andric #if SANITIZER_INTERCEPT_STRERROR 40768d75effSDimitry Andric INTERCEPTOR(char *, strerror, int errnum) { 40868d75effSDimitry Andric __lsan::ScopedInterceptorDisabler disabler; 40968d75effSDimitry Andric return REAL(strerror)(errnum); 41068d75effSDimitry Andric } 41168d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_STRERROR INTERCEPT_FUNCTION(strerror) 41268d75effSDimitry Andric #else 41368d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_STRERROR 41468d75effSDimitry Andric #endif 41568d75effSDimitry Andric 4165ffd83dbSDimitry Andric #if SANITIZER_POSIX 4175ffd83dbSDimitry Andric 41868d75effSDimitry Andric struct ThreadParam { 41968d75effSDimitry Andric void *(*callback)(void *arg); 42068d75effSDimitry Andric void *param; 42168d75effSDimitry Andric atomic_uintptr_t tid; 42268d75effSDimitry Andric }; 42368d75effSDimitry Andric 42468d75effSDimitry Andric extern "C" void *__lsan_thread_start_func(void *arg) { 42568d75effSDimitry Andric ThreadParam *p = (ThreadParam*)arg; 42668d75effSDimitry Andric void* (*callback)(void *arg) = p->callback; 42768d75effSDimitry Andric void *param = p->param; 42868d75effSDimitry Andric // Wait until the last iteration to maximize the chance that we are the last 42968d75effSDimitry Andric // destructor to run. 43068d75effSDimitry Andric #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD 43168d75effSDimitry Andric if (pthread_setspecific(g_thread_finalize_key, 43268d75effSDimitry Andric (void*)GetPthreadDestructorIterations())) { 43368d75effSDimitry Andric Report("LeakSanitizer: failed to set thread key.\n"); 43468d75effSDimitry Andric Die(); 43568d75effSDimitry Andric } 43668d75effSDimitry Andric #endif 43768d75effSDimitry Andric int tid = 0; 43868d75effSDimitry Andric while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0) 43968d75effSDimitry Andric internal_sched_yield(); 44068d75effSDimitry Andric ThreadStart(tid, GetTid()); 44168d75effSDimitry Andric atomic_store(&p->tid, 0, memory_order_release); 44268d75effSDimitry Andric return callback(param); 44368d75effSDimitry Andric } 44468d75effSDimitry Andric 44568d75effSDimitry Andric INTERCEPTOR(int, pthread_create, void *th, void *attr, 44668d75effSDimitry Andric void *(*callback)(void *), void *param) { 44768d75effSDimitry Andric ENSURE_LSAN_INITED; 44868d75effSDimitry Andric EnsureMainThreadIDIsCorrect(); 44968d75effSDimitry Andric __sanitizer_pthread_attr_t myattr; 45068d75effSDimitry Andric if (!attr) { 45168d75effSDimitry Andric pthread_attr_init(&myattr); 45268d75effSDimitry Andric attr = &myattr; 45368d75effSDimitry Andric } 45468d75effSDimitry Andric AdjustStackSize(attr); 45568d75effSDimitry Andric int detached = 0; 45668d75effSDimitry Andric pthread_attr_getdetachstate(attr, &detached); 45768d75effSDimitry Andric ThreadParam p; 45868d75effSDimitry Andric p.callback = callback; 45968d75effSDimitry Andric p.param = param; 46068d75effSDimitry Andric atomic_store(&p.tid, 0, memory_order_relaxed); 46168d75effSDimitry Andric int res; 46268d75effSDimitry Andric { 46368d75effSDimitry Andric // Ignore all allocations made by pthread_create: thread stack/TLS may be 46468d75effSDimitry Andric // stored by pthread for future reuse even after thread destruction, and 46568d75effSDimitry Andric // the linked list it's stored in doesn't even hold valid pointers to the 46668d75effSDimitry Andric // objects, the latter are calculated by obscure pointer arithmetic. 46768d75effSDimitry Andric ScopedInterceptorDisabler disabler; 46868d75effSDimitry Andric res = REAL(pthread_create)(th, attr, __lsan_thread_start_func, &p); 46968d75effSDimitry Andric } 47068d75effSDimitry Andric if (res == 0) { 471349cc55cSDimitry Andric int tid = ThreadCreate(GetCurrentThread(), IsStateDetached(detached)); 472fe6060f1SDimitry Andric CHECK_NE(tid, kMainTid); 47368d75effSDimitry Andric atomic_store(&p.tid, tid, memory_order_release); 47468d75effSDimitry Andric while (atomic_load(&p.tid, memory_order_acquire) != 0) 47568d75effSDimitry Andric internal_sched_yield(); 47668d75effSDimitry Andric } 47768d75effSDimitry Andric if (attr == &myattr) 47868d75effSDimitry Andric pthread_attr_destroy(&myattr); 47968d75effSDimitry Andric return res; 48068d75effSDimitry Andric } 48168d75effSDimitry Andric 482*0eae32dcSDimitry Andric INTERCEPTOR(int, pthread_join, void *t, void **arg) { 483*0eae32dcSDimitry Andric return REAL(pthread_join)(t, arg); 484*0eae32dcSDimitry Andric } 485*0eae32dcSDimitry Andric 486*0eae32dcSDimitry Andric DEFINE_REAL_PTHREAD_FUNCTIONS 487*0eae32dcSDimitry Andric 48868d75effSDimitry Andric INTERCEPTOR(void, _exit, int status) { 48968d75effSDimitry Andric if (status == 0 && HasReportedLeaks()) status = common_flags()->exitcode; 49068d75effSDimitry Andric REAL(_exit)(status); 49168d75effSDimitry Andric } 49268d75effSDimitry Andric 49368d75effSDimitry Andric #define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name) 49468d75effSDimitry Andric #include "sanitizer_common/sanitizer_signal_interceptors.inc" 49568d75effSDimitry Andric 4965ffd83dbSDimitry Andric #endif // SANITIZER_POSIX 4975ffd83dbSDimitry Andric 49868d75effSDimitry Andric namespace __lsan { 49968d75effSDimitry Andric 50068d75effSDimitry Andric void InitializeInterceptors() { 5015ffd83dbSDimitry Andric // Fuchsia doesn't use interceptors that require any setup. 5025ffd83dbSDimitry Andric #if !SANITIZER_FUCHSIA 50368d75effSDimitry Andric InitializeSignalInterceptors(); 50468d75effSDimitry Andric 50568d75effSDimitry Andric INTERCEPT_FUNCTION(malloc); 50668d75effSDimitry Andric INTERCEPT_FUNCTION(free); 50768d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_CFREE; 50868d75effSDimitry Andric INTERCEPT_FUNCTION(calloc); 50968d75effSDimitry Andric INTERCEPT_FUNCTION(realloc); 51068d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_MEMALIGN; 51168d75effSDimitry Andric LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN; 51268d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC; 51368d75effSDimitry Andric INTERCEPT_FUNCTION(posix_memalign); 51468d75effSDimitry Andric INTERCEPT_FUNCTION(valloc); 51568d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_PVALLOC; 51668d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE; 51768d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_MALLINFO; 51868d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_MALLOPT; 51968d75effSDimitry Andric INTERCEPT_FUNCTION(pthread_create); 520*0eae32dcSDimitry Andric INTERCEPT_FUNCTION(pthread_join); 52168d75effSDimitry Andric INTERCEPT_FUNCTION(_exit); 52268d75effSDimitry Andric 52368d75effSDimitry Andric LSAN_MAYBE_INTERCEPT__LWP_EXIT; 52468d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_THR_EXIT; 52568d75effSDimitry Andric 52668d75effSDimitry Andric LSAN_MAYBE_INTERCEPT___CXA_ATEXIT; 52768d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_ATEXIT; 52868d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK; 52968d75effSDimitry Andric 53068d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_STRERROR; 53168d75effSDimitry Andric 53268d75effSDimitry Andric #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD 53368d75effSDimitry Andric if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) { 53468d75effSDimitry Andric Report("LeakSanitizer: failed to create thread key.\n"); 53568d75effSDimitry Andric Die(); 53668d75effSDimitry Andric } 53768d75effSDimitry Andric #endif 5385ffd83dbSDimitry Andric 5395ffd83dbSDimitry Andric #endif // !SANITIZER_FUCHSIA 54068d75effSDimitry Andric } 54168d75effSDimitry Andric 54268d75effSDimitry Andric } // namespace __lsan 543