Home | History | Annotate | Download | only in tests
      1 //===-- sanitizer_allocator_testlib.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 // Malloc replacement library based on CombinedAllocator.
     10 // The primary purpose of this file is an end-to-end integration test
     11 // for CombinedAllocator.
     12 //===----------------------------------------------------------------------===//
     13 /* Usage:
     14 clang++ -std=c++11 -fno-exceptions  -g -fPIC -I. -I../include -Isanitizer \
     15  sanitizer_common/tests/sanitizer_allocator_testlib.cc \
     16  $(\ls sanitizer_common/sanitizer_*.cc | grep -v sanitizer_common_nolibc.cc) \
     17  -shared -lpthread -o testmalloc.so
     18 LD_PRELOAD=`pwd`/testmalloc.so /your/app
     19 */
     20 #include "sanitizer_common/sanitizer_allocator.h"
     21 #include "sanitizer_common/sanitizer_common.h"
     22 #include <stddef.h>
     23 #include <stdio.h>
     24 #include <unistd.h>
     25 #include <string.h>
     26 #include <pthread.h>
     27 
     28 #ifndef SANITIZER_MALLOC_HOOK
     29 # define SANITIZER_MALLOC_HOOK(p, s)
     30 #endif
     31 
     32 #ifndef SANITIZER_FREE_HOOK
     33 # define SANITIZER_FREE_HOOK(p)
     34 #endif
     35 
     36 namespace {
     37 static const uptr kAllocatorSpace = 0x600000000000ULL;
     38 static const uptr kAllocatorSize  =  0x10000000000ULL;  // 1T.
     39 
     40 // typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, 0,
     41 typedef SizeClassAllocator64<~(uptr)0, kAllocatorSize, 0,
     42   CompactSizeClassMap> PrimaryAllocator;
     43 typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
     44 typedef LargeMmapAllocator<> SecondaryAllocator;
     45 typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
     46           SecondaryAllocator> Allocator;
     47 
     48 static Allocator allocator;
     49 static bool global_inited;
     50 static THREADLOCAL AllocatorCache cache;
     51 static THREADLOCAL bool thread_inited;
     52 static pthread_key_t pkey;
     53 
     54 static void thread_dtor(void *v) {
     55   if ((uptr)v != 3) {
     56     pthread_setspecific(pkey, (void*)((uptr)v + 1));
     57     return;
     58   }
     59   allocator.SwallowCache(&cache);
     60 }
     61 
     62 static void NOINLINE thread_init() {
     63   if (!global_inited) {
     64     global_inited = true;
     65     allocator.Init(false /*may_return_null*/);
     66     pthread_key_create(&pkey, thread_dtor);
     67   }
     68   thread_inited = true;
     69   pthread_setspecific(pkey, (void*)1);
     70   cache.Init(nullptr);
     71 }
     72 }  // namespace
     73 
     74 extern "C" {
     75 void *malloc(size_t size) {
     76   if (UNLIKELY(!thread_inited))
     77     thread_init();
     78   void *p = allocator.Allocate(&cache, size, 8);
     79   SANITIZER_MALLOC_HOOK(p, size);
     80   return p;
     81 }
     82 
     83 void free(void *p) {
     84   if (UNLIKELY(!thread_inited))
     85     thread_init();
     86   SANITIZER_FREE_HOOK(p);
     87   allocator.Deallocate(&cache, p);
     88 }
     89 
     90 void *calloc(size_t nmemb, size_t size) {
     91   if (UNLIKELY(!thread_inited))
     92     thread_init();
     93   size *= nmemb;
     94   void *p = allocator.Allocate(&cache, size, 8, false);
     95   memset(p, 0, size);
     96   SANITIZER_MALLOC_HOOK(p, size);
     97   return p;
     98 }
     99 
    100 void *realloc(void *p, size_t size) {
    101   if (UNLIKELY(!thread_inited))
    102     thread_init();
    103   if (p) {
    104     SANITIZER_FREE_HOOK(p);
    105   }
    106   p = allocator.Reallocate(&cache, p, size, 8);
    107   if (p) {
    108     SANITIZER_MALLOC_HOOK(p, size);
    109   }
    110   return p;
    111 }
    112 
    113 void *memalign(size_t alignment, size_t size) {
    114   if (UNLIKELY(!thread_inited))
    115     thread_init();
    116   void *p = allocator.Allocate(&cache, size, alignment);
    117   SANITIZER_MALLOC_HOOK(p, size);
    118   return p;
    119 }
    120 
    121 int posix_memalign(void **memptr, size_t alignment, size_t size) {
    122   if (UNLIKELY(!thread_inited))
    123     thread_init();
    124   *memptr = allocator.Allocate(&cache, size, alignment);
    125   SANITIZER_MALLOC_HOOK(*memptr, size);
    126   return 0;
    127 }
    128 
    129 void *valloc(size_t size) {
    130   if (UNLIKELY(!thread_inited))
    131     thread_init();
    132   if (size == 0)
    133     size = GetPageSizeCached();
    134   void *p = allocator.Allocate(&cache, size, GetPageSizeCached());
    135   SANITIZER_MALLOC_HOOK(p, size);
    136   return p;
    137 }
    138 
    139 void cfree(void *p) ALIAS("free");
    140 void *pvalloc(size_t size) ALIAS("valloc");
    141 void *__libc_memalign(size_t alignment, size_t size) ALIAS("memalign");
    142 
    143 void malloc_usable_size() {
    144 }
    145 
    146 void mallinfo() {
    147 }
    148 
    149 void mallopt() {
    150 }
    151 }  // extern "C"
    152 
    153 namespace std {
    154   struct nothrow_t;
    155 }
    156 
    157 void *operator new(size_t size) ALIAS("malloc");
    158 void *operator new[](size_t size) ALIAS("malloc");
    159 void *operator new(size_t size, std::nothrow_t const&) ALIAS("malloc");
    160 void *operator new[](size_t size, std::nothrow_t const&) ALIAS("malloc");
    161 void operator delete(void *ptr) throw() ALIAS("free");
    162 void operator delete[](void *ptr) throw() ALIAS("free");
    163 void operator delete(void *ptr, std::nothrow_t const&) ALIAS("free");
    164 void operator delete[](void *ptr, std::nothrow_t const&) ALIAS("free");
    165