tsan_flags.cc revision 26127735454fddae3495794f38189d57dde6510f
17ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===-- tsan_flags.cc -------------------------------------------*- C++ -*-===//
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 = "";
507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Let a frontend override.
527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  OverrideFlags(f);
537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Override from command line.
557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->enable_annotations, "enable_annotations");
567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->suppress_equal_stacks, "suppress_equal_stacks");
577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->suppress_equal_addresses, "suppress_equal_addresses");
587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->report_thread_leaks, "report_thread_leaks");
597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->report_signal_unsafe, "report_signal_unsafe");
607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->force_seq_cst_atomics, "force_seq_cst_atomics");
617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->strip_path_prefix, "strip_path_prefix");
627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->suppressions, "suppressions");
637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->exitcode, "exitcode");
647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->log_fileno, "log_fileno");
657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->atexit_sleep_ms, "atexit_sleep_ms");
667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Flag(env, &f->verbosity, "verbosity");
6726127735454fddae3495794f38189d57dde6510fDmitry Vyukov  Flag(env, &f->profile_memory, "profile_memory");
687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic const char *GetFlagValue(const char *env, const char *name,
717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                                const char **end) {
727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (env == 0)
737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return *end = 0;
747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *pos = internal_strstr(env, name);
757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (pos == 0)
767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return *end = 0;
777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  pos += internal_strlen(name);
787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (pos[0] != '=')
797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return *end = pos;
807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  pos += 1;
817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (pos[0] == '"') {
827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    pos += 1;
837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    *end = internal_strchr(pos, '"');
847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else if (pos[0] == '\'') {
857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    pos += 1;
867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    *end = internal_strchr(pos, '\'');
877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else {
887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    *end = internal_strchr(pos, ' ');
897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (*end == 0)
917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    *end = pos + internal_strlen(pos);
927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return pos;
937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void Flag(const char *env, bool *flag, const char *name) {
967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *end = 0;
977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *val = GetFlagValue(env, name, &end);
987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (val == 0)
997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
1007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int len = end - val;
1017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (len == 1 && val[0] == '0')
1027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    *flag = false;
1037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  else if (len == 1 && val[0] == '1')
1047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    *flag = true;
1057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
1067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void Flag(const char *env, int *flag, const char *name) {
1087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *end = 0;
1097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *val = GetFlagValue(env, name, &end);
1107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (val == 0)
1117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
1127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  bool minus = false;
1137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (val != end && val[0] == '-') {
1147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    minus = true;
1157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    val += 1;
1167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
1177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int v = 0;
1187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  for (; val != end; val++) {
1197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (val[0] < '0' || val[0] > '9')
1207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      break;
1217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    v = v * 10 + val[0] - '0';
1227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
1237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (minus)
1247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    v = -v;
1257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  *flag = v;
1267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
1277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void Flag(const char *env, const char **flag, const char *name) {
1297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *end = 0;
1307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *val = GetFlagValue(env, name, &end);
1317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (val == 0)
1327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
1337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int len = end - val;
1347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  char *f = (char*)internal_alloc(MBlockFlag, len + 1);
1357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  internal_memcpy(f, val, len);
1367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  f[len] = 0;
1377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  *flag = f;
1387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
1397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}  // namespace __tsan
141