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