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#ifdef __linux__ 17 18#include "asan_allocator.h" 19#include "asan_interceptors.h" 20#include "asan_internal.h" 21#include "asan_stack.h" 22 23#if ASAN_ANDROID 24DECLARE_REAL_AND_INTERCEPTOR(void*, malloc, uptr size); 25DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr); 26DECLARE_REAL_AND_INTERCEPTOR(void*, calloc, uptr nmemb, uptr size); 27DECLARE_REAL_AND_INTERCEPTOR(void*, realloc, void *ptr, uptr size); 28DECLARE_REAL_AND_INTERCEPTOR(void*, memalign, uptr boundary, uptr size); 29 30struct MallocDebug { 31 void* (*malloc)(uptr bytes); 32 void (*free)(void* mem); 33 void* (*calloc)(uptr n_elements, uptr elem_size); 34 void* (*realloc)(void* oldMem, uptr bytes); 35 void* (*memalign)(uptr alignment, uptr bytes); 36}; 37 38const MallocDebug asan_malloc_dispatch ALIGNED(32) = { 39 WRAP(malloc), WRAP(free), WRAP(calloc), WRAP(realloc), WRAP(memalign) 40}; 41 42extern "C" const MallocDebug* __libc_malloc_dispatch; 43 44namespace __asan { 45void ReplaceSystemMalloc() { 46 __libc_malloc_dispatch = &asan_malloc_dispatch; 47} 48} // namespace __asan 49 50#else // ANDROID 51 52namespace __asan { 53void ReplaceSystemMalloc() { 54} 55} // namespace __asan 56#endif // ANDROID 57 58// ---------------------- Replacement functions ---------------- {{{1 59using namespace __asan; // NOLINT 60 61INTERCEPTOR(void, free, void *ptr) { 62 GET_STACK_TRACE_HERE_FOR_FREE(ptr); 63 asan_free(ptr, &stack); 64} 65 66INTERCEPTOR(void, cfree, void *ptr) { 67 GET_STACK_TRACE_HERE_FOR_FREE(ptr); 68 asan_free(ptr, &stack); 69} 70 71INTERCEPTOR(void*, malloc, uptr size) { 72 GET_STACK_TRACE_HERE_FOR_MALLOC; 73 return asan_malloc(size, &stack); 74} 75 76INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { 77 if (!asan_inited) { 78 // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. 79 const uptr kCallocPoolSize = 1024; 80 static uptr calloc_memory_for_dlsym[kCallocPoolSize]; 81 static uptr allocated; 82 uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; 83 void *mem = (void*)&calloc_memory_for_dlsym[allocated]; 84 allocated += size_in_words; 85 CHECK(allocated < kCallocPoolSize); 86 return mem; 87 } 88 GET_STACK_TRACE_HERE_FOR_MALLOC; 89 return asan_calloc(nmemb, size, &stack); 90} 91 92INTERCEPTOR(void*, realloc, void *ptr, uptr size) { 93 GET_STACK_TRACE_HERE_FOR_MALLOC; 94 return asan_realloc(ptr, size, &stack); 95} 96 97INTERCEPTOR(void*, memalign, uptr boundary, uptr size) { 98 GET_STACK_TRACE_HERE_FOR_MALLOC; 99 return asan_memalign(boundary, size, &stack); 100} 101 102INTERCEPTOR(void*, __libc_memalign, uptr align, uptr s) 103 ALIAS("memalign"); 104 105INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { 106 GET_STACK_TRACE_HERE_FOR_MALLOC; 107 return asan_malloc_usable_size(ptr, &stack); 108} 109 110// We avoid including malloc.h for portability reasons. 111// man mallinfo says the fields are "long", but the implementation uses int. 112// It doesn't matter much -- we just need to make sure that the libc's mallinfo 113// is not called. 114struct fake_mallinfo { 115 int x[10]; 116}; 117 118INTERCEPTOR(struct fake_mallinfo, mallinfo, void) { 119 struct fake_mallinfo res; 120 REAL(memset)(&res, 0, sizeof(res)); 121 return res; 122} 123 124INTERCEPTOR(int, mallopt, int cmd, int value) { 125 return -1; 126} 127 128INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { 129 GET_STACK_TRACE_HERE_FOR_MALLOC; 130 // Printf("posix_memalign: %zx %zu\n", alignment, size); 131 return asan_posix_memalign(memptr, alignment, size, &stack); 132} 133 134INTERCEPTOR(void*, valloc, uptr size) { 135 GET_STACK_TRACE_HERE_FOR_MALLOC; 136 return asan_valloc(size, &stack); 137} 138 139INTERCEPTOR(void*, pvalloc, uptr size) { 140 GET_STACK_TRACE_HERE_FOR_MALLOC; 141 return asan_pvalloc(size, &stack); 142} 143 144#endif // __linux__ 145