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:
14clang++ -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
17LD_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
35namespace {
36static const uptr kAllocatorSpace = 0x600000000000ULL;
37static const uptr kAllocatorSize  =  0x10000000000ULL;  // 1T.
38
39typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, 0,
40  CompactSizeClassMap> PrimaryAllocator;
41typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
42typedef LargeMmapAllocator<> SecondaryAllocator;
43typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
44          SecondaryAllocator> Allocator;
45
46static Allocator allocator;
47static bool global_inited;
48static THREADLOCAL AllocatorCache cache;
49static THREADLOCAL bool thread_inited;
50static pthread_key_t pkey;
51
52static 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
60static 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
72extern "C" {
73void *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
81void free(void *p) {
82  if (UNLIKELY(!thread_inited))
83    thread_init();
84  SANITIZER_FREE_HOOK(p);
85  allocator.Deallocate(&cache, p);
86}
87
88void *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
98void *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
111void *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
119int 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
127void *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
137void cfree(void *p) ALIAS("free");
138void *pvalloc(size_t size) ALIAS("valloc");
139void *__libc_memalign(size_t alignment, size_t size) ALIAS("memalign");
140
141void malloc_usable_size() {
142}
143
144void mallinfo() {
145}
146
147void mallopt() {
148}
149}  // extern "C"
150
151namespace std {
152  struct nothrow_t;
153}
154
155void *operator new(size_t size) ALIAS("malloc");
156void *operator new[](size_t size) ALIAS("malloc");
157void *operator new(size_t size, std::nothrow_t const&) ALIAS("malloc");
158void *operator new[](size_t size, std::nothrow_t const&) ALIAS("malloc");
159void operator delete(void *ptr) throw() ALIAS("free");
160void operator delete[](void *ptr) throw() ALIAS("free");
161void operator delete(void *ptr, std::nothrow_t const&) ALIAS("free");
162void operator delete[](void *ptr, std::nothrow_t const&) ALIAS("free");
163