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 7081ad6265SDimitry Andric #if !SANITIZER_APPLE 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) { 80*6c05f3a7SDimitry Andric if (UNLIKELY(!p)) 81*6c05f3a7SDimitry Andric return; 82349cc55cSDimitry Andric if (DlsymAlloc::PointerIsMine(p)) 83349cc55cSDimitry Andric return DlsymAlloc::Free(p); 8468d75effSDimitry Andric ENSURE_LSAN_INITED; 8568d75effSDimitry Andric lsan_free(p); 8668d75effSDimitry Andric } 8768d75effSDimitry Andric 8868d75effSDimitry Andric INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { 89349cc55cSDimitry Andric if (DlsymAlloc::Use()) 90349cc55cSDimitry Andric return DlsymAlloc::Callocate(nmemb, size); 9168d75effSDimitry Andric ENSURE_LSAN_INITED; 9268d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 9368d75effSDimitry Andric return lsan_calloc(nmemb, size, stack); 9468d75effSDimitry Andric } 9568d75effSDimitry Andric 96349cc55cSDimitry Andric INTERCEPTOR(void *, realloc, void *ptr, uptr size) { 97349cc55cSDimitry Andric if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr)) 98349cc55cSDimitry Andric return DlsymAlloc::Realloc(ptr, size); 9968d75effSDimitry Andric ENSURE_LSAN_INITED; 10068d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 101349cc55cSDimitry Andric return lsan_realloc(ptr, size, stack); 10268d75effSDimitry Andric } 10368d75effSDimitry Andric 10468d75effSDimitry Andric INTERCEPTOR(void*, reallocarray, void *q, uptr nmemb, uptr size) { 10568d75effSDimitry Andric ENSURE_LSAN_INITED; 10668d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 10768d75effSDimitry Andric return lsan_reallocarray(q, nmemb, size, stack); 10868d75effSDimitry Andric } 10968d75effSDimitry Andric 11068d75effSDimitry Andric INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { 11168d75effSDimitry Andric ENSURE_LSAN_INITED; 11268d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 11368d75effSDimitry Andric return lsan_posix_memalign(memptr, alignment, size, stack); 11468d75effSDimitry Andric } 11568d75effSDimitry Andric 11668d75effSDimitry Andric INTERCEPTOR(void*, valloc, uptr size) { 11768d75effSDimitry Andric ENSURE_LSAN_INITED; 11868d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 11968d75effSDimitry Andric return lsan_valloc(size, stack); 12068d75effSDimitry Andric } 12181ad6265SDimitry Andric #endif // !SANITIZER_APPLE 12268d75effSDimitry Andric 12368d75effSDimitry Andric #if SANITIZER_INTERCEPT_MEMALIGN 12468d75effSDimitry Andric INTERCEPTOR(void*, memalign, uptr alignment, uptr size) { 12568d75effSDimitry Andric ENSURE_LSAN_INITED; 12668d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 12768d75effSDimitry Andric return lsan_memalign(alignment, size, stack); 12868d75effSDimitry Andric } 12968d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign) 130e8d8bef9SDimitry Andric #else 131e8d8bef9SDimitry Andric #define LSAN_MAYBE_INTERCEPT_MEMALIGN 132e8d8bef9SDimitry Andric #endif // SANITIZER_INTERCEPT_MEMALIGN 13368d75effSDimitry Andric 134e8d8bef9SDimitry Andric #if SANITIZER_INTERCEPT___LIBC_MEMALIGN 13568d75effSDimitry Andric INTERCEPTOR(void *, __libc_memalign, uptr alignment, uptr size) { 13668d75effSDimitry Andric ENSURE_LSAN_INITED; 13768d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 13868d75effSDimitry Andric void *res = lsan_memalign(alignment, size, stack); 13968d75effSDimitry Andric DTLS_on_libc_memalign(res, size); 14068d75effSDimitry Andric return res; 14168d75effSDimitry Andric } 14268d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign) 14368d75effSDimitry Andric #else 14468d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN 145e8d8bef9SDimitry Andric #endif // SANITIZER_INTERCEPT___LIBC_MEMALIGN 14668d75effSDimitry Andric 14768d75effSDimitry Andric #if SANITIZER_INTERCEPT_ALIGNED_ALLOC 14868d75effSDimitry Andric INTERCEPTOR(void*, aligned_alloc, uptr alignment, uptr size) { 14968d75effSDimitry Andric ENSURE_LSAN_INITED; 15068d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 15168d75effSDimitry Andric return lsan_aligned_alloc(alignment, size, stack); 15268d75effSDimitry Andric } 15368d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC INTERCEPT_FUNCTION(aligned_alloc) 15468d75effSDimitry Andric #else 15568d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC 15668d75effSDimitry Andric #endif 15768d75effSDimitry Andric 15868d75effSDimitry Andric #if SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE 15968d75effSDimitry Andric INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { 16068d75effSDimitry Andric ENSURE_LSAN_INITED; 16168d75effSDimitry Andric return GetMallocUsableSize(ptr); 16268d75effSDimitry Andric } 16368d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE \ 16468d75effSDimitry Andric INTERCEPT_FUNCTION(malloc_usable_size) 16568d75effSDimitry Andric #else 16668d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE 16768d75effSDimitry Andric #endif 16868d75effSDimitry Andric 16968d75effSDimitry Andric #if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 17068d75effSDimitry Andric struct fake_mallinfo { 17168d75effSDimitry Andric int x[10]; 17268d75effSDimitry Andric }; 17368d75effSDimitry Andric 17468d75effSDimitry Andric INTERCEPTOR(struct fake_mallinfo, mallinfo, void) { 17568d75effSDimitry Andric struct fake_mallinfo res; 17668d75effSDimitry Andric internal_memset(&res, 0, sizeof(res)); 17768d75effSDimitry Andric return res; 17868d75effSDimitry Andric } 17968d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo) 18068d75effSDimitry Andric 18168d75effSDimitry Andric INTERCEPTOR(int, mallopt, int cmd, int value) { 18268d75effSDimitry Andric return 0; 18368d75effSDimitry Andric } 18468d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt) 18568d75effSDimitry Andric #else 18668d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_MALLINFO 18768d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_MALLOPT 18868d75effSDimitry Andric #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 18968d75effSDimitry Andric 19068d75effSDimitry Andric #if SANITIZER_INTERCEPT_PVALLOC 19168d75effSDimitry Andric INTERCEPTOR(void*, pvalloc, uptr size) { 19268d75effSDimitry Andric ENSURE_LSAN_INITED; 19368d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 19468d75effSDimitry Andric return lsan_pvalloc(size, stack); 19568d75effSDimitry Andric } 19668d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc) 19768d75effSDimitry Andric #else 19868d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_PVALLOC 19968d75effSDimitry Andric #endif // SANITIZER_INTERCEPT_PVALLOC 20068d75effSDimitry Andric 20168d75effSDimitry Andric #if SANITIZER_INTERCEPT_CFREE 20206c3fb27SDimitry Andric INTERCEPTOR(void, cfree, void *p) ALIAS(WRAP(free)); 20368d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree) 20468d75effSDimitry Andric #else 20568d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_CFREE 20668d75effSDimitry Andric #endif // SANITIZER_INTERCEPT_CFREE 20768d75effSDimitry Andric 20868d75effSDimitry Andric #if SANITIZER_INTERCEPT_MCHECK_MPROBE 20968d75effSDimitry Andric INTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) { 21068d75effSDimitry Andric return 0; 21168d75effSDimitry Andric } 21268d75effSDimitry Andric 21368d75effSDimitry Andric INTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) { 21468d75effSDimitry Andric return 0; 21568d75effSDimitry Andric } 21668d75effSDimitry Andric 21768d75effSDimitry Andric INTERCEPTOR(int, mprobe, void *ptr) { 21868d75effSDimitry Andric return 0; 21968d75effSDimitry Andric } 22068d75effSDimitry Andric #endif // SANITIZER_INTERCEPT_MCHECK_MPROBE 22168d75effSDimitry Andric 22268d75effSDimitry Andric 22368d75effSDimitry Andric // TODO(alekseys): throw std::bad_alloc instead of dying on OOM. 22468d75effSDimitry Andric #define OPERATOR_NEW_BODY(nothrow)\ 22568d75effSDimitry Andric ENSURE_LSAN_INITED;\ 22668d75effSDimitry Andric GET_STACK_TRACE_MALLOC;\ 22768d75effSDimitry Andric void *res = lsan_malloc(size, stack);\ 22868d75effSDimitry Andric if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\ 22968d75effSDimitry Andric return res; 23068d75effSDimitry Andric #define OPERATOR_NEW_BODY_ALIGN(nothrow)\ 23168d75effSDimitry Andric ENSURE_LSAN_INITED;\ 23268d75effSDimitry Andric GET_STACK_TRACE_MALLOC;\ 23368d75effSDimitry Andric void *res = lsan_memalign((uptr)align, size, stack);\ 23468d75effSDimitry Andric if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\ 23568d75effSDimitry Andric return res; 23668d75effSDimitry Andric 23768d75effSDimitry Andric #define OPERATOR_DELETE_BODY\ 23868d75effSDimitry Andric ENSURE_LSAN_INITED;\ 23968d75effSDimitry Andric lsan_free(ptr); 24068d75effSDimitry Andric 24168d75effSDimitry Andric // On OS X it's not enough to just provide our own 'operator new' and 24268d75effSDimitry Andric // 'operator delete' implementations, because they're going to be in the runtime 24368d75effSDimitry Andric // dylib, and the main executable will depend on both the runtime dylib and 24468d75effSDimitry Andric // libstdc++, each of has its implementation of new and delete. 24568d75effSDimitry Andric // To make sure that C++ allocation/deallocation operators are overridden on 24668d75effSDimitry Andric // OS X we need to intercept them using their mangled names. 24781ad6265SDimitry Andric #if !SANITIZER_APPLE 24868d75effSDimitry Andric 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) { OPERATOR_NEW_BODY(false /*nothrow*/); } 25368d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 25468d75effSDimitry Andric void *operator new(size_t size, std::nothrow_t const&) 25568d75effSDimitry Andric { OPERATOR_NEW_BODY(true /*nothrow*/); } 25668d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 25768d75effSDimitry Andric void *operator new[](size_t size, std::nothrow_t const&) 25868d75effSDimitry Andric { OPERATOR_NEW_BODY(true /*nothrow*/); } 25968d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 26068d75effSDimitry Andric void *operator new(size_t size, std::align_val_t align) 26168d75effSDimitry Andric { OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); } 26268d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 26368d75effSDimitry Andric void *operator new[](size_t size, std::align_val_t align) 26468d75effSDimitry Andric { OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); } 26568d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 26668d75effSDimitry Andric void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&) 26768d75effSDimitry Andric { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); } 26868d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 26968d75effSDimitry Andric void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&) 27068d75effSDimitry Andric { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); } 27168d75effSDimitry Andric 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) NOEXCEPT { OPERATOR_DELETE_BODY; } 27668d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 27768d75effSDimitry Andric void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; } 27868d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 27968d75effSDimitry Andric void operator delete[](void *ptr, std::nothrow_t const &) 28068d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 28168d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 28268d75effSDimitry Andric void operator delete(void *ptr, size_t size) NOEXCEPT 28368d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 28468d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 28568d75effSDimitry Andric void operator delete[](void *ptr, size_t size) NOEXCEPT 28668d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 28768d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 28868d75effSDimitry Andric void operator delete(void *ptr, std::align_val_t) NOEXCEPT 28968d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 29068d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 29168d75effSDimitry Andric void operator delete[](void *ptr, std::align_val_t) NOEXCEPT 29268d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 29368d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 29468d75effSDimitry Andric void operator delete(void *ptr, std::align_val_t, std::nothrow_t const&) 29568d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 29668d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 29768d75effSDimitry Andric void operator delete[](void *ptr, std::align_val_t, std::nothrow_t const&) 29868d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 29968d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 30068d75effSDimitry Andric void operator delete(void *ptr, size_t size, std::align_val_t) NOEXCEPT 30168d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 30268d75effSDimitry Andric INTERCEPTOR_ATTRIBUTE 30368d75effSDimitry Andric void operator delete[](void *ptr, size_t size, std::align_val_t) NOEXCEPT 30468d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 30568d75effSDimitry Andric 30681ad6265SDimitry Andric #else // SANITIZER_APPLE 30768d75effSDimitry Andric 30868d75effSDimitry Andric INTERCEPTOR(void *, _Znwm, size_t size) 30968d75effSDimitry Andric { OPERATOR_NEW_BODY(false /*nothrow*/); } 31068d75effSDimitry Andric INTERCEPTOR(void *, _Znam, size_t size) 31168d75effSDimitry Andric { OPERATOR_NEW_BODY(false /*nothrow*/); } 31268d75effSDimitry Andric INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) 31368d75effSDimitry Andric { OPERATOR_NEW_BODY(true /*nothrow*/); } 31468d75effSDimitry Andric INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) 31568d75effSDimitry Andric { OPERATOR_NEW_BODY(true /*nothrow*/); } 31668d75effSDimitry Andric 31768d75effSDimitry Andric INTERCEPTOR(void, _ZdlPv, void *ptr) 31868d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 31968d75effSDimitry Andric INTERCEPTOR(void, _ZdaPv, void *ptr) 32068d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 32168d75effSDimitry Andric INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) 32268d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 32368d75effSDimitry Andric INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) 32468d75effSDimitry Andric { OPERATOR_DELETE_BODY; } 32568d75effSDimitry Andric 32681ad6265SDimitry Andric #endif // !SANITIZER_APPLE 32768d75effSDimitry Andric 32868d75effSDimitry Andric 32968d75effSDimitry Andric ///// Thread initialization and finalization. ///// 33068d75effSDimitry Andric 3315ffd83dbSDimitry Andric #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD && !SANITIZER_FUCHSIA 33268d75effSDimitry Andric static unsigned g_thread_finalize_key; 33368d75effSDimitry Andric 33468d75effSDimitry Andric static void thread_finalize(void *v) { 33568d75effSDimitry Andric uptr iter = (uptr)v; 33668d75effSDimitry Andric if (iter > 1) { 33768d75effSDimitry Andric if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) { 33868d75effSDimitry Andric Report("LeakSanitizer: failed to set thread key.\n"); 33968d75effSDimitry Andric Die(); 34068d75effSDimitry Andric } 34168d75effSDimitry Andric return; 34268d75effSDimitry Andric } 34368d75effSDimitry Andric ThreadFinish(); 34468d75effSDimitry Andric } 34568d75effSDimitry Andric #endif 34668d75effSDimitry Andric 34768d75effSDimitry Andric #if SANITIZER_NETBSD 34868d75effSDimitry Andric INTERCEPTOR(void, _lwp_exit) { 34968d75effSDimitry Andric ENSURE_LSAN_INITED; 35068d75effSDimitry Andric ThreadFinish(); 35168d75effSDimitry Andric REAL(_lwp_exit)(); 35268d75effSDimitry Andric } 35368d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT__LWP_EXIT INTERCEPT_FUNCTION(_lwp_exit) 35468d75effSDimitry Andric #else 35568d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT__LWP_EXIT 35668d75effSDimitry Andric #endif 35768d75effSDimitry Andric 35868d75effSDimitry Andric #if SANITIZER_INTERCEPT_THR_EXIT 35968d75effSDimitry Andric INTERCEPTOR(void, thr_exit, tid_t *state) { 36068d75effSDimitry Andric ENSURE_LSAN_INITED; 36168d75effSDimitry Andric ThreadFinish(); 36268d75effSDimitry Andric REAL(thr_exit)(state); 36368d75effSDimitry Andric } 36468d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_THR_EXIT INTERCEPT_FUNCTION(thr_exit) 36568d75effSDimitry Andric #else 36668d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_THR_EXIT 36768d75effSDimitry Andric #endif 36868d75effSDimitry Andric 36968d75effSDimitry Andric #if SANITIZER_INTERCEPT___CXA_ATEXIT 37068d75effSDimitry Andric INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, 37168d75effSDimitry Andric void *dso_handle) { 37268d75effSDimitry Andric __lsan::ScopedInterceptorDisabler disabler; 37368d75effSDimitry Andric return REAL(__cxa_atexit)(func, arg, dso_handle); 37468d75effSDimitry Andric } 37568d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT INTERCEPT_FUNCTION(__cxa_atexit) 37668d75effSDimitry Andric #else 37768d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT 37868d75effSDimitry Andric #endif 37968d75effSDimitry Andric 38068d75effSDimitry Andric #if SANITIZER_INTERCEPT_ATEXIT 38168d75effSDimitry Andric INTERCEPTOR(int, atexit, void (*f)()) { 38268d75effSDimitry Andric __lsan::ScopedInterceptorDisabler disabler; 38368d75effSDimitry Andric return REAL(__cxa_atexit)((void (*)(void *a))f, 0, 0); 38468d75effSDimitry Andric } 38568d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_ATEXIT INTERCEPT_FUNCTION(atexit) 38668d75effSDimitry Andric #else 38768d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_ATEXIT 38868d75effSDimitry Andric #endif 38968d75effSDimitry Andric 39068d75effSDimitry Andric #if SANITIZER_INTERCEPT_PTHREAD_ATFORK 39168d75effSDimitry Andric extern "C" { 39268d75effSDimitry Andric extern int _pthread_atfork(void (*prepare)(), void (*parent)(), 39368d75effSDimitry Andric void (*child)()); 3940fca6ea1SDimitry Andric } 39568d75effSDimitry Andric 39668d75effSDimitry Andric INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(), 39768d75effSDimitry Andric void (*child)()) { 39868d75effSDimitry Andric __lsan::ScopedInterceptorDisabler disabler; 39968d75effSDimitry Andric // REAL(pthread_atfork) cannot be called due to symbol indirections at least 40068d75effSDimitry Andric // on NetBSD 40168d75effSDimitry Andric return _pthread_atfork(prepare, parent, child); 40268d75effSDimitry Andric } 40368d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK INTERCEPT_FUNCTION(pthread_atfork) 40468d75effSDimitry Andric #else 40568d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK 40668d75effSDimitry Andric #endif 40768d75effSDimitry Andric 40868d75effSDimitry Andric #if SANITIZER_INTERCEPT_STRERROR 40968d75effSDimitry Andric INTERCEPTOR(char *, strerror, int errnum) { 41068d75effSDimitry Andric __lsan::ScopedInterceptorDisabler disabler; 41168d75effSDimitry Andric return REAL(strerror)(errnum); 41268d75effSDimitry Andric } 41368d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_STRERROR INTERCEPT_FUNCTION(strerror) 41468d75effSDimitry Andric #else 41568d75effSDimitry Andric #define LSAN_MAYBE_INTERCEPT_STRERROR 41668d75effSDimitry Andric #endif 41768d75effSDimitry Andric 4185ffd83dbSDimitry Andric #if SANITIZER_POSIX 4195ffd83dbSDimitry Andric 42006c3fb27SDimitry Andric template <bool Detached> 42106c3fb27SDimitry Andric static void *ThreadStartFunc(void *arg) { 42206c3fb27SDimitry Andric u32 parent_tid = (uptr)arg; 42306c3fb27SDimitry Andric uptr tid = ThreadCreate(parent_tid, Detached); 42468d75effSDimitry Andric // Wait until the last iteration to maximize the chance that we are the last 42568d75effSDimitry Andric // destructor to run. 42668d75effSDimitry Andric #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD 42768d75effSDimitry Andric if (pthread_setspecific(g_thread_finalize_key, 42868d75effSDimitry Andric (void*)GetPthreadDestructorIterations())) { 42968d75effSDimitry Andric Report("LeakSanitizer: failed to set thread key.\n"); 43068d75effSDimitry Andric Die(); 43168d75effSDimitry Andric } 43268d75effSDimitry Andric # endif 43368d75effSDimitry Andric ThreadStart(tid, GetTid()); 43406c3fb27SDimitry Andric auto self = GetThreadSelf(); 43506c3fb27SDimitry Andric auto args = GetThreadArgRetval().GetArgs(self); 43606c3fb27SDimitry Andric void *retval = (*args.routine)(args.arg_retval); 43706c3fb27SDimitry Andric GetThreadArgRetval().Finish(self, retval); 43806c3fb27SDimitry Andric return retval; 43968d75effSDimitry Andric } 44068d75effSDimitry Andric 44168d75effSDimitry Andric INTERCEPTOR(int, pthread_create, void *th, void *attr, 44268d75effSDimitry Andric void *(*callback)(void *), void *param) { 44368d75effSDimitry Andric ENSURE_LSAN_INITED; 44468d75effSDimitry Andric EnsureMainThreadIDIsCorrect(); 44506c3fb27SDimitry Andric 44606c3fb27SDimitry Andric bool detached = [attr]() { 44706c3fb27SDimitry Andric int d = 0; 44806c3fb27SDimitry Andric return attr && !pthread_attr_getdetachstate(attr, &d) && IsStateDetached(d); 44906c3fb27SDimitry Andric }(); 45006c3fb27SDimitry Andric 45168d75effSDimitry Andric __sanitizer_pthread_attr_t myattr; 45268d75effSDimitry Andric if (!attr) { 45368d75effSDimitry Andric pthread_attr_init(&myattr); 45468d75effSDimitry Andric attr = &myattr; 45568d75effSDimitry Andric } 45668d75effSDimitry Andric AdjustStackSize(attr); 45706c3fb27SDimitry Andric uptr this_tid = GetCurrentThreadId(); 45806c3fb27SDimitry Andric int result; 45968d75effSDimitry Andric { 46068d75effSDimitry Andric // Ignore all allocations made by pthread_create: thread stack/TLS may be 46168d75effSDimitry Andric // stored by pthread for future reuse even after thread destruction, and 46268d75effSDimitry Andric // the linked list it's stored in doesn't even hold valid pointers to the 46368d75effSDimitry Andric // objects, the latter are calculated by obscure pointer arithmetic. 46468d75effSDimitry Andric ScopedInterceptorDisabler disabler; 46506c3fb27SDimitry Andric GetThreadArgRetval().Create(detached, {callback, param}, [&]() -> uptr { 46606c3fb27SDimitry Andric result = REAL(pthread_create)( 46706c3fb27SDimitry Andric th, attr, detached ? ThreadStartFunc<true> : ThreadStartFunc<false>, 46806c3fb27SDimitry Andric (void *)this_tid); 46906c3fb27SDimitry Andric return result ? 0 : *(uptr *)(th); 47006c3fb27SDimitry Andric }); 47168d75effSDimitry Andric } 47268d75effSDimitry Andric if (attr == &myattr) 47368d75effSDimitry Andric pthread_attr_destroy(&myattr); 47406c3fb27SDimitry Andric return result; 47568d75effSDimitry Andric } 47668d75effSDimitry Andric 47706c3fb27SDimitry Andric INTERCEPTOR(int, pthread_join, void *thread, void **retval) { 47806c3fb27SDimitry Andric int result; 47906c3fb27SDimitry Andric GetThreadArgRetval().Join((uptr)thread, [&]() { 48006c3fb27SDimitry Andric result = REAL(pthread_join)(thread, retval); 48106c3fb27SDimitry Andric return !result; 48206c3fb27SDimitry Andric }); 48306c3fb27SDimitry Andric return result; 4840eae32dcSDimitry Andric } 4850eae32dcSDimitry Andric 48606c3fb27SDimitry Andric INTERCEPTOR(int, pthread_detach, void *thread) { 48706c3fb27SDimitry Andric int result; 48806c3fb27SDimitry Andric GetThreadArgRetval().Detach((uptr)thread, [&]() { 48906c3fb27SDimitry Andric result = REAL(pthread_detach)(thread); 49006c3fb27SDimitry Andric return !result; 49106c3fb27SDimitry Andric }); 49206c3fb27SDimitry Andric return result; 49306c3fb27SDimitry Andric } 49406c3fb27SDimitry Andric 4955f757f3fSDimitry Andric INTERCEPTOR(void, pthread_exit, void *retval) { 49606c3fb27SDimitry Andric GetThreadArgRetval().Finish(GetThreadSelf(), retval); 4975f757f3fSDimitry Andric REAL(pthread_exit)(retval); 49806c3fb27SDimitry Andric } 49906c3fb27SDimitry Andric 50006c3fb27SDimitry Andric # if SANITIZER_INTERCEPT_TRYJOIN 50106c3fb27SDimitry Andric INTERCEPTOR(int, pthread_tryjoin_np, void *thread, void **ret) { 50206c3fb27SDimitry Andric int result; 50306c3fb27SDimitry Andric GetThreadArgRetval().Join((uptr)thread, [&]() { 50406c3fb27SDimitry Andric result = REAL(pthread_tryjoin_np)(thread, ret); 50506c3fb27SDimitry Andric return !result; 50606c3fb27SDimitry Andric }); 50706c3fb27SDimitry Andric return result; 50806c3fb27SDimitry Andric } 50906c3fb27SDimitry Andric # define LSAN_MAYBE_INTERCEPT_TRYJOIN INTERCEPT_FUNCTION(pthread_tryjoin_np) 51006c3fb27SDimitry Andric # else 51106c3fb27SDimitry Andric # define LSAN_MAYBE_INTERCEPT_TRYJOIN 51206c3fb27SDimitry Andric # endif // SANITIZER_INTERCEPT_TRYJOIN 51306c3fb27SDimitry Andric 51406c3fb27SDimitry Andric # if SANITIZER_INTERCEPT_TIMEDJOIN 51506c3fb27SDimitry Andric INTERCEPTOR(int, pthread_timedjoin_np, void *thread, void **ret, 51606c3fb27SDimitry Andric const struct timespec *abstime) { 51706c3fb27SDimitry Andric int result; 51806c3fb27SDimitry Andric GetThreadArgRetval().Join((uptr)thread, [&]() { 51906c3fb27SDimitry Andric result = REAL(pthread_timedjoin_np)(thread, ret, abstime); 52006c3fb27SDimitry Andric return !result; 52106c3fb27SDimitry Andric }); 52206c3fb27SDimitry Andric return result; 52306c3fb27SDimitry Andric } 52406c3fb27SDimitry Andric # define LSAN_MAYBE_INTERCEPT_TIMEDJOIN \ 52506c3fb27SDimitry Andric INTERCEPT_FUNCTION(pthread_timedjoin_np) 52606c3fb27SDimitry Andric # else 52706c3fb27SDimitry Andric # define LSAN_MAYBE_INTERCEPT_TIMEDJOIN 52806c3fb27SDimitry Andric # endif // SANITIZER_INTERCEPT_TIMEDJOIN 52906c3fb27SDimitry Andric 5300fca6ea1SDimitry Andric DEFINE_INTERNAL_PTHREAD_FUNCTIONS 5310eae32dcSDimitry Andric 53268d75effSDimitry Andric INTERCEPTOR(void, _exit, int status) { 53368d75effSDimitry Andric if (status == 0 && HasReportedLeaks()) status = common_flags()->exitcode; 53468d75effSDimitry Andric REAL(_exit)(status); 53568d75effSDimitry Andric } 53668d75effSDimitry Andric 53768d75effSDimitry Andric #define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name) 53806c3fb27SDimitry Andric #define SIGNAL_INTERCEPTOR_ENTER() ENSURE_LSAN_INITED 53968d75effSDimitry Andric #include "sanitizer_common/sanitizer_signal_interceptors.inc" 54068d75effSDimitry Andric 5415ffd83dbSDimitry Andric #endif // SANITIZER_POSIX 5425ffd83dbSDimitry Andric 54368d75effSDimitry Andric namespace __lsan { 54468d75effSDimitry Andric 54568d75effSDimitry Andric void InitializeInterceptors() { 5465ffd83dbSDimitry Andric // Fuchsia doesn't use interceptors that require any setup. 5475ffd83dbSDimitry Andric #if !SANITIZER_FUCHSIA 5480fca6ea1SDimitry Andric __interception::DoesNotSupportStaticLinking(); 54968d75effSDimitry Andric InitializeSignalInterceptors(); 55068d75effSDimitry Andric 55168d75effSDimitry Andric INTERCEPT_FUNCTION(malloc); 55268d75effSDimitry Andric INTERCEPT_FUNCTION(free); 55368d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_CFREE; 55468d75effSDimitry Andric INTERCEPT_FUNCTION(calloc); 55568d75effSDimitry Andric INTERCEPT_FUNCTION(realloc); 55668d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_MEMALIGN; 55768d75effSDimitry Andric LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN; 55868d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC; 55968d75effSDimitry Andric INTERCEPT_FUNCTION(posix_memalign); 56068d75effSDimitry Andric INTERCEPT_FUNCTION(valloc); 56168d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_PVALLOC; 56268d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE; 56368d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_MALLINFO; 56468d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_MALLOPT; 56568d75effSDimitry Andric INTERCEPT_FUNCTION(pthread_create); 5660eae32dcSDimitry Andric INTERCEPT_FUNCTION(pthread_join); 56706c3fb27SDimitry Andric INTERCEPT_FUNCTION(pthread_detach); 56806c3fb27SDimitry Andric INTERCEPT_FUNCTION(pthread_exit); 56906c3fb27SDimitry Andric LSAN_MAYBE_INTERCEPT_TIMEDJOIN; 57006c3fb27SDimitry Andric LSAN_MAYBE_INTERCEPT_TRYJOIN; 57168d75effSDimitry Andric INTERCEPT_FUNCTION(_exit); 57268d75effSDimitry Andric 57368d75effSDimitry Andric LSAN_MAYBE_INTERCEPT__LWP_EXIT; 57468d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_THR_EXIT; 57568d75effSDimitry Andric 57668d75effSDimitry Andric LSAN_MAYBE_INTERCEPT___CXA_ATEXIT; 57768d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_ATEXIT; 57868d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK; 57968d75effSDimitry Andric 58068d75effSDimitry Andric LSAN_MAYBE_INTERCEPT_STRERROR; 58168d75effSDimitry Andric 58268d75effSDimitry Andric #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD 58368d75effSDimitry Andric if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) { 58468d75effSDimitry Andric Report("LeakSanitizer: failed to create thread key.\n"); 58568d75effSDimitry Andric Die(); 58668d75effSDimitry Andric } 58768d75effSDimitry Andric #endif 5885ffd83dbSDimitry Andric 5895ffd83dbSDimitry Andric #endif // !SANITIZER_FUCHSIA 59068d75effSDimitry Andric } 59168d75effSDimitry Andric 59268d75effSDimitry Andric } // namespace __lsan 593