204 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			204 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- sanitizer_allocator_testlib.cc ------------------------------------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| // Malloc replacement library based on CombinedAllocator.
 | |
| // The primary purpose of this file is an end-to-end integration test
 | |
| // for CombinedAllocator.
 | |
| //===----------------------------------------------------------------------===//
 | |
| /* Usage:
 | |
| clang++ -std=c++11 -fno-exceptions  -g -fPIC -I. -I../include -Isanitizer \
 | |
|  sanitizer_common/tests/sanitizer_allocator_testlib.cc \
 | |
|  $(\ls sanitizer_common/sanitizer_*.cc | grep -v sanitizer_common_nolibc.cc) \
 | |
|   sanitizer_common/sanitizer_linux_x86_64.S \
 | |
|  -shared -lpthread -o testmalloc.so
 | |
| LD_PRELOAD=`pwd`/testmalloc.so /your/app
 | |
| */
 | |
| #include "sanitizer_common/sanitizer_allocator.h"
 | |
| #include "sanitizer_common/sanitizer_common.h"
 | |
| #include <stddef.h>
 | |
| #include <stdio.h>
 | |
| #include <unistd.h>
 | |
| #include <string.h>
 | |
| #include <pthread.h>
 | |
| 
 | |
| #ifndef SANITIZER_MALLOC_HOOK
 | |
| # define SANITIZER_MALLOC_HOOK(p, s)
 | |
| #endif
 | |
| 
 | |
| #ifndef SANITIZER_FREE_HOOK
 | |
| # define SANITIZER_FREE_HOOK(p)
 | |
| #endif
 | |
| 
 | |
| static const uptr kAllocatorSpace = 0x600000000000ULL;
 | |
| static const uptr kAllocatorSize  =  0x10000000000ULL;  // 1T.
 | |
| 
 | |
| struct __AP64 {
 | |
|   static const uptr kSpaceBeg = ~(uptr)0;
 | |
|   static const uptr kSpaceSize = kAllocatorSize;
 | |
|   static const uptr kMetadataSize = 0;
 | |
|   typedef CompactSizeClassMap SizeClassMap;
 | |
|   typedef NoOpMapUnmapCallback MapUnmapCallback;
 | |
|   static const uptr kFlags =
 | |
|       SizeClassAllocator64FlagMasks::kRandomShuffleChunks;
 | |
| };
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| typedef SizeClassAllocator64<__AP64> PrimaryAllocator;
 | |
| typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
 | |
| typedef LargeMmapAllocator<> SecondaryAllocator;
 | |
| typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
 | |
|           SecondaryAllocator> Allocator;
 | |
| 
 | |
| static Allocator allocator;
 | |
| static bool global_inited;
 | |
| static THREADLOCAL AllocatorCache cache;
 | |
| static THREADLOCAL bool thread_inited;
 | |
| static pthread_key_t pkey;
 | |
| 
 | |
| static void thread_dtor(void *v) {
 | |
|   if ((uptr)v != 3) {
 | |
|     pthread_setspecific(pkey, (void*)((uptr)v + 1));
 | |
|     return;
 | |
|   }
 | |
|   allocator.SwallowCache(&cache);
 | |
| }
 | |
| 
 | |
| static size_t GetRss() {
 | |
|   if (FILE *f = fopen("/proc/self/statm", "r")) {
 | |
|     size_t size = 0, rss = 0;
 | |
|     fscanf(f, "%zd %zd", &size, &rss);
 | |
|     fclose(f);
 | |
|     return rss << 12;  // rss is in pages.
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| struct AtExit {
 | |
|   ~AtExit() {
 | |
|     allocator.PrintStats();
 | |
|     Printf("RSS: %zdM\n", GetRss() >> 20);
 | |
|   }
 | |
| };
 | |
| 
 | |
| static AtExit at_exit;
 | |
| 
 | |
| static void NOINLINE thread_init() {
 | |
|   if (!global_inited) {
 | |
|     global_inited = true;
 | |
|     allocator.Init(false /*may_return_null*/);
 | |
|     pthread_key_create(&pkey, thread_dtor);
 | |
|   }
 | |
|   thread_inited = true;
 | |
|   pthread_setspecific(pkey, (void*)1);
 | |
|   cache.Init(nullptr);
 | |
| }
 | |
| }  // namespace
 | |
| 
 | |
| extern "C" {
 | |
| void *malloc(size_t size) {
 | |
|   if (UNLIKELY(!thread_inited))
 | |
|     thread_init();
 | |
|   void *p = allocator.Allocate(&cache, size, 8);
 | |
|   SANITIZER_MALLOC_HOOK(p, size);
 | |
|   return p;
 | |
| }
 | |
| 
 | |
| void free(void *p) {
 | |
|   if (UNLIKELY(!thread_inited))
 | |
|     thread_init();
 | |
|   SANITIZER_FREE_HOOK(p);
 | |
|   allocator.Deallocate(&cache, p);
 | |
| }
 | |
| 
 | |
| void *calloc(size_t nmemb, size_t size) {
 | |
|   if (UNLIKELY(!thread_inited))
 | |
|     thread_init();
 | |
|   size *= nmemb;
 | |
|   void *p = allocator.Allocate(&cache, size, 8, false);
 | |
|   memset(p, 0, size);
 | |
|   SANITIZER_MALLOC_HOOK(p, size);
 | |
|   return p;
 | |
| }
 | |
| 
 | |
| void *realloc(void *p, size_t size) {
 | |
|   if (UNLIKELY(!thread_inited))
 | |
|     thread_init();
 | |
|   if (p) {
 | |
|     SANITIZER_FREE_HOOK(p);
 | |
|   }
 | |
|   p = allocator.Reallocate(&cache, p, size, 8);
 | |
|   if (p) {
 | |
|     SANITIZER_MALLOC_HOOK(p, size);
 | |
|   }
 | |
|   return p;
 | |
| }
 | |
| 
 | |
| #if SANITIZER_INTERCEPT_MEMALIGN
 | |
| void *memalign(size_t alignment, size_t size) {
 | |
|   if (UNLIKELY(!thread_inited))
 | |
|     thread_init();
 | |
|   void *p = allocator.Allocate(&cache, size, alignment);
 | |
|   SANITIZER_MALLOC_HOOK(p, size);
 | |
|   return p;
 | |
| }
 | |
| #endif // SANITIZER_INTERCEPT_MEMALIGN
 | |
| 
 | |
| int posix_memalign(void **memptr, size_t alignment, size_t size) {
 | |
|   if (UNLIKELY(!thread_inited))
 | |
|     thread_init();
 | |
|   *memptr = allocator.Allocate(&cache, size, alignment);
 | |
|   SANITIZER_MALLOC_HOOK(*memptr, size);
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| void *valloc(size_t size) {
 | |
|   if (UNLIKELY(!thread_inited))
 | |
|     thread_init();
 | |
|   if (size == 0)
 | |
|     size = GetPageSizeCached();
 | |
|   void *p = allocator.Allocate(&cache, size, GetPageSizeCached());
 | |
|   SANITIZER_MALLOC_HOOK(p, size);
 | |
|   return p;
 | |
| }
 | |
| 
 | |
| #if SANITIZER_INTERCEPT_CFREE
 | |
| void cfree(void *p) ALIAS("free");
 | |
| #endif // SANITIZER_INTERCEPT_CFREE
 | |
| #if SANITIZER_INTERCEPT_PVALLOC
 | |
| void *pvalloc(size_t size) ALIAS("valloc");
 | |
| #endif // SANITIZER_INTERCEPT_PVALLOC
 | |
| #if SANITIZER_INTERCEPT_MEMALIGN
 | |
| void *__libc_memalign(size_t alignment, size_t size) ALIAS("memalign");
 | |
| #endif // SANITIZER_INTERCEPT_MEMALIGN
 | |
| 
 | |
| void malloc_usable_size() {
 | |
| }
 | |
| 
 | |
| #if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
 | |
| void mallinfo() {
 | |
| }
 | |
| 
 | |
| void mallopt() {
 | |
| }
 | |
| #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
 | |
| }  // extern "C"
 | |
| 
 | |
| namespace std {
 | |
|   struct nothrow_t;
 | |
| }
 | |
| 
 | |
| void *operator new(size_t size) ALIAS("malloc");
 | |
| void *operator new[](size_t size) ALIAS("malloc");
 | |
| void *operator new(size_t size, std::nothrow_t const&) ALIAS("malloc");
 | |
| void *operator new[](size_t size, std::nothrow_t const&) ALIAS("malloc");
 | |
| void operator delete(void *ptr) throw() ALIAS("free");
 | |
| void operator delete[](void *ptr) throw() ALIAS("free");
 | |
| void operator delete(void *ptr, std::nothrow_t const&) ALIAS("free");
 | |
| void operator delete[](void *ptr, std::nothrow_t const&) ALIAS("free");
 |