llvm-project
139 строк · 4.2 Кб
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-exception
6//
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) {32internal_memcpy(this, &other, sizeof(*this));33}
34
35// Copy the string from "s" to "out", making the following substitutions:
36// %b = binary basename
37// %p = pid
38// %d = binary directory
39void SubstituteForFlagValue(const char *s, char *out, uptr out_size) {40char *out_end = out + out_size;41while (*s && out < out_end - 1) {42if (s[0] != '%') {43*out++ = *s++;44continue;45}46switch (s[1]) {47case 'b': {48const char *base = GetProcessName();49CHECK(base);50while (*base && out < out_end - 1)51*out++ = *base++;52s += 2; // skip "%b"53break;54}55case 'p': {56int pid = internal_getpid();57char buf[32];58char *buf_pos = buf + 32;59do {60*--buf_pos = (pid % 10) + '0';61pid /= 10;62} while (pid);63while (buf_pos < buf + 32 && out < out_end - 1)64*out++ = *buf_pos++;65s += 2; // skip "%p"66break;67}68case 'd': {69uptr len = ReadBinaryDir(out, out_end - out);70out += len;71s += 2; // skip "%d"72break;73}74default:75*out++ = *s++;76break;77}78}79CHECK(out < out_end - 1);80*out = '\0';81}
82
83class FlagHandlerInclude final : public FlagHandlerBase {84FlagParser *parser_;85bool ignore_missing_;86const char *original_path_;87
88public:89explicit FlagHandlerInclude(FlagParser *parser, bool ignore_missing)90: parser_(parser), ignore_missing_(ignore_missing), original_path_("") {}91bool Parse(const char *value) final {92original_path_ = value;93if (internal_strchr(value, '%')) {94char *buf = (char *)MmapOrDie(kMaxPathLength, "FlagHandlerInclude");95SubstituteForFlagValue(value, buf, kMaxPathLength);96bool res = parser_->ParseFile(buf, ignore_missing_);97UnmapOrDie(buf, kMaxPathLength);98return res;99}100return parser_->ParseFile(value, ignore_missing_);101}102bool 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.106return FormatString(buffer, size, original_path_);107}108};109
110void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) {111FlagHandlerInclude *fh_include = new (GetGlobalLowLevelAllocator())112FlagHandlerInclude(parser, /*ignore_missing*/ false);113parser->RegisterHandler("include", fh_include,114"read more options from the given file");115FlagHandlerInclude *fh_include_if_exists = new (GetGlobalLowLevelAllocator())116FlagHandlerInclude(parser, /*ignore_missing*/ true);117parser->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) \124RegisterFlag(parser, #Name, Description, &cf->Name);125#include "sanitizer_flags.inc"126#undef COMMON_FLAG127
128RegisterIncludeFlags(parser, cf);129}
130
131void InitializeCommonFlags(CommonFlags *cf) {132// need to record coverage to generate coverage report.133cf->coverage |= cf->html_cov_report;134SetVerbosity(cf->verbosity);135
136InitializePlatformCommonFlags(cf);137}
138
139} // namespace __sanitizer140