201 lines · cpp
1//===-- sanitizer_allocator_testlib.cpp -----------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8// Malloc replacement library based on CombinedAllocator.9// The primary purpose of this file is an end-to-end integration test10// for CombinedAllocator.11//===----------------------------------------------------------------------===//12/* Usage:13clang++ -std=c++11 -fno-exceptions -g -fPIC -I. -I../include -Isanitizer \14 sanitizer_common/tests/sanitizer_allocator_testlib.cpp \15 $(\ls sanitizer_common/sanitizer_*.cpp | grep -v sanitizer_common_nolibc.cpp) \16 sanitizer_common/sanitizer_linux_x86_64.S \17 -shared -lpthread -o testmalloc.so18LD_PRELOAD=`pwd`/testmalloc.so /your/app19*/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_HOOK29# define SANITIZER_MALLOC_HOOK(p, s)30#endif31 32#ifndef SANITIZER_FREE_HOOK33# define SANITIZER_FREE_HOOK(p)34#endif35 36static const uptr kAllocatorSpace = 0x600000000000ULL;37static const uptr kAllocatorSize = 0x10000000000ULL; // 1T.38 39struct __AP64 {40 static const uptr kSpaceBeg = ~(uptr)0;41 static const uptr kSpaceSize = kAllocatorSize;42 static const uptr kMetadataSize = 0;43 typedef CompactSizeClassMap SizeClassMap;44 typedef NoOpMapUnmapCallback MapUnmapCallback;45 static const uptr kFlags =46 SizeClassAllocator64FlagMasks::kRandomShuffleChunks;47};48 49namespace {50 51typedef SizeClassAllocator64<__AP64> PrimaryAllocator;52typedef CombinedAllocator<PrimaryAllocator> Allocator;53typedef Allocator::AllocatorCache AllocatorCache;54 55static Allocator allocator;56static bool global_inited;57static THREADLOCAL AllocatorCache cache;58static THREADLOCAL bool thread_inited;59static pthread_key_t pkey;60 61static void thread_dtor(void *v) {62 if ((uptr)v != 3) {63 pthread_setspecific(pkey, (void*)((uptr)v + 1));64 return;65 }66 allocator.SwallowCache(&cache);67}68 69static size_t GetRss() {70 if (FILE *f = fopen("/proc/self/statm", "r")) {71 size_t size = 0, rss = 0;72 fscanf(f, "%zd %zd", &size, &rss);73 fclose(f);74 return rss << 12; // rss is in pages.75 }76 return 0;77}78 79struct AtExit {80 ~AtExit() {81 allocator.PrintStats();82 Printf("RSS: %zdM\n", GetRss() >> 20);83 }84};85 86static AtExit at_exit;87 88static void NOINLINE thread_init() {89 if (!global_inited) {90 global_inited = true;91 allocator.Init(false /*may_return_null*/);92 pthread_key_create(&pkey, thread_dtor);93 }94 thread_inited = true;95 pthread_setspecific(pkey, (void*)1);96 cache.Init(nullptr);97}98} // namespace99 100extern "C" {101void *malloc(size_t size) {102 if (UNLIKELY(!thread_inited))103 thread_init();104 void *p = allocator.Allocate(&cache, size, 8);105 SANITIZER_MALLOC_HOOK(p, size);106 return p;107}108 109void free(void *p) {110 if (UNLIKELY(!thread_inited))111 thread_init();112 SANITIZER_FREE_HOOK(p);113 allocator.Deallocate(&cache, p);114}115 116void *calloc(size_t nmemb, size_t size) {117 if (UNLIKELY(!thread_inited))118 thread_init();119 size *= nmemb;120 void *p = allocator.Allocate(&cache, size, 8, false);121 memset(p, 0, size);122 SANITIZER_MALLOC_HOOK(p, size);123 return p;124}125 126void *realloc(void *p, size_t size) {127 if (UNLIKELY(!thread_inited))128 thread_init();129 if (p) {130 SANITIZER_FREE_HOOK(p);131 }132 p = allocator.Reallocate(&cache, p, size, 8);133 if (p) {134 SANITIZER_MALLOC_HOOK(p, size);135 }136 return p;137}138 139#if SANITIZER_INTERCEPT_MEMALIGN140void *memalign(size_t alignment, size_t size) {141 if (UNLIKELY(!thread_inited))142 thread_init();143 void *p = allocator.Allocate(&cache, size, alignment);144 SANITIZER_MALLOC_HOOK(p, size);145 return p;146}147#endif // SANITIZER_INTERCEPT_MEMALIGN148 149int posix_memalign(void **memptr, size_t alignment, size_t size) {150 if (UNLIKELY(!thread_inited))151 thread_init();152 *memptr = allocator.Allocate(&cache, size, alignment);153 SANITIZER_MALLOC_HOOK(*memptr, size);154 return 0;155}156 157void *valloc(size_t size) {158 if (UNLIKELY(!thread_inited))159 thread_init();160 if (size == 0)161 size = GetPageSizeCached();162 void *p = allocator.Allocate(&cache, size, GetPageSizeCached());163 SANITIZER_MALLOC_HOOK(p, size);164 return p;165}166 167#if SANITIZER_INTERCEPT_CFREE168void cfree(void *p) ALIAS(free);169#endif // SANITIZER_INTERCEPT_CFREE170#if SANITIZER_INTERCEPT_PVALLOC171void *pvalloc(size_t size) ALIAS(valloc);172#endif // SANITIZER_INTERCEPT_PVALLOC173#if SANITIZER_INTERCEPT_MEMALIGN174void *__libc_memalign(size_t alignment, size_t size) ALIAS(memalign);175#endif // SANITIZER_INTERCEPT_MEMALIGN176 177void malloc_usable_size() {178}179 180#if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO181void mallinfo() {182}183 184void mallopt() {185}186#endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO187} // extern "C"188 189namespace std {190 struct nothrow_t;191}192 193void *operator new(size_t size) ALIAS(malloc);194void *operator new[](size_t size) ALIAS(malloc);195void *operator new(size_t size, std::nothrow_t const&) ALIAS(malloc);196void *operator new[](size_t size, std::nothrow_t const&) ALIAS(malloc);197void operator delete(void *ptr) throw() ALIAS(free);198void operator delete[](void *ptr) throw() ALIAS(free);199void operator delete(void *ptr, std::nothrow_t const&) ALIAS(free);200void operator delete[](void *ptr, std::nothrow_t const&) ALIAS(free);201