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 
thread_dtor(void * v)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 
thread_init()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" {
malloc(size_t size)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 
free(void * p)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 
calloc(size_t nmemb,size_t size)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 
realloc(void * p,size_t size)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 
memalign(size_t alignment,size_t size)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 
posix_memalign(void ** memptr,size_t alignment,size_t size)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 
valloc(size_t size)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 
malloc_usable_size()141 void malloc_usable_size() {
142 }
143 
mallinfo()144 void mallinfo() {
145 }
146 
mallopt()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