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