168d75effSDimitry Andric //===-- tsan_flags.cpp ----------------------------------------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is a part of ThreadSanitizer (TSan), a race detector. 1068d75effSDimitry Andric // 1168d75effSDimitry Andric //===----------------------------------------------------------------------===// 1268d75effSDimitry Andric 1368d75effSDimitry Andric #include "sanitizer_common/sanitizer_flags.h" 1468d75effSDimitry Andric #include "sanitizer_common/sanitizer_flag_parser.h" 1568d75effSDimitry Andric #include "sanitizer_common/sanitizer_libc.h" 1668d75effSDimitry Andric #include "tsan_flags.h" 1768d75effSDimitry Andric #include "tsan_rtl.h" 1868d75effSDimitry Andric #include "tsan_mman.h" 1968d75effSDimitry Andric #include "ubsan/ubsan_flags.h" 2068d75effSDimitry Andric 2168d75effSDimitry Andric namespace __tsan { 2268d75effSDimitry Andric 2368d75effSDimitry Andric // Can be overriden in frontend. 2468d75effSDimitry Andric #ifdef TSAN_EXTERNAL_HOOKS 2568d75effSDimitry Andric extern "C" const char* __tsan_default_options(); 2668d75effSDimitry Andric #else 2768d75effSDimitry Andric SANITIZER_WEAK_DEFAULT_IMPL 2868d75effSDimitry Andric const char *__tsan_default_options() { 2968d75effSDimitry Andric return ""; 3068d75effSDimitry Andric } 3168d75effSDimitry Andric #endif 3268d75effSDimitry Andric 3368d75effSDimitry Andric void Flags::SetDefaults() { 3468d75effSDimitry Andric #define TSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 3568d75effSDimitry Andric #include "tsan_flags.inc" 3668d75effSDimitry Andric #undef TSAN_FLAG 3768d75effSDimitry Andric // DDFlags 3868d75effSDimitry Andric second_deadlock_stack = false; 3968d75effSDimitry Andric } 4068d75effSDimitry Andric 4168d75effSDimitry Andric void RegisterTsanFlags(FlagParser *parser, Flags *f) { 4268d75effSDimitry Andric #define TSAN_FLAG(Type, Name, DefaultValue, Description) \ 4368d75effSDimitry Andric RegisterFlag(parser, #Name, Description, &f->Name); 4468d75effSDimitry Andric #include "tsan_flags.inc" 4568d75effSDimitry Andric #undef TSAN_FLAG 4668d75effSDimitry Andric // DDFlags 4768d75effSDimitry Andric RegisterFlag(parser, "second_deadlock_stack", 4868d75effSDimitry Andric "Report where each mutex is locked in deadlock reports", 4968d75effSDimitry Andric &f->second_deadlock_stack); 5068d75effSDimitry Andric } 5168d75effSDimitry Andric 5268d75effSDimitry Andric void InitializeFlags(Flags *f, const char *env, const char *env_option_name) { 5368d75effSDimitry Andric SetCommonFlagsDefaults(); 5468d75effSDimitry Andric { 5568d75effSDimitry Andric // Override some common flags defaults. 5668d75effSDimitry Andric CommonFlags cf; 5768d75effSDimitry Andric cf.CopyFrom(*common_flags()); 58*349cc55cSDimitry Andric cf.external_symbolizer_path = GetEnv("TSAN_SYMBOLIZER_PATH"); 5968d75effSDimitry Andric cf.allow_addr2line = true; 6068d75effSDimitry Andric if (SANITIZER_GO) { 6168d75effSDimitry Andric // Does not work as expected for Go: runtime handles SIGABRT and crashes. 6268d75effSDimitry Andric cf.abort_on_error = false; 6368d75effSDimitry Andric // Go does not have mutexes. 6468d75effSDimitry Andric cf.detect_deadlocks = false; 6568d75effSDimitry Andric } 6668d75effSDimitry Andric cf.print_suppressions = false; 6768d75effSDimitry Andric cf.stack_trace_format = " #%n %f %S %M"; 6868d75effSDimitry Andric cf.exitcode = 66; 6968d75effSDimitry Andric cf.intercept_tls_get_addr = true; 7068d75effSDimitry Andric OverrideCommonFlags(cf); 7168d75effSDimitry Andric } 7268d75effSDimitry Andric 7368d75effSDimitry Andric f->SetDefaults(); 7468d75effSDimitry Andric 7568d75effSDimitry Andric FlagParser parser; 7668d75effSDimitry Andric RegisterTsanFlags(&parser, f); 7768d75effSDimitry Andric RegisterCommonFlags(&parser); 7868d75effSDimitry Andric 7968d75effSDimitry Andric #if TSAN_CONTAINS_UBSAN 8068d75effSDimitry Andric __ubsan::Flags *uf = __ubsan::flags(); 8168d75effSDimitry Andric uf->SetDefaults(); 8268d75effSDimitry Andric 8368d75effSDimitry Andric FlagParser ubsan_parser; 8468d75effSDimitry Andric __ubsan::RegisterUbsanFlags(&ubsan_parser, uf); 8568d75effSDimitry Andric RegisterCommonFlags(&ubsan_parser); 8668d75effSDimitry Andric #endif 8768d75effSDimitry Andric 8868d75effSDimitry Andric // Let a frontend override. 8968d75effSDimitry Andric parser.ParseString(__tsan_default_options()); 9068d75effSDimitry Andric #if TSAN_CONTAINS_UBSAN 91e8d8bef9SDimitry Andric const char *ubsan_default_options = __ubsan_default_options(); 9268d75effSDimitry Andric ubsan_parser.ParseString(ubsan_default_options); 9368d75effSDimitry Andric #endif 9468d75effSDimitry Andric // Override from command line. 9568d75effSDimitry Andric parser.ParseString(env, env_option_name); 9668d75effSDimitry Andric #if TSAN_CONTAINS_UBSAN 9768d75effSDimitry Andric ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS"); 9868d75effSDimitry Andric #endif 9968d75effSDimitry Andric 10068d75effSDimitry Andric // Sanity check. 10168d75effSDimitry Andric if (!f->report_bugs) { 10268d75effSDimitry Andric f->report_thread_leaks = false; 10368d75effSDimitry Andric f->report_destroy_locked = false; 10468d75effSDimitry Andric f->report_signal_unsafe = false; 10568d75effSDimitry Andric } 10668d75effSDimitry Andric 10768d75effSDimitry Andric InitializeCommonFlags(); 10868d75effSDimitry Andric 10968d75effSDimitry Andric if (Verbosity()) ReportUnrecognizedFlags(); 11068d75effSDimitry Andric 11168d75effSDimitry Andric if (common_flags()->help) parser.PrintFlagDescriptions(); 11268d75effSDimitry Andric 11368d75effSDimitry Andric if (f->history_size < 0 || f->history_size > 7) { 11468d75effSDimitry Andric Printf("ThreadSanitizer: incorrect value for history_size" 11568d75effSDimitry Andric " (must be [0..7])\n"); 11668d75effSDimitry Andric Die(); 11768d75effSDimitry Andric } 11868d75effSDimitry Andric 11968d75effSDimitry Andric if (f->io_sync < 0 || f->io_sync > 2) { 12068d75effSDimitry Andric Printf("ThreadSanitizer: incorrect value for io_sync" 12168d75effSDimitry Andric " (must be [0..2])\n"); 12268d75effSDimitry Andric Die(); 12368d75effSDimitry Andric } 12468d75effSDimitry Andric } 12568d75effSDimitry Andric 12668d75effSDimitry Andric } // namespace __tsan 127