[compiler-rt] r295761 - [compiler-rt][asan] Fix incorrect macro preventing ICF with MSVC

Etienne Bergeron via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 21 12:04:47 PST 2017


Author: etienneb
Date: Tue Feb 21 14:04:47 2017
New Revision: 295761

URL: http://llvm.org/viewvc/llvm-project?rev=295761&view=rev
Log:
[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

Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_dll_thunk.h

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_dll_thunk.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_dll_thunk.h?rev=295761&r1=295760&r2=295761&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_dll_thunk.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_dll_thunk.h Tue Feb 21 14:04:47 2017
@@ -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)




More information about the llvm-commits mailing list