Skip to content

Commit ae456a2

Browse files
committed
Because all DLLs get initialized before the main module
weak functions are registered after the asan runtime initializes. This means __asan_default_options isn't available during asan runtime initialization. Thus we split asan flag processing into two parts and register a callback for the second part that's executed after __asan_default_options is registered.
1 parent 7b189a6 commit ae456a2

File tree

1 file changed

+85
-11
lines changed

1 file changed

+85
-11
lines changed

compiler-rt/lib/asan/asan_flags.cpp

Lines changed: 85 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@
1111
// ASan flag parsing logic.
1212
//===----------------------------------------------------------------------===//
1313

14-
#include "asan_activation.h"
1514
#include "asan_flags.h"
15+
16+
#include "asan_activation.h"
1617
#include "asan_interface_internal.h"
1718
#include "asan_stack.h"
1819
#include "lsan/lsan_common.h"
1920
#include "sanitizer_common/sanitizer_common.h"
20-
#include "sanitizer_common/sanitizer_flags.h"
2121
#include "sanitizer_common/sanitizer_flag_parser.h"
22+
#include "sanitizer_common/sanitizer_flags.h"
23+
#include "sanitizer_common/sanitizer_win_interception.h"
2224
#include "ubsan/ubsan_flags.h"
2325
#include "ubsan/ubsan_platform.h"
2426

@@ -47,7 +49,21 @@ static void RegisterAsanFlags(FlagParser *parser, Flags *f) {
4749
#undef ASAN_FLAG
4850
}
4951

50-
void InitializeFlags() {
52+
static void DisplayHelpMessages(FlagParser *parser) {
53+
// TODO(eugenis): dump all flags at verbosity>=2?
54+
if (Verbosity()) {
55+
ReportUnrecognizedFlags();
56+
}
57+
58+
if (common_flags()->help) {
59+
parser->PrintFlagDescriptions();
60+
}
61+
}
62+
63+
static void InitializeDefaultFlags() {
64+
Flags *f = flags();
65+
FlagParser asan_parser;
66+
5167
// Set the default values and prepare for parsing ASan and common flags.
5268
SetCommonFlagsDefaults();
5369
{
@@ -60,10 +76,8 @@ void InitializeFlags() {
6076
cf.exitcode = 1;
6177
OverrideCommonFlags(cf);
6278
}
63-
Flags *f = flags();
6479
f->SetDefaults();
6580

66-
FlagParser asan_parser;
6781
RegisterAsanFlags(&asan_parser, f);
6882
RegisterCommonFlags(&asan_parser);
6983

@@ -126,13 +140,12 @@ void InitializeFlags() {
126140

127141
InitializeCommonFlags();
128142

129-
// TODO(eugenis): dump all flags at verbosity>=2?
130-
if (Verbosity()) ReportUnrecognizedFlags();
143+
// TODO(samsonov): print all of the flags (ASan, LSan, common).
144+
DisplayHelpMessages(&asan_parser);
145+
}
131146

132-
if (common_flags()->help) {
133-
// TODO(samsonov): print all of the flags (ASan, LSan, common).
134-
asan_parser.PrintFlagDescriptions();
135-
}
147+
static void ProcessFlags() {
148+
Flags *f = flags();
136149

137150
// Flag validation:
138151
if (!CAN_SANITIZE_LEAKS && common_flags()->detect_leaks) {
@@ -199,6 +212,67 @@ void InitializeFlags() {
199212
}
200213
}
201214

215+
void InitializeFlags() {
216+
InitializeDefaultFlags();
217+
ProcessFlags();
218+
219+
#if SANITIZER_WINDOWS
220+
// On Windows, weak symbols are emulated by having the user program
221+
// register which weak functions are defined.
222+
// The ASAN DLL will initialize flags prior to user module initialization,
223+
// so __asan_default_options will not point to the user definition yet.
224+
// We still want to ensure we capture when options are passed via
225+
// __asan_default_options, so we add a callback to be run
226+
// when it is registered with the runtime.
227+
228+
// There is theoretically time between the initial ProcessFlags and
229+
// registering the weak callback where a weak function could be added and we
230+
// would miss it, but in practice, InitializeFlags will always happen under
231+
// the loader lock (if built as a DLL) and so will any calls to
232+
// __sanitizer_register_weak_function.
233+
AddRegisterWeakFunctionCallback(
234+
reinterpret_cast<uptr>(__asan_default_options), []() {
235+
FlagParser asan_parser;
236+
237+
RegisterAsanFlags(&asan_parser, flags());
238+
RegisterCommonFlags(&asan_parser);
239+
asan_parser.ParseString(__asan_default_options());
240+
241+
DisplayHelpMessages(&asan_parser);
242+
ProcessFlags();
243+
});
244+
245+
# if CAN_SANITIZE_UB
246+
AddRegisterWeakFunctionCallback(
247+
reinterpret_cast<uptr>(__ubsan_default_options), []() {
248+
FlagParser ubsan_parser;
249+
250+
__ubsan::RegisterUbsanFlags(&ubsan_parser, __ubsan::flags());
251+
RegisterCommonFlags(&ubsan_parser);
252+
ubsan_parser.ParseString(__ubsan_default_options());
253+
254+
// To match normal behavior, do not print UBSan help.
255+
ProcessFlags();
256+
});
257+
# endif
258+
259+
# if CAN_SANITIZE_LEAKS
260+
AddRegisterWeakFunctionCallback(
261+
reinterpret_cast<uptr>(__lsan_default_options), []() {
262+
FlagParser lsan_parser;
263+
264+
__lsan::RegisterLsanFlags(&lsan_parser, __lsan::flags());
265+
RegisterCommonFlags(&lsan_parser);
266+
lsan_parser.ParseString(__lsan_default_options());
267+
268+
// To match normal behavior, do not print LSan help.
269+
ProcessFlags();
270+
});
271+
# endif
272+
273+
#endif
274+
}
275+
202276
} // namespace __asan
203277

204278
SANITIZER_INTERFACE_WEAK_DEF(const char*, __asan_default_options, void) {

0 commit comments

Comments
 (0)