int malloc_context_size;
bool poison_heap;
- void CopyFrom(const Flags *f, const CommonFlags *cf) {
- allocator_options.SetFrom(f, cf);
- malloc_context_size = cf->malloc_context_size;
- poison_heap = f->poison_heap;
- }
-
void OverrideFromActivationFlags() {
Flags f;
CommonFlags cf;
// Copy the current activation flags.
- 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;
-
+ allocator_options.CopyTo(&f, &cf);
cf.malloc_context_size = malloc_context_size;
f.poison_heap = poison_heap;
ParseCommonFlagsFromString(&cf, buf);
ParseFlagsFromString(&f, buf);
- CopyFrom(&f, &cf);
+ allocator_options.SetFrom(&f, &cf);
+ malloc_context_size = cf.malloc_context_size;
+ poison_heap = f.poison_heap;
}
void Print() {
static bool asan_is_deactivated;
-void AsanStartDeactivated() {
+void AsanDeactivate() {
+ CHECK(!asan_is_deactivated);
VReport(1, "Deactivating ASan\n");
- // Save flag values.
- asan_deactivated_flags.CopyFrom(flags(), common_flags());
-
- // FIXME: Don't overwrite commandline flags. Instead, make the flags store
- // the original values calculated during flag parsing, and re-initialize
- // the necessary runtime objects.
- flags()->quarantine_size = 0;
- flags()->max_redzone = 16;
- flags()->poison_heap = false;
- common_flags()->malloc_context_size = 0;
- flags()->alloc_dealloc_mismatch = false;
- common_flags()->allocator_may_return_null = true;
+
+ // Stash runtime state.
+ GetAllocatorOptions(&asan_deactivated_flags.allocator_options);
+ asan_deactivated_flags.malloc_context_size = GetMallocContextSize();
+ asan_deactivated_flags.poison_heap = CanPoisonMemory();
+
+ // Deactivate the runtime.
+ SetCanPoisonMemory(false);
+ SetMallocContextSize(1);
+ AllocatorOptions disabled = asan_deactivated_flags.allocator_options;
+ disabled.quarantine_size_mb = 0;
+ disabled.min_redzone = 16; // Redzone must be at least 16 bytes long.
+ disabled.max_redzone = 16;
+ disabled.alloc_dealloc_mismatch = false;
+ disabled.may_return_null = true;
+ ReInitializeAllocator(disabled);
asan_is_deactivated = true;
}
#define ASAN_ACTIVATION_H
namespace __asan {
-void AsanStartDeactivated();
+void AsanDeactivate();
void AsanActivate();
} // namespace __asan
alloc_dealloc_mismatch = f->alloc_dealloc_mismatch;
}
+void AllocatorOptions::CopyTo(Flags *f, CommonFlags *cf) {
+ f->quarantine_size = (int)quarantine_size_mb << 20;
+ f->redzone = min_redzone;
+ f->max_redzone = max_redzone;
+ cf->allocator_may_return_null = may_return_null;
+ f->alloc_dealloc_mismatch = alloc_dealloc_mismatch;
+}
+
struct Allocator {
static const uptr kMaxAllowedMallocSize =
FIRST_32_SECOND_64(3UL << 30, 64UL << 30);
SharedInitCode(options);
}
+ void GetOptions(AllocatorOptions *options) const {
+ options->quarantine_size_mb = quarantine.GetSize() >> 20;
+ options->min_redzone = atomic_load(&min_redzone, memory_order_acquire);
+ options->max_redzone = atomic_load(&max_redzone, memory_order_acquire);
+ options->may_return_null = allocator.MayReturnNull();
+ options->alloc_dealloc_mismatch =
+ atomic_load(&alloc_dealloc_mismatch, memory_order_acquire);
+ }
+
// -------------------- Helper methods. -------------------------
uptr ComputeRZLog(uptr user_requested_size) {
u32 rz_log =
instance.ReInitialize(options);
}
+void GetAllocatorOptions(AllocatorOptions *options) {
+ instance.GetOptions(options);
+}
+
AsanChunkView FindHeapChunkByAddress(uptr addr) {
return instance.FindHeapChunkByAddress(addr);
}
u8 alloc_dealloc_mismatch;
void SetFrom(const Flags *f, const CommonFlags *cf);
+ void CopyTo(Flags *f, CommonFlags *cf);
};
void InitializeAllocator(const AllocatorOptions &options);
void ReInitializeAllocator(const AllocatorOptions &options);
+void GetAllocatorOptions(AllocatorOptions *options);
class AsanChunkView {
public:
VReport(1, "Parsed ASAN_OPTIONS: %s\n", env);
}
- // If ASan starts in deactivated state, stash and clear some flags.
- // Otherwise, let activation flags override current settings.
- if (flags()->start_deactivated) {
- AsanStartDeactivated();
- } else {
- // Parse flags that may change between startup and activation.
- // On Android they come from a system property.
- // On other platforms this is no-op.
+ // Let activation flags override current settings. On Android they come
+ // from a system property. On other platforms this is no-op.
+ if (!flags()->start_deactivated) {
char buf[100];
GetExtraActivationFlags(buf, sizeof(buf));
ParseCommonFlagsFromString(cf, buf);
MaybeStartBackgroudThread();
+ // Now that ASan runtime is (mostly) initialized, deactivate it if
+ // necessary, so that it can be re-activated when requested.
+ if (flags()->start_deactivated)
+ AsanDeactivate();
+
// On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited
// should be set to 1 prior to initializing the threads.
asan_inited = 1;
return res;
}
+ bool MayReturnNull() const {
+ return atomic_load(&may_return_null_, memory_order_acquire);
+ }
+
void *ReturnNullOrDie() {
- if (atomic_load(&may_return_null_, memory_order_acquire))
+ if (MayReturnNull())
return 0;
ReportAllocatorCannotReturnNull();
}