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