tsan: fix Go build
[blocksruntime.git] / lib / sanitizer_common / sanitizer_flags.cc
blobcbff0a541a17686114d7b6d1d2e17e80616e4315
1 //===-- sanitizer_flags.cc ------------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
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) {
24 f->symbolize = true;
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";
32 f->verbosity = 0;
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;
66 if (!f->symbolize)
67 f->external_symbolizer_path = "";
70 static bool GetFlagValue(const char *env, const char *name,
71 const char **value, int *value_length) {
72 if (env == 0)
73 return false;
74 const char *pos = 0;
75 for (;;) {
76 pos = internal_strstr(env, name);
77 if (pos == 0)
78 return false;
79 if (pos != env && ((pos[-1] >= 'a' && pos[-1] <= 'z') || pos[-1] == '_')) {
80 // Seems to be middle of another flag name or value.
81 env = pos + 1;
82 continue;
84 break;
86 pos += internal_strlen(name);
87 const char *end;
88 if (pos[0] != '=') {
89 end = pos;
90 } else {
91 pos += 1;
92 if (pos[0] == '"') {
93 pos += 1;
94 end = internal_strchr(pos, '"');
95 } else if (pos[0] == '\'') {
96 pos += 1;
97 end = internal_strchr(pos, '\'');
98 } else {
99 // Read until the next space or colon.
100 end = pos + internal_strcspn(pos, " :");
102 if (end == 0)
103 end = pos + internal_strlen(pos);
105 *value = pos;
106 *value_length = end - pos;
107 return true;
110 static bool StartsWith(const char *flag, int flag_length, const char *value) {
111 if (!flag || !value)
112 return false;
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) {
119 const char *value;
120 int value_length;
121 if (!GetFlagValue(env, name, &value, &value_length))
122 return;
123 if (StartsWith(value, value_length, "0") ||
124 StartsWith(value, value_length, "no") ||
125 StartsWith(value, value_length, "false"))
126 *flag = false;
127 if (StartsWith(value, value_length, "1") ||
128 StartsWith(value, value_length, "yes") ||
129 StartsWith(value, value_length, "true"))
130 *flag = true;
133 void ParseFlag(const char *env, int *flag, const char *name) {
134 const char *value;
135 int value_length;
136 if (!GetFlagValue(env, name, &value, &value_length))
137 return;
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) {
144 const char *value;
145 int value_length;
146 if (!GetFlagValue(env, name, &value, &value_length))
147 return;
148 // Copy the flag value. Don't use locks here, as flags are parsed at
149 // tool startup.
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';
153 *flag = value_copy;
156 } // namespace __sanitizer