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 return memprof_memalign(boundary, size, &stack, FROM_MALLOC); 94 } 95 #endif // SANITIZER_INTERCEPT_MEMALIGN 96 97 #if SANITIZER_INTERCEPT_ALIGNED_ALLOC 98 INTERCEPTOR(void *, aligned_alloc, uptr boundary, uptr size) { 99 GET_STACK_TRACE_MALLOC; 100 return memprof_aligned_alloc(boundary, size, &stack); 101 } 102 #endif // SANITIZER_INTERCEPT_ALIGNED_ALLOC 103 104 INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { 105 return memprof_malloc_usable_size(ptr); 106 } 107 108 #if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 109 // We avoid including malloc.h for portability reasons. 110 // man mallinfo says the fields are "long", but the implementation uses int. 111 // It doesn't matter much -- we just need to make sure that the libc's mallinfo 112 // is not called. 113 struct fake_mallinfo { 114 int x[10]; 115 }; 116 117 INTERCEPTOR(struct fake_mallinfo, mallinfo, void) { 118 struct fake_mallinfo res; 119 REAL(memset)(&res, 0, sizeof(res)); 120 return res; 121 } 122 123 INTERCEPTOR(int, mallopt, int cmd, int value) { return 0; } 124 #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 125 126 INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { 127 GET_STACK_TRACE_MALLOC; 128 return memprof_posix_memalign(memptr, alignment, size, &stack); 129 } 130 131 INTERCEPTOR(void *, valloc, uptr size) { 132 GET_STACK_TRACE_MALLOC; 133 return memprof_valloc(size, &stack); 134 } 135 136 #if SANITIZER_INTERCEPT_PVALLOC 137 INTERCEPTOR(void *, pvalloc, uptr size) { 138 GET_STACK_TRACE_MALLOC; 139 return memprof_pvalloc(size, &stack); 140 } 141 #endif // SANITIZER_INTERCEPT_PVALLOC 142 143 INTERCEPTOR(void, malloc_stats, void) { __memprof_print_accumulated_stats(); } 144 145 namespace __memprof { 146 void ReplaceSystemMalloc() {} 147 } // namespace __memprof 148