xref: /freebsd/contrib/llvm-project/compiler-rt/lib/asan/asan_flags.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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 
MaybeUseAsanDefaultOptionsCompileDefinition()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 
SetDefaults()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 
RegisterAsanFlags(FlagParser * parser,Flags * f)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 
InitializeFlags()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 
90*81ad6265SDimitry Andric   if (SANITIZER_APPLE) {
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   }
1430eae32dcSDimitry Andric   // Ensure that redzone is at least ASAN_SHADOW_GRANULARITY.
1440eae32dcSDimitry Andric   if (f->redzone < (int)ASAN_SHADOW_GRANULARITY)
1450eae32dcSDimitry 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 
SANITIZER_INTERFACE_WEAK_DEF(const char *,__asan_default_options,void)20468d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(const char*, __asan_default_options, void) {
20568d75effSDimitry Andric   return "";
20668d75effSDimitry Andric }
207