Home | History | Annotate | Download | only in asan
      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