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_flag_parser.h" 17*e8d8bef9SDimitry Andric #include "sanitizer_libc.h" 18*e8d8bef9SDimitry Andric #include "sanitizer_linux.h" 19*e8d8bef9SDimitry Andric #include "sanitizer_list.h" 2068d75effSDimitry Andric 2168d75effSDimitry Andric namespace __sanitizer { 2268d75effSDimitry Andric 2368d75effSDimitry Andric CommonFlags common_flags_dont_use; 2468d75effSDimitry Andric 2568d75effSDimitry Andric void CommonFlags::SetDefaults() { 2668d75effSDimitry Andric #define COMMON_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 2768d75effSDimitry Andric #include "sanitizer_flags.inc" 2868d75effSDimitry Andric #undef COMMON_FLAG 2968d75effSDimitry Andric } 3068d75effSDimitry Andric 3168d75effSDimitry Andric void CommonFlags::CopyFrom(const CommonFlags &other) { 3268d75effSDimitry Andric internal_memcpy(this, &other, sizeof(*this)); 3368d75effSDimitry Andric } 3468d75effSDimitry Andric 3568d75effSDimitry Andric // Copy the string from "s" to "out", making the following substitutions: 3668d75effSDimitry Andric // %b = binary basename 3768d75effSDimitry Andric // %p = pid 3868d75effSDimitry Andric void SubstituteForFlagValue(const char *s, char *out, uptr out_size) { 3968d75effSDimitry Andric char *out_end = out + out_size; 4068d75effSDimitry Andric while (*s && out < out_end - 1) { 4168d75effSDimitry Andric if (s[0] != '%') { 4268d75effSDimitry Andric *out++ = *s++; 4368d75effSDimitry Andric continue; 4468d75effSDimitry Andric } 4568d75effSDimitry Andric switch (s[1]) { 4668d75effSDimitry Andric case 'b': { 4768d75effSDimitry Andric const char *base = GetProcessName(); 4868d75effSDimitry Andric CHECK(base); 4968d75effSDimitry Andric while (*base && out < out_end - 1) 5068d75effSDimitry Andric *out++ = *base++; 5168d75effSDimitry Andric s += 2; // skip "%b" 5268d75effSDimitry Andric break; 5368d75effSDimitry Andric } 5468d75effSDimitry Andric case 'p': { 5568d75effSDimitry Andric int pid = internal_getpid(); 5668d75effSDimitry Andric char buf[32]; 5768d75effSDimitry Andric char *buf_pos = buf + 32; 5868d75effSDimitry Andric do { 5968d75effSDimitry Andric *--buf_pos = (pid % 10) + '0'; 6068d75effSDimitry Andric pid /= 10; 6168d75effSDimitry Andric } while (pid); 6268d75effSDimitry Andric while (buf_pos < buf + 32 && out < out_end - 1) 6368d75effSDimitry Andric *out++ = *buf_pos++; 6468d75effSDimitry Andric s += 2; // skip "%p" 6568d75effSDimitry Andric break; 6668d75effSDimitry Andric } 6768d75effSDimitry Andric default: 6868d75effSDimitry Andric *out++ = *s++; 6968d75effSDimitry Andric break; 7068d75effSDimitry Andric } 7168d75effSDimitry Andric } 7268d75effSDimitry Andric CHECK(out < out_end - 1); 7368d75effSDimitry Andric *out = '\0'; 7468d75effSDimitry Andric } 7568d75effSDimitry Andric 76*e8d8bef9SDimitry Andric class FlagHandlerInclude final : public FlagHandlerBase { 7768d75effSDimitry Andric FlagParser *parser_; 7868d75effSDimitry Andric bool ignore_missing_; 79480093f4SDimitry Andric const char *original_path_; 8068d75effSDimitry Andric 8168d75effSDimitry Andric public: 8268d75effSDimitry Andric explicit FlagHandlerInclude(FlagParser *parser, bool ignore_missing) 83480093f4SDimitry Andric : parser_(parser), ignore_missing_(ignore_missing), original_path_("") {} 8468d75effSDimitry Andric bool Parse(const char *value) final { 85480093f4SDimitry Andric original_path_ = value; 8668d75effSDimitry Andric if (internal_strchr(value, '%')) { 8768d75effSDimitry Andric char *buf = (char *)MmapOrDie(kMaxPathLength, "FlagHandlerInclude"); 8868d75effSDimitry Andric SubstituteForFlagValue(value, buf, kMaxPathLength); 8968d75effSDimitry Andric bool res = parser_->ParseFile(buf, ignore_missing_); 9068d75effSDimitry Andric UnmapOrDie(buf, kMaxPathLength); 9168d75effSDimitry Andric return res; 9268d75effSDimitry Andric } 9368d75effSDimitry Andric return parser_->ParseFile(value, ignore_missing_); 9468d75effSDimitry Andric } 95*e8d8bef9SDimitry Andric bool Format(char *buffer, uptr size) override { 96480093f4SDimitry Andric // Note `original_path_` isn't actually what's parsed due to `%` 97480093f4SDimitry Andric // substitutions. Printing the substituted path would require holding onto 98480093f4SDimitry Andric // mmap'ed memory. 99480093f4SDimitry Andric return FormatString(buffer, size, original_path_); 100480093f4SDimitry Andric } 10168d75effSDimitry Andric }; 10268d75effSDimitry Andric 10368d75effSDimitry Andric void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) { 10468d75effSDimitry Andric FlagHandlerInclude *fh_include = new (FlagParser::Alloc) 10568d75effSDimitry Andric FlagHandlerInclude(parser, /*ignore_missing*/ false); 10668d75effSDimitry Andric parser->RegisterHandler("include", fh_include, 10768d75effSDimitry Andric "read more options from the given file"); 10868d75effSDimitry Andric FlagHandlerInclude *fh_include_if_exists = new (FlagParser::Alloc) 10968d75effSDimitry Andric FlagHandlerInclude(parser, /*ignore_missing*/ true); 11068d75effSDimitry Andric parser->RegisterHandler( 11168d75effSDimitry Andric "include_if_exists", fh_include_if_exists, 11268d75effSDimitry Andric "read more options from the given file (if it exists)"); 11368d75effSDimitry Andric } 11468d75effSDimitry Andric 11568d75effSDimitry Andric void RegisterCommonFlags(FlagParser *parser, CommonFlags *cf) { 11668d75effSDimitry Andric #define COMMON_FLAG(Type, Name, DefaultValue, Description) \ 11768d75effSDimitry Andric RegisterFlag(parser, #Name, Description, &cf->Name); 11868d75effSDimitry Andric #include "sanitizer_flags.inc" 11968d75effSDimitry Andric #undef COMMON_FLAG 12068d75effSDimitry Andric 12168d75effSDimitry Andric RegisterIncludeFlags(parser, cf); 12268d75effSDimitry Andric } 12368d75effSDimitry Andric 12468d75effSDimitry Andric void InitializeCommonFlags(CommonFlags *cf) { 12568d75effSDimitry Andric // need to record coverage to generate coverage report. 12668d75effSDimitry Andric cf->coverage |= cf->html_cov_report; 12768d75effSDimitry Andric SetVerbosity(cf->verbosity); 128*e8d8bef9SDimitry Andric 129*e8d8bef9SDimitry Andric InitializePlatformCommonFlags(cf); 13068d75effSDimitry Andric } 13168d75effSDimitry Andric 13268d75effSDimitry Andric } // namespace __sanitizer 133