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