//===-- 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++ -fno-exceptions -g -fPIC -I. -I../include -Isanitizer \ sanitizer_common/tests/sanitizer_allocator_testlib.cc \ sanitizer_common/sanitizer_*.cc -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 namespace { static const uptr kAllocatorSpace = 0x600000000000ULL; static const uptr kAllocatorSize = 0x10000000000ULL; // 1T. typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, 0, CompactSizeClassMap> 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 void NOINLINE thread_init() { if (!global_inited) { global_inited = true; allocator.Init(); pthread_key_create(&pkey, thread_dtor); } thread_inited = true; pthread_setspecific(pkey, (void*)1); cache.Init(); } } // 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; } 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; } 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; } void cfree(void *p) ALIAS("free"); void *pvalloc(size_t size) ALIAS("valloc"); void *__libc_memalign(size_t alignment, size_t size) ALIAS("memalign"); void malloc_usable_size() { } void mallinfo() { } void mallopt() { } } // 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");