summaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/sanitizer_win_dll_thunk.h
diff options
context:
space:
mode:
authorEtienne Bergeron <etienneb@google.com>2017-02-21 20:04:47 +0000
committerEtienne Bergeron <etienneb@google.com>2017-02-21 20:04:47 +0000
commit796f898b43d4a9573c3880a0ed47ceea6662b274 (patch)
tree51ba54deb24f3274c0b3636eb67c43f1ebb9bc25 /lib/sanitizer_common/sanitizer_win_dll_thunk.h
parentcf1dffa34854a5d1d7f15fe2acf8d65db6dd3843 (diff)
downloadcompiler-rt-796f898b43d4a9573c3880a0ed47ceea6662b274.tar.gz
[compiler-rt][asan] Fix incorrect macro preventing ICF with MSVC
Summary: The DLL thunks are stubs added to an instrumented DLL to redirect ASAN API calls to the real ones in the main executable. These thunks must contain dummy code before __asan_init got called. Unfortunately, MSVC linker is doing ICF and is merging functions with the same body. In our case, this two ASAN thunks were incorrectly merged: ``` asan_interface.inc:16 INTERFACE_FUNCTION(__asan_before_dynamic_init) ``` ``` sanitizer_common_interface.inc:16 INTERFACE_FUNCTION(__sanitizer_verify_contiguous_container) ``` The same thunk got patched twice. After the second patching, calls to `__asan_before_dynamic_init` are redirected to `__sanitizer_verify_contiguous_container` and trigger a DCHECK on incorrect operands/ The problem was caused by the macro that is only using __LINE__ to prevent collapsing code. ``` #define INTERCEPT_SANITIZER_FUNCTION(name) extern "C" __declspec(noinline) void name() { volatile int prevent_icf = (__LINE__ << 8); (void)prevent_icf; ``` The current patch is adding __COUNTER__ which is safer than __LINE__. Also, to precent ICF (guarantee that code is different), we are using a unique attribute: - the name of the function Reviewers: rnk Reviewed By: rnk Subscribers: llvm-commits, kubamracek, chrisha, dberris Differential Revision: https://reviews.llvm.org/D30219 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@295761 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/sanitizer_common/sanitizer_win_dll_thunk.h')
-rw-r--r--lib/sanitizer_common/sanitizer_win_dll_thunk.h12
1 files changed, 10 insertions, 2 deletions
diff --git a/lib/sanitizer_common/sanitizer_win_dll_thunk.h b/lib/sanitizer_common/sanitizer_win_dll_thunk.h
index 00a3b023d..2f9ebdaa6 100644
--- a/lib/sanitizer_common/sanitizer_win_dll_thunk.h
+++ b/lib/sanitizer_common/sanitizer_win_dll_thunk.h
@@ -53,7 +53,11 @@ extern "C" int __dll_thunk_init();
// after __asan_init, thus an empty implementation is sufficient.
#define INTERCEPT_SANITIZER_FUNCTION(name) \
extern "C" __declspec(noinline) void name() { \
- volatile int prevent_icf = (__LINE__ << 8); (void)prevent_icf; \
+ volatile int prevent_icf = (__LINE__ << 8) ^ __COUNTER__; \
+ static const char function_name[] = #name; \
+ for (const char* ptr = &function_name[0]; *ptr; ++ptr) \
+ prevent_icf ^= *ptr; \
+ (void)prevent_icf; \
__debugbreak(); \
} \
INTERCEPT_OR_DIE(#name, name)
@@ -64,7 +68,11 @@ extern "C" int __dll_thunk_init();
// we consider the default impl provided by asan library.
#define INTERCEPT_SANITIZER_WEAK_FUNCTION(name) \
extern "C" __declspec(noinline) void name() { \
- volatile int prevent_icf = (__LINE__ << 8); (void)prevent_icf; \
+ volatile int prevent_icf = (__LINE__ << 8) ^ __COUNTER__; \
+ static const char function_name[] = #name; \
+ for (const char* ptr = &function_name[0]; *ptr; ++ptr) \
+ prevent_icf ^= *ptr; \
+ (void)prevent_icf; \
__debugbreak(); \
} \
INTERCEPT_WHEN_POSSIBLE(#name, STRINGIFY(WEAK_EXPORT_NAME(name)), name)