xref: /llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_flags.cpp (revision afd170bdd983006b281e7b3d5a2d4571d3e36352)
165492d95SNico Weber //===-- sanitizer_flags.cpp -----------------------------------------------===//
265492d95SNico Weber //
365492d95SNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
465492d95SNico Weber // See https://llvm.org/LICENSE.txt for license information.
565492d95SNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
665492d95SNico Weber //
765492d95SNico Weber //===----------------------------------------------------------------------===//
865492d95SNico Weber //
965492d95SNico Weber // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
1065492d95SNico Weber //
1165492d95SNico Weber //===----------------------------------------------------------------------===//
1265492d95SNico Weber 
1365492d95SNico Weber #include "sanitizer_flags.h"
1465492d95SNico Weber 
1565492d95SNico Weber #include "sanitizer_common.h"
1665492d95SNico Weber #include "sanitizer_flag_parser.h"
17484ec6beSVy Nguyen #include "sanitizer_libc.h"
18484ec6beSVy Nguyen #include "sanitizer_linux.h"
19484ec6beSVy Nguyen #include "sanitizer_list.h"
2065492d95SNico Weber 
2165492d95SNico Weber namespace __sanitizer {
2265492d95SNico Weber 
2365492d95SNico Weber CommonFlags common_flags_dont_use;
2465492d95SNico Weber 
SetDefaults()2565492d95SNico Weber void CommonFlags::SetDefaults() {
2665492d95SNico Weber #define COMMON_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
2765492d95SNico Weber #include "sanitizer_flags.inc"
2865492d95SNico Weber #undef COMMON_FLAG
2965492d95SNico Weber }
3065492d95SNico Weber 
CopyFrom(const CommonFlags & other)3165492d95SNico Weber void CommonFlags::CopyFrom(const CommonFlags &other) {
3265492d95SNico Weber   internal_memcpy(this, &other, sizeof(*this));
3365492d95SNico Weber }
3465492d95SNico Weber 
3565492d95SNico Weber // Copy the string from "s" to "out", making the following substitutions:
3665492d95SNico Weber // %b = binary basename
3765492d95SNico Weber // %p = pid
389ba623c6SAmy Huang // %d = binary directory
SubstituteForFlagValue(const char * s,char * out,uptr out_size)3965492d95SNico Weber void SubstituteForFlagValue(const char *s, char *out, uptr out_size) {
4065492d95SNico Weber   char *out_end = out + out_size;
4165492d95SNico Weber   while (*s && out < out_end - 1) {
4265492d95SNico Weber     if (s[0] != '%') {
4365492d95SNico Weber       *out++ = *s++;
4465492d95SNico Weber       continue;
4565492d95SNico Weber     }
4665492d95SNico Weber     switch (s[1]) {
4765492d95SNico Weber       case 'b': {
4865492d95SNico Weber         const char *base = GetProcessName();
4965492d95SNico Weber         CHECK(base);
5065492d95SNico Weber         while (*base && out < out_end - 1)
5165492d95SNico Weber           *out++ = *base++;
5265492d95SNico Weber         s += 2; // skip "%b"
5365492d95SNico Weber         break;
5465492d95SNico Weber       }
5565492d95SNico Weber       case 'p': {
5665492d95SNico Weber         int pid = internal_getpid();
5765492d95SNico Weber         char buf[32];
5865492d95SNico Weber         char *buf_pos = buf + 32;
5965492d95SNico Weber         do {
6065492d95SNico Weber           *--buf_pos = (pid % 10) + '0';
6165492d95SNico Weber           pid /= 10;
6265492d95SNico Weber         } while (pid);
6365492d95SNico Weber         while (buf_pos < buf + 32 && out < out_end - 1)
6465492d95SNico Weber           *out++ = *buf_pos++;
6565492d95SNico Weber         s += 2; // skip "%p"
6665492d95SNico Weber         break;
6765492d95SNico Weber       }
689ba623c6SAmy Huang       case 'd': {
699ba623c6SAmy Huang         uptr len = ReadBinaryDir(out, out_end - out);
709ba623c6SAmy Huang         out += len;
719ba623c6SAmy Huang         s += 2;  // skip "%d"
729ba623c6SAmy Huang         break;
739ba623c6SAmy Huang       }
7465492d95SNico Weber       default:
7565492d95SNico Weber         *out++ = *s++;
7665492d95SNico Weber         break;
7765492d95SNico Weber     }
7865492d95SNico Weber   }
7965492d95SNico Weber   CHECK(out < out_end - 1);
8065492d95SNico Weber   *out = '\0';
8165492d95SNico Weber }
8265492d95SNico Weber 
83d48f2d7cSVitaly Buka class FlagHandlerInclude final : public FlagHandlerBase {
8465492d95SNico Weber   FlagParser *parser_;
8565492d95SNico Weber   bool ignore_missing_;
864c39f341SDan Liew   const char *original_path_;
8765492d95SNico Weber 
8865492d95SNico Weber  public:
FlagHandlerInclude(FlagParser * parser,bool ignore_missing)8965492d95SNico Weber   explicit FlagHandlerInclude(FlagParser *parser, bool ignore_missing)
904c39f341SDan Liew       : parser_(parser), ignore_missing_(ignore_missing), original_path_("") {}
Parse(const char * value)9165492d95SNico Weber   bool Parse(const char *value) final {
924c39f341SDan Liew     original_path_ = value;
9365492d95SNico Weber     if (internal_strchr(value, '%')) {
9465492d95SNico Weber       char *buf = (char *)MmapOrDie(kMaxPathLength, "FlagHandlerInclude");
9565492d95SNico Weber       SubstituteForFlagValue(value, buf, kMaxPathLength);
9665492d95SNico Weber       bool res = parser_->ParseFile(buf, ignore_missing_);
9765492d95SNico Weber       UnmapOrDie(buf, kMaxPathLength);
9865492d95SNico Weber       return res;
9965492d95SNico Weber     }
10065492d95SNico Weber     return parser_->ParseFile(value, ignore_missing_);
10165492d95SNico Weber   }
Format(char * buffer,uptr size)102947bf0fdSLogan Smith   bool Format(char *buffer, uptr size) override {
1034c39f341SDan Liew     // Note `original_path_` isn't actually what's parsed due to `%`
1044c39f341SDan Liew     // substitutions. Printing the substituted path would require holding onto
1054c39f341SDan Liew     // mmap'ed memory.
1064c39f341SDan Liew     return FormatString(buffer, size, original_path_);
1074c39f341SDan Liew   }
10865492d95SNico Weber };
10965492d95SNico Weber 
RegisterIncludeFlags(FlagParser * parser,CommonFlags * cf)11065492d95SNico Weber void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) {
111*afd170bdSLeonard Chan   FlagHandlerInclude *fh_include = new (GetGlobalLowLevelAllocator())
11265492d95SNico Weber       FlagHandlerInclude(parser, /*ignore_missing*/ false);
11365492d95SNico Weber   parser->RegisterHandler("include", fh_include,
11465492d95SNico Weber                           "read more options from the given file");
115*afd170bdSLeonard Chan   FlagHandlerInclude *fh_include_if_exists = new (GetGlobalLowLevelAllocator())
11665492d95SNico Weber       FlagHandlerInclude(parser, /*ignore_missing*/ true);
11765492d95SNico Weber   parser->RegisterHandler(
11865492d95SNico Weber       "include_if_exists", fh_include_if_exists,
11965492d95SNico Weber       "read more options from the given file (if it exists)");
12065492d95SNico Weber }
12165492d95SNico Weber 
RegisterCommonFlags(FlagParser * parser,CommonFlags * cf)12265492d95SNico Weber void RegisterCommonFlags(FlagParser *parser, CommonFlags *cf) {
12365492d95SNico Weber #define COMMON_FLAG(Type, Name, DefaultValue, Description) \
12465492d95SNico Weber   RegisterFlag(parser, #Name, Description, &cf->Name);
12565492d95SNico Weber #include "sanitizer_flags.inc"
12665492d95SNico Weber #undef COMMON_FLAG
12765492d95SNico Weber 
12865492d95SNico Weber   RegisterIncludeFlags(parser, cf);
12965492d95SNico Weber }
13065492d95SNico Weber 
InitializeCommonFlags(CommonFlags * cf)13165492d95SNico Weber void InitializeCommonFlags(CommonFlags *cf) {
13265492d95SNico Weber   // need to record coverage to generate coverage report.
13365492d95SNico Weber   cf->coverage |= cf->html_cov_report;
13465492d95SNico Weber   SetVerbosity(cf->verbosity);
135484ec6beSVy Nguyen 
1366c164d60SVitaly Buka   InitializePlatformCommonFlags(cf);
13765492d95SNico Weber }
13865492d95SNico Weber 
13965492d95SNico Weber }  // namespace __sanitizer
140