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" 26*349cc55cSDimitry 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 33*349cc55cSDimitry Andric struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> { 34*349cc55cSDimitry Andric static bool UseImpl() { return memprof_init_is_running; } 35*349cc55cSDimitry Andric }; 36e8d8bef9SDimitry Andric 37e8d8bef9SDimitry Andric INTERCEPTOR(void, free, void *ptr) { 38*349cc55cSDimitry Andric if (DlsymAlloc::PointerIsMine(ptr)) 39*349cc55cSDimitry 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) { 46*349cc55cSDimitry Andric if (DlsymAlloc::PointerIsMine(ptr)) 47*349cc55cSDimitry 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) { 54*349cc55cSDimitry Andric if (DlsymAlloc::Use()) 55*349cc55cSDimitry 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) { 62*349cc55cSDimitry Andric if (DlsymAlloc::Use()) 63*349cc55cSDimitry 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) { 70*349cc55cSDimitry Andric if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr)) 71*349cc55cSDimitry 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) { 107e8d8bef9SDimitry Andric GET_CURRENT_PC_BP_SP; 108e8d8bef9SDimitry Andric (void)sp; 109e8d8bef9SDimitry Andric return memprof_malloc_usable_size(ptr, pc, bp); 110e8d8bef9SDimitry Andric } 111e8d8bef9SDimitry Andric 112e8d8bef9SDimitry Andric #if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 113e8d8bef9SDimitry Andric // We avoid including malloc.h for portability reasons. 114e8d8bef9SDimitry Andric // man mallinfo says the fields are "long", but the implementation uses int. 115e8d8bef9SDimitry Andric // It doesn't matter much -- we just need to make sure that the libc's mallinfo 116e8d8bef9SDimitry Andric // is not called. 117e8d8bef9SDimitry Andric struct fake_mallinfo { 118e8d8bef9SDimitry Andric int x[10]; 119e8d8bef9SDimitry Andric }; 120e8d8bef9SDimitry Andric 121e8d8bef9SDimitry Andric INTERCEPTOR(struct fake_mallinfo, mallinfo, void) { 122e8d8bef9SDimitry Andric struct fake_mallinfo res; 123e8d8bef9SDimitry Andric REAL(memset)(&res, 0, sizeof(res)); 124e8d8bef9SDimitry Andric return res; 125e8d8bef9SDimitry Andric } 126e8d8bef9SDimitry Andric 127e8d8bef9SDimitry Andric INTERCEPTOR(int, mallopt, int cmd, int value) { return 0; } 128e8d8bef9SDimitry Andric #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 129e8d8bef9SDimitry Andric 130e8d8bef9SDimitry Andric INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { 131e8d8bef9SDimitry Andric GET_STACK_TRACE_MALLOC; 132e8d8bef9SDimitry Andric return memprof_posix_memalign(memptr, alignment, size, &stack); 133e8d8bef9SDimitry Andric } 134e8d8bef9SDimitry Andric 135e8d8bef9SDimitry Andric INTERCEPTOR(void *, valloc, uptr size) { 136e8d8bef9SDimitry Andric GET_STACK_TRACE_MALLOC; 137e8d8bef9SDimitry Andric return memprof_valloc(size, &stack); 138e8d8bef9SDimitry Andric } 139e8d8bef9SDimitry Andric 140e8d8bef9SDimitry Andric #if SANITIZER_INTERCEPT_PVALLOC 141e8d8bef9SDimitry Andric INTERCEPTOR(void *, pvalloc, uptr size) { 142e8d8bef9SDimitry Andric GET_STACK_TRACE_MALLOC; 143e8d8bef9SDimitry Andric return memprof_pvalloc(size, &stack); 144e8d8bef9SDimitry Andric } 145e8d8bef9SDimitry Andric #endif // SANITIZER_INTERCEPT_PVALLOC 146e8d8bef9SDimitry Andric 147e8d8bef9SDimitry Andric INTERCEPTOR(void, malloc_stats, void) { __memprof_print_accumulated_stats(); } 148e8d8bef9SDimitry Andric 149e8d8bef9SDimitry Andric namespace __memprof { 150e8d8bef9SDimitry Andric void ReplaceSystemMalloc() {} 151e8d8bef9SDimitry Andric } // namespace __memprof 152