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