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 void CommonFlags::SetDefaults() { 26 #define COMMON_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 27 #include "sanitizer_flags.inc" 28 #undef COMMON_FLAG 29 } 30 31 void CommonFlags::CopyFrom(const CommonFlags &other) { 32 internal_memcpy(this, &other, sizeof(*this)); 33 } 34 35 // Copy the string from "s" to "out", making the following substitutions: 36 // %b = binary basename 37 // %p = pid 38 void SubstituteForFlagValue(const char *s, char *out, uptr out_size) { 39 char *out_end = out + out_size; 40 while (*s && out < out_end - 1) { 41 if (s[0] != '%') { 42 *out++ = *s++; 43 continue; 44 } 45 switch (s[1]) { 46 case 'b': { 47 const char *base = GetProcessName(); 48 CHECK(base); 49 while (*base && out < out_end - 1) 50 *out++ = *base++; 51 s += 2; // skip "%b" 52 break; 53 } 54 case 'p': { 55 int pid = internal_getpid(); 56 char buf[32]; 57 char *buf_pos = buf + 32; 58 do { 59 *--buf_pos = (pid % 10) + '0'; 60 pid /= 10; 61 } while (pid); 62 while (buf_pos < buf + 32 && out < out_end - 1) 63 *out++ = *buf_pos++; 64 s += 2; // skip "%p" 65 break; 66 } 67 default: 68 *out++ = *s++; 69 break; 70 } 71 } 72 CHECK(out < out_end - 1); 73 *out = '\0'; 74 } 75 76 class FlagHandlerInclude : public FlagHandlerBase { 77 FlagParser *parser_; 78 bool ignore_missing_; 79 80 public: 81 explicit FlagHandlerInclude(FlagParser *parser, bool ignore_missing) 82 : parser_(parser), ignore_missing_(ignore_missing) {} 83 bool Parse(const char *value) final { 84 if (internal_strchr(value, '%')) { 85 char *buf = (char *)MmapOrDie(kMaxPathLength, "FlagHandlerInclude"); 86 SubstituteForFlagValue(value, buf, kMaxPathLength); 87 bool res = parser_->ParseFile(buf, ignore_missing_); 88 UnmapOrDie(buf, kMaxPathLength); 89 return res; 90 } 91 return parser_->ParseFile(value, ignore_missing_); 92 } 93 }; 94 95 void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) { 96 FlagHandlerInclude *fh_include = new (FlagParser::Alloc) // NOLINT 97 FlagHandlerInclude(parser, /*ignore_missing*/ false); 98 parser->RegisterHandler("include", fh_include, 99 "read more options from the given file"); 100 FlagHandlerInclude *fh_include_if_exists = new (FlagParser::Alloc) // NOLINT 101 FlagHandlerInclude(parser, /*ignore_missing*/ true); 102 parser->RegisterHandler( 103 "include_if_exists", fh_include_if_exists, 104 "read more options from the given file (if it exists)"); 105 } 106 107 void RegisterCommonFlags(FlagParser *parser, CommonFlags *cf) { 108 #define COMMON_FLAG(Type, Name, DefaultValue, Description) \ 109 RegisterFlag(parser, #Name, Description, &cf->Name); 110 #include "sanitizer_flags.inc" 111 #undef COMMON_FLAG 112 113 RegisterIncludeFlags(parser, cf); 114 } 115 116 void InitializeCommonFlags(CommonFlags *cf) { 117 // need to record coverage to generate coverage report. 118 cf->coverage |= cf->html_cov_report; 119 SetVerbosity(cf->verbosity); 120 } 121 122 } // namespace __sanitizer 123