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