Skip to content

Commit 54dc36f

Browse files
committed
[SanitizerCommon] Print the current value of options when printing out help.
Summary: Previously it wasn't obvious what the default value of various sanitizer options were. A very close approximation of the "default values" for the options are the current value of the options at the time of printing the help output. In the case that no other options are provided then the current values are the default values (apart from `help`). ``` ASAN_OPTIONS=help=1 ./program ``` This patch causes the current option values to be printed when the `help` output is enabled. The original intention for this patch was to append `(Default: <value>)` to an option's help text. However because this is technically wrong (and misleading) I've opted to append `(Current Value: <value>)` instead. When trying to implement a way of displaying the default value of the options I tried another solution where the default value used in `*.inc` files were used to create compile time strings that where used when printing the help output. This solution was not satisfactory for several reasons: * Stringifying the default values with the preprocessor did not work very well in several cases. Some options contain boolean operators which no amount of macro expansion can get rid of. * It was much more invasive than this patch. Every sanitizer had to be changed. * The settings of `__<sanitizer>_default_options()` are ignored. For those reasons I opted for the solution in this patch. rdar://problem/42567204 Reviewers: kubamracek, yln, kcc, dvyukov, vitalybuka, cryptoad, eugenis, samsonov Subscribers: #sanitizers, llvm-commits Tags: #sanitizers, #llvm Differential Revision: https://reviews.llvm.org/D69546 (cherry picked from commit 4c39f34)
1 parent d976623 commit 54dc36f

File tree

5 files changed

+108
-5
lines changed

5 files changed

+108
-5
lines changed

compiler-rt/lib/msan/msan.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ class FlagHandlerKeepGoing : public FlagHandlerBase {
122122
*halt_on_error_ = !tmp;
123123
return true;
124124
}
125+
bool Format(char *buffer, uptr size) final {
126+
const char *keep_going_str = (*halt_on_error_) ? "false" : "true";
127+
return FormatString(buffer, size, keep_going_str);
128+
}
125129
};
126130

127131
static void RegisterMsanFlags(FlagParser *parser, Flags *f) {

compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,16 @@ char *FlagParser::ll_strndup(const char *s, uptr n) {
5656
}
5757

5858
void FlagParser::PrintFlagDescriptions() {
59+
char buffer[128];
60+
buffer[sizeof(buffer) - 1] = '\0';
5961
Printf("Available flags for %s:\n", SanitizerToolName);
60-
for (int i = 0; i < n_flags_; ++i)
61-
Printf("\t%s\n\t\t- %s\n", flags_[i].name, flags_[i].desc);
62+
for (int i = 0; i < n_flags_; ++i) {
63+
bool truncated = !(flags_[i].handler->Format(buffer, sizeof(buffer)));
64+
CHECK_EQ(buffer[sizeof(buffer) - 1], '\0');
65+
const char *truncation_str = truncated ? " Truncated" : "";
66+
Printf("\t%s\n\t\t- %s (Current Value%s: %s)\n", flags_[i].name,
67+
flags_[i].desc, truncation_str, buffer);
68+
}
6269
}
6370

6471
void FlagParser::fatal_error(const char *err) {

compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,23 @@ namespace __sanitizer {
2222
class FlagHandlerBase {
2323
public:
2424
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) {
29+
if (size > 0)
30+
buffer[0] = '\0';
31+
return false;
32+
}
2533

2634
protected:
2735
~FlagHandlerBase() {}
36+
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;
41+
}
2842
};
2943

3044
template <typename T>
@@ -34,6 +48,7 @@ class FlagHandler : public FlagHandlerBase {
3448
public:
3549
explicit FlagHandler(T *t) : t_(t) {}
3650
bool Parse(const char *value) final;
51+
bool Format(char *buffer, uptr size) final;
3752
};
3853

3954
inline bool ParseBool(const char *value, bool *b) {
@@ -59,6 +74,11 @@ inline bool FlagHandler<bool>::Parse(const char *value) {
5974
return false;
6075
}
6176

77+
template <>
78+
inline bool FlagHandler<bool>::Format(char *buffer, uptr size) {
79+
return FormatString(buffer, size, *t_ ? "true" : "false");
80+
}
81+
6282
template <>
6383
inline bool FlagHandler<HandleSignalMode>::Parse(const char *value) {
6484
bool b;
@@ -75,12 +95,23 @@ inline bool FlagHandler<HandleSignalMode>::Parse(const char *value) {
7595
return false;
7696
}
7797

98+
template <>
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;
102+
}
103+
78104
template <>
79105
inline bool FlagHandler<const char *>::Parse(const char *value) {
80106
*t_ = value;
81107
return true;
82108
}
83109

110+
template <>
111+
inline bool FlagHandler<const char *>::Format(char *buffer, uptr size) {
112+
return FormatString(buffer, size, *t_);
113+
}
114+
84115
template <>
85116
inline bool FlagHandler<int>::Parse(const char *value) {
86117
const char *value_end;
@@ -90,6 +121,12 @@ inline bool FlagHandler<int>::Parse(const char *value) {
90121
return ok;
91122
}
92123

124+
template <>
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;
128+
}
129+
93130
template <>
94131
inline bool FlagHandler<uptr>::Parse(const char *value) {
95132
const char *value_end;
@@ -99,6 +136,12 @@ inline bool FlagHandler<uptr>::Parse(const char *value) {
99136
return ok;
100137
}
101138

139+
template <>
140+
inline bool FlagHandler<uptr>::Format(char *buffer, uptr size) {
141+
uptr num_symbols_should_write = internal_snprintf(buffer, size, "%p", *t_);
142+
return num_symbols_should_write < size;
143+
}
144+
102145
template <>
103146
inline bool FlagHandler<s64>::Parse(const char *value) {
104147
const char *value_end;
@@ -108,6 +151,12 @@ inline bool FlagHandler<s64>::Parse(const char *value) {
108151
return ok;
109152
}
110153

154+
template <>
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;
158+
}
159+
111160
class FlagParser {
112161
static const int kMaxFlags = 200;
113162
struct Flag {

compiler-rt/lib/sanitizer_common/sanitizer_flags.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,13 @@ void SubstituteForFlagValue(const char *s, char *out, uptr out_size) {
7575
class FlagHandlerInclude : public FlagHandlerBase {
7676
FlagParser *parser_;
7777
bool ignore_missing_;
78+
const char *original_path_;
7879

7980
public:
8081
explicit FlagHandlerInclude(FlagParser *parser, bool ignore_missing)
81-
: parser_(parser), ignore_missing_(ignore_missing) {}
82+
: parser_(parser), ignore_missing_(ignore_missing), original_path_("") {}
8283
bool Parse(const char *value) final {
84+
original_path_ = value;
8385
if (internal_strchr(value, '%')) {
8486
char *buf = (char *)MmapOrDie(kMaxPathLength, "FlagHandlerInclude");
8587
SubstituteForFlagValue(value, buf, kMaxPathLength);
@@ -89,6 +91,12 @@ class FlagHandlerInclude : public FlagHandlerBase {
8991
}
9092
return parser_->ParseFile(value, ignore_missing_);
9193
}
94+
bool Format(char *buffer, uptr size) {
95+
// Note `original_path_` isn't actually what's parsed due to `%`
96+
// substitutions. Printing the substituted path would require holding onto
97+
// mmap'ed memory.
98+
return FormatString(buffer, size, original_path_);
99+
}
92100
};
93101

94102
void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) {
Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,43 @@
11
// RUN: %clangxx -O0 %s -o %t
2-
// RUN: %env_tool_opts=help=1 %run %t 2>&1 | FileCheck %s
2+
// RUN: %env_tool_opts=help=1,include_if_exists=___some_path_that_does_not_exist___ %run %t 2>&1 | FileCheck %s
3+
// RUN: %env_tool_opts=help=1,symbolize=0 %run %t 2>&1 | FileCheck --check-prefix=CHECK-CV %s
4+
// RUN: %env_tool_opts=help=1,sancov_path=/long/path/that/requires/truncation/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaB \
5+
// RUN: %run %t 2>&1 | FileCheck --check-prefix=CHECK-TRUNCATION %s
36

47
int main() {
58
}
69

710
// CHECK: Available flags for {{.*}}Sanitizer:
8-
// CHECK: handle_segv
11+
12+
//
13+
// Bool option
14+
// CHECK: {{^[ \t]+symbolize$}}
15+
// CHECK-NEXT: (Current Value: true)
16+
//
17+
// String option
18+
// CHECK: {{^[ \t]+log_path$}}
19+
// CHECK-NEXT: (Current Value: {{.+}})
20+
//
21+
// int option
22+
// CHECK: {{^[ \t]+verbosity$}}
23+
// CHECK-NEXT: (Current Value: {{-?[0-9]+}})
24+
//
25+
// HandleSignalMode option
26+
// CHECK: {{^[ \t]+handle_segv$}}
27+
// CHECK-NEXT: (Current Value: {{0|1|2}})
28+
//
29+
// uptr option
30+
// CHECK: {{^[ \t]+mmap_limit_mb$}}
31+
// CHECK-NEXT: (Current Value: 0x{{[0-9a-fA-F]+}})
32+
//
33+
// FlagHandlerInclude option
34+
// CHECK: include_if_exists
35+
// CHECK-NEXT: (Current Value: ___some_path_that_does_not_exist___)
36+
37+
// Test we show the current value and not the default.
38+
// CHECK-CV: {{^[ \t]+symbolize$}}
39+
// CHECK-CV-NEXT: (Current Value: false)
40+
41+
// Test truncation of long paths.
42+
// CHECK-TRUNCATION: sancov_path
43+
// CHECK-TRUNCATION-NEXT: (Current Value Truncated: /long/path/that/requires/truncation/aaa{{a+}})

0 commit comments

Comments
 (0)