xref: /netbsd-src/sys/external/bsd/compiler_rt/dist/lib/sanitizer_common/tests/sanitizer_allocator_testlib.cc (revision a7c257b03e4462df2b1020128fb82716512d7856)
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   sanitizer_common/sanitizer_linux_x86_64.S \
18  -shared -lpthread -o testmalloc.so
19 LD_PRELOAD=`pwd`/testmalloc.so /your/app
20 */
21 #include "sanitizer_common/sanitizer_allocator.h"
22 #include "sanitizer_common/sanitizer_common.h"
23 #include <stddef.h>
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <pthread.h>
28 
29 #ifndef SANITIZER_MALLOC_HOOK
30 # define SANITIZER_MALLOC_HOOK(p, s)
31 #endif
32 
33 #ifndef SANITIZER_FREE_HOOK
34 # define SANITIZER_FREE_HOOK(p)
35 #endif
36 
37 static const uptr kAllocatorSpace = 0x600000000000ULL;
38 static const uptr kAllocatorSize  =  0x10000000000ULL;  // 1T.
39 
40 struct __AP64 {
41   static const uptr kSpaceBeg = ~(uptr)0;
42   static const uptr kSpaceSize = kAllocatorSize;
43   static const uptr kMetadataSize = 0;
44   typedef CompactSizeClassMap SizeClassMap;
45   typedef NoOpMapUnmapCallback MapUnmapCallback;
46   static const uptr kFlags =
47       SizeClassAllocator64FlagMasks::kRandomShuffleChunks;
48 };
49 
50 namespace {
51 
52 typedef SizeClassAllocator64<__AP64> PrimaryAllocator;
53 typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
54 typedef LargeMmapAllocator<> SecondaryAllocator;
55 typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
56           SecondaryAllocator> Allocator;
57 
58 static Allocator allocator;
59 static bool global_inited;
60 static THREADLOCAL AllocatorCache cache;
61 static THREADLOCAL bool thread_inited;
62 static pthread_key_t pkey;
63 
thread_dtor(void * v)64 static void thread_dtor(void *v) {
65   if ((uptr)v != 3) {
66     pthread_setspecific(pkey, (void*)((uptr)v + 1));
67     return;
68   }
69   allocator.SwallowCache(&cache);
70 }
71 
GetRss()72 static size_t GetRss() {
73   if (FILE *f = fopen("/proc/self/statm", "r")) {
74     size_t size = 0, rss = 0;
75     fscanf(f, "%zd %zd", &size, &rss);
76     fclose(f);
77     return rss << 12;  // rss is in pages.
78   }
79   return 0;
80 }
81 
82 struct AtExit {
~AtExit__anon8eaf0b4d0111::AtExit83   ~AtExit() {
84     allocator.PrintStats();
85     Printf("RSS: %zdM\n", GetRss() >> 20);
86   }
87 };
88 
89 static AtExit at_exit;
90 
thread_init()91 static void NOINLINE thread_init() {
92   if (!global_inited) {
93     global_inited = true;
94     allocator.Init(false /*may_return_null*/);
95     pthread_key_create(&pkey, thread_dtor);
96   }
97   thread_inited = true;
98   pthread_setspecific(pkey, (void*)1);
99   cache.Init(nullptr);
100 }
101 }  // namespace
102 
103 extern "C" {
malloc(size_t size)104 void *malloc(size_t size) {
105   if (UNLIKELY(!thread_inited))
106     thread_init();
107   void *p = allocator.Allocate(&cache, size, 8);
108   SANITIZER_MALLOC_HOOK(p, size);
109   return p;
110 }
111 
free(void * p)112 void free(void *p) {
113   if (UNLIKELY(!thread_inited))
114     thread_init();
115   SANITIZER_FREE_HOOK(p);
116   allocator.Deallocate(&cache, p);
117 }
118 
calloc(size_t nmemb,size_t size)119 void *calloc(size_t nmemb, size_t size) {
120   if (UNLIKELY(!thread_inited))
121     thread_init();
122   size *= nmemb;
123   void *p = allocator.Allocate(&cache, size, 8, false);
124   memset(p, 0, size);
125   SANITIZER_MALLOC_HOOK(p, size);
126   return p;
127 }
128 
realloc(void * p,size_t size)129 void *realloc(void *p, size_t size) {
130   if (UNLIKELY(!thread_inited))
131     thread_init();
132   if (p) {
133     SANITIZER_FREE_HOOK(p);
134   }
135   p = allocator.Reallocate(&cache, p, size, 8);
136   if (p) {
137     SANITIZER_MALLOC_HOOK(p, size);
138   }
139   return p;
140 }
141 
142 #if SANITIZER_INTERCEPT_MEMALIGN
memalign(size_t alignment,size_t size)143 void *memalign(size_t alignment, size_t size) {
144   if (UNLIKELY(!thread_inited))
145     thread_init();
146   void *p = allocator.Allocate(&cache, size, alignment);
147   SANITIZER_MALLOC_HOOK(p, size);
148   return p;
149 }
150 #endif // SANITIZER_INTERCEPT_MEMALIGN
151 
posix_memalign(void ** memptr,size_t alignment,size_t size)152 int posix_memalign(void **memptr, size_t alignment, size_t size) {
153   if (UNLIKELY(!thread_inited))
154     thread_init();
155   *memptr = allocator.Allocate(&cache, size, alignment);
156   SANITIZER_MALLOC_HOOK(*memptr, size);
157   return 0;
158 }
159 
valloc(size_t size)160 void *valloc(size_t size) {
161   if (UNLIKELY(!thread_inited))
162     thread_init();
163   if (size == 0)
164     size = GetPageSizeCached();
165   void *p = allocator.Allocate(&cache, size, GetPageSizeCached());
166   SANITIZER_MALLOC_HOOK(p, size);
167   return p;
168 }
169 
170 #if SANITIZER_INTERCEPT_CFREE
171 void cfree(void *p) ALIAS("free");
172 #endif // SANITIZER_INTERCEPT_CFREE
173 #if SANITIZER_INTERCEPT_PVALLOC
174 void *pvalloc(size_t size) ALIAS("valloc");
175 #endif // SANITIZER_INTERCEPT_PVALLOC
176 #if SANITIZER_INTERCEPT_MEMALIGN
177 void *__libc_memalign(size_t alignment, size_t size) ALIAS("memalign");
178 #endif // SANITIZER_INTERCEPT_MEMALIGN
179 
malloc_usable_size()180 void malloc_usable_size() {
181 }
182 
183 #if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
mallinfo()184 void mallinfo() {
185 }
186 
mallopt()187 void mallopt() {
188 }
189 #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
190 }  // extern "C"
191 
192 namespace std {
193   struct nothrow_t;
194 }
195 
196 void *operator new(size_t size) ALIAS("malloc");
197 void *operator new[](size_t size) ALIAS("malloc");
198 void *operator new(size_t size, std::nothrow_t const&) ALIAS("malloc");
199 void *operator new[](size_t size, std::nothrow_t const&) ALIAS("malloc");
200 void operator delete(void *ptr) throw() ALIAS("free");
201 void operator delete[](void *ptr) throw() ALIAS("free");
202 void operator delete(void *ptr, std::nothrow_t const&) ALIAS("free");
203 void operator delete[](void *ptr, std::nothrow_t const&) ALIAS("free");
204