1 //===-- sanitizer_flags.cc ------------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
10 //===----------------------------------------------------------------------===//
12 #include "sanitizer_flags.h"
14 #include "sanitizer_common.h"
15 #include "sanitizer_libc.h"
17 namespace __sanitizer
{
19 void SetCommonFlagsDefaults(CommonFlags
*f
) {
21 f
->external_symbolizer_path
= 0;
22 f
->strip_path_prefix
= "";
23 f
->fast_unwind_on_fatal
= false;
24 f
->fast_unwind_on_malloc
= true;
25 f
->handle_ioctl
= false;
26 f
->malloc_context_size
= 1;
27 f
->log_path
= "stderr";
29 f
->detect_leaks
= false;
30 f
->leak_check_at_exit
= true;
31 f
->allocator_may_return_null
= false;
32 f
->print_summary
= true;
35 void ParseCommonFlagsFromString(CommonFlags
*f
, const char *str
) {
36 ParseFlag(str
, &f
->symbolize
, "symbolize");
37 ParseFlag(str
, &f
->external_symbolizer_path
, "external_symbolizer_path");
38 ParseFlag(str
, &f
->strip_path_prefix
, "strip_path_prefix");
39 ParseFlag(str
, &f
->fast_unwind_on_fatal
, "fast_unwind_on_fatal");
40 ParseFlag(str
, &f
->fast_unwind_on_malloc
, "fast_unwind_on_malloc");
41 ParseFlag(str
, &f
->handle_ioctl
, "handle_ioctl");
42 ParseFlag(str
, &f
->malloc_context_size
, "malloc_context_size");
43 ParseFlag(str
, &f
->log_path
, "log_path");
44 ParseFlag(str
, &f
->verbosity
, "verbosity");
45 ParseFlag(str
, &f
->detect_leaks
, "detect_leaks");
46 ParseFlag(str
, &f
->leak_check_at_exit
, "leak_check_at_exit");
47 ParseFlag(str
, &f
->allocator_may_return_null
, "allocator_may_return_null");
48 ParseFlag(str
, &f
->print_summary
, "print_summary");
50 // Do a sanity check for certain flags.
51 if (f
->malloc_context_size
< 1)
52 f
->malloc_context_size
= 1;
55 static bool GetFlagValue(const char *env
, const char *name
,
56 const char **value
, int *value_length
) {
61 pos
= internal_strstr(env
, name
);
64 if (pos
!= env
&& ((pos
[-1] >= 'a' && pos
[-1] <= 'z') || pos
[-1] == '_')) {
65 // Seems to be middle of another flag name or value.
71 pos
+= internal_strlen(name
);
79 end
= internal_strchr(pos
, '"');
80 } else if (pos
[0] == '\'') {
82 end
= internal_strchr(pos
, '\'');
84 // Read until the next space or colon.
85 end
= pos
+ internal_strcspn(pos
, " :");
88 end
= pos
+ internal_strlen(pos
);
91 *value_length
= end
- pos
;
95 static bool StartsWith(const char *flag
, int flag_length
, const char *value
) {
98 int value_length
= internal_strlen(value
);
99 return (flag_length
>= value_length
) &&
100 (0 == internal_strncmp(flag
, value
, value_length
));
103 void ParseFlag(const char *env
, bool *flag
, const char *name
) {
106 if (!GetFlagValue(env
, name
, &value
, &value_length
))
108 if (StartsWith(value
, value_length
, "0") ||
109 StartsWith(value
, value_length
, "no") ||
110 StartsWith(value
, value_length
, "false"))
112 if (StartsWith(value
, value_length
, "1") ||
113 StartsWith(value
, value_length
, "yes") ||
114 StartsWith(value
, value_length
, "true"))
118 void ParseFlag(const char *env
, int *flag
, const char *name
) {
121 if (!GetFlagValue(env
, name
, &value
, &value_length
))
123 *flag
= static_cast<int>(internal_atoll(value
));
126 static LowLevelAllocator allocator_for_flags
;
128 void ParseFlag(const char *env
, const char **flag
, const char *name
) {
131 if (!GetFlagValue(env
, name
, &value
, &value_length
))
133 // Copy the flag value. Don't use locks here, as flags are parsed at
135 char *value_copy
= (char*)(allocator_for_flags
.Allocate(value_length
+ 1));
136 internal_memcpy(value_copy
, value
, value_length
);
137 value_copy
[value_length
] = '\0';
141 } // namespace __sanitizer