Index: lib/asan/asan_flags.cc =================================================================== --- lib/asan/asan_flags.cc +++ lib/asan/asan_flags.cc @@ -176,13 +176,15 @@ } void InitializeFlags(Flags *f) { - CommonFlags *cf = common_flags(); SetCommonFlagsDefaults(); - cf->detect_leaks = CAN_SANITIZE_LEAKS; - cf->external_symbolizer_path = GetEnv("ASAN_SYMBOLIZER_PATH"); - cf->malloc_context_size = kDefaultMallocContextSize; - cf->intercept_tls_get_addr = true; - cf->coverage = false; + { + CommonFlags cf = *common_flags(); + cf.detect_leaks = CAN_SANITIZE_LEAKS; + cf.external_symbolizer_path = GetEnv("ASAN_SYMBOLIZER_PATH"); + cf.malloc_context_size = kDefaultMallocContextSize; + cf.intercept_tls_get_addr = true; + OverrideCommonFlags(cf); + } internal_memset(f, 0, sizeof(*f)); f->quarantine_size = (ASAN_LOW_MEMORY) ? 1UL << 26 : 1UL << 28; @@ -263,17 +265,17 @@ } // Flag validation: - if (!CAN_SANITIZE_LEAKS && cf->detect_leaks) { + if (!CAN_SANITIZE_LEAKS && common_flags()->detect_leaks) { Report("%s: detect_leaks is not supported on this platform.\n", SanitizerToolName); - cf->detect_leaks = false; + Die(); } // Make "strict_init_order" imply "check_initialization_order". // TODO(samsonov): Use a single runtime flag for an init-order checker. if (f->strict_init_order) { f->check_initialization_order = true; } - CHECK_LE((uptr)cf->malloc_context_size, kStackTraceMax); + CHECK_LE((uptr)common_flags()->malloc_context_size, kStackTraceMax); CHECK_LE(f->min_uar_stack_size_log, f->max_uar_stack_size_log); CHECK_GE(f->redzone, 16); CHECK_GE(f->max_redzone, f->redzone); Index: lib/lsan/lsan_common.cc =================================================================== --- lib/lsan/lsan_common.cc +++ lib/lsan/lsan_common.cc @@ -74,12 +74,13 @@ // Set defaults for common flags (only in standalone mode) and parse // them from LSAN_OPTIONS. - CommonFlags *cf = common_flags(); if (standalone) { SetCommonFlagsDefaults(); - cf->external_symbolizer_path = GetEnv("LSAN_SYMBOLIZER_PATH"); - cf->malloc_context_size = 30; - cf->detect_leaks = true; + CommonFlags cf = *common_flags(); + cf.external_symbolizer_path = GetEnv("LSAN_SYMBOLIZER_PATH"); + cf.malloc_context_size = 30; + cf.detect_leaks = true; + OverrideCommonFlags(cf); } ParseCommonFlagsFromString(options); } Index: lib/msan/msan.cc =================================================================== --- lib/msan/msan.cc +++ lib/msan/msan.cc @@ -144,14 +144,17 @@ } static void InitializeFlags(Flags *f, const char *options) { - CommonFlags *cf = common_flags(); SetCommonFlagsDefaults(); - cf->external_symbolizer_path = GetEnv("MSAN_SYMBOLIZER_PATH"); - cf->malloc_context_size = 20; - cf->handle_ioctl = true; - // FIXME: test and enable. - cf->check_printf = false; - cf->intercept_tls_get_addr = true; + { + CommonFlags cf = *common_flags(); + cf.external_symbolizer_path = GetEnv("MSAN_SYMBOLIZER_PATH"); + cf.malloc_context_size = 20; + cf.handle_ioctl = true; + // FIXME: test and enable. + cf.check_printf = false; + cf.intercept_tls_get_addr = true; + OverrideCommonFlags(cf); + } internal_memset(f, 0, sizeof(*f)); f->poison_heap_with_zeroes = false; Index: lib/sanitizer_common/sanitizer_flags.h =================================================================== --- lib/sanitizer_common/sanitizer_flags.h +++ lib/sanitizer_common/sanitizer_flags.h @@ -71,7 +71,7 @@ // Functions to get/set global CommonFlags shared by all sanitizer runtimes: extern CommonFlags common_flags_dont_use; -inline CommonFlags *common_flags() { +inline const CommonFlags *common_flags() { return &common_flags_dont_use; } @@ -82,6 +82,16 @@ inline void ParseCommonFlagsFromString(const char *str) { common_flags_dont_use.ParseFromString(str); } + +// This function can only be used to setup tool-specific overrides for +// CommonFlags defaults. Generally, it should only be used right after +// SetCommonFlagsDefaults(), but before ParseCommonFlagsFromString(), and +// only during the flags initialization (i.e. before they are used for +// the first time). +inline void OverrideCommonFlags(const CommonFlags &cf) { + common_flags_dont_use = cf; +} + void PrintFlagDescriptions(); } // namespace __sanitizer Index: lib/tsan/dd/dd_rtl.cc =================================================================== --- lib/tsan/dd/dd_rtl.cc +++ lib/tsan/dd/dd_rtl.cc @@ -70,10 +70,13 @@ // Default values. f->second_deadlock_stack = false; - CommonFlags *cf = common_flags(); SetCommonFlagsDefaults(); - // Override some common flags defaults. - cf->allow_addr2line = true; + { + // Override some common flags defaults. + CommonFlags cf = *common_flags(); + cf.allow_addr2line = true; + OverrideCommonFlags(cf); + } // Override from command line. ParseFlag(env, &f->second_deadlock_stack, "second_deadlock_stack", ""); Index: lib/tsan/rtl/tsan_flags.cc =================================================================== --- lib/tsan/rtl/tsan_flags.cc +++ lib/tsan/rtl/tsan_flags.cc @@ -93,13 +93,16 @@ // DDFlags f->second_deadlock_stack = false; - CommonFlags *cf = common_flags(); SetCommonFlagsDefaults(); - // Override some common flags defaults. - cf->allow_addr2line = true; - cf->detect_deadlocks = true; - cf->print_suppressions = false; - cf->stack_trace_format = " #%n %f %S %M"; + { + // Override some common flags defaults. + CommonFlags cf = *common_flags(); + cf.allow_addr2line = true; + cf.detect_deadlocks = true; + cf.print_suppressions = false; + cf.stack_trace_format = " #%n %f %S %M"; + OverrideCommonFlags(cf); + } // Let a frontend override. ParseFlags(f, __tsan_default_options()); @@ -115,7 +118,8 @@ f->report_signal_unsafe = false; } - if (cf->help) PrintFlagDescriptions(); + if (common_flags()->help) + PrintFlagDescriptions(); if (f->history_size < 0 || f->history_size > 7) { Printf("ThreadSanitizer: incorrect value for history_size" Index: lib/ubsan/ubsan_flags.cc =================================================================== --- lib/ubsan/ubsan_flags.cc +++ lib/ubsan/ubsan_flags.cc @@ -22,9 +22,10 @@ } void InitializeCommonFlags() { - CommonFlags *cf = common_flags(); SetCommonFlagsDefaults(); - cf->print_summary = false; + CommonFlags cf = *common_flags(); + cf.print_summary = false; + OverrideCommonFlags(cf); // Override from user-specified string. ParseCommonFlagsFromString(MaybeCallUbsanDefaultOptions()); // Override from environment variable.