]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/asan/asan_win_dll_thunk.cc
MFV 316870
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / asan / asan_win_dll_thunk.cc
1 //===-- asan_win_dll_thunk.cc ---------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of AddressSanitizer, an address sanity checker.
11 //
12 // This file defines a family of thunks that should be statically linked into
13 // the DLLs that have ASan instrumentation in order to delegate the calls to the
14 // shared runtime that lives in the main binary.
15 // See https://github.com/google/sanitizers/issues/209 for the details.
16 //===----------------------------------------------------------------------===//
17
18 // Only compile this code when building asan_dll_thunk.lib
19 // Using #ifdef rather than relying on Makefiles etc.
20 // simplifies the build procedure.
21 #ifdef ASAN_DLL_THUNK
22 #include "asan_init_version.h"
23 #include "asan_globals_win.h"
24 #include "interception/interception.h"
25 #include "sanitizer_common/sanitizer_platform_interceptors.h"
26
27 #ifdef _M_IX86
28 #define WINAPI __stdcall
29 #else
30 #define WINAPI
31 #endif
32
33 // ---------- Function interception helper functions and macros ----------- {{{1
34 extern "C" {
35 void *WINAPI GetModuleHandleA(const char *module_name);
36 void *WINAPI GetProcAddress(void *module, const char *proc_name);
37 void abort();
38 }
39
40 using namespace __sanitizer;
41
42 static uptr getRealProcAddressOrDie(const char *name) {
43   uptr ret =
44       __interception::InternalGetProcAddress((void *)GetModuleHandleA(0), name);
45   if (!ret)
46     abort();
47   return ret;
48 }
49
50 // We need to intercept some functions (e.g. ASan interface, memory allocator --
51 // let's call them "hooks") exported by the DLL thunk and forward the hooks to
52 // the runtime in the main module.
53 // However, we don't want to keep two lists of these hooks.
54 // To avoid that, the list of hooks should be defined using the
55 // INTERCEPT_WHEN_POSSIBLE macro. Then, all these hooks can be intercepted
56 // at once by calling INTERCEPT_HOOKS().
57
58 // Use macro+template magic to automatically generate the list of hooks.
59 // Each hook at line LINE defines a template class with a static
60 // FunctionInterceptor<LINE>::Execute() method intercepting the hook.
61 // The default implementation of FunctionInterceptor<LINE> is to call
62 // the Execute() method corresponding to the previous line.
63 template<int LINE>
64 struct FunctionInterceptor {
65   static void Execute() { FunctionInterceptor<LINE-1>::Execute(); }
66 };
67
68 // There shouldn't be any hooks with negative definition line number.
69 template<>
70 struct FunctionInterceptor<0> {
71   static void Execute() {}
72 };
73
74 #define INTERCEPT_WHEN_POSSIBLE(main_function, dll_function)                   \
75   template <> struct FunctionInterceptor<__LINE__> {                           \
76     static void Execute() {                                                    \
77       uptr wrapper = getRealProcAddressOrDie(main_function);                   \
78       if (!__interception::OverrideFunction((uptr)dll_function, wrapper, 0))   \
79         abort();                                                               \
80       FunctionInterceptor<__LINE__ - 1>::Execute();                            \
81     }                                                                          \
82   };
83
84 // Special case of hooks -- ASan own interface functions.  Those are only called
85 // after __asan_init, thus an empty implementation is sufficient.
86 #define INTERFACE_FUNCTION(name)                                               \
87   extern "C" __declspec(noinline) void name() {                                \
88     volatile int prevent_icf = (__LINE__ << 8); (void)prevent_icf;             \
89     __debugbreak();                                                            \
90   }                                                                            \
91   INTERCEPT_WHEN_POSSIBLE(#name, name)
92
93 // INTERCEPT_HOOKS must be used after the last INTERCEPT_WHEN_POSSIBLE.
94 #define INTERCEPT_HOOKS FunctionInterceptor<__LINE__>::Execute
95
96 // We can't define our own version of strlen etc. because that would lead to
97 // link-time or even type mismatch errors.  Instead, we can declare a function
98 // just to be able to get its address.  Me may miss the first few calls to the
99 // functions since it can be called before __asan_init, but that would lead to
100 // false negatives in the startup code before user's global initializers, which
101 // isn't a big deal.
102 #define INTERCEPT_LIBRARY_FUNCTION(name)                                       \
103   extern "C" void name();                                                      \
104   INTERCEPT_WHEN_POSSIBLE(WRAPPER_NAME(name), name)
105
106 // Disable compiler warnings that show up if we declare our own version
107 // of a compiler intrinsic (e.g. strlen).
108 #pragma warning(disable: 4391)
109 #pragma warning(disable: 4392)
110
111 static void InterceptHooks();
112 // }}}
113
114 // ---------- Function wrapping helpers ----------------------------------- {{{1
115 #define WRAP_V_V(name)                                                         \
116   extern "C" void name() {                                                     \
117     typedef decltype(name) *fntype;                                            \
118     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
119     fn();                                                                      \
120   }                                                                            \
121   INTERCEPT_WHEN_POSSIBLE(#name, name);
122
123 #define WRAP_V_W(name)                                                         \
124   extern "C" void name(void *arg) {                                            \
125     typedef decltype(name) *fntype;                                            \
126     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
127     fn(arg);                                                                   \
128   }                                                                            \
129   INTERCEPT_WHEN_POSSIBLE(#name, name);
130
131 #define WRAP_V_WW(name)                                                        \
132   extern "C" void name(void *arg1, void *arg2) {                               \
133     typedef decltype(name) *fntype;                                            \
134     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
135     fn(arg1, arg2);                                                            \
136   }                                                                            \
137   INTERCEPT_WHEN_POSSIBLE(#name, name);
138
139 #define WRAP_V_WWW(name)                                                       \
140   extern "C" void name(void *arg1, void *arg2, void *arg3) {                   \
141     typedef decltype(name) *fntype;                                            \
142     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
143     fn(arg1, arg2, arg3);                                                      \
144   }                                                                            \
145   INTERCEPT_WHEN_POSSIBLE(#name, name);
146
147 #define WRAP_W_V(name)                                                         \
148   extern "C" void *name() {                                                    \
149     typedef decltype(name) *fntype;                                            \
150     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
151     return fn();                                                               \
152   }                                                                            \
153   INTERCEPT_WHEN_POSSIBLE(#name, name);
154
155 #define WRAP_W_W(name)                                                         \
156   extern "C" void *name(void *arg) {                                           \
157     typedef decltype(name) *fntype;                                            \
158     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
159     return fn(arg);                                                            \
160   }                                                                            \
161   INTERCEPT_WHEN_POSSIBLE(#name, name);
162
163 #define WRAP_W_WW(name)                                                        \
164   extern "C" void *name(void *arg1, void *arg2) {                              \
165     typedef decltype(name) *fntype;                                            \
166     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
167     return fn(arg1, arg2);                                                     \
168   }                                                                            \
169   INTERCEPT_WHEN_POSSIBLE(#name, name);
170
171 #define WRAP_W_WWW(name)                                                       \
172   extern "C" void *name(void *arg1, void *arg2, void *arg3) {                  \
173     typedef decltype(name) *fntype;                                            \
174     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
175     return fn(arg1, arg2, arg3);                                               \
176   }                                                                            \
177   INTERCEPT_WHEN_POSSIBLE(#name, name);
178
179 #define WRAP_W_WWWW(name)                                                      \
180   extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4) {      \
181     typedef decltype(name) *fntype;                                            \
182     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
183     return fn(arg1, arg2, arg3, arg4);                                         \
184   }                                                                            \
185   INTERCEPT_WHEN_POSSIBLE(#name, name);
186
187 #define WRAP_W_WWWWW(name)                                                     \
188   extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4,        \
189                         void *arg5) {                                          \
190     typedef decltype(name) *fntype;                                            \
191     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
192     return fn(arg1, arg2, arg3, arg4, arg5);                                   \
193   }                                                                            \
194   INTERCEPT_WHEN_POSSIBLE(#name, name);
195
196 #define WRAP_W_WWWWWW(name)                                                    \
197   extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4,        \
198                         void *arg5, void *arg6) {                              \
199     typedef decltype(name) *fntype;                                            \
200     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
201     return fn(arg1, arg2, arg3, arg4, arg5, arg6);                             \
202   }                                                                            \
203   INTERCEPT_WHEN_POSSIBLE(#name, name);
204 // }}}
205
206 // ----------------- ASan own interface functions --------------------
207 // Don't use the INTERFACE_FUNCTION machinery for this function as we actually
208 // want to call it in the __asan_init interceptor.
209 WRAP_W_V(__asan_should_detect_stack_use_after_return)
210 WRAP_W_V(__asan_get_shadow_memory_dynamic_address)
211
212 extern "C" {
213   int __asan_option_detect_stack_use_after_return;
214   uptr __asan_shadow_memory_dynamic_address;
215
216   // Manually wrap __asan_init as we need to initialize
217   // __asan_option_detect_stack_use_after_return afterwards.
218   void __asan_init() {
219     typedef void (*fntype)();
220     static fntype fn = 0;
221     // __asan_init is expected to be called by only one thread.
222     if (fn) return;
223
224     fn = (fntype)getRealProcAddressOrDie("__asan_init");
225     fn();
226     __asan_option_detect_stack_use_after_return =
227         (__asan_should_detect_stack_use_after_return() != 0);
228     __asan_shadow_memory_dynamic_address =
229         (uptr)__asan_get_shadow_memory_dynamic_address();
230     InterceptHooks();
231   }
232 }
233
234 extern "C" void __asan_version_mismatch_check() {
235   // Do nothing.
236 }
237
238 INTERFACE_FUNCTION(__asan_handle_no_return)
239 INTERFACE_FUNCTION(__asan_unhandled_exception_filter)
240
241 INTERFACE_FUNCTION(__asan_report_store1)
242 INTERFACE_FUNCTION(__asan_report_store2)
243 INTERFACE_FUNCTION(__asan_report_store4)
244 INTERFACE_FUNCTION(__asan_report_store8)
245 INTERFACE_FUNCTION(__asan_report_store16)
246 INTERFACE_FUNCTION(__asan_report_store_n)
247
248 INTERFACE_FUNCTION(__asan_report_load1)
249 INTERFACE_FUNCTION(__asan_report_load2)
250 INTERFACE_FUNCTION(__asan_report_load4)
251 INTERFACE_FUNCTION(__asan_report_load8)
252 INTERFACE_FUNCTION(__asan_report_load16)
253 INTERFACE_FUNCTION(__asan_report_load_n)
254
255 INTERFACE_FUNCTION(__asan_store1)
256 INTERFACE_FUNCTION(__asan_store2)
257 INTERFACE_FUNCTION(__asan_store4)
258 INTERFACE_FUNCTION(__asan_store8)
259 INTERFACE_FUNCTION(__asan_store16)
260 INTERFACE_FUNCTION(__asan_storeN)
261
262 INTERFACE_FUNCTION(__asan_load1)
263 INTERFACE_FUNCTION(__asan_load2)
264 INTERFACE_FUNCTION(__asan_load4)
265 INTERFACE_FUNCTION(__asan_load8)
266 INTERFACE_FUNCTION(__asan_load16)
267 INTERFACE_FUNCTION(__asan_loadN)
268
269 INTERFACE_FUNCTION(__asan_memcpy);
270 INTERFACE_FUNCTION(__asan_memset);
271 INTERFACE_FUNCTION(__asan_memmove);
272
273 INTERFACE_FUNCTION(__asan_set_shadow_00);
274 INTERFACE_FUNCTION(__asan_set_shadow_f1);
275 INTERFACE_FUNCTION(__asan_set_shadow_f2);
276 INTERFACE_FUNCTION(__asan_set_shadow_f3);
277 INTERFACE_FUNCTION(__asan_set_shadow_f5);
278 INTERFACE_FUNCTION(__asan_set_shadow_f8);
279
280 INTERFACE_FUNCTION(__asan_alloca_poison);
281 INTERFACE_FUNCTION(__asan_allocas_unpoison);
282
283 INTERFACE_FUNCTION(__asan_register_globals)
284 INTERFACE_FUNCTION(__asan_unregister_globals)
285
286 INTERFACE_FUNCTION(__asan_before_dynamic_init)
287 INTERFACE_FUNCTION(__asan_after_dynamic_init)
288
289 INTERFACE_FUNCTION(__asan_poison_stack_memory)
290 INTERFACE_FUNCTION(__asan_unpoison_stack_memory)
291
292 INTERFACE_FUNCTION(__asan_poison_memory_region)
293 INTERFACE_FUNCTION(__asan_unpoison_memory_region)
294
295 INTERFACE_FUNCTION(__asan_address_is_poisoned)
296 INTERFACE_FUNCTION(__asan_region_is_poisoned)
297
298 INTERFACE_FUNCTION(__asan_get_current_fake_stack)
299 INTERFACE_FUNCTION(__asan_addr_is_in_fake_stack)
300
301 INTERFACE_FUNCTION(__asan_stack_malloc_0)
302 INTERFACE_FUNCTION(__asan_stack_malloc_1)
303 INTERFACE_FUNCTION(__asan_stack_malloc_2)
304 INTERFACE_FUNCTION(__asan_stack_malloc_3)
305 INTERFACE_FUNCTION(__asan_stack_malloc_4)
306 INTERFACE_FUNCTION(__asan_stack_malloc_5)
307 INTERFACE_FUNCTION(__asan_stack_malloc_6)
308 INTERFACE_FUNCTION(__asan_stack_malloc_7)
309 INTERFACE_FUNCTION(__asan_stack_malloc_8)
310 INTERFACE_FUNCTION(__asan_stack_malloc_9)
311 INTERFACE_FUNCTION(__asan_stack_malloc_10)
312
313 INTERFACE_FUNCTION(__asan_stack_free_0)
314 INTERFACE_FUNCTION(__asan_stack_free_1)
315 INTERFACE_FUNCTION(__asan_stack_free_2)
316 INTERFACE_FUNCTION(__asan_stack_free_4)
317 INTERFACE_FUNCTION(__asan_stack_free_5)
318 INTERFACE_FUNCTION(__asan_stack_free_6)
319 INTERFACE_FUNCTION(__asan_stack_free_7)
320 INTERFACE_FUNCTION(__asan_stack_free_8)
321 INTERFACE_FUNCTION(__asan_stack_free_9)
322 INTERFACE_FUNCTION(__asan_stack_free_10)
323
324 // FIXME: we might want to have a sanitizer_win_dll_thunk?
325 INTERFACE_FUNCTION(__sanitizer_annotate_contiguous_container)
326 INTERFACE_FUNCTION(__sanitizer_contiguous_container_find_bad_address)
327 INTERFACE_FUNCTION(__sanitizer_cov)
328 INTERFACE_FUNCTION(__sanitizer_cov_dump)
329 INTERFACE_FUNCTION(__sanitizer_dump_coverage)
330 INTERFACE_FUNCTION(__sanitizer_dump_trace_pc_guard_coverage)
331 INTERFACE_FUNCTION(__sanitizer_cov_indir_call16)
332 INTERFACE_FUNCTION(__sanitizer_cov_init)
333 INTERFACE_FUNCTION(__sanitizer_cov_module_init)
334 INTERFACE_FUNCTION(__sanitizer_cov_trace_basic_block)
335 INTERFACE_FUNCTION(__sanitizer_cov_trace_func_enter)
336 INTERFACE_FUNCTION(__sanitizer_cov_trace_pc_guard)
337 INTERFACE_FUNCTION(__sanitizer_cov_trace_pc_guard_init)
338 INTERFACE_FUNCTION(__sanitizer_cov_with_check)
339 INTERFACE_FUNCTION(__sanitizer_get_allocated_size)
340 INTERFACE_FUNCTION(__sanitizer_get_coverage_guards)
341 INTERFACE_FUNCTION(__sanitizer_get_current_allocated_bytes)
342 INTERFACE_FUNCTION(__sanitizer_get_estimated_allocated_size)
343 INTERFACE_FUNCTION(__sanitizer_get_free_bytes)
344 INTERFACE_FUNCTION(__sanitizer_get_heap_size)
345 INTERFACE_FUNCTION(__sanitizer_get_ownership)
346 INTERFACE_FUNCTION(__sanitizer_get_total_unique_caller_callee_pairs)
347 INTERFACE_FUNCTION(__sanitizer_get_total_unique_coverage)
348 INTERFACE_FUNCTION(__sanitizer_get_unmapped_bytes)
349 INTERFACE_FUNCTION(__sanitizer_maybe_open_cov_file)
350 INTERFACE_FUNCTION(__sanitizer_print_stack_trace)
351 INTERFACE_FUNCTION(__sanitizer_symbolize_pc)
352 INTERFACE_FUNCTION(__sanitizer_symbolize_global)
353 INTERFACE_FUNCTION(__sanitizer_ptr_cmp)
354 INTERFACE_FUNCTION(__sanitizer_ptr_sub)
355 INTERFACE_FUNCTION(__sanitizer_report_error_summary)
356 INTERFACE_FUNCTION(__sanitizer_reset_coverage)
357 INTERFACE_FUNCTION(__sanitizer_get_number_of_counters)
358 INTERFACE_FUNCTION(__sanitizer_update_counter_bitset_and_clear_counters)
359 INTERFACE_FUNCTION(__sanitizer_sandbox_on_notify)
360 INTERFACE_FUNCTION(__sanitizer_set_death_callback)
361 INTERFACE_FUNCTION(__sanitizer_set_report_path)
362 INTERFACE_FUNCTION(__sanitizer_set_report_fd)
363 INTERFACE_FUNCTION(__sanitizer_unaligned_load16)
364 INTERFACE_FUNCTION(__sanitizer_unaligned_load32)
365 INTERFACE_FUNCTION(__sanitizer_unaligned_load64)
366 INTERFACE_FUNCTION(__sanitizer_unaligned_store16)
367 INTERFACE_FUNCTION(__sanitizer_unaligned_store32)
368 INTERFACE_FUNCTION(__sanitizer_unaligned_store64)
369 INTERFACE_FUNCTION(__sanitizer_verify_contiguous_container)
370 INTERFACE_FUNCTION(__sanitizer_install_malloc_and_free_hooks)
371 INTERFACE_FUNCTION(__sanitizer_start_switch_fiber)
372 INTERFACE_FUNCTION(__sanitizer_finish_switch_fiber)
373 INTERFACE_FUNCTION(__sanitizer_get_module_and_offset_for_pc)
374
375 // TODO(timurrrr): Add more interface functions on the as-needed basis.
376
377 // ----------------- Memory allocation functions ---------------------
378 WRAP_V_W(free)
379 WRAP_V_W(_free_base)
380 WRAP_V_WW(_free_dbg)
381
382 WRAP_W_W(malloc)
383 WRAP_W_W(_malloc_base)
384 WRAP_W_WWWW(_malloc_dbg)
385
386 WRAP_W_WW(calloc)
387 WRAP_W_WW(_calloc_base)
388 WRAP_W_WWWWW(_calloc_dbg)
389 WRAP_W_WWW(_calloc_impl)
390
391 WRAP_W_WW(realloc)
392 WRAP_W_WW(_realloc_base)
393 WRAP_W_WWW(_realloc_dbg)
394 WRAP_W_WWW(_recalloc)
395 WRAP_W_WWW(_recalloc_base)
396
397 WRAP_W_W(_msize)
398 WRAP_W_W(_expand)
399 WRAP_W_W(_expand_dbg)
400
401 // TODO(timurrrr): Might want to add support for _aligned_* allocation
402 // functions to detect a bit more bugs.  Those functions seem to wrap malloc().
403
404 // TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cc).
405
406 INTERCEPT_LIBRARY_FUNCTION(atoi);
407 INTERCEPT_LIBRARY_FUNCTION(atol);
408
409 #ifdef _WIN64
410 INTERCEPT_LIBRARY_FUNCTION(__C_specific_handler);
411 #else
412 INTERCEPT_LIBRARY_FUNCTION(_except_handler3);
413
414 // _except_handler4 checks -GS cookie which is different for each module, so we
415 // can't use INTERCEPT_LIBRARY_FUNCTION(_except_handler4).
416 INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) {
417   __asan_handle_no_return();
418   return REAL(_except_handler4)(a, b, c, d);
419 }
420 #endif
421
422 INTERCEPT_LIBRARY_FUNCTION(frexp);
423 INTERCEPT_LIBRARY_FUNCTION(longjmp);
424 #if SANITIZER_INTERCEPT_MEMCHR
425 INTERCEPT_LIBRARY_FUNCTION(memchr);
426 #endif
427 INTERCEPT_LIBRARY_FUNCTION(memcmp);
428 INTERCEPT_LIBRARY_FUNCTION(memcpy);
429 INTERCEPT_LIBRARY_FUNCTION(memmove);
430 INTERCEPT_LIBRARY_FUNCTION(memset);
431 INTERCEPT_LIBRARY_FUNCTION(strcat);  // NOLINT
432 INTERCEPT_LIBRARY_FUNCTION(strchr);
433 INTERCEPT_LIBRARY_FUNCTION(strcmp);
434 INTERCEPT_LIBRARY_FUNCTION(strcpy);  // NOLINT
435 INTERCEPT_LIBRARY_FUNCTION(strcspn);
436 INTERCEPT_LIBRARY_FUNCTION(strdup);
437 INTERCEPT_LIBRARY_FUNCTION(strlen);
438 INTERCEPT_LIBRARY_FUNCTION(strncat);
439 INTERCEPT_LIBRARY_FUNCTION(strncmp);
440 INTERCEPT_LIBRARY_FUNCTION(strncpy);
441 INTERCEPT_LIBRARY_FUNCTION(strnlen);
442 INTERCEPT_LIBRARY_FUNCTION(strpbrk);
443 INTERCEPT_LIBRARY_FUNCTION(strrchr);
444 INTERCEPT_LIBRARY_FUNCTION(strspn);
445 INTERCEPT_LIBRARY_FUNCTION(strstr);
446 INTERCEPT_LIBRARY_FUNCTION(strtol);
447 INTERCEPT_LIBRARY_FUNCTION(wcslen);
448
449 // Must be after all the interceptor declarations due to the way INTERCEPT_HOOKS
450 // is defined.
451 void InterceptHooks() {
452   INTERCEPT_HOOKS();
453 #ifndef _WIN64
454   INTERCEPT_FUNCTION(_except_handler4);
455 #endif
456 }
457
458 // We want to call __asan_init before C/C++ initializers/constructors are
459 // executed, otherwise functions like memset might be invoked.
460 // For some strange reason, merely linking in asan_preinit.cc doesn't work
461 // as the callback is never called...  Is link.exe doing something too smart?
462
463 // In DLLs, the callbacks are expected to return 0,
464 // otherwise CRT initialization fails.
465 static int call_asan_init() {
466   __asan_init();
467   return 0;
468 }
469 #pragma section(".CRT$XIB", long, read)  // NOLINT
470 __declspec(allocate(".CRT$XIB")) int (*__asan_preinit)() = call_asan_init;
471
472 static void WINAPI asan_thread_init(void *mod, unsigned long reason,
473                                    void *reserved) {
474   if (reason == /*DLL_PROCESS_ATTACH=*/1) __asan_init();
475 }
476
477 #pragma section(".CRT$XLAB", long, read)  // NOLINT
478 __declspec(allocate(".CRT$XLAB")) void (WINAPI *__asan_tls_init)(void *,
479     unsigned long, void *) = asan_thread_init;
480
481 ASAN_LINK_GLOBALS_WIN()
482
483 #endif // ASAN_DLL_THUNK