tsan_flags.cc revision b78caa645f70eff2f037f1f8bb43ca9129dbd8d9
1//===-- tsan_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 (TSan), a race detector.
11//
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_common/sanitizer_libc.h"
15#include "tsan_flags.h"
16#include "tsan_rtl.h"
17#include "tsan_mman.h"
18
19namespace __tsan {
20
21static void Flag(const char *env, bool *flag, const char *name);
22static void Flag(const char *env, int *flag, const char *name);
23static void Flag(const char *env, const char **flag, const char *name);
24
25Flags *flags() {
26  return &CTX()->flags;
27}
28
29// Can be overriden in frontend.
30void WEAK OverrideFlags(Flags *f) {
31  (void)f;
32}
33
34void InitializeFlags(Flags *f, const char *env) {
35  internal_memset(f, 0, sizeof(*f));
36
37  // Default values.
38  f->enable_annotations = true;
39  f->suppress_equal_stacks = true;
40  f->suppress_equal_addresses = true;
41  f->report_thread_leaks = true;
42  f->report_signal_unsafe = true;
43  f->force_seq_cst_atomics = false;
44  f->strip_path_prefix = "";
45  f->suppressions = "";
46  f->exitcode = 66;
47  f->log_fileno = 2;
48  f->atexit_sleep_ms = 1000;
49  f->verbosity = 0;
50  f->profile_memory = "";
51  f->flush_memory_ms = 0;
52  f->stop_on_start = false;
53  f->running_on_valgrind = false;
54  f->use_internal_symbolizer = false;
55
56  // Let a frontend override.
57  OverrideFlags(f);
58
59  // Override from command line.
60  Flag(env, &f->enable_annotations, "enable_annotations");
61  Flag(env, &f->suppress_equal_stacks, "suppress_equal_stacks");
62  Flag(env, &f->suppress_equal_addresses, "suppress_equal_addresses");
63  Flag(env, &f->report_thread_leaks, "report_thread_leaks");
64  Flag(env, &f->report_signal_unsafe, "report_signal_unsafe");
65  Flag(env, &f->force_seq_cst_atomics, "force_seq_cst_atomics");
66  Flag(env, &f->strip_path_prefix, "strip_path_prefix");
67  Flag(env, &f->suppressions, "suppressions");
68  Flag(env, &f->exitcode, "exitcode");
69  Flag(env, &f->log_fileno, "log_fileno");
70  Flag(env, &f->atexit_sleep_ms, "atexit_sleep_ms");
71  Flag(env, &f->verbosity, "verbosity");
72  Flag(env, &f->profile_memory, "profile_memory");
73  Flag(env, &f->flush_memory_ms, "flush_memory_ms");
74  Flag(env, &f->stop_on_start, "stop_on_start");
75  Flag(env, &f->use_internal_symbolizer, "use_internal_symbolizer");
76}
77
78static const char *GetFlagValue(const char *env, const char *name,
79                                const char **end) {
80  if (env == 0)
81    return *end = 0;
82  const char *pos = internal_strstr(env, name);
83  if (pos == 0)
84    return *end = 0;
85  pos += internal_strlen(name);
86  if (pos[0] != '=')
87    return *end = pos;
88  pos += 1;
89  if (pos[0] == '"') {
90    pos += 1;
91    *end = internal_strchr(pos, '"');
92  } else if (pos[0] == '\'') {
93    pos += 1;
94    *end = internal_strchr(pos, '\'');
95  } else {
96    *end = internal_strchr(pos, ' ');
97  }
98  if (*end == 0)
99    *end = pos + internal_strlen(pos);
100  return pos;
101}
102
103static void Flag(const char *env, bool *flag, const char *name) {
104  const char *end = 0;
105  const char *val = GetFlagValue(env, name, &end);
106  if (val == 0)
107    return;
108  int len = end - val;
109  if (len == 1 && val[0] == '0')
110    *flag = false;
111  else if (len == 1 && val[0] == '1')
112    *flag = true;
113}
114
115static void Flag(const char *env, int *flag, const char *name) {
116  const char *end = 0;
117  const char *val = GetFlagValue(env, name, &end);
118  if (val == 0)
119    return;
120  bool minus = false;
121  if (val != end && val[0] == '-') {
122    minus = true;
123    val += 1;
124  }
125  int v = 0;
126  for (; val != end; val++) {
127    if (val[0] < '0' || val[0] > '9')
128      break;
129    v = v * 10 + val[0] - '0';
130  }
131  if (minus)
132    v = -v;
133  *flag = v;
134}
135
136static void Flag(const char *env, const char **flag, const char *name) {
137  const char *end = 0;
138  const char *val = GetFlagValue(env, name, &end);
139  if (val == 0)
140    return;
141  int len = end - val;
142  char *f = (char*)internal_alloc(MBlockFlag, len + 1);
143  internal_memcpy(f, val, len);
144  f[len] = 0;
145  *flag = f;
146}
147
148}  // namespace __tsan
149