asan_malloc_linux.cc revision 5d71de26cedae3dafc17449fe0182045c0bd20e8
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 27DECLARE_REAL_AND_INTERCEPTOR(void*, malloc, uptr size) 28DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr) 29DECLARE_REAL_AND_INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) 30DECLARE_REAL_AND_INTERCEPTOR(void*, realloc, void *ptr, uptr size) 31DECLARE_REAL_AND_INTERCEPTOR(void*, memalign, uptr boundary, uptr size) 32DECLARE_REAL_AND_INTERCEPTOR(uptr, malloc_usable_size, void *mem) 33 34struct 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 43ALIGNED(32) const MallocDebug asan_malloc_dispatch = { 44 WRAP(malloc), WRAP(free), WRAP(calloc), 45 WRAP(realloc), WRAP(memalign), WRAP(malloc_usable_size)}; 46 47namespace __asan { 48void 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 59namespace __asan { 60void ReplaceSystemMalloc() { 61} 62} // namespace __asan 63#endif // SANITIZER_ANDROID 64 65// ---------------------- Replacement functions ---------------- {{{1 66using namespace __asan; // NOLINT 67 68INTERCEPTOR(void, free, void *ptr) { 69 GET_STACK_TRACE_FREE; 70 asan_free(ptr, &stack, FROM_MALLOC); 71} 72 73INTERCEPTOR(void, cfree, void *ptr) { 74 GET_STACK_TRACE_FREE; 75 asan_free(ptr, &stack, FROM_MALLOC); 76} 77 78INTERCEPTOR(void*, malloc, uptr size) { 79 GET_STACK_TRACE_MALLOC; 80 return asan_malloc(size, &stack); 81} 82 83INTERCEPTOR(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 99INTERCEPTOR(void*, realloc, void *ptr, uptr size) { 100 GET_STACK_TRACE_MALLOC; 101 return asan_realloc(ptr, size, &stack); 102} 103 104INTERCEPTOR(void*, memalign, uptr boundary, uptr size) { 105 GET_STACK_TRACE_MALLOC; 106 return asan_memalign(boundary, size, &stack, FROM_MALLOC); 107} 108 109INTERCEPTOR(void*, aligned_alloc, uptr boundary, uptr size) { 110 GET_STACK_TRACE_MALLOC; 111 return asan_memalign(boundary, size, &stack, FROM_MALLOC); 112} 113 114INTERCEPTOR(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 121INTERCEPTOR(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. 131struct fake_mallinfo { 132 int x[10]; 133}; 134 135INTERCEPTOR(struct fake_mallinfo, mallinfo, void) { 136 struct fake_mallinfo res; 137 REAL(memset)(&res, 0, sizeof(res)); 138 return res; 139} 140 141INTERCEPTOR(int, mallopt, int cmd, int value) { 142 return -1; 143} 144 145INTERCEPTOR(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 151INTERCEPTOR(void*, valloc, uptr size) { 152 GET_STACK_TRACE_MALLOC; 153 return asan_valloc(size, &stack); 154} 155 156INTERCEPTOR(void*, pvalloc, uptr size) { 157 GET_STACK_TRACE_MALLOC; 158 return asan_pvalloc(size, &stack); 159} 160 161INTERCEPTOR(void, malloc_stats, void) { 162 __asan_print_accumulated_stats(); 163} 164 165#endif // SANITIZER_FREEBSD || SANITIZER_LINUX 166