sanitizer_flags.cpp revision 360784
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 20namespace __sanitizer { 21 22CommonFlags common_flags_dont_use; 23 24void CommonFlags::SetDefaults() { 25#define COMMON_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 26#include "sanitizer_flags.inc" 27#undef COMMON_FLAG 28} 29 30void 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 37void 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 75class FlagHandlerInclude : public FlagHandlerBase { 76 FlagParser *parser_; 77 bool ignore_missing_; 78 const char *original_path_; 79 80 public: 81 explicit FlagHandlerInclude(FlagParser *parser, bool ignore_missing) 82 : parser_(parser), ignore_missing_(ignore_missing), original_path_("") {} 83 bool Parse(const char *value) final { 84 original_path_ = value; 85 if (internal_strchr(value, '%')) { 86 char *buf = (char *)MmapOrDie(kMaxPathLength, "FlagHandlerInclude"); 87 SubstituteForFlagValue(value, buf, kMaxPathLength); 88 bool res = parser_->ParseFile(buf, ignore_missing_); 89 UnmapOrDie(buf, kMaxPathLength); 90 return res; 91 } 92 return parser_->ParseFile(value, ignore_missing_); 93 } 94 bool Format(char *buffer, uptr size) { 95 // Note `original_path_` isn't actually what's parsed due to `%` 96 // substitutions. Printing the substituted path would require holding onto 97 // mmap'ed memory. 98 return FormatString(buffer, size, original_path_); 99 } 100}; 101 102void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) { 103 FlagHandlerInclude *fh_include = new (FlagParser::Alloc) 104 FlagHandlerInclude(parser, /*ignore_missing*/ false); 105 parser->RegisterHandler("include", fh_include, 106 "read more options from the given file"); 107 FlagHandlerInclude *fh_include_if_exists = new (FlagParser::Alloc) 108 FlagHandlerInclude(parser, /*ignore_missing*/ true); 109 parser->RegisterHandler( 110 "include_if_exists", fh_include_if_exists, 111 "read more options from the given file (if it exists)"); 112} 113 114void RegisterCommonFlags(FlagParser *parser, CommonFlags *cf) { 115#define COMMON_FLAG(Type, Name, DefaultValue, Description) \ 116 RegisterFlag(parser, #Name, Description, &cf->Name); 117#include "sanitizer_flags.inc" 118#undef COMMON_FLAG 119 120 RegisterIncludeFlags(parser, cf); 121} 122 123void InitializeCommonFlags(CommonFlags *cf) { 124 // need to record coverage to generate coverage report. 125 cf->coverage |= cf->html_cov_report; 126 SetVerbosity(cf->verbosity); 127} 128 129} // namespace __sanitizer 130