1*7c3d14c8STreehugger Robot //===-- asan_flags.cc -------------------------------------------*- C++ -*-===//
2*7c3d14c8STreehugger Robot //
3*7c3d14c8STreehugger Robot // The LLVM Compiler Infrastructure
4*7c3d14c8STreehugger Robot //
5*7c3d14c8STreehugger Robot // This file is distributed under the University of Illinois Open Source
6*7c3d14c8STreehugger Robot // License. See LICENSE.TXT for details.
7*7c3d14c8STreehugger Robot //
8*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
9*7c3d14c8STreehugger Robot //
10*7c3d14c8STreehugger Robot // This file is a part of AddressSanitizer, an address sanity checker.
11*7c3d14c8STreehugger Robot //
12*7c3d14c8STreehugger Robot // ASan flag parsing logic.
13*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
14*7c3d14c8STreehugger Robot
15*7c3d14c8STreehugger Robot #include "asan_activation.h"
16*7c3d14c8STreehugger Robot #include "asan_flags.h"
17*7c3d14c8STreehugger Robot #include "asan_interface_internal.h"
18*7c3d14c8STreehugger Robot #include "asan_stack.h"
19*7c3d14c8STreehugger Robot #include "lsan/lsan_common.h"
20*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_common.h"
21*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_flags.h"
22*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_flag_parser.h"
23*7c3d14c8STreehugger Robot #include "ubsan/ubsan_flags.h"
24*7c3d14c8STreehugger Robot #include "ubsan/ubsan_platform.h"
25*7c3d14c8STreehugger Robot
26*7c3d14c8STreehugger Robot namespace __asan {
27*7c3d14c8STreehugger Robot
28*7c3d14c8STreehugger Robot Flags asan_flags_dont_use_directly; // use via flags().
29*7c3d14c8STreehugger Robot
MaybeCallAsanDefaultOptions()30*7c3d14c8STreehugger Robot static const char *MaybeCallAsanDefaultOptions() {
31*7c3d14c8STreehugger Robot return (&__asan_default_options) ? __asan_default_options() : "";
32*7c3d14c8STreehugger Robot }
33*7c3d14c8STreehugger Robot
MaybeUseAsanDefaultOptionsCompileDefinition()34*7c3d14c8STreehugger Robot static const char *MaybeUseAsanDefaultOptionsCompileDefinition() {
35*7c3d14c8STreehugger Robot #ifdef ASAN_DEFAULT_OPTIONS
36*7c3d14c8STreehugger Robot // Stringize the macro value.
37*7c3d14c8STreehugger Robot # define ASAN_STRINGIZE(x) #x
38*7c3d14c8STreehugger Robot # define ASAN_STRINGIZE_OPTIONS(options) ASAN_STRINGIZE(options)
39*7c3d14c8STreehugger Robot return ASAN_STRINGIZE_OPTIONS(ASAN_DEFAULT_OPTIONS);
40*7c3d14c8STreehugger Robot #else
41*7c3d14c8STreehugger Robot return "";
42*7c3d14c8STreehugger Robot #endif
43*7c3d14c8STreehugger Robot }
44*7c3d14c8STreehugger Robot
SetDefaults()45*7c3d14c8STreehugger Robot void Flags::SetDefaults() {
46*7c3d14c8STreehugger Robot #define ASAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
47*7c3d14c8STreehugger Robot #include "asan_flags.inc"
48*7c3d14c8STreehugger Robot #undef ASAN_FLAG
49*7c3d14c8STreehugger Robot }
50*7c3d14c8STreehugger Robot
RegisterAsanFlags(FlagParser * parser,Flags * f)51*7c3d14c8STreehugger Robot static void RegisterAsanFlags(FlagParser *parser, Flags *f) {
52*7c3d14c8STreehugger Robot #define ASAN_FLAG(Type, Name, DefaultValue, Description) \
53*7c3d14c8STreehugger Robot RegisterFlag(parser, #Name, Description, &f->Name);
54*7c3d14c8STreehugger Robot #include "asan_flags.inc"
55*7c3d14c8STreehugger Robot #undef ASAN_FLAG
56*7c3d14c8STreehugger Robot }
57*7c3d14c8STreehugger Robot
InitializeFlags()58*7c3d14c8STreehugger Robot void InitializeFlags() {
59*7c3d14c8STreehugger Robot // Set the default values and prepare for parsing ASan and common flags.
60*7c3d14c8STreehugger Robot SetCommonFlagsDefaults();
61*7c3d14c8STreehugger Robot {
62*7c3d14c8STreehugger Robot CommonFlags cf;
63*7c3d14c8STreehugger Robot cf.CopyFrom(*common_flags());
64*7c3d14c8STreehugger Robot cf.detect_leaks = CAN_SANITIZE_LEAKS;
65*7c3d14c8STreehugger Robot cf.external_symbolizer_path = GetEnv("ASAN_SYMBOLIZER_PATH");
66*7c3d14c8STreehugger Robot cf.malloc_context_size = kDefaultMallocContextSize;
67*7c3d14c8STreehugger Robot cf.intercept_tls_get_addr = true;
68*7c3d14c8STreehugger Robot cf.exitcode = 1;
69*7c3d14c8STreehugger Robot OverrideCommonFlags(cf);
70*7c3d14c8STreehugger Robot }
71*7c3d14c8STreehugger Robot Flags *f = flags();
72*7c3d14c8STreehugger Robot f->SetDefaults();
73*7c3d14c8STreehugger Robot
74*7c3d14c8STreehugger Robot FlagParser asan_parser;
75*7c3d14c8STreehugger Robot RegisterAsanFlags(&asan_parser, f);
76*7c3d14c8STreehugger Robot RegisterCommonFlags(&asan_parser);
77*7c3d14c8STreehugger Robot
78*7c3d14c8STreehugger Robot // Set the default values and prepare for parsing LSan and UBSan flags
79*7c3d14c8STreehugger Robot // (which can also overwrite common flags).
80*7c3d14c8STreehugger Robot #if CAN_SANITIZE_LEAKS
81*7c3d14c8STreehugger Robot __lsan::Flags *lf = __lsan::flags();
82*7c3d14c8STreehugger Robot lf->SetDefaults();
83*7c3d14c8STreehugger Robot
84*7c3d14c8STreehugger Robot FlagParser lsan_parser;
85*7c3d14c8STreehugger Robot __lsan::RegisterLsanFlags(&lsan_parser, lf);
86*7c3d14c8STreehugger Robot RegisterCommonFlags(&lsan_parser);
87*7c3d14c8STreehugger Robot #endif
88*7c3d14c8STreehugger Robot
89*7c3d14c8STreehugger Robot #if CAN_SANITIZE_UB
90*7c3d14c8STreehugger Robot __ubsan::Flags *uf = __ubsan::flags();
91*7c3d14c8STreehugger Robot uf->SetDefaults();
92*7c3d14c8STreehugger Robot
93*7c3d14c8STreehugger Robot FlagParser ubsan_parser;
94*7c3d14c8STreehugger Robot __ubsan::RegisterUbsanFlags(&ubsan_parser, uf);
95*7c3d14c8STreehugger Robot RegisterCommonFlags(&ubsan_parser);
96*7c3d14c8STreehugger Robot #endif
97*7c3d14c8STreehugger Robot
98*7c3d14c8STreehugger Robot // Override from ASan compile definition.
99*7c3d14c8STreehugger Robot const char *asan_compile_def = MaybeUseAsanDefaultOptionsCompileDefinition();
100*7c3d14c8STreehugger Robot asan_parser.ParseString(asan_compile_def);
101*7c3d14c8STreehugger Robot
102*7c3d14c8STreehugger Robot // Override from user-specified string.
103*7c3d14c8STreehugger Robot const char *asan_default_options = MaybeCallAsanDefaultOptions();
104*7c3d14c8STreehugger Robot asan_parser.ParseString(asan_default_options);
105*7c3d14c8STreehugger Robot #if CAN_SANITIZE_UB
106*7c3d14c8STreehugger Robot const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions();
107*7c3d14c8STreehugger Robot ubsan_parser.ParseString(ubsan_default_options);
108*7c3d14c8STreehugger Robot #endif
109*7c3d14c8STreehugger Robot
110*7c3d14c8STreehugger Robot // Override from command line.
111*7c3d14c8STreehugger Robot asan_parser.ParseString(GetEnv("ASAN_OPTIONS"));
112*7c3d14c8STreehugger Robot #if CAN_SANITIZE_LEAKS
113*7c3d14c8STreehugger Robot lsan_parser.ParseString(GetEnv("LSAN_OPTIONS"));
114*7c3d14c8STreehugger Robot #endif
115*7c3d14c8STreehugger Robot #if CAN_SANITIZE_UB
116*7c3d14c8STreehugger Robot ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS"));
117*7c3d14c8STreehugger Robot #endif
118*7c3d14c8STreehugger Robot
119*7c3d14c8STreehugger Robot InitializeCommonFlags();
120*7c3d14c8STreehugger Robot
121*7c3d14c8STreehugger Robot // TODO(eugenis): dump all flags at verbosity>=2?
122*7c3d14c8STreehugger Robot if (Verbosity()) ReportUnrecognizedFlags();
123*7c3d14c8STreehugger Robot
124*7c3d14c8STreehugger Robot if (common_flags()->help) {
125*7c3d14c8STreehugger Robot // TODO(samsonov): print all of the flags (ASan, LSan, common).
126*7c3d14c8STreehugger Robot asan_parser.PrintFlagDescriptions();
127*7c3d14c8STreehugger Robot }
128*7c3d14c8STreehugger Robot
129*7c3d14c8STreehugger Robot // Flag validation:
130*7c3d14c8STreehugger Robot if (!CAN_SANITIZE_LEAKS && common_flags()->detect_leaks) {
131*7c3d14c8STreehugger Robot Report("%s: detect_leaks is not supported on this platform.\n",
132*7c3d14c8STreehugger Robot SanitizerToolName);
133*7c3d14c8STreehugger Robot Die();
134*7c3d14c8STreehugger Robot }
135*7c3d14c8STreehugger Robot // Make "strict_init_order" imply "check_initialization_order".
136*7c3d14c8STreehugger Robot // TODO(samsonov): Use a single runtime flag for an init-order checker.
137*7c3d14c8STreehugger Robot if (f->strict_init_order) {
138*7c3d14c8STreehugger Robot f->check_initialization_order = true;
139*7c3d14c8STreehugger Robot }
140*7c3d14c8STreehugger Robot CHECK_LE((uptr)common_flags()->malloc_context_size, kStackTraceMax);
141*7c3d14c8STreehugger Robot CHECK_LE(f->min_uar_stack_size_log, f->max_uar_stack_size_log);
142*7c3d14c8STreehugger Robot CHECK_GE(f->redzone, 16);
143*7c3d14c8STreehugger Robot CHECK_GE(f->max_redzone, f->redzone);
144*7c3d14c8STreehugger Robot CHECK_LE(f->max_redzone, 2048);
145*7c3d14c8STreehugger Robot CHECK(IsPowerOfTwo(f->redzone));
146*7c3d14c8STreehugger Robot CHECK(IsPowerOfTwo(f->max_redzone));
147*7c3d14c8STreehugger Robot
148*7c3d14c8STreehugger Robot // quarantine_size is deprecated but we still honor it.
149*7c3d14c8STreehugger Robot // quarantine_size can not be used together with quarantine_size_mb.
150*7c3d14c8STreehugger Robot if (f->quarantine_size >= 0 && f->quarantine_size_mb >= 0) {
151*7c3d14c8STreehugger Robot Report("%s: please use either 'quarantine_size' (deprecated) or "
152*7c3d14c8STreehugger Robot "quarantine_size_mb, but not both\n", SanitizerToolName);
153*7c3d14c8STreehugger Robot Die();
154*7c3d14c8STreehugger Robot }
155*7c3d14c8STreehugger Robot if (f->quarantine_size >= 0)
156*7c3d14c8STreehugger Robot f->quarantine_size_mb = f->quarantine_size >> 20;
157*7c3d14c8STreehugger Robot if (f->quarantine_size_mb < 0) {
158*7c3d14c8STreehugger Robot const int kDefaultQuarantineSizeMb =
159*7c3d14c8STreehugger Robot (ASAN_LOW_MEMORY) ? 1UL << 6 : 1UL << 8;
160*7c3d14c8STreehugger Robot f->quarantine_size_mb = kDefaultQuarantineSizeMb;
161*7c3d14c8STreehugger Robot }
162*7c3d14c8STreehugger Robot if (!f->replace_str && common_flags()->intercept_strlen) {
163*7c3d14c8STreehugger Robot Report("WARNING: strlen interceptor is enabled even though replace_str=0. "
164*7c3d14c8STreehugger Robot "Use intercept_strlen=0 to disable it.");
165*7c3d14c8STreehugger Robot }
166*7c3d14c8STreehugger Robot if (!f->replace_str && common_flags()->intercept_strchr) {
167*7c3d14c8STreehugger Robot Report("WARNING: strchr* interceptors are enabled even though "
168*7c3d14c8STreehugger Robot "replace_str=0. Use intercept_strchr=0 to disable them.");
169*7c3d14c8STreehugger Robot }
170*7c3d14c8STreehugger Robot }
171*7c3d14c8STreehugger Robot
172*7c3d14c8STreehugger Robot } // namespace __asan
173*7c3d14c8STreehugger Robot
174*7c3d14c8STreehugger Robot #if !SANITIZER_SUPPORTS_WEAK_HOOKS
175*7c3d14c8STreehugger Robot extern "C" {
176*7c3d14c8STreehugger Robot SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
__asan_default_options()177*7c3d14c8STreehugger Robot const char* __asan_default_options() { return ""; }
178*7c3d14c8STreehugger Robot } // extern "C"
179*7c3d14c8STreehugger Robot #endif
180