asan_malloc_linux.cc revision 1b17f5b79d58c5aff291dde05727ad0b215b81c6
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_LINUX 19 20#include "asan_allocator.h" 21#include "asan_interceptors.h" 22#include "asan_internal.h" 23#include "asan_stack.h" 24 25#if SANITIZER_ANDROID 26DECLARE_REAL_AND_INTERCEPTOR(void*, malloc, uptr size) 27DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr) 28DECLARE_REAL_AND_INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) 29DECLARE_REAL_AND_INTERCEPTOR(void*, realloc, void *ptr, uptr size) 30DECLARE_REAL_AND_INTERCEPTOR(void*, memalign, uptr boundary, uptr size) 31 32struct MallocDebug { 33 void* (*malloc)(uptr bytes); 34 void (*free)(void* mem); 35 void* (*calloc)(uptr n_elements, uptr elem_size); 36 void* (*realloc)(void* oldMem, uptr bytes); 37 void* (*memalign)(uptr alignment, uptr bytes); 38}; 39 40const MallocDebug asan_malloc_dispatch ALIGNED(32) = { 41 WRAP(malloc), WRAP(free), WRAP(calloc), WRAP(realloc), WRAP(memalign) 42}; 43 44extern "C" const MallocDebug* __libc_malloc_dispatch; 45 46namespace __asan { 47void ReplaceSystemMalloc() { 48 __libc_malloc_dispatch = &asan_malloc_dispatch; 49} 50} // namespace __asan 51 52#else // ANDROID 53 54namespace __asan { 55void ReplaceSystemMalloc() { 56} 57} // namespace __asan 58#endif // ANDROID 59 60// ---------------------- Replacement functions ---------------- {{{1 61using namespace __asan; // NOLINT 62 63INTERCEPTOR(void, free, void *ptr) { 64 GET_STACK_TRACE_FREE; 65 asan_free(ptr, &stack, FROM_MALLOC); 66} 67 68INTERCEPTOR(void, cfree, void *ptr) { 69 GET_STACK_TRACE_FREE; 70 asan_free(ptr, &stack, FROM_MALLOC); 71} 72 73INTERCEPTOR(void*, malloc, uptr size) { 74 GET_STACK_TRACE_MALLOC; 75 return asan_malloc(size, &stack); 76} 77 78INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { 79 if (!asan_inited) { 80 // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. 81 const uptr kCallocPoolSize = 1024; 82 static uptr calloc_memory_for_dlsym[kCallocPoolSize]; 83 static uptr allocated; 84 uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; 85 void *mem = (void*)&calloc_memory_for_dlsym[allocated]; 86 allocated += size_in_words; 87 CHECK(allocated < kCallocPoolSize); 88 return mem; 89 } 90 GET_STACK_TRACE_MALLOC; 91 return asan_calloc(nmemb, size, &stack); 92} 93 94INTERCEPTOR(void*, realloc, void *ptr, uptr size) { 95 GET_STACK_TRACE_MALLOC; 96 return asan_realloc(ptr, size, &stack); 97} 98 99INTERCEPTOR(void*, memalign, uptr boundary, uptr size) { 100 GET_STACK_TRACE_MALLOC; 101 return asan_memalign(boundary, size, &stack, FROM_MALLOC); 102} 103 104INTERCEPTOR(void*, __libc_memalign, uptr align, uptr s) 105 ALIAS("memalign"); 106 107INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { 108 GET_CURRENT_PC_BP_SP; 109 (void)sp; 110 return asan_malloc_usable_size(ptr, pc, bp); 111} 112 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. 117struct fake_mallinfo { 118 int x[10]; 119}; 120 121INTERCEPTOR(struct fake_mallinfo, mallinfo, void) { 122 struct fake_mallinfo res; 123 REAL(memset)(&res, 0, sizeof(res)); 124 return res; 125} 126 127INTERCEPTOR(int, mallopt, int cmd, int value) { 128 return -1; 129} 130 131INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { 132 GET_STACK_TRACE_MALLOC; 133 // Printf("posix_memalign: %zx %zu\n", alignment, size); 134 return asan_posix_memalign(memptr, alignment, size, &stack); 135} 136 137INTERCEPTOR(void*, valloc, uptr size) { 138 GET_STACK_TRACE_MALLOC; 139 return asan_valloc(size, &stack); 140} 141 142INTERCEPTOR(void*, pvalloc, uptr size) { 143 GET_STACK_TRACE_MALLOC; 144 return asan_pvalloc(size, &stack); 145} 146 147INTERCEPTOR(void, malloc_stats, void) { 148 __asan_print_accumulated_stats(); 149} 150 151#endif // SANITIZER_LINUX 152