summaryrefslogtreecommitdiff
path: root/test/asan/TestCases/Windows
diff options
context:
space:
mode:
Diffstat (limited to 'test/asan/TestCases/Windows')
-rw-r--r--test/asan/TestCases/Windows/tls_init.cc51
1 files changed, 51 insertions, 0 deletions
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 <windows.h>
+#include <stdio.h>
+#include <string.h>
+
+#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);
+}