summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_testlib.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_testlib.cpp')
-rw-r--r--compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_testlib.cpp200
1 files changed, 200 insertions, 0 deletions
diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_testlib.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_testlib.cpp
new file mode 100644
index 00000000000..93af8be17d1
--- /dev/null
+++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_testlib.cpp
@@ -0,0 +1,200 @@
+//===-- sanitizer_allocator_testlib.cpp -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// 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.cpp \
+ $(\ls sanitizer_common/sanitizer_*.cpp | grep -v sanitizer_common_nolibc.cpp) \
+ 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 CombinedAllocator<PrimaryAllocator> Allocator;
+typedef Allocator::AllocatorCache AllocatorCache;
+
+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");
OpenPOWER on IntegriCloud