1 //===-- sanitizer_flag_parser.h ---------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
11 //===----------------------------------------------------------------------===//
13 #ifndef SANITIZER_FLAG_REGISTRY_H
14 #define SANITIZER_FLAG_REGISTRY_H
16 #include "sanitizer_internal_defs.h"
17 #include "sanitizer_libc.h"
18 #include "sanitizer_common.h"
20 namespace __sanitizer
{
22 class FlagHandlerBase
{
24 virtual bool Parse(const char *value
) { return false; }
25 // Write the C string representation of the current value (truncated to fit)
26 // into the buffer of size `size`. Returns false if truncation occurred and
27 // returns true otherwise.
28 virtual bool Format(char *buffer
, uptr size
) {
37 inline bool FormatString(char *buffer
, uptr size
, const char *str_to_use
) {
38 uptr num_symbols_should_write
=
39 internal_snprintf(buffer
, size
, "%s", str_to_use
);
40 return num_symbols_should_write
< size
;
45 class FlagHandler final
: public FlagHandlerBase
{
49 explicit FlagHandler(T
*t
) : t_(t
) {}
50 bool Parse(const char *value
) final
;
51 bool Format(char *buffer
, uptr size
) final
;
54 inline bool ParseBool(const char *value
, bool *b
) {
55 if (internal_strcmp(value
, "0") == 0 ||
56 internal_strcmp(value
, "no") == 0 ||
57 internal_strcmp(value
, "false") == 0) {
61 if (internal_strcmp(value
, "1") == 0 ||
62 internal_strcmp(value
, "yes") == 0 ||
63 internal_strcmp(value
, "true") == 0) {
71 inline bool FlagHandler
<bool>::Parse(const char *value
) {
72 if (ParseBool(value
, t_
)) return true;
73 Printf("ERROR: Invalid value for bool option: '%s'\n", value
);
78 inline bool FlagHandler
<bool>::Format(char *buffer
, uptr size
) {
79 return FormatString(buffer
, size
, *t_
? "true" : "false");
83 inline bool FlagHandler
<HandleSignalMode
>::Parse(const char *value
) {
85 if (ParseBool(value
, &b
)) {
86 *t_
= b
? kHandleSignalYes
: kHandleSignalNo
;
89 if (internal_strcmp(value
, "2") == 0 ||
90 internal_strcmp(value
, "exclusive") == 0) {
91 *t_
= kHandleSignalExclusive
;
94 Printf("ERROR: Invalid value for signal handler option: '%s'\n", value
);
99 inline bool FlagHandler
<HandleSignalMode
>::Format(char *buffer
, uptr size
) {
100 uptr num_symbols_should_write
= internal_snprintf(buffer
, size
, "%d", *t_
);
101 return num_symbols_should_write
< size
;
105 inline bool FlagHandler
<const char *>::Parse(const char *value
) {
111 inline bool FlagHandler
<const char *>::Format(char *buffer
, uptr size
) {
112 return FormatString(buffer
, size
, *t_
);
116 inline bool FlagHandler
<int>::Parse(const char *value
) {
117 const char *value_end
;
118 *t_
= internal_simple_strtoll(value
, &value_end
, 10);
119 bool ok
= *value_end
== 0;
120 if (!ok
) Printf("ERROR: Invalid value for int option: '%s'\n", value
);
125 inline bool FlagHandler
<int>::Format(char *buffer
, uptr size
) {
126 uptr num_symbols_should_write
= internal_snprintf(buffer
, size
, "%d", *t_
);
127 return num_symbols_should_write
< size
;
131 inline bool FlagHandler
<uptr
>::Parse(const char *value
) {
132 const char *value_end
;
133 *t_
= internal_simple_strtoll(value
, &value_end
, 10);
134 bool ok
= *value_end
== 0;
135 if (!ok
) Printf("ERROR: Invalid value for uptr option: '%s'\n", value
);
140 inline bool FlagHandler
<uptr
>::Format(char *buffer
, uptr size
) {
141 uptr num_symbols_should_write
= internal_snprintf(buffer
, size
, "0x%zx", *t_
);
142 return num_symbols_should_write
< size
;
146 inline bool FlagHandler
<s64
>::Parse(const char *value
) {
147 const char *value_end
;
148 *t_
= internal_simple_strtoll(value
, &value_end
, 10);
149 bool ok
= *value_end
== 0;
150 if (!ok
) Printf("ERROR: Invalid value for s64 option: '%s'\n", value
);
155 inline bool FlagHandler
<s64
>::Format(char *buffer
, uptr size
) {
156 uptr num_symbols_should_write
= internal_snprintf(buffer
, size
, "%lld", *t_
);
157 return num_symbols_should_write
< size
;
161 static const int kMaxFlags
= 200;
165 FlagHandlerBase
*handler
;
174 void RegisterHandler(const char *name
, FlagHandlerBase
*handler
,
176 void ParseString(const char *s
, const char *env_name
= 0);
177 void ParseStringFromEnv(const char *env_name
);
178 bool ParseFile(const char *path
, bool ignore_missing
);
179 void PrintFlagDescriptions();
181 static LowLevelAllocator Alloc
;
184 void fatal_error(const char *err
);
185 bool is_space(char c
);
186 void skip_whitespace();
187 void parse_flags(const char *env_option_name
);
188 void parse_flag(const char *env_option_name
);
189 bool run_handler(const char *name
, const char *value
);
190 char *ll_strndup(const char *s
, uptr n
);
193 template <typename T
>
194 static void RegisterFlag(FlagParser
*parser
, const char *name
, const char *desc
,
196 FlagHandler
<T
> *fh
= new (FlagParser::Alloc
) FlagHandler
<T
>(var
);
197 parser
->RegisterHandler(name
, fh
, desc
);
200 void ReportUnrecognizedFlags();
202 } // namespace __sanitizer
204 #endif // SANITIZER_FLAG_REGISTRY_H