From 91a6efd7648b46b5defdb883de44711fe8e3c723 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Tue, 8 Nov 2016 20:45:45 +0000 Subject: [asan/win] Add init hooks to .CRT$XLAB Summary: User applications may register hooks in the .CRT$XL* callback list, which is called very early by the loader. This is very common in Chromium: https://cs.chromium.org/search/?q=CRT.XL&sq=package:chromium&type=cs This has flown under the radar for a long time because the loader appears to catch exceptions originating from these callbacks. It's a real problem when you're debugging an asan application, though, since it makes the program crash early. The solution is to add our own callback to this list, and sort it very early in the list like we do elsewhere. Also add a test with such an instrumented callback, and test that it gets called with asan. Reviewers: etienneb Subscribers: llvm-commits, kubabrecka Differential Revision: https://reviews.llvm.org/D26404 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@286290 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/asan/TestCases/Windows/tls_init.cc | 51 +++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 test/asan/TestCases/Windows/tls_init.cc (limited to 'test/asan/TestCases/Windows') diff --git a/test/asan/TestCases/Windows/tls_init.cc b/test/asan/TestCases/Windows/tls_init.cc new file mode 100644 index 000000000..c29c4a377 --- /dev/null +++ b/test/asan/TestCases/Windows/tls_init.cc @@ -0,0 +1,51 @@ +// RUN: %clang_cl_asan %s -Fe%t.exe +// RUN: %run %t.exe | FileCheck %s + +// CHECK: my_thread_callback +// CHECK: ran_before_main: 1 + +#include +#include +#include + +#pragma comment (lib, "dbghelp") + +static bool ran_before_main = false; + +extern "C" void __asan_init(void); + +static void NTAPI /*__attribute__((no_sanitize_address))*/ +my_thread_callback(PVOID module, DWORD reason, PVOID reserved) { + ran_before_main = true; + static const char str[] = "my_thread_callback\n"; + + // Fail the test if we aren't called for the expected reason or we can't write + // stdout. + if (reason != DLL_PROCESS_ATTACH) + return; + HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); + if (!out || out == INVALID_HANDLE_VALUE) + return; + + DWORD written = 0; + WriteFile(out, &str[0], sizeof(str), &written, NULL); +} + +extern "C" { +#pragma const_seg(".CRT$XLC") +extern const PIMAGE_TLS_CALLBACK p_thread_callback; +const PIMAGE_TLS_CALLBACK p_thread_callback = my_thread_callback; +#pragma const_seg() +} + +#ifdef _WIN64 +#pragma comment(linker, "/INCLUDE:_tls_used") +#pragma comment(linker, "/INCLUDE:p_thread_callback") +#else +#pragma comment(linker, "/INCLUDE:__tls_used") +#pragma comment(linker, "/INCLUDE:_p_thread_callback") +#endif + +int main() { + printf("ran_before_main: %d\n", ran_before_main); +} -- cgit v1.2.3