1*68d75effSDimitry Andric //===-- tsan_flags.cpp ----------------------------------------------------===// 2*68d75effSDimitry Andric // 3*68d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*68d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*68d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*68d75effSDimitry Andric // 7*68d75effSDimitry Andric //===----------------------------------------------------------------------===// 8*68d75effSDimitry Andric // 9*68d75effSDimitry Andric // This file is a part of ThreadSanitizer (TSan), a race detector. 10*68d75effSDimitry Andric // 11*68d75effSDimitry Andric //===----------------------------------------------------------------------===// 12*68d75effSDimitry Andric 13*68d75effSDimitry Andric #include "sanitizer_common/sanitizer_flags.h" 14*68d75effSDimitry Andric #include "sanitizer_common/sanitizer_flag_parser.h" 15*68d75effSDimitry Andric #include "sanitizer_common/sanitizer_libc.h" 16*68d75effSDimitry Andric #include "tsan_flags.h" 17*68d75effSDimitry Andric #include "tsan_rtl.h" 18*68d75effSDimitry Andric #include "tsan_mman.h" 19*68d75effSDimitry Andric #include "ubsan/ubsan_flags.h" 20*68d75effSDimitry Andric 21*68d75effSDimitry Andric namespace __tsan { 22*68d75effSDimitry Andric 23*68d75effSDimitry Andric // Can be overriden in frontend. 24*68d75effSDimitry Andric #ifdef TSAN_EXTERNAL_HOOKS 25*68d75effSDimitry Andric extern "C" const char* __tsan_default_options(); 26*68d75effSDimitry Andric #else 27*68d75effSDimitry Andric SANITIZER_WEAK_DEFAULT_IMPL 28*68d75effSDimitry Andric const char *__tsan_default_options() { 29*68d75effSDimitry Andric return ""; 30*68d75effSDimitry Andric } 31*68d75effSDimitry Andric #endif 32*68d75effSDimitry Andric 33*68d75effSDimitry Andric void Flags::SetDefaults() { 34*68d75effSDimitry Andric #define TSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 35*68d75effSDimitry Andric #include "tsan_flags.inc" 36*68d75effSDimitry Andric #undef TSAN_FLAG 37*68d75effSDimitry Andric // DDFlags 38*68d75effSDimitry Andric second_deadlock_stack = false; 39*68d75effSDimitry Andric } 40*68d75effSDimitry Andric 41*68d75effSDimitry Andric void RegisterTsanFlags(FlagParser *parser, Flags *f) { 42*68d75effSDimitry Andric #define TSAN_FLAG(Type, Name, DefaultValue, Description) \ 43*68d75effSDimitry Andric RegisterFlag(parser, #Name, Description, &f->Name); 44*68d75effSDimitry Andric #include "tsan_flags.inc" 45*68d75effSDimitry Andric #undef TSAN_FLAG 46*68d75effSDimitry Andric // DDFlags 47*68d75effSDimitry Andric RegisterFlag(parser, "second_deadlock_stack", 48*68d75effSDimitry Andric "Report where each mutex is locked in deadlock reports", 49*68d75effSDimitry Andric &f->second_deadlock_stack); 50*68d75effSDimitry Andric } 51*68d75effSDimitry Andric 52*68d75effSDimitry Andric void InitializeFlags(Flags *f, const char *env, const char *env_option_name) { 53*68d75effSDimitry Andric SetCommonFlagsDefaults(); 54*68d75effSDimitry Andric { 55*68d75effSDimitry Andric // Override some common flags defaults. 56*68d75effSDimitry Andric CommonFlags cf; 57*68d75effSDimitry Andric cf.CopyFrom(*common_flags()); 58*68d75effSDimitry Andric cf.allow_addr2line = true; 59*68d75effSDimitry Andric if (SANITIZER_GO) { 60*68d75effSDimitry Andric // Does not work as expected for Go: runtime handles SIGABRT and crashes. 61*68d75effSDimitry Andric cf.abort_on_error = false; 62*68d75effSDimitry Andric // Go does not have mutexes. 63*68d75effSDimitry Andric cf.detect_deadlocks = false; 64*68d75effSDimitry Andric } 65*68d75effSDimitry Andric cf.print_suppressions = false; 66*68d75effSDimitry Andric cf.stack_trace_format = " #%n %f %S %M"; 67*68d75effSDimitry Andric cf.exitcode = 66; 68*68d75effSDimitry Andric cf.intercept_tls_get_addr = true; 69*68d75effSDimitry Andric OverrideCommonFlags(cf); 70*68d75effSDimitry Andric } 71*68d75effSDimitry Andric 72*68d75effSDimitry Andric f->SetDefaults(); 73*68d75effSDimitry Andric 74*68d75effSDimitry Andric FlagParser parser; 75*68d75effSDimitry Andric RegisterTsanFlags(&parser, f); 76*68d75effSDimitry Andric RegisterCommonFlags(&parser); 77*68d75effSDimitry Andric 78*68d75effSDimitry Andric #if TSAN_CONTAINS_UBSAN 79*68d75effSDimitry Andric __ubsan::Flags *uf = __ubsan::flags(); 80*68d75effSDimitry Andric uf->SetDefaults(); 81*68d75effSDimitry Andric 82*68d75effSDimitry Andric FlagParser ubsan_parser; 83*68d75effSDimitry Andric __ubsan::RegisterUbsanFlags(&ubsan_parser, uf); 84*68d75effSDimitry Andric RegisterCommonFlags(&ubsan_parser); 85*68d75effSDimitry Andric #endif 86*68d75effSDimitry Andric 87*68d75effSDimitry Andric // Let a frontend override. 88*68d75effSDimitry Andric parser.ParseString(__tsan_default_options()); 89*68d75effSDimitry Andric #if TSAN_CONTAINS_UBSAN 90*68d75effSDimitry Andric const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions(); 91*68d75effSDimitry Andric ubsan_parser.ParseString(ubsan_default_options); 92*68d75effSDimitry Andric #endif 93*68d75effSDimitry Andric // Override from command line. 94*68d75effSDimitry Andric parser.ParseString(env, env_option_name); 95*68d75effSDimitry Andric #if TSAN_CONTAINS_UBSAN 96*68d75effSDimitry Andric ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS"); 97*68d75effSDimitry Andric #endif 98*68d75effSDimitry Andric 99*68d75effSDimitry Andric // Sanity check. 100*68d75effSDimitry Andric if (!f->report_bugs) { 101*68d75effSDimitry Andric f->report_thread_leaks = false; 102*68d75effSDimitry Andric f->report_destroy_locked = false; 103*68d75effSDimitry Andric f->report_signal_unsafe = false; 104*68d75effSDimitry Andric } 105*68d75effSDimitry Andric 106*68d75effSDimitry Andric InitializeCommonFlags(); 107*68d75effSDimitry Andric 108*68d75effSDimitry Andric if (Verbosity()) ReportUnrecognizedFlags(); 109*68d75effSDimitry Andric 110*68d75effSDimitry Andric if (common_flags()->help) parser.PrintFlagDescriptions(); 111*68d75effSDimitry Andric 112*68d75effSDimitry Andric if (f->history_size < 0 || f->history_size > 7) { 113*68d75effSDimitry Andric Printf("ThreadSanitizer: incorrect value for history_size" 114*68d75effSDimitry Andric " (must be [0..7])\n"); 115*68d75effSDimitry Andric Die(); 116*68d75effSDimitry Andric } 117*68d75effSDimitry Andric 118*68d75effSDimitry Andric if (f->io_sync < 0 || f->io_sync > 2) { 119*68d75effSDimitry Andric Printf("ThreadSanitizer: incorrect value for io_sync" 120*68d75effSDimitry Andric " (must be [0..2])\n"); 121*68d75effSDimitry Andric Die(); 122*68d75effSDimitry Andric } 123*68d75effSDimitry Andric } 124*68d75effSDimitry Andric 125*68d75effSDimitry Andric } // namespace __tsan 126