1 //===-- asan_malloc_linux.cc ----------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is a part of AddressSanitizer, an address sanity checker. 11 // 12 // Linux-specific malloc interception. 13 // We simply define functions like malloc, free, realloc, etc. 14 // They will replace the corresponding libc functions automagically. 15 //===----------------------------------------------------------------------===// 16 17 #include "sanitizer_common/sanitizer_platform.h" 18 #if SANITIZER_FREEBSD || SANITIZER_LINUX 19 20 #include "sanitizer_common/sanitizer_tls_get_addr.h" 21 #include "asan_allocator.h" 22 #include "asan_interceptors.h" 23 #include "asan_internal.h" 24 #include "asan_stack.h" 25 26 #if SANITIZER_ANDROID 27 DECLARE_REAL_AND_INTERCEPTOR(void*, malloc, uptr size) 28 DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr) 29 DECLARE_REAL_AND_INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) 30 DECLARE_REAL_AND_INTERCEPTOR(void*, realloc, void *ptr, uptr size) 31 DECLARE_REAL_AND_INTERCEPTOR(void*, memalign, uptr boundary, uptr size) 32 DECLARE_REAL_AND_INTERCEPTOR(uptr, malloc_usable_size, void *mem) 33 34 struct MallocDebug { 35 void *(*malloc)(uptr bytes); 36 void (*free)(void *mem); 37 void *(*calloc)(uptr n_elements, uptr elem_size); 38 void *(*realloc)(void *oldMem, uptr bytes); 39 void *(*memalign)(uptr alignment, uptr bytes); 40 uptr (*malloc_usable_size)(void *mem); 41 }; 42 43 ALIGNED(32) const MallocDebug asan_malloc_dispatch = { 44 WRAP(malloc), WRAP(free), WRAP(calloc), 45 WRAP(realloc), WRAP(memalign), WRAP(malloc_usable_size)}; 46 47 namespace __asan { 48 void ReplaceSystemMalloc() { 49 const MallocDebug** __libc_malloc_dispatch_p; 50 __libc_malloc_dispatch_p = 51 (const MallocDebug **)AsanDlSymNext("__libc_malloc_dispatch"); 52 if (__libc_malloc_dispatch_p) 53 *__libc_malloc_dispatch_p = &asan_malloc_dispatch; 54 } 55 } // namespace __asan 56 57 #else // SANITIZER_ANDROID 58 59 namespace __asan { 60 void ReplaceSystemMalloc() { 61 } 62 } // namespace __asan 63 #endif // SANITIZER_ANDROID 64 65 // ---------------------- Replacement functions ---------------- {{{1 66 using namespace __asan; // NOLINT 67 68 INTERCEPTOR(void, free, void *ptr) { 69 GET_STACK_TRACE_FREE; 70 asan_free(ptr, &stack, FROM_MALLOC); 71 } 72 73 INTERCEPTOR(void, cfree, void *ptr) { 74 GET_STACK_TRACE_FREE; 75 asan_free(ptr, &stack, FROM_MALLOC); 76 } 77 78 INTERCEPTOR(void*, malloc, uptr size) { 79 GET_STACK_TRACE_MALLOC; 80 return asan_malloc(size, &stack); 81 } 82 83 INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { 84 if (UNLIKELY(!asan_inited)) { 85 // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. 86 const uptr kCallocPoolSize = 1024; 87 static uptr calloc_memory_for_dlsym[kCallocPoolSize]; 88 static uptr allocated; 89 uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; 90 void *mem = (void*)&calloc_memory_for_dlsym[allocated]; 91 allocated += size_in_words; 92 CHECK(allocated < kCallocPoolSize); 93 return mem; 94 } 95 GET_STACK_TRACE_MALLOC; 96 return asan_calloc(nmemb, size, &stack); 97 } 98 99 INTERCEPTOR(void*, realloc, void *ptr, uptr size) { 100 GET_STACK_TRACE_MALLOC; 101 return asan_realloc(ptr, size, &stack); 102 } 103 104 INTERCEPTOR(void*, memalign, uptr boundary, uptr size) { 105 GET_STACK_TRACE_MALLOC; 106 return asan_memalign(boundary, size, &stack, FROM_MALLOC); 107 } 108 109 INTERCEPTOR(void*, aligned_alloc, uptr boundary, uptr size) { 110 GET_STACK_TRACE_MALLOC; 111 return asan_memalign(boundary, size, &stack, FROM_MALLOC); 112 } 113 114 INTERCEPTOR(void*, __libc_memalign, uptr boundary, uptr size) { 115 GET_STACK_TRACE_MALLOC; 116 void *res = asan_memalign(boundary, size, &stack, FROM_MALLOC); 117 DTLS_on_libc_memalign(res, size * boundary); 118 return res; 119 } 120 121 INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { 122 GET_CURRENT_PC_BP_SP; 123 (void)sp; 124 return asan_malloc_usable_size(ptr, pc, bp); 125 } 126 127 // We avoid including malloc.h for portability reasons. 128 // man mallinfo says the fields are "long", but the implementation uses int. 129 // It doesn't matter much -- we just need to make sure that the libc's mallinfo 130 // is not called. 131 struct fake_mallinfo { 132 int x[10]; 133 }; 134 135 INTERCEPTOR(struct fake_mallinfo, mallinfo, void) { 136 struct fake_mallinfo res; 137 REAL(memset)(&res, 0, sizeof(res)); 138 return res; 139 } 140 141 INTERCEPTOR(int, mallopt, int cmd, int value) { 142 return -1; 143 } 144 145 INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { 146 GET_STACK_TRACE_MALLOC; 147 // Printf("posix_memalign: %zx %zu\n", alignment, size); 148 return asan_posix_memalign(memptr, alignment, size, &stack); 149 } 150 151 INTERCEPTOR(void*, valloc, uptr size) { 152 GET_STACK_TRACE_MALLOC; 153 return asan_valloc(size, &stack); 154 } 155 156 INTERCEPTOR(void*, pvalloc, uptr size) { 157 GET_STACK_TRACE_MALLOC; 158 return asan_pvalloc(size, &stack); 159 } 160 161 INTERCEPTOR(void, malloc_stats, void) { 162 __asan_print_accumulated_stats(); 163 } 164 165 #endif // SANITIZER_FREEBSD || SANITIZER_LINUX 166