1*65abcf6cSAlvin Wong // RUN: %clang_cl_asan %s -Fe%t.exe /MD
2*65abcf6cSAlvin Wong // RUN: %run %t.exe | FileCheck %s
3*65abcf6cSAlvin Wong
4*65abcf6cSAlvin Wong // CHECK: my_thread_callback
5*65abcf6cSAlvin Wong // CHECK: ran_before_main: 1
6*65abcf6cSAlvin Wong
7*65abcf6cSAlvin Wong #include <windows.h>
8*65abcf6cSAlvin Wong #include <stdio.h>
9*65abcf6cSAlvin Wong #include <string.h>
10*65abcf6cSAlvin Wong
11*65abcf6cSAlvin Wong #pragma comment (lib, "dbghelp")
12*65abcf6cSAlvin Wong
13*65abcf6cSAlvin Wong static bool ran_before_main = false;
14*65abcf6cSAlvin Wong
15*65abcf6cSAlvin Wong extern "C" void __asan_init(void);
16*65abcf6cSAlvin Wong
17*65abcf6cSAlvin Wong static void NTAPI /*__attribute__((no_sanitize_address))*/
my_thread_callback(PVOID module,DWORD reason,PVOID reserved)18*65abcf6cSAlvin Wong my_thread_callback(PVOID module, DWORD reason, PVOID reserved) {
19*65abcf6cSAlvin Wong ran_before_main = true;
20*65abcf6cSAlvin Wong static const char str[] = "my_thread_callback\n";
21*65abcf6cSAlvin Wong
22*65abcf6cSAlvin Wong // Fail the test if we aren't called for the expected reason or we can't write
23*65abcf6cSAlvin Wong // stdout.
24*65abcf6cSAlvin Wong if (reason != DLL_PROCESS_ATTACH)
25*65abcf6cSAlvin Wong return;
26*65abcf6cSAlvin Wong HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
27*65abcf6cSAlvin Wong if (!out || out == INVALID_HANDLE_VALUE)
28*65abcf6cSAlvin Wong return;
29*65abcf6cSAlvin Wong
30*65abcf6cSAlvin Wong DWORD written = 0;
31*65abcf6cSAlvin Wong WriteFile(out, &str[0], sizeof(str), &written, NULL);
32*65abcf6cSAlvin Wong }
33*65abcf6cSAlvin Wong
34*65abcf6cSAlvin Wong extern "C" {
35*65abcf6cSAlvin Wong #pragma const_seg(".CRT$XLC")
36*65abcf6cSAlvin Wong extern const PIMAGE_TLS_CALLBACK p_thread_callback;
37*65abcf6cSAlvin Wong const PIMAGE_TLS_CALLBACK p_thread_callback = my_thread_callback;
38*65abcf6cSAlvin Wong #pragma const_seg()
39*65abcf6cSAlvin Wong }
40*65abcf6cSAlvin Wong
41*65abcf6cSAlvin Wong #ifdef _WIN64
42*65abcf6cSAlvin Wong #pragma comment(linker, "/INCLUDE:_tls_used")
43*65abcf6cSAlvin Wong #pragma comment(linker, "/INCLUDE:p_thread_callback")
44*65abcf6cSAlvin Wong #else
45*65abcf6cSAlvin Wong #pragma comment(linker, "/INCLUDE:__tls_used")
46*65abcf6cSAlvin Wong #pragma comment(linker, "/INCLUDE:_p_thread_callback")
47*65abcf6cSAlvin Wong #endif
48*65abcf6cSAlvin Wong
main()49*65abcf6cSAlvin Wong int main() {
50*65abcf6cSAlvin Wong printf("ran_before_main: %d\n", ran_before_main);
51*65abcf6cSAlvin Wong }
52