1 //===-- sanitizer_flags.cc ------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
12 //===----------------------------------------------------------------------===//
14 #include "sanitizer_flags.h"
16 #include "sanitizer_common.h"
17 #include "sanitizer_libc.h"
19 namespace __sanitizer
{
21 CommonFlags common_flags_dont_use
;
23 void SetCommonFlagsDefaults(CommonFlags
*f
) {
25 f
->external_symbolizer_path
= 0;
26 f
->strip_path_prefix
= "";
27 f
->fast_unwind_on_fatal
= false;
28 f
->fast_unwind_on_malloc
= true;
29 f
->handle_ioctl
= false;
30 f
->malloc_context_size
= 1;
31 f
->log_path
= "stderr";
33 f
->detect_leaks
= false;
34 f
->leak_check_at_exit
= true;
35 f
->allocator_may_return_null
= false;
36 f
->print_summary
= true;
37 f
->check_printf
= false;
38 // TODO(glider): tools may want to set different defaults for handle_segv.
39 f
->handle_segv
= SANITIZER_NEEDS_SEGV
;
40 f
->allow_user_segv_handler
= false;
41 f
->use_sigaltstack
= false;
44 void ParseCommonFlagsFromString(CommonFlags
*f
, const char *str
) {
45 ParseFlag(str
, &f
->symbolize
, "symbolize");
46 ParseFlag(str
, &f
->external_symbolizer_path
, "external_symbolizer_path");
47 ParseFlag(str
, &f
->strip_path_prefix
, "strip_path_prefix");
48 ParseFlag(str
, &f
->fast_unwind_on_fatal
, "fast_unwind_on_fatal");
49 ParseFlag(str
, &f
->fast_unwind_on_malloc
, "fast_unwind_on_malloc");
50 ParseFlag(str
, &f
->handle_ioctl
, "handle_ioctl");
51 ParseFlag(str
, &f
->malloc_context_size
, "malloc_context_size");
52 ParseFlag(str
, &f
->log_path
, "log_path");
53 ParseFlag(str
, &f
->verbosity
, "verbosity");
54 ParseFlag(str
, &f
->detect_leaks
, "detect_leaks");
55 ParseFlag(str
, &f
->leak_check_at_exit
, "leak_check_at_exit");
56 ParseFlag(str
, &f
->allocator_may_return_null
, "allocator_may_return_null");
57 ParseFlag(str
, &f
->print_summary
, "print_summary");
58 ParseFlag(str
, &f
->check_printf
, "check_printf");
59 ParseFlag(str
, &f
->handle_segv
, "handle_segv");
60 ParseFlag(str
, &f
->allow_user_segv_handler
, "allow_user_segv_handler");
61 ParseFlag(str
, &f
->use_sigaltstack
, "use_sigaltstack");
63 // Do a sanity check for certain flags.
64 if (f
->malloc_context_size
< 1)
65 f
->malloc_context_size
= 1;
67 f
->external_symbolizer_path
= "";
70 static bool GetFlagValue(const char *env
, const char *name
,
71 const char **value
, int *value_length
) {
76 pos
= internal_strstr(env
, name
);
79 if (pos
!= env
&& ((pos
[-1] >= 'a' && pos
[-1] <= 'z') || pos
[-1] == '_')) {
80 // Seems to be middle of another flag name or value.
86 pos
+= internal_strlen(name
);
94 end
= internal_strchr(pos
, '"');
95 } else if (pos
[0] == '\'') {
97 end
= internal_strchr(pos
, '\'');
99 // Read until the next space or colon.
100 end
= pos
+ internal_strcspn(pos
, " :");
103 end
= pos
+ internal_strlen(pos
);
106 *value_length
= end
- pos
;
110 static bool StartsWith(const char *flag
, int flag_length
, const char *value
) {
113 int value_length
= internal_strlen(value
);
114 return (flag_length
>= value_length
) &&
115 (0 == internal_strncmp(flag
, value
, value_length
));
118 void ParseFlag(const char *env
, bool *flag
, const char *name
) {
121 if (!GetFlagValue(env
, name
, &value
, &value_length
))
123 if (StartsWith(value
, value_length
, "0") ||
124 StartsWith(value
, value_length
, "no") ||
125 StartsWith(value
, value_length
, "false"))
127 if (StartsWith(value
, value_length
, "1") ||
128 StartsWith(value
, value_length
, "yes") ||
129 StartsWith(value
, value_length
, "true"))
133 void ParseFlag(const char *env
, int *flag
, const char *name
) {
136 if (!GetFlagValue(env
, name
, &value
, &value_length
))
138 *flag
= static_cast<int>(internal_atoll(value
));
141 static LowLevelAllocator allocator_for_flags
;
143 void ParseFlag(const char *env
, const char **flag
, const char *name
) {
146 if (!GetFlagValue(env
, name
, &value
, &value_length
))
148 // Copy the flag value. Don't use locks here, as flags are parsed at
150 char *value_copy
= (char*)(allocator_for_flags
.Allocate(value_length
+ 1));
151 internal_memcpy(value_copy
, value
, value_length
);
152 value_copy
[value_length
] = '\0';
156 } // namespace __sanitizer