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