1*7c3d14c8STreehugger Robot //===-- sanitizer_flags.cc ------------------------------------------------===//
2*7c3d14c8STreehugger Robot //
3*7c3d14c8STreehugger Robot // The LLVM Compiler Infrastructure
4*7c3d14c8STreehugger Robot //
5*7c3d14c8STreehugger Robot // This file is distributed under the University of Illinois Open Source
6*7c3d14c8STreehugger Robot // License. See LICENSE.TXT for details.
7*7c3d14c8STreehugger Robot //
8*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
9*7c3d14c8STreehugger Robot //
10*7c3d14c8STreehugger Robot // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
11*7c3d14c8STreehugger Robot //
12*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
13*7c3d14c8STreehugger Robot
14*7c3d14c8STreehugger Robot #include "sanitizer_flags.h"
15*7c3d14c8STreehugger Robot
16*7c3d14c8STreehugger Robot #include "sanitizer_common.h"
17*7c3d14c8STreehugger Robot #include "sanitizer_libc.h"
18*7c3d14c8STreehugger Robot #include "sanitizer_list.h"
19*7c3d14c8STreehugger Robot #include "sanitizer_flag_parser.h"
20*7c3d14c8STreehugger Robot
21*7c3d14c8STreehugger Robot namespace __sanitizer {
22*7c3d14c8STreehugger Robot
23*7c3d14c8STreehugger Robot CommonFlags common_flags_dont_use;
24*7c3d14c8STreehugger Robot
25*7c3d14c8STreehugger Robot struct FlagDescription {
26*7c3d14c8STreehugger Robot const char *name;
27*7c3d14c8STreehugger Robot const char *description;
28*7c3d14c8STreehugger Robot FlagDescription *next;
29*7c3d14c8STreehugger Robot };
30*7c3d14c8STreehugger Robot
31*7c3d14c8STreehugger Robot IntrusiveList<FlagDescription> flag_descriptions;
32*7c3d14c8STreehugger Robot
33*7c3d14c8STreehugger Robot // If set, the tool will install its own SEGV signal handler by default.
34*7c3d14c8STreehugger Robot #ifndef SANITIZER_NEEDS_SEGV
35*7c3d14c8STreehugger Robot # define SANITIZER_NEEDS_SEGV 1
36*7c3d14c8STreehugger Robot #endif
37*7c3d14c8STreehugger Robot
SetDefaults()38*7c3d14c8STreehugger Robot void CommonFlags::SetDefaults() {
39*7c3d14c8STreehugger Robot #define COMMON_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
40*7c3d14c8STreehugger Robot #include "sanitizer_flags.inc"
41*7c3d14c8STreehugger Robot #undef COMMON_FLAG
42*7c3d14c8STreehugger Robot }
43*7c3d14c8STreehugger Robot
CopyFrom(const CommonFlags & other)44*7c3d14c8STreehugger Robot void CommonFlags::CopyFrom(const CommonFlags &other) {
45*7c3d14c8STreehugger Robot internal_memcpy(this, &other, sizeof(*this));
46*7c3d14c8STreehugger Robot }
47*7c3d14c8STreehugger Robot
48*7c3d14c8STreehugger Robot // Copy the string from "s" to "out", making the following substitutions:
49*7c3d14c8STreehugger Robot // %b = binary basename
50*7c3d14c8STreehugger Robot // %p = pid
SubstituteForFlagValue(const char * s,char * out,uptr out_size)51*7c3d14c8STreehugger Robot void SubstituteForFlagValue(const char *s, char *out, uptr out_size) {
52*7c3d14c8STreehugger Robot char *out_end = out + out_size;
53*7c3d14c8STreehugger Robot while (*s && out < out_end - 1) {
54*7c3d14c8STreehugger Robot if (s[0] != '%') {
55*7c3d14c8STreehugger Robot *out++ = *s++;
56*7c3d14c8STreehugger Robot continue;
57*7c3d14c8STreehugger Robot }
58*7c3d14c8STreehugger Robot switch (s[1]) {
59*7c3d14c8STreehugger Robot case 'b': {
60*7c3d14c8STreehugger Robot const char *base = GetProcessName();
61*7c3d14c8STreehugger Robot CHECK(base);
62*7c3d14c8STreehugger Robot while (*base && out < out_end - 1)
63*7c3d14c8STreehugger Robot *out++ = *base++;
64*7c3d14c8STreehugger Robot s += 2; // skip "%b"
65*7c3d14c8STreehugger Robot break;
66*7c3d14c8STreehugger Robot }
67*7c3d14c8STreehugger Robot case 'p': {
68*7c3d14c8STreehugger Robot int pid = internal_getpid();
69*7c3d14c8STreehugger Robot char buf[32];
70*7c3d14c8STreehugger Robot char *buf_pos = buf + 32;
71*7c3d14c8STreehugger Robot do {
72*7c3d14c8STreehugger Robot *--buf_pos = (pid % 10) + '0';
73*7c3d14c8STreehugger Robot pid /= 10;
74*7c3d14c8STreehugger Robot } while (pid);
75*7c3d14c8STreehugger Robot while (buf_pos < buf + 32 && out < out_end - 1)
76*7c3d14c8STreehugger Robot *out++ = *buf_pos++;
77*7c3d14c8STreehugger Robot s += 2; // skip "%p"
78*7c3d14c8STreehugger Robot break;
79*7c3d14c8STreehugger Robot }
80*7c3d14c8STreehugger Robot default:
81*7c3d14c8STreehugger Robot *out++ = *s++;
82*7c3d14c8STreehugger Robot break;
83*7c3d14c8STreehugger Robot }
84*7c3d14c8STreehugger Robot }
85*7c3d14c8STreehugger Robot CHECK(out < out_end - 1);
86*7c3d14c8STreehugger Robot *out = '\0';
87*7c3d14c8STreehugger Robot }
88*7c3d14c8STreehugger Robot
89*7c3d14c8STreehugger Robot class FlagHandlerInclude : public FlagHandlerBase {
90*7c3d14c8STreehugger Robot FlagParser *parser_;
91*7c3d14c8STreehugger Robot bool ignore_missing_;
92*7c3d14c8STreehugger Robot
93*7c3d14c8STreehugger Robot public:
FlagHandlerInclude(FlagParser * parser,bool ignore_missing)94*7c3d14c8STreehugger Robot explicit FlagHandlerInclude(FlagParser *parser, bool ignore_missing)
95*7c3d14c8STreehugger Robot : parser_(parser), ignore_missing_(ignore_missing) {}
Parse(const char * value)96*7c3d14c8STreehugger Robot bool Parse(const char *value) final {
97*7c3d14c8STreehugger Robot if (internal_strchr(value, '%')) {
98*7c3d14c8STreehugger Robot char *buf = (char *)MmapOrDie(kMaxPathLength, "FlagHandlerInclude");
99*7c3d14c8STreehugger Robot SubstituteForFlagValue(value, buf, kMaxPathLength);
100*7c3d14c8STreehugger Robot bool res = parser_->ParseFile(buf, ignore_missing_);
101*7c3d14c8STreehugger Robot UnmapOrDie(buf, kMaxPathLength);
102*7c3d14c8STreehugger Robot return res;
103*7c3d14c8STreehugger Robot }
104*7c3d14c8STreehugger Robot return parser_->ParseFile(value, ignore_missing_);
105*7c3d14c8STreehugger Robot }
106*7c3d14c8STreehugger Robot };
107*7c3d14c8STreehugger Robot
RegisterIncludeFlags(FlagParser * parser,CommonFlags * cf)108*7c3d14c8STreehugger Robot void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) {
109*7c3d14c8STreehugger Robot FlagHandlerInclude *fh_include = new (FlagParser::Alloc) // NOLINT
110*7c3d14c8STreehugger Robot FlagHandlerInclude(parser, /*ignore_missing*/ false);
111*7c3d14c8STreehugger Robot parser->RegisterHandler("include", fh_include,
112*7c3d14c8STreehugger Robot "read more options from the given file");
113*7c3d14c8STreehugger Robot FlagHandlerInclude *fh_include_if_exists = new (FlagParser::Alloc) // NOLINT
114*7c3d14c8STreehugger Robot FlagHandlerInclude(parser, /*ignore_missing*/ true);
115*7c3d14c8STreehugger Robot parser->RegisterHandler(
116*7c3d14c8STreehugger Robot "include_if_exists", fh_include_if_exists,
117*7c3d14c8STreehugger Robot "read more options from the given file (if it exists)");
118*7c3d14c8STreehugger Robot }
119*7c3d14c8STreehugger Robot
RegisterCommonFlags(FlagParser * parser,CommonFlags * cf)120*7c3d14c8STreehugger Robot void RegisterCommonFlags(FlagParser *parser, CommonFlags *cf) {
121*7c3d14c8STreehugger Robot #define COMMON_FLAG(Type, Name, DefaultValue, Description) \
122*7c3d14c8STreehugger Robot RegisterFlag(parser, #Name, Description, &cf->Name);
123*7c3d14c8STreehugger Robot #include "sanitizer_flags.inc"
124*7c3d14c8STreehugger Robot #undef COMMON_FLAG
125*7c3d14c8STreehugger Robot
126*7c3d14c8STreehugger Robot RegisterIncludeFlags(parser, cf);
127*7c3d14c8STreehugger Robot }
128*7c3d14c8STreehugger Robot
InitializeCommonFlags(CommonFlags * cf)129*7c3d14c8STreehugger Robot void InitializeCommonFlags(CommonFlags *cf) {
130*7c3d14c8STreehugger Robot // need to record coverage to generate coverage report.
131*7c3d14c8STreehugger Robot cf->coverage |= cf->html_cov_report;
132*7c3d14c8STreehugger Robot SetVerbosity(cf->verbosity);
133*7c3d14c8STreehugger Robot }
134*7c3d14c8STreehugger Robot
135*7c3d14c8STreehugger Robot } // namespace __sanitizer
136