168d75effSDimitry Andric //===-- sanitizer_flags.cpp -----------------------------------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is a part of ThreadSanitizer/AddressSanitizer runtime. 1068d75effSDimitry Andric // 1168d75effSDimitry Andric //===----------------------------------------------------------------------===// 1268d75effSDimitry Andric 1368d75effSDimitry Andric #include "sanitizer_flags.h" 1468d75effSDimitry Andric 1568d75effSDimitry Andric #include "sanitizer_common.h" 1668d75effSDimitry Andric #include "sanitizer_libc.h" 1768d75effSDimitry Andric #include "sanitizer_list.h" 1868d75effSDimitry Andric #include "sanitizer_flag_parser.h" 1968d75effSDimitry Andric 2068d75effSDimitry Andric namespace __sanitizer { 2168d75effSDimitry Andric 2268d75effSDimitry Andric CommonFlags common_flags_dont_use; 2368d75effSDimitry Andric 2468d75effSDimitry Andric void CommonFlags::SetDefaults() { 2568d75effSDimitry Andric #define COMMON_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 2668d75effSDimitry Andric #include "sanitizer_flags.inc" 2768d75effSDimitry Andric #undef COMMON_FLAG 2868d75effSDimitry Andric } 2968d75effSDimitry Andric 3068d75effSDimitry Andric void CommonFlags::CopyFrom(const CommonFlags &other) { 3168d75effSDimitry Andric internal_memcpy(this, &other, sizeof(*this)); 3268d75effSDimitry Andric } 3368d75effSDimitry Andric 3468d75effSDimitry Andric // Copy the string from "s" to "out", making the following substitutions: 3568d75effSDimitry Andric // %b = binary basename 3668d75effSDimitry Andric // %p = pid 3768d75effSDimitry Andric void SubstituteForFlagValue(const char *s, char *out, uptr out_size) { 3868d75effSDimitry Andric char *out_end = out + out_size; 3968d75effSDimitry Andric while (*s && out < out_end - 1) { 4068d75effSDimitry Andric if (s[0] != '%') { 4168d75effSDimitry Andric *out++ = *s++; 4268d75effSDimitry Andric continue; 4368d75effSDimitry Andric } 4468d75effSDimitry Andric switch (s[1]) { 4568d75effSDimitry Andric case 'b': { 4668d75effSDimitry Andric const char *base = GetProcessName(); 4768d75effSDimitry Andric CHECK(base); 4868d75effSDimitry Andric while (*base && out < out_end - 1) 4968d75effSDimitry Andric *out++ = *base++; 5068d75effSDimitry Andric s += 2; // skip "%b" 5168d75effSDimitry Andric break; 5268d75effSDimitry Andric } 5368d75effSDimitry Andric case 'p': { 5468d75effSDimitry Andric int pid = internal_getpid(); 5568d75effSDimitry Andric char buf[32]; 5668d75effSDimitry Andric char *buf_pos = buf + 32; 5768d75effSDimitry Andric do { 5868d75effSDimitry Andric *--buf_pos = (pid % 10) + '0'; 5968d75effSDimitry Andric pid /= 10; 6068d75effSDimitry Andric } while (pid); 6168d75effSDimitry Andric while (buf_pos < buf + 32 && out < out_end - 1) 6268d75effSDimitry Andric *out++ = *buf_pos++; 6368d75effSDimitry Andric s += 2; // skip "%p" 6468d75effSDimitry Andric break; 6568d75effSDimitry Andric } 6668d75effSDimitry Andric default: 6768d75effSDimitry Andric *out++ = *s++; 6868d75effSDimitry Andric break; 6968d75effSDimitry Andric } 7068d75effSDimitry Andric } 7168d75effSDimitry Andric CHECK(out < out_end - 1); 7268d75effSDimitry Andric *out = '\0'; 7368d75effSDimitry Andric } 7468d75effSDimitry Andric 7568d75effSDimitry Andric class FlagHandlerInclude : public FlagHandlerBase { 7668d75effSDimitry Andric FlagParser *parser_; 7768d75effSDimitry Andric bool ignore_missing_; 78*480093f4SDimitry Andric const char *original_path_; 7968d75effSDimitry Andric 8068d75effSDimitry Andric public: 8168d75effSDimitry Andric explicit FlagHandlerInclude(FlagParser *parser, bool ignore_missing) 82*480093f4SDimitry Andric : parser_(parser), ignore_missing_(ignore_missing), original_path_("") {} 8368d75effSDimitry Andric bool Parse(const char *value) final { 84*480093f4SDimitry Andric original_path_ = value; 8568d75effSDimitry Andric if (internal_strchr(value, '%')) { 8668d75effSDimitry Andric char *buf = (char *)MmapOrDie(kMaxPathLength, "FlagHandlerInclude"); 8768d75effSDimitry Andric SubstituteForFlagValue(value, buf, kMaxPathLength); 8868d75effSDimitry Andric bool res = parser_->ParseFile(buf, ignore_missing_); 8968d75effSDimitry Andric UnmapOrDie(buf, kMaxPathLength); 9068d75effSDimitry Andric return res; 9168d75effSDimitry Andric } 9268d75effSDimitry Andric return parser_->ParseFile(value, ignore_missing_); 9368d75effSDimitry Andric } 94*480093f4SDimitry Andric bool Format(char *buffer, uptr size) { 95*480093f4SDimitry Andric // Note `original_path_` isn't actually what's parsed due to `%` 96*480093f4SDimitry Andric // substitutions. Printing the substituted path would require holding onto 97*480093f4SDimitry Andric // mmap'ed memory. 98*480093f4SDimitry Andric return FormatString(buffer, size, original_path_); 99*480093f4SDimitry Andric } 10068d75effSDimitry Andric }; 10168d75effSDimitry Andric 10268d75effSDimitry Andric void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) { 10368d75effSDimitry Andric FlagHandlerInclude *fh_include = new (FlagParser::Alloc) 10468d75effSDimitry Andric FlagHandlerInclude(parser, /*ignore_missing*/ false); 10568d75effSDimitry Andric parser->RegisterHandler("include", fh_include, 10668d75effSDimitry Andric "read more options from the given file"); 10768d75effSDimitry Andric FlagHandlerInclude *fh_include_if_exists = new (FlagParser::Alloc) 10868d75effSDimitry Andric FlagHandlerInclude(parser, /*ignore_missing*/ true); 10968d75effSDimitry Andric parser->RegisterHandler( 11068d75effSDimitry Andric "include_if_exists", fh_include_if_exists, 11168d75effSDimitry Andric "read more options from the given file (if it exists)"); 11268d75effSDimitry Andric } 11368d75effSDimitry Andric 11468d75effSDimitry Andric void RegisterCommonFlags(FlagParser *parser, CommonFlags *cf) { 11568d75effSDimitry Andric #define COMMON_FLAG(Type, Name, DefaultValue, Description) \ 11668d75effSDimitry Andric RegisterFlag(parser, #Name, Description, &cf->Name); 11768d75effSDimitry Andric #include "sanitizer_flags.inc" 11868d75effSDimitry Andric #undef COMMON_FLAG 11968d75effSDimitry Andric 12068d75effSDimitry Andric RegisterIncludeFlags(parser, cf); 12168d75effSDimitry Andric } 12268d75effSDimitry Andric 12368d75effSDimitry Andric void InitializeCommonFlags(CommonFlags *cf) { 12468d75effSDimitry Andric // need to record coverage to generate coverage report. 12568d75effSDimitry Andric cf->coverage |= cf->html_cov_report; 12668d75effSDimitry Andric SetVerbosity(cf->verbosity); 12768d75effSDimitry Andric } 12868d75effSDimitry Andric 12968d75effSDimitry Andric } // namespace __sanitizer 130