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