[asan/win] Fix incremental linking vs. global registration
The MSVC incremental linker pads every global out to 256 bytes in case it changes size after an incremental link. So, skip over null entries in the DSO-wide asan globals array. This only works if the global padding size is divisible by the size of the asan global object, so add some defensive CHECKs. llvm-svn: 287780
This commit is contained in:
parent
8d0381d61f
commit
f174a0bbd2
|
@ -64,7 +64,6 @@ set(ASAN_DYNAMIC_CFLAGS ${ASAN_CFLAGS})
|
|||
append_list_if(COMPILER_RT_HAS_FTLS_MODEL_INITIAL_EXEC
|
||||
-ftls-model=initial-exec ASAN_DYNAMIC_CFLAGS)
|
||||
append_list_if(MSVC /DEBUG ASAN_DYNAMIC_LINK_FLAGS)
|
||||
append_list_if(MSVC /INCREMENTAL:NO ASAN_DYNAMIC_LINK_FLAGS)
|
||||
|
||||
append_list_if(COMPILER_RT_HAS_LIBC c ASAN_DYNAMIC_LIBS)
|
||||
append_list_if(COMPILER_RT_HAS_LIBDL dl ASAN_DYNAMIC_LIBS)
|
||||
|
|
|
@ -192,7 +192,6 @@ static inline bool UseODRIndicator(const Global *g) {
|
|||
// This function may be called more than once for every global
|
||||
// so we store the globals in a map.
|
||||
static void RegisterGlobal(const Global *g) {
|
||||
CHECK(g->beg);
|
||||
CHECK(asan_inited);
|
||||
if (flags()->report_globals >= 2)
|
||||
ReportGlobal(*g, "Added");
|
||||
|
@ -349,6 +348,20 @@ void __asan_register_globals(__asan_global *globals, uptr n) {
|
|||
Printf("=== ID %d; %p %p\n", stack_id, &globals[0], &globals[n - 1]);
|
||||
}
|
||||
for (uptr i = 0; i < n; i++) {
|
||||
if (SANITIZER_WINDOWS && globals[i].beg == 0) {
|
||||
// The MSVC incremental linker may pad globals out to 256 bytes. As long
|
||||
// as __asan_global is less than 256 bytes large and its size is a power
|
||||
// of two, we can skip over the padding.
|
||||
static_assert(
|
||||
sizeof(__asan_global) < 256 &&
|
||||
(sizeof(__asan_global) & (sizeof(__asan_global) - 1)) == 0,
|
||||
"sizeof(__asan_global) incompatible with incremental linker padding");
|
||||
// If these are padding bytes, the rest of the global should be zero.
|
||||
CHECK(globals[i].size == 0 && globals[i].size_with_redzone == 0 &&
|
||||
globals[i].name == nullptr && globals[i].module_name == nullptr &&
|
||||
globals[i].odr_indicator == 0);
|
||||
continue;
|
||||
}
|
||||
RegisterGlobal(&globals[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,13 +19,13 @@ namespace __asan {
|
|||
#pragma section(".ASAN$GA", read, write) // NOLINT
|
||||
#pragma section(".ASAN$GZ", read, write) // NOLINT
|
||||
extern "C" __declspec(allocate(".ASAN$GA"))
|
||||
uptr __asan_globals_start = 0;
|
||||
__asan_global __asan_globals_start = {};
|
||||
extern "C" __declspec(allocate(".ASAN$GZ"))
|
||||
uptr __asan_globals_end = 0;
|
||||
__asan_global __asan_globals_end = {};
|
||||
#pragma comment(linker, "/merge:.ASAN=.data")
|
||||
|
||||
static void call_on_globals(void (*hook)(__asan_global *, uptr)) {
|
||||
__asan_global *start = (__asan_global *)(&__asan_globals_start + 1);
|
||||
__asan_global *start = &__asan_globals_start + 1;
|
||||
__asan_global *end = (__asan_global *)&__asan_globals_end;
|
||||
// We know end >= start because the linker sorts the portion after the dollar
|
||||
// sign alphabetically.
|
||||
|
|
|
@ -47,8 +47,6 @@ else()
|
|||
endif()
|
||||
if(MSVC)
|
||||
list(APPEND ASAN_UNITTEST_COMMON_CFLAGS -gcodeview)
|
||||
# Incremental linking appears to break our global registration mechanism.
|
||||
list(APPEND ASAN_UNITTEST_COMMON_LINKFLAGS -Wl,-incremental:no)
|
||||
endif()
|
||||
list(APPEND ASAN_UNITTEST_COMMON_LINKFLAGS -g)
|
||||
|
||||
|
|
Loading…
Reference in New Issue