[compiler-rt] r224605 - [ASan] Introduce AllocatorOptions to configure allocator behavior.

Alexey Samsonov vonosmas at gmail.com
Fri Dec 19 11:35:11 PST 2014


Author: samsonov
Date: Fri Dec 19 13:35:11 2014
New Revision: 224605

URL: http://llvm.org/viewvc/llvm-project?rev=224605&view=rev
Log:
[ASan] Introduce AllocatorOptions to configure allocator behavior.

Summary:
Reduce the dependency of allocator code on runtime flags. Instead,
pass a bunch of options that configure allocator behavior at
initialization or re-initialization. That would allow us to
cleaner modify allocator behavior during a program execution
when ASan is activated or de-activated.

Test Plan: regression test suite

Reviewers: kcc

Subscribers: llvm-commits, eugenis

Differential Revision: http://reviews.llvm.org/D6711

Modified:
    compiler-rt/trunk/lib/asan/asan_activation.cc
    compiler-rt/trunk/lib/asan/asan_allocator.cc
    compiler-rt/trunk/lib/asan/asan_allocator.h
    compiler-rt/trunk/lib/asan/asan_rtl.cc

Modified: compiler-rt/trunk/lib/asan/asan_activation.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_activation.cc?rev=224605&r1=224604&r2=224605&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_activation.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_activation.cc Fri Dec 19 13:35:11 2014
@@ -23,20 +23,14 @@
 namespace __asan {
 
 static struct AsanDeactivatedFlags {
-  int quarantine_size;
-  int max_redzone;
+  AllocatorOptions allocator_options;
   int malloc_context_size;
   bool poison_heap;
-  bool alloc_dealloc_mismatch;
-  bool allocator_may_return_null;
 
   void CopyFrom(const Flags *f, const CommonFlags *cf) {
-    quarantine_size = f->quarantine_size;
-    max_redzone = f->max_redzone;
+    allocator_options.SetFrom(f, cf);
     malloc_context_size = cf->malloc_context_size;
     poison_heap = f->poison_heap;
-    alloc_dealloc_mismatch = f->alloc_dealloc_mismatch;
-    allocator_may_return_null = cf->allocator_may_return_null;
   }
 
   void OverrideFromActivationFlags() {
@@ -44,12 +38,14 @@ static struct AsanDeactivatedFlags {
     CommonFlags cf;
 
     // Copy the current activation flags.
-    f.quarantine_size = quarantine_size;
-    f.max_redzone = max_redzone;
+    f.quarantine_size = allocator_options.quarantine_size_mb << 20;
+    f.redzone = allocator_options.min_redzone;
+    f.max_redzone = allocator_options.max_redzone;
+    cf.allocator_may_return_null = allocator_options.may_return_null;
+    f.alloc_dealloc_mismatch = allocator_options.alloc_dealloc_mismatch;
+
     cf.malloc_context_size = malloc_context_size;
     f.poison_heap = poison_heap;
-    f.alloc_dealloc_mismatch = alloc_dealloc_mismatch;
-    cf.allocator_may_return_null = allocator_may_return_null;
 
     // Check if activation flags need to be overriden.
     // FIXME: Add diagnostic to check that activation flags string doesn't
@@ -63,11 +59,13 @@ static struct AsanDeactivatedFlags {
   }
 
   void Print() {
-    Report("quarantine_size %d, max_redzone %d, poison_heap %d, "
+    Report("quarantine_size_mb %d, max_redzone %d, poison_heap %d, "
            "malloc_context_size %d, alloc_dealloc_mismatch %d, "
            "allocator_may_return_null %d\n",
-           quarantine_size, max_redzone, poison_heap, malloc_context_size,
-           alloc_dealloc_mismatch, allocator_may_return_null);
+           allocator_options.quarantine_size_mb, allocator_options.max_redzone,
+           poison_heap, malloc_context_size,
+           allocator_options.alloc_dealloc_mismatch,
+           allocator_options.may_return_null);
   }
 } asan_deactivated_flags;
 
@@ -97,16 +95,9 @@ void AsanActivate() {
 
   asan_deactivated_flags.OverrideFromActivationFlags();
 
-  // Restore flag values.
-  // FIXME: this is not atomic, and there may be other threads alive.
-  flags()->max_redzone = asan_deactivated_flags.max_redzone;
-  flags()->alloc_dealloc_mismatch =
-      asan_deactivated_flags.alloc_dealloc_mismatch;
-
   SetCanPoisonMemory(asan_deactivated_flags.poison_heap);
   SetMallocContextSize(asan_deactivated_flags.malloc_context_size);
-  ReInitializeAllocator(asan_deactivated_flags.allocator_may_return_null,
-                        asan_deactivated_flags.quarantine_size);
+  ReInitializeAllocator(asan_deactivated_flags.allocator_options);
 
   asan_is_deactivated = false;
   if (common_flags()->verbosity) {

Modified: compiler-rt/trunk/lib/asan/asan_allocator.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_allocator.cc?rev=224605&r1=224604&r2=224605&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_allocator.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_allocator.cc Fri Dec 19 13:35:11 2014
@@ -205,6 +205,14 @@ QuarantineCache *GetQuarantineCache(Asan
   return reinterpret_cast<QuarantineCache *>(ms->quarantine_cache);
 }
 
+void AllocatorOptions::SetFrom(const Flags *f, const CommonFlags *cf) {
+  quarantine_size_mb = f->quarantine_size >> 20;
+  min_redzone = f->redzone;
+  max_redzone = f->max_redzone;
+  may_return_null = cf->allocator_may_return_null;
+  alloc_dealloc_mismatch = f->alloc_dealloc_mismatch;
+}
+
 struct Allocator {
   static const uptr kMaxAllowedMallocSize =
       FIRST_32_SECOND_64(3UL << 30, 64UL << 30);
@@ -217,19 +225,42 @@ struct Allocator {
   AllocatorCache fallback_allocator_cache;
   QuarantineCache fallback_quarantine_cache;
 
+  // ------------------- Options --------------------------
+  atomic_uint16_t min_redzone;
+  atomic_uint16_t max_redzone;
+  atomic_uint8_t alloc_dealloc_mismatch;
+
+  // ------------------- Initialization ------------------------
   explicit Allocator(LinkerInitialized)
       : quarantine(LINKER_INITIALIZED),
         fallback_quarantine_cache(LINKER_INITIALIZED) {}
 
-  // ------------------- Initialization ------------------------
-  void Initialize(bool may_return_null, uptr quarantine_size) {
-    allocator.Init(may_return_null);
-    quarantine.Init(quarantine_size, kMaxThreadLocalQuarantine);
-  }
-
-  void ReInitialize(bool may_return_null, uptr quarantine_size) {
-    allocator.SetMayReturnNull(may_return_null);
-    quarantine.Init(quarantine_size, kMaxThreadLocalQuarantine);
+  void CheckOptions(const AllocatorOptions &options) const {
+    CHECK_GE(options.min_redzone, 16);
+    CHECK_GE(options.max_redzone, options.min_redzone);
+    CHECK_LE(options.max_redzone, 2048);
+    CHECK(IsPowerOfTwo(options.min_redzone));
+    CHECK(IsPowerOfTwo(options.max_redzone));
+  }
+
+  void SharedInitCode(const AllocatorOptions &options) {
+    CheckOptions(options);
+    quarantine.Init((uptr)options.quarantine_size_mb << 20,
+                    kMaxThreadLocalQuarantine);
+    atomic_store(&alloc_dealloc_mismatch, options.alloc_dealloc_mismatch,
+                 memory_order_release);
+    atomic_store(&min_redzone, options.min_redzone, memory_order_release);
+    atomic_store(&max_redzone, options.max_redzone, memory_order_release);
+  }
+
+  void Initialize(const AllocatorOptions &options) {
+    allocator.Init(options.may_return_null);
+    SharedInitCode(options);
+  }
+
+  void ReInitialize(const AllocatorOptions &options) {
+    allocator.SetMayReturnNull(options.may_return_null);
+    SharedInitCode(options);
   }
 
   // -------------------- Helper methods. -------------------------
@@ -242,8 +273,9 @@ struct Allocator {
       user_requested_size <= (1 << 14) - 256  ? 4 :
       user_requested_size <= (1 << 15) - 512  ? 5 :
       user_requested_size <= (1 << 16) - 1024 ? 6 : 7;
-    return Min(Max(rz_log, RZSize2Log(flags()->redzone)),
-               RZSize2Log(flags()->max_redzone));
+    u32 min_rz = atomic_load(&min_redzone, memory_order_acquire);
+    u32 max_rz = atomic_load(&max_redzone, memory_order_acquire);
+    return Min(Max(rz_log, RZSize2Log(min_rz)), RZSize2Log(max_rz));
   }
 
   // We have an address between two chunks, and we want to report just one.
@@ -419,9 +451,12 @@ struct Allocator {
                        AllocType alloc_type) {
     CHECK_EQ(m->chunk_state, CHUNK_QUARANTINE);
 
-    if (m->alloc_type != alloc_type && flags()->alloc_dealloc_mismatch)
-      ReportAllocTypeMismatch((uptr)ptr, stack,
-                              (AllocType)m->alloc_type, (AllocType)alloc_type);
+    if (m->alloc_type != alloc_type) {
+      if (atomic_load(&alloc_dealloc_mismatch, memory_order_acquire)) {
+        ReportAllocTypeMismatch((uptr)ptr, stack, (AllocType)m->alloc_type,
+                                (AllocType)alloc_type);
+      }
+    }
 
     CHECK_GE(m->alloc_tid, 0);
     if (SANITIZER_WORDSIZE == 64)  // On 32-bits this resides in user area.
@@ -619,12 +654,12 @@ StackTrace AsanChunkView::GetFreeStack()
   return GetStackTraceFromId(chunk_->free_context_id);
 }
 
-void InitializeAllocator(bool may_return_null, uptr quarantine_size) {
-  instance.Initialize(may_return_null, quarantine_size);
+void InitializeAllocator(const AllocatorOptions &options) {
+  instance.Initialize(options);
 }
 
-void ReInitializeAllocator(bool may_return_null, uptr quarantine_size) {
-  instance.ReInitialize(may_return_null, quarantine_size);
+void ReInitializeAllocator(const AllocatorOptions &options) {
+  instance.ReInitialize(options);
 }
 
 AsanChunkView FindHeapChunkByAddress(uptr addr) {

Modified: compiler-rt/trunk/lib/asan/asan_allocator.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_allocator.h?rev=224605&r1=224604&r2=224605&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_allocator.h (original)
+++ compiler-rt/trunk/lib/asan/asan_allocator.h Fri Dec 19 13:35:11 2014
@@ -15,6 +15,7 @@
 #ifndef ASAN_ALLOCATOR_H
 #define ASAN_ALLOCATOR_H
 
+#include "asan_flags.h"
 #include "asan_internal.h"
 #include "asan_interceptors.h"
 #include "sanitizer_common/sanitizer_allocator.h"
@@ -31,8 +32,18 @@ enum AllocType {
 static const uptr kNumberOfSizeClasses = 255;
 struct AsanChunk;
 
-void InitializeAllocator(bool may_return_null, uptr quarantine_size);
-void ReInitializeAllocator(bool may_return_null, uptr quarantine_size);
+struct AllocatorOptions {
+  u32 quarantine_size_mb;
+  u16 min_redzone;
+  u16 max_redzone;
+  u8 may_return_null;
+  u8 alloc_dealloc_mismatch;
+
+  void SetFrom(const Flags *f, const CommonFlags *cf);
+};
+
+void InitializeAllocator(const AllocatorOptions &options);
+void ReInitializeAllocator(const AllocatorOptions &options);
 
 class AsanChunkView {
  public:

Modified: compiler-rt/trunk/lib/asan/asan_rtl.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_rtl.cc?rev=224605&r1=224604&r2=224605&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_rtl.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_rtl.cc Fri Dec 19 13:35:11 2014
@@ -391,8 +391,9 @@ static void AsanInitInternal() {
   AsanTSDInit(PlatformTSDDtor);
   InstallDeadlySignalHandlers(AsanOnSIGSEGV);
 
-  InitializeAllocator(common_flags()->allocator_may_return_null,
-                      flags()->quarantine_size);
+  AllocatorOptions allocator_options;
+  allocator_options.SetFrom(flags(), common_flags());
+  InitializeAllocator(allocator_options);
 
   MaybeStartBackgroudThread();
 





More information about the llvm-commits mailing list