1 //===-- sanitizer_flags.cc ------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is a part of ThreadSanitizer/AddressSanitizer runtime. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "sanitizer_flags.h" 15 16 #include "sanitizer_common.h" 17 #include "sanitizer_libc.h" 18 #include "sanitizer_list.h" 19 #include "sanitizer_flag_parser.h" 20 21 namespace __sanitizer { 22 23 CommonFlags common_flags_dont_use; 24 25 struct FlagDescription { 26 const char *name; 27 const char *description; 28 FlagDescription *next; 29 }; 30 31 IntrusiveList<FlagDescription> flag_descriptions; 32 33 // If set, the tool will install its own SEGV signal handler by default. 34 #ifndef SANITIZER_NEEDS_SEGV 35 # define SANITIZER_NEEDS_SEGV 1 36 #endif 37 38 void CommonFlags::SetDefaults() { 39 #define COMMON_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 40 #include "sanitizer_flags.inc" 41 #undef COMMON_FLAG 42 } 43 44 void CommonFlags::CopyFrom(const CommonFlags &other) { 45 internal_memcpy(this, &other, sizeof(*this)); 46 } 47 48 // Copy the string from "s" to "out", replacing "%b" with the binary basename. 49 static void SubstituteBinaryName(const char *s, char *out, uptr out_size) { 50 char *out_end = out + out_size; 51 while (*s && out < out_end - 1) { 52 if (s[0] != '%' || s[1] != 'b') { *out++ = *s++; continue; } 53 const char *base = GetProcessName(); 54 CHECK(base); 55 while (*base && out < out_end - 1) 56 *out++ = *base++; 57 s += 2; // skip "%b" 58 } 59 *out = '\0'; 60 } 61 62 class FlagHandlerInclude : public FlagHandlerBase { 63 FlagParser *parser_; 64 bool ignore_missing_; 65 66 public: 67 explicit FlagHandlerInclude(FlagParser *parser, bool ignore_missing) 68 : parser_(parser), ignore_missing_(ignore_missing) {} 69 bool Parse(const char *value) final { 70 if (internal_strchr(value, '%')) { 71 char *buf = (char *)MmapOrDie(kMaxPathLength, "FlagHandlerInclude"); 72 SubstituteBinaryName(value, buf, kMaxPathLength); 73 bool res = parser_->ParseFile(buf, ignore_missing_); 74 UnmapOrDie(buf, kMaxPathLength); 75 return res; 76 } 77 return parser_->ParseFile(value, ignore_missing_); 78 } 79 }; 80 81 void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) { 82 FlagHandlerInclude *fh_include = new (FlagParser::Alloc) // NOLINT 83 FlagHandlerInclude(parser, /*ignore_missing*/ false); 84 parser->RegisterHandler("include", fh_include, 85 "read more options from the given file"); 86 FlagHandlerInclude *fh_include_if_exists = new (FlagParser::Alloc) // NOLINT 87 FlagHandlerInclude(parser, /*ignore_missing*/ true); 88 parser->RegisterHandler( 89 "include_if_exists", fh_include_if_exists, 90 "read more options from the given file (if it exists)"); 91 } 92 93 void RegisterCommonFlags(FlagParser *parser, CommonFlags *cf) { 94 #define COMMON_FLAG(Type, Name, DefaultValue, Description) \ 95 RegisterFlag(parser, #Name, Description, &cf->Name); 96 #include "sanitizer_flags.inc" 97 #undef COMMON_FLAG 98 99 RegisterIncludeFlags(parser, cf); 100 } 101 102 } // namespace __sanitizer 103