summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimur Iskhodzhanov <timurrrr@google.com>2014-06-02 14:40:07 +0000
committerTimur Iskhodzhanov <timurrrr@google.com>2014-06-02 14:40:07 +0000
commitb1415c46fb5859d29ebd04bf78bc542881a590e7 (patch)
treebb6044800dd47dc7d9bf7f201695166cb1c7f9c2
parent82899febf07aa2cc42761102f92609a804034ba2 (diff)
downloadbcm5719-llvm-b1415c46fb5859d29ebd04bf78bc542881a590e7.tar.gz
bcm5719-llvm-b1415c46fb5859d29ebd04bf78bc542881a590e7.zip
[ASan Win] Manually call __asan_init early in the DLL initialization process to avoid a null function call in cout/cerr constructors
llvm-svn: 210030
-rw-r--r--compiler-rt/lib/asan/asan_dll_thunk.cc17
-rw-r--r--compiler-rt/test/asan/TestCases/Windows/dll_cerr.cc23
2 files changed, 39 insertions, 1 deletions
diff --git a/compiler-rt/lib/asan/asan_dll_thunk.cc b/compiler-rt/lib/asan/asan_dll_thunk.cc
index 15482ba8ca3..aa27c404f4d 100644
--- a/compiler-rt/lib/asan/asan_dll_thunk.cc
+++ b/compiler-rt/lib/asan/asan_dll_thunk.cc
@@ -325,9 +325,24 @@ INTERCEPT_LIBRARY_FUNCTION(strnlen);
INTERCEPT_LIBRARY_FUNCTION(strtol);
INTERCEPT_LIBRARY_FUNCTION(wcslen);
-// Must be at the end of the file due to the way INTERCEPT_HOOKS is defined.
+// Must be after all the interceptor declarations due to the way INTERCEPT_HOOKS
+// is defined.
void InterceptHooks() {
INTERCEPT_HOOKS();
}
+// We want to call __asan_init before C/C++ initializers/constructors are
+// executed, otherwise functions like memset might be invoked.
+// For some strange reason, merely linking in asan_preinit.cc doesn't work
+// as the callback is never called... Is link.exe doing something too smart?
+
+// In DLLs, the callbacks are expected to return 0,
+// otherwise CRT initialization fails.
+static int call_asan_init() {
+ __asan_init_v3();
+ return 0;
+}
+#pragma section(".CRT$XIB", long, read) // NOLINT
+__declspec(allocate(".CRT$XIB")) int (*__asan_preinit)() = call_asan_init;
+
#endif // ASAN_DLL_THUNK
diff --git a/compiler-rt/test/asan/TestCases/Windows/dll_cerr.cc b/compiler-rt/test/asan/TestCases/Windows/dll_cerr.cc
new file mode 100644
index 00000000000..8f1a699ba80
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/Windows/dll_cerr.cc
@@ -0,0 +1,23 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: %run %t %t.dll 2>&1 | FileCheck %s
+
+// Test that it works correctly even with ICF enabled.
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll -link /OPT:REF /OPT:ICF
+// RUN: %run %t %t.dll 2>&1 | FileCheck %s
+
+#include <iostream>
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ // Just make sure we can use cout.
+ std::cout << "All ok\n";
+// CHECK: All ok
+
+ // This line forces a declaration of some global basic_ostream internal object that
+ // calls memcpy() in its constructor. This doesn't work if __asan_init is not
+ // called early enough.
+ std::cout << 42;
+// CHECK: 42
+ return 0;
+}
OpenPOWER on IntegriCloud