Daily bump.
[official-gcc.git] / libsanitizer / sanitizer_common / sanitizer_flags.cc
blobd7e7118212e30b95d78e2a070a303bb6685995d5
1 //===-- sanitizer_flags.cc ------------------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
9 //
10 //===----------------------------------------------------------------------===//
12 #include "sanitizer_flags.h"
14 #include "sanitizer_common.h"
15 #include "sanitizer_libc.h"
16 #include "sanitizer_list.h"
18 namespace __sanitizer {
20 CommonFlags common_flags_dont_use;
22 struct FlagDescription {
23 const char *name;
24 const char *description;
25 FlagDescription *next;
28 IntrusiveList<FlagDescription> flag_descriptions;
30 // If set, the tool will install its own SEGV signal handler by default.
31 #ifndef SANITIZER_NEEDS_SEGV
32 # define SANITIZER_NEEDS_SEGV 1
33 #endif
35 void SetCommonFlagsDefaults(CommonFlags *f) {
36 f->symbolize = true;
37 f->external_symbolizer_path = 0;
38 f->allow_addr2line = false;
39 f->strip_path_prefix = "";
40 f->fast_unwind_on_check = false;
41 f->fast_unwind_on_fatal = false;
42 f->fast_unwind_on_malloc = true;
43 f->handle_ioctl = false;
44 f->malloc_context_size = 1;
45 f->log_path = "stderr";
46 f->verbosity = 0;
47 f->detect_leaks = true;
48 f->leak_check_at_exit = true;
49 f->allocator_may_return_null = false;
50 f->print_summary = true;
51 f->check_printf = true;
52 // TODO(glider): tools may want to set different defaults for handle_segv.
53 f->handle_segv = SANITIZER_NEEDS_SEGV;
54 f->allow_user_segv_handler = false;
55 f->use_sigaltstack = true;
56 f->detect_deadlocks = false;
57 f->clear_shadow_mmap_threshold = 64 * 1024;
58 f->color = "auto";
59 f->legacy_pthread_cond = false;
60 f->intercept_tls_get_addr = false;
61 f->coverage = false;
62 f->coverage_direct = SANITIZER_ANDROID;
63 f->coverage_dir = ".";
64 f->full_address_space = false;
65 f->suppressions = "";
66 f->print_suppressions = true;
67 f->disable_coredump = (SANITIZER_WORDSIZE == 64);
68 f->symbolize_inline_frames = true;
69 f->stack_trace_format = "DEFAULT";
72 void ParseCommonFlagsFromString(CommonFlags *f, const char *str) {
73 ParseFlag(str, &f->symbolize, "symbolize",
74 "If set, use the online symbolizer from common sanitizer runtime to turn "
75 "virtual addresses to file/line locations.");
76 ParseFlag(str, &f->external_symbolizer_path, "external_symbolizer_path",
77 "Path to external symbolizer. If empty, the tool will search $PATH for "
78 "the symbolizer.");
79 ParseFlag(str, &f->allow_addr2line, "allow_addr2line",
80 "If set, allows online symbolizer to run addr2line binary to symbolize "
81 "stack traces (addr2line will only be used if llvm-symbolizer binary is "
82 "unavailable.");
83 ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix",
84 "Strips this prefix from file paths in error reports.");
85 ParseFlag(str, &f->fast_unwind_on_check, "fast_unwind_on_check",
86 "If available, use the fast frame-pointer-based unwinder on "
87 "internal CHECK failures.");
88 ParseFlag(str, &f->fast_unwind_on_fatal, "fast_unwind_on_fatal",
89 "If available, use the fast frame-pointer-based unwinder on fatal "
90 "errors.");
91 ParseFlag(str, &f->fast_unwind_on_malloc, "fast_unwind_on_malloc",
92 "If available, use the fast frame-pointer-based unwinder on "
93 "malloc/free.");
94 ParseFlag(str, &f->handle_ioctl, "handle_ioctl",
95 "Intercept and handle ioctl requests.");
96 ParseFlag(str, &f->malloc_context_size, "malloc_context_size",
97 "Max number of stack frames kept for each allocation/deallocation.");
98 ParseFlag(str, &f->log_path, "log_path",
99 "Write logs to \"log_path.pid\". The special values are \"stdout\" and "
100 "\"stderr\". The default is \"stderr\".");
101 ParseFlag(str, &f->verbosity, "verbosity",
102 "Verbosity level (0 - silent, 1 - a bit of output, 2+ - more output).");
103 ParseFlag(str, &f->detect_leaks, "detect_leaks",
104 "Enable memory leak detection.");
105 ParseFlag(str, &f->leak_check_at_exit, "leak_check_at_exit",
106 "Invoke leak checking in an atexit handler. Has no effect if "
107 "detect_leaks=false, or if __lsan_do_leak_check() is called before the "
108 "handler has a chance to run.");
109 ParseFlag(str, &f->allocator_may_return_null, "allocator_may_return_null",
110 "If false, the allocator will crash instead of returning 0 on "
111 "out-of-memory.");
112 ParseFlag(str, &f->print_summary, "print_summary",
113 "If false, disable printing error summaries in addition to error "
114 "reports.");
115 ParseFlag(str, &f->check_printf, "check_printf",
116 "Check printf arguments.");
117 ParseFlag(str, &f->handle_segv, "handle_segv",
118 "If set, registers the tool's custom SEGV handler (both SIGBUS and "
119 "SIGSEGV on OSX).");
120 ParseFlag(str, &f->allow_user_segv_handler, "allow_user_segv_handler",
121 "If set, allows user to register a SEGV handler even if the tool "
122 "registers one.");
123 ParseFlag(str, &f->use_sigaltstack, "use_sigaltstack",
124 "If set, uses alternate stack for signal handling.");
125 ParseFlag(str, &f->detect_deadlocks, "detect_deadlocks",
126 "If set, deadlock detection is enabled.");
127 ParseFlag(str, &f->clear_shadow_mmap_threshold,
128 "clear_shadow_mmap_threshold",
129 "Large shadow regions are zero-filled using mmap(NORESERVE) instead of "
130 "memset(). This is the threshold size in bytes.");
131 ParseFlag(str, &f->color, "color",
132 "Colorize reports: (always|never|auto).");
133 ParseFlag(str, &f->legacy_pthread_cond, "legacy_pthread_cond",
134 "Enables support for dynamic libraries linked with libpthread 2.2.5.");
135 ParseFlag(str, &f->intercept_tls_get_addr, "intercept_tls_get_addr",
136 "Intercept __tls_get_addr.");
137 ParseFlag(str, &f->help, "help", "Print the flag descriptions.");
138 ParseFlag(str, &f->mmap_limit_mb, "mmap_limit_mb",
139 "Limit the amount of mmap-ed memory (excluding shadow) in Mb; "
140 "not a user-facing flag, used mosly for testing the tools");
141 ParseFlag(str, &f->coverage, "coverage",
142 "If set, coverage information will be dumped at program shutdown (if the "
143 "coverage instrumentation was enabled at compile time).");
144 ParseFlag(str, &f->coverage_direct, "coverage_direct",
145 "If set, coverage information will be dumped directly to a memory "
146 "mapped file. This way data is not lost even if the process is "
147 "suddenly killed.");
148 ParseFlag(str, &f->coverage_dir, "coverage_dir",
149 "Target directory for coverage dumps. Defaults to the current "
150 "directory.");
151 ParseFlag(str, &f->full_address_space, "full_address_space",
152 "Sanitize complete address space; "
153 "by default kernel area on 32-bit platforms will not be sanitized");
154 ParseFlag(str, &f->suppressions, "suppressions", "Suppressions file name.");
155 ParseFlag(str, &f->print_suppressions, "print_suppressions",
156 "Print matched suppressions at exit.");
157 ParseFlag(str, &f->disable_coredump, "disable_coredump",
158 "Disable core dumping. By default, disable_core=1 on 64-bit to avoid "
159 "dumping a 16T+ core file. Ignored on OSes that don't dump core by"
160 "default and for sanitizers that don't reserve lots of virtual memory.");
161 ParseFlag(str, &f->symbolize_inline_frames, "symbolize_inline_frames",
162 "Print inlined frames in stacktraces. Defaults to true.");
163 ParseFlag(str, &f->stack_trace_format, "stack_trace_format",
164 "Format string used to render stack frames. "
165 "See sanitizer_stacktrace_printer.h for the format description. "
166 "Use DEFAULT to get default format.");
168 // Do a sanity check for certain flags.
169 if (f->malloc_context_size < 1)
170 f->malloc_context_size = 1;
173 static bool GetFlagValue(const char *env, const char *name,
174 const char **value, int *value_length) {
175 if (env == 0)
176 return false;
177 const char *pos = 0;
178 for (;;) {
179 pos = internal_strstr(env, name);
180 if (pos == 0)
181 return false;
182 const char *name_end = pos + internal_strlen(name);
183 if ((pos != env &&
184 ((pos[-1] >= 'a' && pos[-1] <= 'z') || pos[-1] == '_')) ||
185 *name_end != '=') {
186 // Seems to be middle of another flag name or value.
187 env = pos + 1;
188 continue;
190 pos = name_end;
191 break;
193 const char *end;
194 if (pos[0] != '=') {
195 end = pos;
196 } else {
197 pos += 1;
198 if (pos[0] == '"') {
199 pos += 1;
200 end = internal_strchr(pos, '"');
201 } else if (pos[0] == '\'') {
202 pos += 1;
203 end = internal_strchr(pos, '\'');
204 } else {
205 // Read until the next space or colon.
206 end = pos + internal_strcspn(pos, " :");
208 if (end == 0)
209 end = pos + internal_strlen(pos);
211 *value = pos;
212 *value_length = end - pos;
213 return true;
216 static bool StartsWith(const char *flag, int flag_length, const char *value) {
217 if (!flag || !value)
218 return false;
219 int value_length = internal_strlen(value);
220 return (flag_length >= value_length) &&
221 (0 == internal_strncmp(flag, value, value_length));
224 static LowLevelAllocator allocator_for_flags;
226 // The linear scan is suboptimal, but the number of flags is relatively small.
227 bool FlagInDescriptionList(const char *name) {
228 IntrusiveList<FlagDescription>::Iterator it(&flag_descriptions);
229 while (it.hasNext()) {
230 if (!internal_strcmp(it.next()->name, name)) return true;
232 return false;
235 void AddFlagDescription(const char *name, const char *description) {
236 if (FlagInDescriptionList(name)) return;
237 FlagDescription *new_description = new(allocator_for_flags) FlagDescription;
238 new_description->name = name;
239 new_description->description = description;
240 flag_descriptions.push_back(new_description);
243 // TODO(glider): put the descriptions inside CommonFlags.
244 void PrintFlagDescriptions() {
245 IntrusiveList<FlagDescription>::Iterator it(&flag_descriptions);
246 Printf("Available flags for %s:\n", SanitizerToolName);
247 while (it.hasNext()) {
248 FlagDescription *descr = it.next();
249 Printf("\t%s\n\t\t- %s\n", descr->name, descr->description);
253 void ParseFlag(const char *env, bool *flag,
254 const char *name, const char *descr) {
255 const char *value;
256 int value_length;
257 AddFlagDescription(name, descr);
258 if (!GetFlagValue(env, name, &value, &value_length))
259 return;
260 if (StartsWith(value, value_length, "0") ||
261 StartsWith(value, value_length, "no") ||
262 StartsWith(value, value_length, "false"))
263 *flag = false;
264 if (StartsWith(value, value_length, "1") ||
265 StartsWith(value, value_length, "yes") ||
266 StartsWith(value, value_length, "true"))
267 *flag = true;
270 void ParseFlag(const char *env, int *flag,
271 const char *name, const char *descr) {
272 const char *value;
273 int value_length;
274 AddFlagDescription(name, descr);
275 if (!GetFlagValue(env, name, &value, &value_length))
276 return;
277 *flag = static_cast<int>(internal_atoll(value));
280 void ParseFlag(const char *env, uptr *flag,
281 const char *name, const char *descr) {
282 const char *value;
283 int value_length;
284 AddFlagDescription(name, descr);
285 if (!GetFlagValue(env, name, &value, &value_length))
286 return;
287 *flag = static_cast<uptr>(internal_atoll(value));
290 void ParseFlag(const char *env, const char **flag,
291 const char *name, const char *descr) {
292 const char *value;
293 int value_length;
294 AddFlagDescription(name, descr);
295 if (!GetFlagValue(env, name, &value, &value_length))
296 return;
297 // Copy the flag value. Don't use locks here, as flags are parsed at
298 // tool startup.
299 char *value_copy = (char*)(allocator_for_flags.Allocate(value_length + 1));
300 internal_memcpy(value_copy, value, value_length);
301 value_copy[value_length] = '\0';
302 *flag = value_copy;
305 } // namespace __sanitizer