[compiler-rt] r182245 - [lsan] Allocator for standalone LSan.

Sergey Matveev earthdok at google.com
Mon May 20 03:54:00 PDT 2013


Author: smatveev
Date: Mon May 20 05:54:00 2013
New Revision: 182245

URL: http://llvm.org/viewvc/llvm-project?rev=182245&view=rev
Log:
[lsan] Allocator for standalone LSan.

This is the first in a series of CLs implementing LeakSanitizer.
http://clang.llvm.org/docs/LeakSanitizer.html

Added:
    compiler-rt/trunk/lib/lsan/
    compiler-rt/trunk/lib/lsan/lsan_allocator.cc
    compiler-rt/trunk/lib/lsan/lsan_allocator.h

Added: compiler-rt/trunk/lib/lsan/lsan_allocator.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_allocator.cc?rev=182245&view=auto
==============================================================================
--- compiler-rt/trunk/lib/lsan/lsan_allocator.cc (added)
+++ compiler-rt/trunk/lib/lsan/lsan_allocator.cc Mon May 20 05:54:00 2013
@@ -0,0 +1,188 @@
+//=-- lsan_allocator.cc ---------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// See lsan_allocator.h for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lsan_allocator.h"
+
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "lsan_common.h"
+
+namespace __lsan {
+
+static const uptr kMaxAllowedMallocSize =
+    FIRST_32_SECOND_64(3UL << 30, 8UL << 30);
+
+static const uptr kAllocatorSpace = 0x600000000000ULL;
+static const uptr kAllocatorSize  =  0x10000000000ULL;  // 1T.
+
+struct ChunkMetadata {
+  bool allocated : 8;  // Must be first.
+  ChunkTag tag : 2;
+  uptr requested_size : 54;
+  u32 stack_trace_id;
+};
+
+typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize,
+        sizeof(ChunkMetadata), CompactSizeClassMap> PrimaryAllocator;
+typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
+typedef LargeMmapAllocator<> SecondaryAllocator;
+typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
+          SecondaryAllocator> Allocator;
+
+static Allocator allocator;
+static THREADLOCAL AllocatorCache cache;
+
+void InitializeAllocator() {
+  allocator.Init();
+}
+
+void AllocatorThreadFinish() {
+  allocator.SwallowCache(&cache);
+}
+
+static ChunkMetadata *Metadata(void *p) {
+  return (ChunkMetadata *)allocator.GetMetaData(p);
+}
+
+static void RegisterAllocation(const StackTrace &stack, void *p, uptr size) {
+  if (!p) return;
+  ChunkMetadata *m = Metadata(p);
+  CHECK(m);
+  m->stack_trace_id = StackDepotPut(stack.trace, stack.size);
+  m->requested_size = size;
+  atomic_store((atomic_uint8_t*)m, 1, memory_order_relaxed);
+}
+
+static void RegisterDeallocation(void *p) {
+  if (!p) return;
+  ChunkMetadata *m = Metadata(p);
+  CHECK(m);
+  atomic_store((atomic_uint8_t*)m, 0, memory_order_relaxed);
+}
+
+void *Allocate(const StackTrace &stack, uptr size, uptr alignment,
+               bool cleared) {
+  if (size == 0)
+    size = 1;
+  if (size > kMaxAllowedMallocSize) {
+      Report("WARNING: LeakSanitizer failed to allocate %p bytes\n",
+             (void*)size);
+      return 0;
+  }
+  void *p = allocator.Allocate(&cache, size, alignment, cleared);
+  RegisterAllocation(stack, p, size);
+  return p;
+}
+
+void Deallocate(void *p) {
+  RegisterDeallocation(p);
+  allocator.Deallocate(&cache, p);
+}
+
+void *Reallocate(const StackTrace &stack, void *p, uptr new_size,
+                 uptr alignment) {
+  RegisterDeallocation(p);
+  if (new_size > kMaxAllowedMallocSize) {
+      Report("WARNING: LeakSanitizer failed to allocate %p bytes\n",
+             (void*)new_size);
+      allocator.Deallocate(&cache, p);
+      return 0;
+  }
+  p = allocator.Reallocate(&cache, p, new_size, alignment);
+  RegisterAllocation(stack, p, new_size);
+  return p;
+}
+
+void GetAllocatorCacheRange(uptr *begin, uptr *end) {
+  *begin = (uptr)&cache;
+  *end = *begin + sizeof(cache);
+}
+
+uptr GetMallocUsableSize(void *p) {
+  ChunkMetadata *m = Metadata(p);
+  if (!m) return 0;
+  return m->requested_size;
+}
+
+///// Interface to the common LSan module. /////
+
+void LockAllocator() {
+  allocator.ForceLock();
+}
+
+void UnlockAllocator() {
+  allocator.ForceUnlock();
+}
+
+void GetAllocatorGlobalRange(uptr *begin, uptr *end) {
+  *begin = (uptr)&allocator;
+  *end = *begin + sizeof(allocator);
+}
+
+void *PointsIntoChunk(void* p) {
+  if (!allocator.PointerIsMine(p)) return 0;
+  void *chunk = allocator.GetBlockBegin(p);
+  if (!chunk) return 0;
+  // LargeMmapAllocator considers pointers to the meta-region of a chunk to be
+  // valid, but we don't want that.
+  if (p < chunk) return 0;
+  ChunkMetadata *m = Metadata(chunk);
+  CHECK(m);
+  if (m->allocated && (uptr)p < (uptr)chunk + m->requested_size)
+    return chunk;
+  return 0;
+}
+
+LsanMetadata::LsanMetadata(void *chunk) {
+  metadata_ = Metadata(chunk);
+  CHECK(metadata_);
+}
+
+bool LsanMetadata::allocated() const {
+  return reinterpret_cast<ChunkMetadata *>(metadata_)->allocated;
+}
+
+ChunkTag LsanMetadata::tag() const {
+  return reinterpret_cast<ChunkMetadata *>(metadata_)->tag;
+}
+
+void LsanMetadata::set_tag(ChunkTag value) {
+  reinterpret_cast<ChunkMetadata *>(metadata_)->tag = value;
+}
+
+uptr LsanMetadata::requested_size() const {
+  return reinterpret_cast<ChunkMetadata *>(metadata_)->requested_size;
+}
+
+u32 LsanMetadata::stack_trace_id() const {
+  return reinterpret_cast<ChunkMetadata *>(metadata_)->stack_trace_id;
+}
+
+template<typename Callable>
+void ForEachChunk(Callable const &callback) {
+  allocator.ForEachChunk(callback);
+}
+
+template void ForEachChunk<ProcessPlatformSpecificAllocationsCb>(
+    ProcessPlatformSpecificAllocationsCb const &callback);
+template void ForEachChunk<PrintLeakedCb>(PrintLeakedCb const &callback);
+template void ForEachChunk<CollectLeaksCb>(CollectLeaksCb const &callback);
+template void ForEachChunk<MarkIndirectlyLeakedCb>(
+    MarkIndirectlyLeakedCb const &callback);
+template void ForEachChunk<ReportLeakedCb>(ReportLeakedCb const &callback);
+template void ForEachChunk<ClearTagCb>(ClearTagCb const &callback);
+
+}  // namespace __lsan

Added: compiler-rt/trunk/lib/lsan/lsan_allocator.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_allocator.h?rev=182245&view=auto
==============================================================================
--- compiler-rt/trunk/lib/lsan/lsan_allocator.h (added)
+++ compiler-rt/trunk/lib/lsan/lsan_allocator.h Mon May 20 05:54:00 2013
@@ -0,0 +1,39 @@
+//=-- lsan_allocator.h ----------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Allocator for standalone LSan.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LSAN_ALLOCATOR_H
+#define LSAN_ALLOCATOR_H
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+namespace __lsan {
+
+void *Allocate(const StackTrace &stack, uptr size, uptr alignment,
+               bool cleared);
+void Deallocate(void *p);
+void *Reallocate(const StackTrace &stack, void *p, uptr new_size,
+                 uptr alignment);
+uptr GetMallocUsableSize(void *p);
+
+template<typename Callable>
+void ForEachChunk(const Callable &callback);
+
+void GetAllocatorCacheRange(uptr *begin, uptr *end);
+void AllocatorThreadFinish();
+void InitializeAllocator();
+
+}  // namespace __lsan
+
+#endif  // LSAN_ALLOCATOR_H





More information about the llvm-commits mailing list