1e8d8bef9SDimitry Andric //===-- memprof_malloc_linux.cpp -----------------------------------------===// 2e8d8bef9SDimitry Andric // 3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric // 7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8e8d8bef9SDimitry Andric // 9e8d8bef9SDimitry Andric // This file is a part of MemProfiler, a memory profiler. 10e8d8bef9SDimitry Andric // 11e8d8bef9SDimitry Andric // Linux-specific malloc interception. 12e8d8bef9SDimitry Andric // We simply define functions like malloc, free, realloc, etc. 13e8d8bef9SDimitry Andric // They will replace the corresponding libc functions automagically. 14e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 15e8d8bef9SDimitry Andric 16e8d8bef9SDimitry Andric #include "sanitizer_common/sanitizer_platform.h" 17e8d8bef9SDimitry Andric #if !SANITIZER_LINUX 18e8d8bef9SDimitry Andric #error Unsupported OS 19e8d8bef9SDimitry Andric #endif 20e8d8bef9SDimitry Andric 21e8d8bef9SDimitry Andric #include "memprof_allocator.h" 22e8d8bef9SDimitry Andric #include "memprof_interceptors.h" 23e8d8bef9SDimitry Andric #include "memprof_internal.h" 24e8d8bef9SDimitry Andric #include "memprof_stack.h" 25e8d8bef9SDimitry Andric #include "sanitizer_common/sanitizer_allocator_checks.h" 26349cc55cSDimitry Andric #include "sanitizer_common/sanitizer_allocator_dlsym.h" 27e8d8bef9SDimitry Andric #include "sanitizer_common/sanitizer_errno.h" 28e8d8bef9SDimitry Andric #include "sanitizer_common/sanitizer_tls_get_addr.h" 29e8d8bef9SDimitry Andric 30e8d8bef9SDimitry Andric // ---------------------- Replacement functions ---------------- {{{1 31e8d8bef9SDimitry Andric using namespace __memprof; 32e8d8bef9SDimitry Andric 33349cc55cSDimitry Andric struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> { 34349cc55cSDimitry Andric static bool UseImpl() { return memprof_init_is_running; } 35349cc55cSDimitry Andric }; 36e8d8bef9SDimitry Andric 37e8d8bef9SDimitry Andric INTERCEPTOR(void, free, void *ptr) { 38349cc55cSDimitry Andric if (DlsymAlloc::PointerIsMine(ptr)) 39349cc55cSDimitry Andric return DlsymAlloc::Free(ptr); 40e8d8bef9SDimitry Andric GET_STACK_TRACE_FREE; 41e8d8bef9SDimitry Andric memprof_free(ptr, &stack, FROM_MALLOC); 42e8d8bef9SDimitry Andric } 43e8d8bef9SDimitry Andric 44e8d8bef9SDimitry Andric #if SANITIZER_INTERCEPT_CFREE 45e8d8bef9SDimitry Andric INTERCEPTOR(void, cfree, void *ptr) { 46349cc55cSDimitry Andric if (DlsymAlloc::PointerIsMine(ptr)) 47349cc55cSDimitry Andric return DlsymAlloc::Free(ptr); 48e8d8bef9SDimitry Andric GET_STACK_TRACE_FREE; 49e8d8bef9SDimitry Andric memprof_free(ptr, &stack, FROM_MALLOC); 50e8d8bef9SDimitry Andric } 51e8d8bef9SDimitry Andric #endif // SANITIZER_INTERCEPT_CFREE 52e8d8bef9SDimitry Andric 53e8d8bef9SDimitry Andric INTERCEPTOR(void *, malloc, uptr size) { 54349cc55cSDimitry Andric if (DlsymAlloc::Use()) 55349cc55cSDimitry Andric return DlsymAlloc::Allocate(size); 56e8d8bef9SDimitry Andric ENSURE_MEMPROF_INITED(); 57e8d8bef9SDimitry Andric GET_STACK_TRACE_MALLOC; 58e8d8bef9SDimitry Andric return memprof_malloc(size, &stack); 59e8d8bef9SDimitry Andric } 60e8d8bef9SDimitry Andric 61e8d8bef9SDimitry Andric INTERCEPTOR(void *, calloc, uptr nmemb, uptr size) { 62349cc55cSDimitry Andric if (DlsymAlloc::Use()) 63349cc55cSDimitry Andric return DlsymAlloc::Callocate(nmemb, size); 64e8d8bef9SDimitry Andric ENSURE_MEMPROF_INITED(); 65e8d8bef9SDimitry Andric GET_STACK_TRACE_MALLOC; 66e8d8bef9SDimitry Andric return memprof_calloc(nmemb, size, &stack); 67e8d8bef9SDimitry Andric } 68e8d8bef9SDimitry Andric 69e8d8bef9SDimitry Andric INTERCEPTOR(void *, realloc, void *ptr, uptr size) { 70349cc55cSDimitry Andric if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr)) 71349cc55cSDimitry Andric return DlsymAlloc::Realloc(ptr, size); 72e8d8bef9SDimitry Andric ENSURE_MEMPROF_INITED(); 73e8d8bef9SDimitry Andric GET_STACK_TRACE_MALLOC; 74e8d8bef9SDimitry Andric return memprof_realloc(ptr, size, &stack); 75e8d8bef9SDimitry Andric } 76e8d8bef9SDimitry Andric 77e8d8bef9SDimitry Andric #if SANITIZER_INTERCEPT_REALLOCARRAY 78e8d8bef9SDimitry Andric INTERCEPTOR(void *, reallocarray, void *ptr, uptr nmemb, uptr size) { 79e8d8bef9SDimitry Andric ENSURE_MEMPROF_INITED(); 80e8d8bef9SDimitry Andric GET_STACK_TRACE_MALLOC; 81e8d8bef9SDimitry Andric return memprof_reallocarray(ptr, nmemb, size, &stack); 82e8d8bef9SDimitry Andric } 83e8d8bef9SDimitry Andric #endif // SANITIZER_INTERCEPT_REALLOCARRAY 84e8d8bef9SDimitry Andric 85e8d8bef9SDimitry Andric #if SANITIZER_INTERCEPT_MEMALIGN 86e8d8bef9SDimitry Andric INTERCEPTOR(void *, memalign, uptr boundary, uptr size) { 87e8d8bef9SDimitry Andric GET_STACK_TRACE_MALLOC; 88e8d8bef9SDimitry Andric return memprof_memalign(boundary, size, &stack, FROM_MALLOC); 89e8d8bef9SDimitry Andric } 90e8d8bef9SDimitry Andric 91e8d8bef9SDimitry Andric INTERCEPTOR(void *, __libc_memalign, uptr boundary, uptr size) { 92e8d8bef9SDimitry Andric GET_STACK_TRACE_MALLOC; 93e8d8bef9SDimitry Andric void *res = memprof_memalign(boundary, size, &stack, FROM_MALLOC); 94e8d8bef9SDimitry Andric DTLS_on_libc_memalign(res, size); 95e8d8bef9SDimitry Andric return res; 96e8d8bef9SDimitry Andric } 97e8d8bef9SDimitry Andric #endif // SANITIZER_INTERCEPT_MEMALIGN 98e8d8bef9SDimitry Andric 99e8d8bef9SDimitry Andric #if SANITIZER_INTERCEPT_ALIGNED_ALLOC 100e8d8bef9SDimitry Andric INTERCEPTOR(void *, aligned_alloc, uptr boundary, uptr size) { 101e8d8bef9SDimitry Andric GET_STACK_TRACE_MALLOC; 102e8d8bef9SDimitry Andric return memprof_aligned_alloc(boundary, size, &stack); 103e8d8bef9SDimitry Andric } 104e8d8bef9SDimitry Andric #endif // SANITIZER_INTERCEPT_ALIGNED_ALLOC 105e8d8bef9SDimitry Andric 106e8d8bef9SDimitry Andric INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { 107*0fca6ea1SDimitry Andric return memprof_malloc_usable_size(ptr); 108e8d8bef9SDimitry Andric } 109e8d8bef9SDimitry Andric 110e8d8bef9SDimitry Andric #if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 111e8d8bef9SDimitry Andric // We avoid including malloc.h for portability reasons. 112e8d8bef9SDimitry Andric // man mallinfo says the fields are "long", but the implementation uses int. 113e8d8bef9SDimitry Andric // It doesn't matter much -- we just need to make sure that the libc's mallinfo 114e8d8bef9SDimitry Andric // is not called. 115e8d8bef9SDimitry Andric struct fake_mallinfo { 116e8d8bef9SDimitry Andric int x[10]; 117e8d8bef9SDimitry Andric }; 118e8d8bef9SDimitry Andric 119e8d8bef9SDimitry Andric INTERCEPTOR(struct fake_mallinfo, mallinfo, void) { 120e8d8bef9SDimitry Andric struct fake_mallinfo res; 121e8d8bef9SDimitry Andric REAL(memset)(&res, 0, sizeof(res)); 122e8d8bef9SDimitry Andric return res; 123e8d8bef9SDimitry Andric } 124e8d8bef9SDimitry Andric 125e8d8bef9SDimitry Andric INTERCEPTOR(int, mallopt, int cmd, int value) { return 0; } 126e8d8bef9SDimitry Andric #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 127e8d8bef9SDimitry Andric 128e8d8bef9SDimitry Andric INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { 129e8d8bef9SDimitry Andric GET_STACK_TRACE_MALLOC; 130e8d8bef9SDimitry Andric return memprof_posix_memalign(memptr, alignment, size, &stack); 131e8d8bef9SDimitry Andric } 132e8d8bef9SDimitry Andric 133e8d8bef9SDimitry Andric INTERCEPTOR(void *, valloc, uptr size) { 134e8d8bef9SDimitry Andric GET_STACK_TRACE_MALLOC; 135e8d8bef9SDimitry Andric return memprof_valloc(size, &stack); 136e8d8bef9SDimitry Andric } 137e8d8bef9SDimitry Andric 138e8d8bef9SDimitry Andric #if SANITIZER_INTERCEPT_PVALLOC 139e8d8bef9SDimitry Andric INTERCEPTOR(void *, pvalloc, uptr size) { 140e8d8bef9SDimitry Andric GET_STACK_TRACE_MALLOC; 141e8d8bef9SDimitry Andric return memprof_pvalloc(size, &stack); 142e8d8bef9SDimitry Andric } 143e8d8bef9SDimitry Andric #endif // SANITIZER_INTERCEPT_PVALLOC 144e8d8bef9SDimitry Andric 145e8d8bef9SDimitry Andric INTERCEPTOR(void, malloc_stats, void) { __memprof_print_accumulated_stats(); } 146e8d8bef9SDimitry Andric 147e8d8bef9SDimitry Andric namespace __memprof { 148e8d8bef9SDimitry Andric void ReplaceSystemMalloc() {} 149e8d8bef9SDimitry Andric } // namespace __memprof 150