tsan_flags.cc revision 603c4be006d8c53905d736bf1f19a49f5ce98276
1603c4be006d8c53905d736bf1f19a49f5ce98276Alexey Samsonov//===-- tsan_flags.cc -----------------------------------------------------===//
27ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
37ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//                     The LLVM Compiler Infrastructure
47ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
57ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is distributed under the University of Illinois Open Source
67ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// License. See LICENSE.TXT for details.
77ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
87ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===//
97ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is a part of ThreadSanitizer (TSan), a race detector.
117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===//
137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_flags.h"
157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_rtl.h"
167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_mman.h"
177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanynamespace __tsan {
197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void Flag(const char *env, bool *flag, const char *name);
217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void Flag(const char *env, int *flag, const char *name);
227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void Flag(const char *env, const char **flag, const char *name);
237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
247ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyFlags *flags() {
257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return &CTX()->flags;
267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Can be overriden in frontend.
297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid WEAK OverrideFlags(Flags *f) {
307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  (void)f;
317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid InitializeFlags(Flags *f, const char *env) {
347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  internal_memset(f, 0, sizeof(*f));
357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Default values.
377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  f->enable_annotations = true;
387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  f->suppress_equal_stacks = true;
397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  f->suppress_equal_addresses = true;
407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  f->report_thread_leaks = true;
417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  f->report_signal_unsafe = true;
427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  f->force_seq_cst_atomics = false;
43b7b6b1cd9df0c954b1f890fcebf373db984923b3Dmitry Vyukov  f->strip_path_prefix = "";
44b7b6b1cd9df0c954b1f890fcebf373db984923b3Dmitry Vyukov  f->suppressions = "";
457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  f->exitcode = 66;
467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  f->log_fileno = 2;
477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  f->atexit_sleep_ms = 1000;
487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  f->verbosity = 0;
4926127735454fddae3495794f38189d57dde6510fDmitry Vyukov  f->profile_memory = "";
50adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  f->flush_memory_ms = 0;
51adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  f->stop_on_start = false;
5224567d409cca096b950574fa4b19aa4c2c67a1f0Dmitry Vyukov  f->running_on_valgrind = false;
5324567d409cca096b950574fa4b19aa4c2c67a1f0Dmitry Vyukov
547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Let a frontend override.
567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  OverrideFlags(f);
577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Override from command line.
597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->enable_annotations, "enable_annotations");
607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->suppress_equal_stacks, "suppress_equal_stacks");
617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->suppress_equal_addresses, "suppress_equal_addresses");
627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->report_thread_leaks, "report_thread_leaks");
637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->report_signal_unsafe, "report_signal_unsafe");
647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->force_seq_cst_atomics, "force_seq_cst_atomics");
657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->strip_path_prefix, "strip_path_prefix");
667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->suppressions, "suppressions");
677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->exitcode, "exitcode");
687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->log_fileno, "log_fileno");
697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->atexit_sleep_ms, "atexit_sleep_ms");
707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->verbosity, "verbosity");
7126127735454fddae3495794f38189d57dde6510fDmitry Vyukov  Flag(env, &f->profile_memory, "profile_memory");
72adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  Flag(env, &f->flush_memory_ms, "flush_memory_ms");
73adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  Flag(env, &f->stop_on_start, "stop_on_start");
747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic const char *GetFlagValue(const char *env, const char *name,
777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                                const char **end) {
787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (env == 0)
797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return *end = 0;
807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *pos = internal_strstr(env, name);
817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (pos == 0)
827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return *end = 0;
837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  pos += internal_strlen(name);
847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (pos[0] != '=')
857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return *end = pos;
867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  pos += 1;
877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (pos[0] == '"') {
887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    pos += 1;
897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    *end = internal_strchr(pos, '"');
907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else if (pos[0] == '\'') {
917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    pos += 1;
927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    *end = internal_strchr(pos, '\'');
937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else {
947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    *end = internal_strchr(pos, ' ');
957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (*end == 0)
977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    *end = pos + internal_strlen(pos);
987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return pos;
997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
1007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void Flag(const char *env, bool *flag, const char *name) {
1027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *end = 0;
1037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *val = GetFlagValue(env, name, &end);
1047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (val == 0)
1057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
1067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int len = end - val;
1077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (len == 1 && val[0] == '0')
1087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    *flag = false;
1097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  else if (len == 1 && val[0] == '1')
1107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    *flag = true;
1117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
1127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void Flag(const char *env, int *flag, const char *name) {
1147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *end = 0;
1157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *val = GetFlagValue(env, name, &end);
1167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (val == 0)
1177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
1187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  bool minus = false;
1197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (val != end && val[0] == '-') {
1207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    minus = true;
1217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    val += 1;
1227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
1237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int v = 0;
1247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  for (; val != end; val++) {
1257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (val[0] < '0' || val[0] > '9')
1267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      break;
1277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    v = v * 10 + val[0] - '0';
1287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
1297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (minus)
1307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    v = -v;
1317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  *flag = v;
1327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
1337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void Flag(const char *env, const char **flag, const char *name) {
1357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *end = 0;
1367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *val = GetFlagValue(env, name, &end);
1377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (val == 0)
1387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
1397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int len = end - val;
1407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  char *f = (char*)internal_alloc(MBlockFlag, len + 1);
1417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  internal_memcpy(f, val, len);
1427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  f[len] = 0;
1437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  *flag = f;
1447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
1457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}  // namespace __tsan
147