From f174a0bbd24b0efda7c7acb6fff1ed5ed9013a00 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 23 Nov 2016 17:37:00 +0000 Subject: [PATCH] [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 --- compiler-rt/lib/asan/CMakeLists.txt | 1 - compiler-rt/lib/asan/asan_globals.cc | 15 ++++++++++++++- compiler-rt/lib/asan/asan_globals_win.cc | 6 +++--- compiler-rt/lib/asan/tests/CMakeLists.txt | 2 -- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/compiler-rt/lib/asan/CMakeLists.txt b/compiler-rt/lib/asan/CMakeLists.txt index 2a946e491a15..e89d8bdabc14 100644 --- a/compiler-rt/lib/asan/CMakeLists.txt +++ b/compiler-rt/lib/asan/CMakeLists.txt @@ -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) diff --git a/compiler-rt/lib/asan/asan_globals.cc b/compiler-rt/lib/asan/asan_globals.cc index c99f4e142a80..ed76af30b31c 100644 --- a/compiler-rt/lib/asan/asan_globals.cc +++ b/compiler-rt/lib/asan/asan_globals.cc @@ -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]); } } diff --git a/compiler-rt/lib/asan/asan_globals_win.cc b/compiler-rt/lib/asan/asan_globals_win.cc index 67d6772b01e6..e20b7eff1f74 100644 --- a/compiler-rt/lib/asan/asan_globals_win.cc +++ b/compiler-rt/lib/asan/asan_globals_win.cc @@ -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. diff --git a/compiler-rt/lib/asan/tests/CMakeLists.txt b/compiler-rt/lib/asan/tests/CMakeLists.txt index c45d35b55a20..3e56763a8041 100644 --- a/compiler-rt/lib/asan/tests/CMakeLists.txt +++ b/compiler-rt/lib/asan/tests/CMakeLists.txt @@ -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)