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