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