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 26 DECLARE_REAL_AND_INTERCEPTOR(void*, malloc, uptr size) 27 DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr) 28 DECLARE_REAL_AND_INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) 29 DECLARE_REAL_AND_INTERCEPTOR(void*, realloc, void *ptr, uptr size) 30 DECLARE_REAL_AND_INTERCEPTOR(void*, memalign, uptr boundary, uptr size) 31 32 struct 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 40 const MallocDebug asan_malloc_dispatch ALIGNED(32) = { 41 WRAP(malloc), WRAP(free), WRAP(calloc), WRAP(realloc), WRAP(memalign) 42 }; 43 44 extern "C" const MallocDebug* __libc_malloc_dispatch; 45 46 namespace __asan { 47 void ReplaceSystemMalloc() { 48 __libc_malloc_dispatch = &asan_malloc_dispatch; 49 } 50 } // namespace __asan 51 52 #else // ANDROID 53 54 namespace __asan { 55 void ReplaceSystemMalloc() { 56 } 57 } // namespace __asan 58 #endif // ANDROID 59 60 // ---------------------- Replacement functions ---------------- {{{1 61 using namespace __asan; // NOLINT 62 63 INTERCEPTOR(void, free, void *ptr) { 64 GET_STACK_TRACE_FREE; 65 asan_free(ptr, &stack, FROM_MALLOC); 66 } 67 68 INTERCEPTOR(void, cfree, void *ptr) { 69 GET_STACK_TRACE_FREE; 70 asan_free(ptr, &stack, FROM_MALLOC); 71 } 72 73 INTERCEPTOR(void*, malloc, uptr size) { 74 GET_STACK_TRACE_MALLOC; 75 return asan_malloc(size, &stack); 76 } 77 78 INTERCEPTOR(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 94 INTERCEPTOR(void*, realloc, void *ptr, uptr size) { 95 GET_STACK_TRACE_MALLOC; 96 return asan_realloc(ptr, size, &stack); 97 } 98 99 INTERCEPTOR(void*, memalign, uptr boundary, uptr size) { 100 GET_STACK_TRACE_MALLOC; 101 return asan_memalign(boundary, size, &stack, FROM_MALLOC); 102 } 103 104 INTERCEPTOR(void*, __libc_memalign, uptr align, uptr s) 105 ALIAS("memalign"); 106 107 INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { 108 GET_STACK_TRACE_MALLOC; 109 return asan_malloc_usable_size(ptr, &stack); 110 } 111 112 // We avoid including malloc.h for portability reasons. 113 // man mallinfo says the fields are "long", but the implementation uses int. 114 // It doesn't matter much -- we just need to make sure that the libc's mallinfo 115 // is not called. 116 struct fake_mallinfo { 117 int x[10]; 118 }; 119 120 INTERCEPTOR(struct fake_mallinfo, mallinfo, void) { 121 struct fake_mallinfo res; 122 REAL(memset)(&res, 0, sizeof(res)); 123 return res; 124 } 125 126 INTERCEPTOR(int, mallopt, int cmd, int value) { 127 return -1; 128 } 129 130 INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { 131 GET_STACK_TRACE_MALLOC; 132 // Printf("posix_memalign: %zx %zu\n", alignment, size); 133 return asan_posix_memalign(memptr, alignment, size, &stack); 134 } 135 136 INTERCEPTOR(void*, valloc, uptr size) { 137 GET_STACK_TRACE_MALLOC; 138 return asan_valloc(size, &stack); 139 } 140 141 INTERCEPTOR(void*, pvalloc, uptr size) { 142 GET_STACK_TRACE_MALLOC; 143 return asan_pvalloc(size, &stack); 144 } 145 146 INTERCEPTOR(void, malloc_stats, void) { 147 __asan_print_accumulated_stats(); 148 } 149 150 #endif // SANITIZER_LINUX 151