168d75effSDimitry Andric //===-- asan_flags.cpp ------------------------------------------*- C++ -*-===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is a part of AddressSanitizer, an address sanity checker. 1068d75effSDimitry Andric // 1168d75effSDimitry Andric // ASan flag parsing logic. 1268d75effSDimitry Andric //===----------------------------------------------------------------------===// 1368d75effSDimitry Andric 1468d75effSDimitry Andric #include "asan_activation.h" 1568d75effSDimitry Andric #include "asan_flags.h" 1668d75effSDimitry Andric #include "asan_interface_internal.h" 1768d75effSDimitry Andric #include "asan_stack.h" 1868d75effSDimitry Andric #include "lsan/lsan_common.h" 1968d75effSDimitry Andric #include "sanitizer_common/sanitizer_common.h" 2068d75effSDimitry Andric #include "sanitizer_common/sanitizer_flags.h" 2168d75effSDimitry Andric #include "sanitizer_common/sanitizer_flag_parser.h" 2268d75effSDimitry Andric #include "ubsan/ubsan_flags.h" 2368d75effSDimitry Andric #include "ubsan/ubsan_platform.h" 2468d75effSDimitry Andric 2568d75effSDimitry Andric namespace __asan { 2668d75effSDimitry Andric 2768d75effSDimitry Andric Flags asan_flags_dont_use_directly; // use via flags(). 2868d75effSDimitry Andric 2968d75effSDimitry Andric static const char *MaybeUseAsanDefaultOptionsCompileDefinition() { 3068d75effSDimitry Andric #ifdef ASAN_DEFAULT_OPTIONS 3168d75effSDimitry Andric return SANITIZER_STRINGIFY(ASAN_DEFAULT_OPTIONS); 3268d75effSDimitry Andric #else 3368d75effSDimitry Andric return ""; 3468d75effSDimitry Andric #endif 3568d75effSDimitry Andric } 3668d75effSDimitry Andric 3768d75effSDimitry Andric void Flags::SetDefaults() { 3868d75effSDimitry Andric #define ASAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 3968d75effSDimitry Andric #include "asan_flags.inc" 4068d75effSDimitry Andric #undef ASAN_FLAG 4168d75effSDimitry Andric } 4268d75effSDimitry Andric 4368d75effSDimitry Andric static void RegisterAsanFlags(FlagParser *parser, Flags *f) { 4468d75effSDimitry Andric #define ASAN_FLAG(Type, Name, DefaultValue, Description) \ 4568d75effSDimitry Andric RegisterFlag(parser, #Name, Description, &f->Name); 4668d75effSDimitry Andric #include "asan_flags.inc" 4768d75effSDimitry Andric #undef ASAN_FLAG 4868d75effSDimitry Andric } 4968d75effSDimitry Andric 5068d75effSDimitry Andric void InitializeFlags() { 5168d75effSDimitry Andric // Set the default values and prepare for parsing ASan and common flags. 5268d75effSDimitry Andric SetCommonFlagsDefaults(); 5368d75effSDimitry Andric { 5468d75effSDimitry Andric CommonFlags cf; 5568d75effSDimitry Andric cf.CopyFrom(*common_flags()); 5668d75effSDimitry Andric cf.detect_leaks = cf.detect_leaks && CAN_SANITIZE_LEAKS; 5768d75effSDimitry Andric cf.external_symbolizer_path = GetEnv("ASAN_SYMBOLIZER_PATH"); 5868d75effSDimitry Andric cf.malloc_context_size = kDefaultMallocContextSize; 5968d75effSDimitry Andric cf.intercept_tls_get_addr = true; 6068d75effSDimitry Andric cf.exitcode = 1; 6168d75effSDimitry Andric OverrideCommonFlags(cf); 6268d75effSDimitry Andric } 6368d75effSDimitry Andric Flags *f = flags(); 6468d75effSDimitry Andric f->SetDefaults(); 6568d75effSDimitry Andric 6668d75effSDimitry Andric FlagParser asan_parser; 6768d75effSDimitry Andric RegisterAsanFlags(&asan_parser, f); 6868d75effSDimitry Andric RegisterCommonFlags(&asan_parser); 6968d75effSDimitry Andric 7068d75effSDimitry Andric // Set the default values and prepare for parsing LSan and UBSan flags 7168d75effSDimitry Andric // (which can also overwrite common flags). 7268d75effSDimitry Andric #if CAN_SANITIZE_LEAKS 7368d75effSDimitry Andric __lsan::Flags *lf = __lsan::flags(); 7468d75effSDimitry Andric lf->SetDefaults(); 7568d75effSDimitry Andric 7668d75effSDimitry Andric FlagParser lsan_parser; 7768d75effSDimitry Andric __lsan::RegisterLsanFlags(&lsan_parser, lf); 7868d75effSDimitry Andric RegisterCommonFlags(&lsan_parser); 7968d75effSDimitry Andric #endif 8068d75effSDimitry Andric 8168d75effSDimitry Andric #if CAN_SANITIZE_UB 8268d75effSDimitry Andric __ubsan::Flags *uf = __ubsan::flags(); 8368d75effSDimitry Andric uf->SetDefaults(); 8468d75effSDimitry Andric 8568d75effSDimitry Andric FlagParser ubsan_parser; 8668d75effSDimitry Andric __ubsan::RegisterUbsanFlags(&ubsan_parser, uf); 8768d75effSDimitry Andric RegisterCommonFlags(&ubsan_parser); 8868d75effSDimitry Andric #endif 8968d75effSDimitry Andric 9068d75effSDimitry Andric if (SANITIZER_MAC) { 9168d75effSDimitry Andric // Support macOS MallocScribble and MallocPreScribble: 9268d75effSDimitry Andric // <https://developer.apple.com/library/content/documentation/Performance/ 9368d75effSDimitry Andric // Conceptual/ManagingMemory/Articles/MallocDebug.html> 9468d75effSDimitry Andric if (GetEnv("MallocScribble")) { 9568d75effSDimitry Andric f->max_free_fill_size = 0x1000; 9668d75effSDimitry Andric } 9768d75effSDimitry Andric if (GetEnv("MallocPreScribble")) { 9868d75effSDimitry Andric f->malloc_fill_byte = 0xaa; 9968d75effSDimitry Andric } 10068d75effSDimitry Andric } 10168d75effSDimitry Andric 10268d75effSDimitry Andric // Override from ASan compile definition. 10368d75effSDimitry Andric const char *asan_compile_def = MaybeUseAsanDefaultOptionsCompileDefinition(); 10468d75effSDimitry Andric asan_parser.ParseString(asan_compile_def); 10568d75effSDimitry Andric 10668d75effSDimitry Andric // Override from user-specified string. 107e8d8bef9SDimitry Andric const char *asan_default_options = __asan_default_options(); 10868d75effSDimitry Andric asan_parser.ParseString(asan_default_options); 10968d75effSDimitry Andric #if CAN_SANITIZE_UB 110e8d8bef9SDimitry Andric const char *ubsan_default_options = __ubsan_default_options(); 11168d75effSDimitry Andric ubsan_parser.ParseString(ubsan_default_options); 11268d75effSDimitry Andric #endif 11368d75effSDimitry Andric #if CAN_SANITIZE_LEAKS 114e8d8bef9SDimitry Andric const char *lsan_default_options = __lsan_default_options(); 11568d75effSDimitry Andric lsan_parser.ParseString(lsan_default_options); 11668d75effSDimitry Andric #endif 11768d75effSDimitry Andric 11868d75effSDimitry Andric // Override from command line. 11968d75effSDimitry Andric asan_parser.ParseStringFromEnv("ASAN_OPTIONS"); 12068d75effSDimitry Andric #if CAN_SANITIZE_LEAKS 12168d75effSDimitry Andric lsan_parser.ParseStringFromEnv("LSAN_OPTIONS"); 12268d75effSDimitry Andric #endif 12368d75effSDimitry Andric #if CAN_SANITIZE_UB 12468d75effSDimitry Andric ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS"); 12568d75effSDimitry Andric #endif 12668d75effSDimitry Andric 12768d75effSDimitry Andric InitializeCommonFlags(); 12868d75effSDimitry Andric 12968d75effSDimitry Andric // TODO(eugenis): dump all flags at verbosity>=2? 13068d75effSDimitry Andric if (Verbosity()) ReportUnrecognizedFlags(); 13168d75effSDimitry Andric 13268d75effSDimitry Andric if (common_flags()->help) { 13368d75effSDimitry Andric // TODO(samsonov): print all of the flags (ASan, LSan, common). 13468d75effSDimitry Andric asan_parser.PrintFlagDescriptions(); 13568d75effSDimitry Andric } 13668d75effSDimitry Andric 13768d75effSDimitry Andric // Flag validation: 13868d75effSDimitry Andric if (!CAN_SANITIZE_LEAKS && common_flags()->detect_leaks) { 13968d75effSDimitry Andric Report("%s: detect_leaks is not supported on this platform.\n", 14068d75effSDimitry Andric SanitizerToolName); 14168d75effSDimitry Andric Die(); 14268d75effSDimitry Andric } 143*0eae32dcSDimitry Andric // Ensure that redzone is at least ASAN_SHADOW_GRANULARITY. 144*0eae32dcSDimitry Andric if (f->redzone < (int)ASAN_SHADOW_GRANULARITY) 145*0eae32dcSDimitry Andric f->redzone = ASAN_SHADOW_GRANULARITY; 14668d75effSDimitry Andric // Make "strict_init_order" imply "check_initialization_order". 14768d75effSDimitry Andric // TODO(samsonov): Use a single runtime flag for an init-order checker. 14868d75effSDimitry Andric if (f->strict_init_order) { 14968d75effSDimitry Andric f->check_initialization_order = true; 15068d75effSDimitry Andric } 15168d75effSDimitry Andric CHECK_LE((uptr)common_flags()->malloc_context_size, kStackTraceMax); 15268d75effSDimitry Andric CHECK_LE(f->min_uar_stack_size_log, f->max_uar_stack_size_log); 15368d75effSDimitry Andric CHECK_GE(f->redzone, 16); 15468d75effSDimitry Andric CHECK_GE(f->max_redzone, f->redzone); 15568d75effSDimitry Andric CHECK_LE(f->max_redzone, 2048); 15668d75effSDimitry Andric CHECK(IsPowerOfTwo(f->redzone)); 15768d75effSDimitry Andric CHECK(IsPowerOfTwo(f->max_redzone)); 15868d75effSDimitry Andric 15968d75effSDimitry Andric // quarantine_size is deprecated but we still honor it. 16068d75effSDimitry Andric // quarantine_size can not be used together with quarantine_size_mb. 16168d75effSDimitry Andric if (f->quarantine_size >= 0 && f->quarantine_size_mb >= 0) { 16268d75effSDimitry Andric Report("%s: please use either 'quarantine_size' (deprecated) or " 16368d75effSDimitry Andric "quarantine_size_mb, but not both\n", SanitizerToolName); 16468d75effSDimitry Andric Die(); 16568d75effSDimitry Andric } 16668d75effSDimitry Andric if (f->quarantine_size >= 0) 16768d75effSDimitry Andric f->quarantine_size_mb = f->quarantine_size >> 20; 16868d75effSDimitry Andric if (f->quarantine_size_mb < 0) { 16968d75effSDimitry Andric const int kDefaultQuarantineSizeMb = 17068d75effSDimitry Andric (ASAN_LOW_MEMORY) ? 1UL << 4 : 1UL << 8; 17168d75effSDimitry Andric f->quarantine_size_mb = kDefaultQuarantineSizeMb; 17268d75effSDimitry Andric } 17368d75effSDimitry Andric if (f->thread_local_quarantine_size_kb < 0) { 17468d75effSDimitry Andric const u32 kDefaultThreadLocalQuarantineSizeKb = 17568d75effSDimitry Andric // It is not advised to go lower than 64Kb, otherwise quarantine batches 17668d75effSDimitry Andric // pushed from thread local quarantine to global one will create too 17768d75effSDimitry Andric // much overhead. One quarantine batch size is 8Kb and it holds up to 17868d75effSDimitry Andric // 1021 chunk, which amounts to 1/8 memory overhead per batch when 17968d75effSDimitry Andric // thread local quarantine is set to 64Kb. 18068d75effSDimitry Andric (ASAN_LOW_MEMORY) ? 1 << 6 : FIRST_32_SECOND_64(1 << 8, 1 << 10); 18168d75effSDimitry Andric f->thread_local_quarantine_size_kb = kDefaultThreadLocalQuarantineSizeKb; 18268d75effSDimitry Andric } 18368d75effSDimitry Andric if (f->thread_local_quarantine_size_kb == 0 && f->quarantine_size_mb > 0) { 18468d75effSDimitry Andric Report("%s: thread_local_quarantine_size_kb can be set to 0 only when " 18568d75effSDimitry Andric "quarantine_size_mb is set to 0\n", SanitizerToolName); 18668d75effSDimitry Andric Die(); 18768d75effSDimitry Andric } 18868d75effSDimitry Andric if (!f->replace_str && common_flags()->intercept_strlen) { 18968d75effSDimitry Andric Report("WARNING: strlen interceptor is enabled even though replace_str=0. " 19068d75effSDimitry Andric "Use intercept_strlen=0 to disable it."); 19168d75effSDimitry Andric } 19268d75effSDimitry Andric if (!f->replace_str && common_flags()->intercept_strchr) { 19368d75effSDimitry Andric Report("WARNING: strchr* interceptors are enabled even though " 19468d75effSDimitry Andric "replace_str=0. Use intercept_strchr=0 to disable them."); 19568d75effSDimitry Andric } 19668d75effSDimitry Andric if (!f->replace_str && common_flags()->intercept_strndup) { 19768d75effSDimitry Andric Report("WARNING: strndup* interceptors are enabled even though " 19868d75effSDimitry Andric "replace_str=0. Use intercept_strndup=0 to disable them."); 19968d75effSDimitry Andric } 20068d75effSDimitry Andric } 20168d75effSDimitry Andric 20268d75effSDimitry Andric } // namespace __asan 20368d75effSDimitry Andric 20468d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(const char*, __asan_default_options, void) { 20568d75effSDimitry Andric return ""; 20668d75effSDimitry Andric } 207