160 lines · cpp
1//===-- tsan_flags.cpp ----------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of ThreadSanitizer (TSan), a race detector.10//11//===----------------------------------------------------------------------===//12 13#include "tsan_flags.h"14 15#include "sanitizer_common/sanitizer_flag_parser.h"16#include "sanitizer_common/sanitizer_flags.h"17#include "sanitizer_common/sanitizer_libc.h"18#include "tsan_interface.h"19#include "tsan_mman.h"20#include "tsan_rtl.h"21#include "ubsan/ubsan_flags.h"22 23#if SANITIZER_APPLE && !SANITIZER_GO24namespace __sanitizer {25 26template <>27inline bool FlagHandler<LockDuringWriteSetting>::Parse(const char *value) {28 if (internal_strcmp(value, "on") == 0) {29 *t_ = kLockDuringAllWrites;30 return true;31 }32 if (internal_strcmp(value, "disable_for_current_process") == 0) {33 *t_ = kNoLockDuringWritesCurrentProcess;34 return true;35 }36 if (internal_strcmp(value, "disable_for_all_processes") == 0) {37 *t_ = kNoLockDuringWritesAllProcesses;38 return true;39 }40 Printf("ERROR: Invalid value for signal handler option: '%s'\n", value);41 return false;42}43 44template <>45inline bool FlagHandler<LockDuringWriteSetting>::Format(char *buffer,46 uptr size) {47 switch (*t_) {48 case kLockDuringAllWrites:49 return FormatString(buffer, size, "on");50 case kNoLockDuringWritesCurrentProcess:51 return FormatString(buffer, size, "disable_for_current_process");52 case kNoLockDuringWritesAllProcesses:53 return FormatString(buffer, size, "disable_for_all_processes");54 }55}56 57} // namespace __sanitizer58#endif // SANITIZER_APPLE && !SANITIZER_GO59 60namespace __tsan {61 62// Can be overriden in frontend.63#ifdef TSAN_EXTERNAL_HOOKS64extern "C" const char *__tsan_default_options();65#else66SANITIZER_WEAK_DEFAULT_IMPL67const char *__tsan_default_options() {68 return "";69}70#endif71 72void Flags::SetDefaults() {73#define TSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;74#include "tsan_flags.inc"75#undef TSAN_FLAG76 // DDFlags77 second_deadlock_stack = false;78}79 80void RegisterTsanFlags(FlagParser *parser, Flags *f) {81#define TSAN_FLAG(Type, Name, DefaultValue, Description) \82 RegisterFlag(parser, #Name, Description, &f->Name);83#include "tsan_flags.inc"84#undef TSAN_FLAG85 // DDFlags86 RegisterFlag(parser, "second_deadlock_stack",87 "Report where each mutex is locked in deadlock reports",88 &f->second_deadlock_stack);89}90 91void InitializeFlags(Flags *f, const char *env, const char *env_option_name) {92 SetCommonFlagsDefaults();93 {94 // Override some common flags defaults.95 CommonFlags cf;96 cf.CopyFrom(*common_flags());97 cf.external_symbolizer_path = GetEnv("TSAN_SYMBOLIZER_PATH");98 cf.allow_addr2line = true;99 if (SANITIZER_GO) {100 // Does not work as expected for Go: runtime handles SIGABRT and crashes.101 cf.abort_on_error = false;102 // Go does not have mutexes.103 cf.detect_deadlocks = false;104 }105 cf.print_suppressions = false;106 cf.stack_trace_format = " #%n %f %S %M";107 cf.exitcode = 66;108 cf.intercept_tls_get_addr = true;109 OverrideCommonFlags(cf);110 }111 112 f->SetDefaults();113 114 FlagParser parser;115 RegisterTsanFlags(&parser, f);116 RegisterCommonFlags(&parser);117 118#if TSAN_CONTAINS_UBSAN119 __ubsan::Flags *uf = __ubsan::flags();120 uf->SetDefaults();121 122 FlagParser ubsan_parser;123 __ubsan::RegisterUbsanFlags(&ubsan_parser, uf);124 RegisterCommonFlags(&ubsan_parser);125#endif126 127 // Let a frontend override.128 parser.ParseString(__tsan_default_options());129#if TSAN_CONTAINS_UBSAN130 const char *ubsan_default_options = __ubsan_default_options();131 ubsan_parser.ParseString(ubsan_default_options);132#endif133 // Override from command line.134 parser.ParseString(env, env_option_name);135#if TSAN_CONTAINS_UBSAN136 ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS");137#endif138 139 // Check flags.140 if (!f->report_bugs) {141 f->report_thread_leaks = false;142 f->report_destroy_locked = false;143 f->report_signal_unsafe = false;144 }145 146 InitializeCommonFlags();147 148 if (Verbosity()) ReportUnrecognizedFlags();149 150 if (common_flags()->help) parser.PrintFlagDescriptions();151 152 if (f->io_sync < 0 || f->io_sync > 2) {153 Printf("ThreadSanitizer: incorrect value for io_sync"154 " (must be [0..2])\n");155 Die();156 }157}158 159} // namespace __tsan160