1 //===-- asan_win_dll_thunk.cpp --------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is a part of AddressSanitizer, an address sanity checker.
10 //
11 // This file defines a family of thunks that should be statically linked into
12 // the DLLs that have ASan instrumentation in order to delegate the calls to the
13 // shared runtime that lives in the main binary.
14 // See https://github.com/google/sanitizers/issues/209 for the details.
15 //===----------------------------------------------------------------------===//
16 
17 #ifdef SANITIZER_DLL_THUNK
18 #include "asan_init_version.h"
19 #include "interception/interception.h"
20 #include "sanitizer_common/sanitizer_win_defs.h"
21 #include "sanitizer_common/sanitizer_win_dll_thunk.h"
22 #include "sanitizer_common/sanitizer_platform_interceptors.h"
23 
24 // ASan own interface functions.
25 #define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name)
26 #define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
27 #include "asan_interface.inc"
28 
29 // Memory allocation functions.
30 INTERCEPT_WRAP_V_W(free)
31 INTERCEPT_WRAP_V_W(_free_base)
32 INTERCEPT_WRAP_V_WW(_free_dbg)
33 
34 INTERCEPT_WRAP_W_W(malloc)
35 INTERCEPT_WRAP_W_W(_malloc_base)
36 INTERCEPT_WRAP_W_WWWW(_malloc_dbg)
37 
38 INTERCEPT_WRAP_W_WW(calloc)
39 INTERCEPT_WRAP_W_WW(_calloc_base)
40 INTERCEPT_WRAP_W_WWWWW(_calloc_dbg)
41 INTERCEPT_WRAP_W_WWW(_calloc_impl)
42 
43 INTERCEPT_WRAP_W_WW(realloc)
44 INTERCEPT_WRAP_W_WW(_realloc_base)
45 INTERCEPT_WRAP_W_WWW(_realloc_dbg)
46 INTERCEPT_WRAP_W_WWW(_recalloc)
47 INTERCEPT_WRAP_W_WWW(_recalloc_base)
48 
49 INTERCEPT_WRAP_W_W(_msize)
50 INTERCEPT_WRAP_W_W(_msize_base)
51 INTERCEPT_WRAP_W_W(_expand)
52 INTERCEPT_WRAP_W_W(_expand_dbg)
53 
54 // TODO(timurrrr): Might want to add support for _aligned_* allocation
55 // functions to detect a bit more bugs.  Those functions seem to wrap malloc().
56 
57 // TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cpp)
58 
59 #  if defined(_MSC_VER) && !defined(__clang__)
60 // Disable warnings such as: 'void memchr(void)': incorrect number of arguments
61 // for intrinsic function, expected '3' arguments.
62 #    pragma warning(push)
63 #    pragma warning(disable : 4392)
64 #  endif
65 
66 INTERCEPT_LIBRARY_FUNCTION(atoi);
67 INTERCEPT_LIBRARY_FUNCTION(atol);
68 INTERCEPT_LIBRARY_FUNCTION(frexp);
69 INTERCEPT_LIBRARY_FUNCTION(longjmp);
70 #if SANITIZER_INTERCEPT_MEMCHR
71 INTERCEPT_LIBRARY_FUNCTION(memchr);
72 #endif
73 INTERCEPT_LIBRARY_FUNCTION(memcmp);
74 INTERCEPT_LIBRARY_FUNCTION(memcpy);
75 INTERCEPT_LIBRARY_FUNCTION(memmove);
76 INTERCEPT_LIBRARY_FUNCTION(memset);
77 INTERCEPT_LIBRARY_FUNCTION(strcat);
78 INTERCEPT_LIBRARY_FUNCTION(strchr);
79 INTERCEPT_LIBRARY_FUNCTION(strcmp);
80 INTERCEPT_LIBRARY_FUNCTION(strcpy);
81 INTERCEPT_LIBRARY_FUNCTION(strcspn);
82 INTERCEPT_LIBRARY_FUNCTION(strdup);
83 INTERCEPT_LIBRARY_FUNCTION(strlen);
84 INTERCEPT_LIBRARY_FUNCTION(strncat);
85 INTERCEPT_LIBRARY_FUNCTION(strncmp);
86 INTERCEPT_LIBRARY_FUNCTION(strncpy);
87 INTERCEPT_LIBRARY_FUNCTION(strnlen);
88 INTERCEPT_LIBRARY_FUNCTION(strpbrk);
89 INTERCEPT_LIBRARY_FUNCTION(strrchr);
90 INTERCEPT_LIBRARY_FUNCTION(strspn);
91 INTERCEPT_LIBRARY_FUNCTION(strstr);
92 INTERCEPT_LIBRARY_FUNCTION(strtok);
93 INTERCEPT_LIBRARY_FUNCTION(strtol);
94 INTERCEPT_LIBRARY_FUNCTION(wcslen);
95 INTERCEPT_LIBRARY_FUNCTION(wcsnlen);
96 
97 #  if defined(_MSC_VER) && !defined(__clang__)
98 #    pragma warning(pop)
99 #  endif
100 
101 #ifdef _WIN64
102 INTERCEPT_LIBRARY_FUNCTION(__C_specific_handler);
103 #else
104 INTERCEPT_LIBRARY_FUNCTION(_except_handler3);
105 // _except_handler4 checks -GS cookie which is different for each module, so we
106 // can't use INTERCEPT_LIBRARY_FUNCTION(_except_handler4).
107 INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) {
108   __asan_handle_no_return();
109   return REAL(_except_handler4)(a, b, c, d);
110 }
111 #endif
112 
113 // Windows specific functions not included in asan_interface.inc.
114 INTERCEPT_WRAP_W_V(__asan_should_detect_stack_use_after_return)
115 INTERCEPT_WRAP_W_V(__asan_get_shadow_memory_dynamic_address)
116 INTERCEPT_WRAP_W_W(__asan_unhandled_exception_filter)
117 
118 using namespace __sanitizer;
119 
120 extern "C" {
121 int __asan_option_detect_stack_use_after_return;
122 uptr __asan_shadow_memory_dynamic_address;
123 } // extern "C"
124 
125 static int asan_dll_thunk_init() {
126   typedef void (*fntype)();
127   static fntype fn = 0;
128   // asan_dll_thunk_init is expected to be called by only one thread.
129   if (fn) return 0;
130 
131   // Ensure all interception was executed.
132   __dll_thunk_init();
133 
134   fn = (fntype) dllThunkGetRealAddrOrDie("__asan_init");
135   fn();
136   __asan_option_detect_stack_use_after_return =
137       (__asan_should_detect_stack_use_after_return() != 0);
138   __asan_shadow_memory_dynamic_address =
139       (uptr)__asan_get_shadow_memory_dynamic_address();
140 
141 #ifndef _WIN64
142   INTERCEPT_FUNCTION(_except_handler4);
143 #endif
144   // In DLLs, the callbacks are expected to return 0,
145   // otherwise CRT initialization fails.
146   return 0;
147 }
148 
149 #pragma section(".CRT$XIB", long, read)
150 __declspec(allocate(".CRT$XIB")) int (*__asan_preinit)() = asan_dll_thunk_init;
151 
152 static void WINAPI asan_thread_init(void *mod, unsigned long reason,
153                                     void *reserved) {
154   if (reason == /*DLL_PROCESS_ATTACH=*/1) asan_dll_thunk_init();
155 }
156 
157 #pragma section(".CRT$XLAB", long, read)
158 __declspec(allocate(".CRT$XLAB")) void (WINAPI *__asan_tls_init)(void *,
159     unsigned long, void *) = asan_thread_init;
160 
161 WIN_FORCE_LINK(__asan_dso_reg_hook)
162 
163 #endif // SANITIZER_DLL_THUNK
164