Skip to content

Commit d6b24fa

Browse files
committedDec 19, 2014
[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 llvm-svn: 224605
1 parent cc09d1c commit d6b24fa

File tree

4 files changed

+81
-43
lines changed

4 files changed

+81
-43
lines changed
 

‎compiler-rt/lib/asan/asan_activation.cc

+14-23
Original file line numberDiff line numberDiff line change
@@ -23,33 +23,29 @@
2323
namespace __asan {
2424

2525
static struct AsanDeactivatedFlags {
26-
int quarantine_size;
27-
int max_redzone;
26+
AllocatorOptions allocator_options;
2827
int malloc_context_size;
2928
bool poison_heap;
30-
bool alloc_dealloc_mismatch;
31-
bool allocator_may_return_null;
3229

3330
void CopyFrom(const Flags *f, const CommonFlags *cf) {
34-
quarantine_size = f->quarantine_size;
35-
max_redzone = f->max_redzone;
31+
allocator_options.SetFrom(f, cf);
3632
malloc_context_size = cf->malloc_context_size;
3733
poison_heap = f->poison_heap;
38-
alloc_dealloc_mismatch = f->alloc_dealloc_mismatch;
39-
allocator_may_return_null = cf->allocator_may_return_null;
4034
}
4135

4236
void OverrideFromActivationFlags() {
4337
Flags f;
4438
CommonFlags cf;
4539

4640
// Copy the current activation flags.
47-
f.quarantine_size = quarantine_size;
48-
f.max_redzone = max_redzone;
41+
f.quarantine_size = allocator_options.quarantine_size_mb << 20;
42+
f.redzone = allocator_options.min_redzone;
43+
f.max_redzone = allocator_options.max_redzone;
44+
cf.allocator_may_return_null = allocator_options.may_return_null;
45+
f.alloc_dealloc_mismatch = allocator_options.alloc_dealloc_mismatch;
46+
4947
cf.malloc_context_size = malloc_context_size;
5048
f.poison_heap = poison_heap;
51-
f.alloc_dealloc_mismatch = alloc_dealloc_mismatch;
52-
cf.allocator_may_return_null = allocator_may_return_null;
5349

5450
// Check if activation flags need to be overriden.
5551
// FIXME: Add diagnostic to check that activation flags string doesn't
@@ -63,11 +59,13 @@ static struct AsanDeactivatedFlags {
6359
}
6460

6561
void Print() {
66-
Report("quarantine_size %d, max_redzone %d, poison_heap %d, "
62+
Report("quarantine_size_mb %d, max_redzone %d, poison_heap %d, "
6763
"malloc_context_size %d, alloc_dealloc_mismatch %d, "
6864
"allocator_may_return_null %d\n",
69-
quarantine_size, max_redzone, poison_heap, malloc_context_size,
70-
alloc_dealloc_mismatch, allocator_may_return_null);
65+
allocator_options.quarantine_size_mb, allocator_options.max_redzone,
66+
poison_heap, malloc_context_size,
67+
allocator_options.alloc_dealloc_mismatch,
68+
allocator_options.may_return_null);
7169
}
7270
} asan_deactivated_flags;
7371

@@ -97,16 +95,9 @@ void AsanActivate() {
9795

9896
asan_deactivated_flags.OverrideFromActivationFlags();
9997

100-
// Restore flag values.
101-
// FIXME: this is not atomic, and there may be other threads alive.
102-
flags()->max_redzone = asan_deactivated_flags.max_redzone;
103-
flags()->alloc_dealloc_mismatch =
104-
asan_deactivated_flags.alloc_dealloc_mismatch;
105-
10698
SetCanPoisonMemory(asan_deactivated_flags.poison_heap);
10799
SetMallocContextSize(asan_deactivated_flags.malloc_context_size);
108-
ReInitializeAllocator(asan_deactivated_flags.allocator_may_return_null,
109-
asan_deactivated_flags.quarantine_size);
100+
ReInitializeAllocator(asan_deactivated_flags.allocator_options);
110101

111102
asan_is_deactivated = false;
112103
if (common_flags()->verbosity) {

‎compiler-rt/lib/asan/asan_allocator.cc

+51-16
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,14 @@ QuarantineCache *GetQuarantineCache(AsanThreadLocalMallocStorage *ms) {
205205
return reinterpret_cast<QuarantineCache *>(ms->quarantine_cache);
206206
}
207207

208+
void AllocatorOptions::SetFrom(const Flags *f, const CommonFlags *cf) {
209+
quarantine_size_mb = f->quarantine_size >> 20;
210+
min_redzone = f->redzone;
211+
max_redzone = f->max_redzone;
212+
may_return_null = cf->allocator_may_return_null;
213+
alloc_dealloc_mismatch = f->alloc_dealloc_mismatch;
214+
}
215+
208216
struct Allocator {
209217
static const uptr kMaxAllowedMallocSize =
210218
FIRST_32_SECOND_64(3UL << 30, 64UL << 30);
@@ -217,19 +225,42 @@ struct Allocator {
217225
AllocatorCache fallback_allocator_cache;
218226
QuarantineCache fallback_quarantine_cache;
219227

228+
// ------------------- Options --------------------------
229+
atomic_uint16_t min_redzone;
230+
atomic_uint16_t max_redzone;
231+
atomic_uint8_t alloc_dealloc_mismatch;
232+
233+
// ------------------- Initialization ------------------------
220234
explicit Allocator(LinkerInitialized)
221235
: quarantine(LINKER_INITIALIZED),
222236
fallback_quarantine_cache(LINKER_INITIALIZED) {}
223237

224-
// ------------------- Initialization ------------------------
225-
void Initialize(bool may_return_null, uptr quarantine_size) {
226-
allocator.Init(may_return_null);
227-
quarantine.Init(quarantine_size, kMaxThreadLocalQuarantine);
238+
void CheckOptions(const AllocatorOptions &options) const {
239+
CHECK_GE(options.min_redzone, 16);
240+
CHECK_GE(options.max_redzone, options.min_redzone);
241+
CHECK_LE(options.max_redzone, 2048);
242+
CHECK(IsPowerOfTwo(options.min_redzone));
243+
CHECK(IsPowerOfTwo(options.max_redzone));
228244
}
229245

230-
void ReInitialize(bool may_return_null, uptr quarantine_size) {
231-
allocator.SetMayReturnNull(may_return_null);
232-
quarantine.Init(quarantine_size, kMaxThreadLocalQuarantine);
246+
void SharedInitCode(const AllocatorOptions &options) {
247+
CheckOptions(options);
248+
quarantine.Init((uptr)options.quarantine_size_mb << 20,
249+
kMaxThreadLocalQuarantine);
250+
atomic_store(&alloc_dealloc_mismatch, options.alloc_dealloc_mismatch,
251+
memory_order_release);
252+
atomic_store(&min_redzone, options.min_redzone, memory_order_release);
253+
atomic_store(&max_redzone, options.max_redzone, memory_order_release);
254+
}
255+
256+
void Initialize(const AllocatorOptions &options) {
257+
allocator.Init(options.may_return_null);
258+
SharedInitCode(options);
259+
}
260+
261+
void ReInitialize(const AllocatorOptions &options) {
262+
allocator.SetMayReturnNull(options.may_return_null);
263+
SharedInitCode(options);
233264
}
234265

235266
// -------------------- Helper methods. -------------------------
@@ -242,8 +273,9 @@ struct Allocator {
242273
user_requested_size <= (1 << 14) - 256 ? 4 :
243274
user_requested_size <= (1 << 15) - 512 ? 5 :
244275
user_requested_size <= (1 << 16) - 1024 ? 6 : 7;
245-
return Min(Max(rz_log, RZSize2Log(flags()->redzone)),
246-
RZSize2Log(flags()->max_redzone));
276+
u32 min_rz = atomic_load(&min_redzone, memory_order_acquire);
277+
u32 max_rz = atomic_load(&max_redzone, memory_order_acquire);
278+
return Min(Max(rz_log, RZSize2Log(min_rz)), RZSize2Log(max_rz));
247279
}
248280

249281
// We have an address between two chunks, and we want to report just one.
@@ -419,9 +451,12 @@ struct Allocator {
419451
AllocType alloc_type) {
420452
CHECK_EQ(m->chunk_state, CHUNK_QUARANTINE);
421453

422-
if (m->alloc_type != alloc_type && flags()->alloc_dealloc_mismatch)
423-
ReportAllocTypeMismatch((uptr)ptr, stack,
424-
(AllocType)m->alloc_type, (AllocType)alloc_type);
454+
if (m->alloc_type != alloc_type) {
455+
if (atomic_load(&alloc_dealloc_mismatch, memory_order_acquire)) {
456+
ReportAllocTypeMismatch((uptr)ptr, stack, (AllocType)m->alloc_type,
457+
(AllocType)alloc_type);
458+
}
459+
}
425460

426461
CHECK_GE(m->alloc_tid, 0);
427462
if (SANITIZER_WORDSIZE == 64) // On 32-bits this resides in user area.
@@ -619,12 +654,12 @@ StackTrace AsanChunkView::GetFreeStack() {
619654
return GetStackTraceFromId(chunk_->free_context_id);
620655
}
621656

622-
void InitializeAllocator(bool may_return_null, uptr quarantine_size) {
623-
instance.Initialize(may_return_null, quarantine_size);
657+
void InitializeAllocator(const AllocatorOptions &options) {
658+
instance.Initialize(options);
624659
}
625660

626-
void ReInitializeAllocator(bool may_return_null, uptr quarantine_size) {
627-
instance.ReInitialize(may_return_null, quarantine_size);
661+
void ReInitializeAllocator(const AllocatorOptions &options) {
662+
instance.ReInitialize(options);
628663
}
629664

630665
AsanChunkView FindHeapChunkByAddress(uptr addr) {

‎compiler-rt/lib/asan/asan_allocator.h

+13-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#ifndef ASAN_ALLOCATOR_H
1616
#define ASAN_ALLOCATOR_H
1717

18+
#include "asan_flags.h"
1819
#include "asan_internal.h"
1920
#include "asan_interceptors.h"
2021
#include "sanitizer_common/sanitizer_allocator.h"
@@ -31,8 +32,18 @@ enum AllocType {
3132
static const uptr kNumberOfSizeClasses = 255;
3233
struct AsanChunk;
3334

34-
void InitializeAllocator(bool may_return_null, uptr quarantine_size);
35-
void ReInitializeAllocator(bool may_return_null, uptr quarantine_size);
35+
struct AllocatorOptions {
36+
u32 quarantine_size_mb;
37+
u16 min_redzone;
38+
u16 max_redzone;
39+
u8 may_return_null;
40+
u8 alloc_dealloc_mismatch;
41+
42+
void SetFrom(const Flags *f, const CommonFlags *cf);
43+
};
44+
45+
void InitializeAllocator(const AllocatorOptions &options);
46+
void ReInitializeAllocator(const AllocatorOptions &options);
3647

3748
class AsanChunkView {
3849
public:

‎compiler-rt/lib/asan/asan_rtl.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -391,8 +391,9 @@ static void AsanInitInternal() {
391391
AsanTSDInit(PlatformTSDDtor);
392392
InstallDeadlySignalHandlers(AsanOnSIGSEGV);
393393

394-
InitializeAllocator(common_flags()->allocator_may_return_null,
395-
flags()->quarantine_size);
394+
AllocatorOptions allocator_options;
395+
allocator_options.SetFrom(flags(), common_flags());
396+
InitializeAllocator(allocator_options);
396397

397398
MaybeStartBackgroudThread();
398399

0 commit comments

Comments
 (0)
Please sign in to comment.