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