2015-01-14 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libsanitizer / asan / asan_win_dll_thunk.cc
blob6adb7d2e942c131eb39cb54f82a15a8671329f58
1 //===-- asan_win_dll_thunk.cc ---------------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is a part of AddressSanitizer, an address sanity checker.
9 //
10 // This file defines a family of thunks that should be statically linked into
11 // the DLLs that have ASan instrumentation in order to delegate the calls to the
12 // shared runtime that lives in the main binary.
13 // See https://code.google.com/p/address-sanitizer/issues/detail?id=209 for the
14 // details.
15 //===----------------------------------------------------------------------===//
17 // Only compile this code when buidling asan_dll_thunk.lib
18 // Using #ifdef rather than relying on Makefiles etc.
19 // simplifies the build procedure.
20 #ifdef ASAN_DLL_THUNK
21 #include "asan_init_version.h"
22 #include "sanitizer_common/sanitizer_interception.h"
24 // ---------- Function interception helper functions and macros ----------- {{{1
25 extern "C" {
26 void *__stdcall GetModuleHandleA(const char *module_name);
27 void *__stdcall GetProcAddress(void *module, const char *proc_name);
28 void abort();
31 static void *getRealProcAddressOrDie(const char *name) {
32 void *ret = GetProcAddress(GetModuleHandleA(0), name);
33 if (!ret)
34 abort();
35 return ret;
38 // We need to intercept some functions (e.g. ASan interface, memory allocator --
39 // let's call them "hooks") exported by the DLL thunk and forward the hooks to
40 // the runtime in the main module.
41 // However, we don't want to keep two lists of these hooks.
42 // To avoid that, the list of hooks should be defined using the
43 // INTERCEPT_WHEN_POSSIBLE macro. Then, all these hooks can be intercepted
44 // at once by calling INTERCEPT_HOOKS().
46 // Use macro+template magic to automatically generate the list of hooks.
47 // Each hook at line LINE defines a template class with a static
48 // FunctionInterceptor<LINE>::Execute() method intercepting the hook.
49 // The default implementation of FunctionInterceptor<LINE> is to call
50 // the Execute() method corresponding to the previous line.
51 template<int LINE>
52 struct FunctionInterceptor {
53 static void Execute() { FunctionInterceptor<LINE-1>::Execute(); }
56 // There shouldn't be any hooks with negative definition line number.
57 template<>
58 struct FunctionInterceptor<0> {
59 static void Execute() {}
62 #define INTERCEPT_WHEN_POSSIBLE(main_function, dll_function) \
63 template<> struct FunctionInterceptor<__LINE__> { \
64 static void Execute() { \
65 void *wrapper = getRealProcAddressOrDie(main_function); \
66 if (!__interception::OverrideFunction((uptr)dll_function, \
67 (uptr)wrapper, 0)) \
68 abort(); \
69 FunctionInterceptor<__LINE__-1>::Execute(); \
70 } \
73 // Special case of hooks -- ASan own interface functions. Those are only called
74 // after __asan_init, thus an empty implementation is sufficient.
75 #define INTERFACE_FUNCTION(name) \
76 extern "C" __declspec(noinline) void name() { \
77 volatile int prevent_icf = (__LINE__ << 8); (void)prevent_icf; \
78 __debugbreak(); \
79 } \
80 INTERCEPT_WHEN_POSSIBLE(#name, name)
82 // INTERCEPT_HOOKS must be used after the last INTERCEPT_WHEN_POSSIBLE.
83 #define INTERCEPT_HOOKS FunctionInterceptor<__LINE__>::Execute
85 // We can't define our own version of strlen etc. because that would lead to
86 // link-time or even type mismatch errors. Instead, we can declare a function
87 // just to be able to get its address. Me may miss the first few calls to the
88 // functions since it can be called before __asan_init, but that would lead to
89 // false negatives in the startup code before user's global initializers, which
90 // isn't a big deal.
91 #define INTERCEPT_LIBRARY_FUNCTION(name) \
92 extern "C" void name(); \
93 INTERCEPT_WHEN_POSSIBLE(WRAPPER_NAME(name), name)
95 // Disable compiler warnings that show up if we declare our own version
96 // of a compiler intrinsic (e.g. strlen).
97 #pragma warning(disable: 4391)
98 #pragma warning(disable: 4392)
100 static void InterceptHooks();
101 // }}}
103 // ---------- Function wrapping helpers ----------------------------------- {{{1
104 #define WRAP_V_V(name) \
105 extern "C" void name() { \
106 typedef void (*fntype)(); \
107 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
108 fn(); \
110 INTERCEPT_WHEN_POSSIBLE(#name, name);
112 #define WRAP_V_W(name) \
113 extern "C" void name(void *arg) { \
114 typedef void (*fntype)(void *arg); \
115 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
116 fn(arg); \
118 INTERCEPT_WHEN_POSSIBLE(#name, name);
120 #define WRAP_V_WW(name) \
121 extern "C" void name(void *arg1, void *arg2) { \
122 typedef void (*fntype)(void *, void *); \
123 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
124 fn(arg1, arg2); \
126 INTERCEPT_WHEN_POSSIBLE(#name, name);
128 #define WRAP_V_WWW(name) \
129 extern "C" void name(void *arg1, void *arg2, void *arg3) { \
130 typedef void *(*fntype)(void *, void *, void *); \
131 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
132 fn(arg1, arg2, arg3); \
134 INTERCEPT_WHEN_POSSIBLE(#name, name);
136 #define WRAP_W_V(name) \
137 extern "C" void *name() { \
138 typedef void *(*fntype)(); \
139 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
140 return fn(); \
142 INTERCEPT_WHEN_POSSIBLE(#name, name);
144 #define WRAP_W_W(name) \
145 extern "C" void *name(void *arg) { \
146 typedef void *(*fntype)(void *arg); \
147 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
148 return fn(arg); \
150 INTERCEPT_WHEN_POSSIBLE(#name, name);
152 #define WRAP_W_WW(name) \
153 extern "C" void *name(void *arg1, void *arg2) { \
154 typedef void *(*fntype)(void *, void *); \
155 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
156 return fn(arg1, arg2); \
158 INTERCEPT_WHEN_POSSIBLE(#name, name);
160 #define WRAP_W_WWW(name) \
161 extern "C" void *name(void *arg1, void *arg2, void *arg3) { \
162 typedef void *(*fntype)(void *, void *, void *); \
163 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
164 return fn(arg1, arg2, arg3); \
166 INTERCEPT_WHEN_POSSIBLE(#name, name);
168 #define WRAP_W_WWWW(name) \
169 extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4) { \
170 typedef void *(*fntype)(void *, void *, void *, void *); \
171 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
172 return fn(arg1, arg2, arg3, arg4); \
174 INTERCEPT_WHEN_POSSIBLE(#name, name);
176 #define WRAP_W_WWWWW(name) \
177 extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \
178 void *arg5) { \
179 typedef void *(*fntype)(void *, void *, void *, void *, void *); \
180 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
181 return fn(arg1, arg2, arg3, arg4, arg5); \
183 INTERCEPT_WHEN_POSSIBLE(#name, name);
185 #define WRAP_W_WWWWWW(name) \
186 extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \
187 void *arg5, void *arg6) { \
188 typedef void *(*fntype)(void *, void *, void *, void *, void *, void *); \
189 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
190 return fn(arg1, arg2, arg3, arg4, arg5, arg6); \
192 INTERCEPT_WHEN_POSSIBLE(#name, name);
193 // }}}
195 // ----------------- ASan own interface functions --------------------
196 // Don't use the INTERFACE_FUNCTION machinery for this function as we actually
197 // want to call it in the __asan_init interceptor.
198 WRAP_W_V(__asan_should_detect_stack_use_after_return)
200 extern "C" {
201 int __asan_option_detect_stack_use_after_return;
203 // Manually wrap __asan_init as we need to initialize
204 // __asan_option_detect_stack_use_after_return afterwards.
205 void __asan_init() {
206 typedef void (*fntype)();
207 static fntype fn = 0;
208 // __asan_init is expected to be called by only one thread.
209 if (fn) return;
211 fn = (fntype)getRealProcAddressOrDie(__asan_init_name);
212 fn();
213 __asan_option_detect_stack_use_after_return =
214 (__asan_should_detect_stack_use_after_return() != 0);
216 InterceptHooks();
220 INTERFACE_FUNCTION(__asan_handle_no_return)
222 INTERFACE_FUNCTION(__asan_report_store1)
223 INTERFACE_FUNCTION(__asan_report_store2)
224 INTERFACE_FUNCTION(__asan_report_store4)
225 INTERFACE_FUNCTION(__asan_report_store8)
226 INTERFACE_FUNCTION(__asan_report_store16)
227 INTERFACE_FUNCTION(__asan_report_store_n)
229 INTERFACE_FUNCTION(__asan_report_load1)
230 INTERFACE_FUNCTION(__asan_report_load2)
231 INTERFACE_FUNCTION(__asan_report_load4)
232 INTERFACE_FUNCTION(__asan_report_load8)
233 INTERFACE_FUNCTION(__asan_report_load16)
234 INTERFACE_FUNCTION(__asan_report_load_n)
236 INTERFACE_FUNCTION(__asan_store1)
237 INTERFACE_FUNCTION(__asan_store2)
238 INTERFACE_FUNCTION(__asan_store4)
239 INTERFACE_FUNCTION(__asan_store8)
240 INTERFACE_FUNCTION(__asan_store16)
241 INTERFACE_FUNCTION(__asan_storeN)
243 INTERFACE_FUNCTION(__asan_load1)
244 INTERFACE_FUNCTION(__asan_load2)
245 INTERFACE_FUNCTION(__asan_load4)
246 INTERFACE_FUNCTION(__asan_load8)
247 INTERFACE_FUNCTION(__asan_load16)
248 INTERFACE_FUNCTION(__asan_loadN)
250 INTERFACE_FUNCTION(__asan_memcpy);
251 INTERFACE_FUNCTION(__asan_memset);
252 INTERFACE_FUNCTION(__asan_memmove);
254 INTERFACE_FUNCTION(__asan_register_globals)
255 INTERFACE_FUNCTION(__asan_unregister_globals)
257 INTERFACE_FUNCTION(__asan_before_dynamic_init)
258 INTERFACE_FUNCTION(__asan_after_dynamic_init)
260 INTERFACE_FUNCTION(__asan_poison_stack_memory)
261 INTERFACE_FUNCTION(__asan_unpoison_stack_memory)
263 INTERFACE_FUNCTION(__asan_poison_memory_region)
264 INTERFACE_FUNCTION(__asan_unpoison_memory_region)
266 INTERFACE_FUNCTION(__asan_address_is_poisoned)
267 INTERFACE_FUNCTION(__asan_region_is_poisoned)
269 INTERFACE_FUNCTION(__asan_get_current_fake_stack)
270 INTERFACE_FUNCTION(__asan_addr_is_in_fake_stack)
272 INTERFACE_FUNCTION(__asan_stack_malloc_0)
273 INTERFACE_FUNCTION(__asan_stack_malloc_1)
274 INTERFACE_FUNCTION(__asan_stack_malloc_2)
275 INTERFACE_FUNCTION(__asan_stack_malloc_3)
276 INTERFACE_FUNCTION(__asan_stack_malloc_4)
277 INTERFACE_FUNCTION(__asan_stack_malloc_5)
278 INTERFACE_FUNCTION(__asan_stack_malloc_6)
279 INTERFACE_FUNCTION(__asan_stack_malloc_7)
280 INTERFACE_FUNCTION(__asan_stack_malloc_8)
281 INTERFACE_FUNCTION(__asan_stack_malloc_9)
282 INTERFACE_FUNCTION(__asan_stack_malloc_10)
284 INTERFACE_FUNCTION(__asan_stack_free_0)
285 INTERFACE_FUNCTION(__asan_stack_free_1)
286 INTERFACE_FUNCTION(__asan_stack_free_2)
287 INTERFACE_FUNCTION(__asan_stack_free_4)
288 INTERFACE_FUNCTION(__asan_stack_free_5)
289 INTERFACE_FUNCTION(__asan_stack_free_6)
290 INTERFACE_FUNCTION(__asan_stack_free_7)
291 INTERFACE_FUNCTION(__asan_stack_free_8)
292 INTERFACE_FUNCTION(__asan_stack_free_9)
293 INTERFACE_FUNCTION(__asan_stack_free_10)
295 INTERFACE_FUNCTION(__sanitizer_cov_module_init)
297 // TODO(timurrrr): Add more interface functions on the as-needed basis.
299 // ----------------- Memory allocation functions ---------------------
300 WRAP_V_W(free)
301 WRAP_V_WW(_free_dbg)
303 WRAP_W_W(malloc)
304 WRAP_W_WWWW(_malloc_dbg)
306 WRAP_W_WW(calloc)
307 WRAP_W_WWWWW(_calloc_dbg)
308 WRAP_W_WWW(_calloc_impl)
310 WRAP_W_WW(realloc)
311 WRAP_W_WWW(_realloc_dbg)
312 WRAP_W_WWW(_recalloc)
314 WRAP_W_W(_msize)
315 WRAP_W_W(_expand)
316 WRAP_W_W(_expand_dbg)
318 // TODO(timurrrr): Might want to add support for _aligned_* allocation
319 // functions to detect a bit more bugs. Those functions seem to wrap malloc().
321 // TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cc).
323 INTERCEPT_LIBRARY_FUNCTION(atoi);
324 INTERCEPT_LIBRARY_FUNCTION(atol);
325 INTERCEPT_LIBRARY_FUNCTION(_except_handler3);
327 // _except_handler4 checks -GS cookie which is different for each module, so we
328 // can't use INTERCEPT_LIBRARY_FUNCTION(_except_handler4).
329 INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) {
330 __asan_handle_no_return();
331 return REAL(_except_handler4)(a, b, c, d);
334 INTERCEPT_LIBRARY_FUNCTION(frexp);
335 INTERCEPT_LIBRARY_FUNCTION(longjmp);
336 INTERCEPT_LIBRARY_FUNCTION(memchr);
337 INTERCEPT_LIBRARY_FUNCTION(memcmp);
338 INTERCEPT_LIBRARY_FUNCTION(memcpy);
339 INTERCEPT_LIBRARY_FUNCTION(memmove);
340 INTERCEPT_LIBRARY_FUNCTION(memset);
341 INTERCEPT_LIBRARY_FUNCTION(strcat); // NOLINT
342 INTERCEPT_LIBRARY_FUNCTION(strchr);
343 INTERCEPT_LIBRARY_FUNCTION(strcmp);
344 INTERCEPT_LIBRARY_FUNCTION(strcpy); // NOLINT
345 INTERCEPT_LIBRARY_FUNCTION(strlen);
346 INTERCEPT_LIBRARY_FUNCTION(strncat);
347 INTERCEPT_LIBRARY_FUNCTION(strncmp);
348 INTERCEPT_LIBRARY_FUNCTION(strncpy);
349 INTERCEPT_LIBRARY_FUNCTION(strnlen);
350 INTERCEPT_LIBRARY_FUNCTION(strtol);
351 INTERCEPT_LIBRARY_FUNCTION(wcslen);
353 // Must be after all the interceptor declarations due to the way INTERCEPT_HOOKS
354 // is defined.
355 void InterceptHooks() {
356 INTERCEPT_HOOKS();
357 INTERCEPT_FUNCTION(_except_handler4);
360 // We want to call __asan_init before C/C++ initializers/constructors are
361 // executed, otherwise functions like memset might be invoked.
362 // For some strange reason, merely linking in asan_preinit.cc doesn't work
363 // as the callback is never called... Is link.exe doing something too smart?
365 // In DLLs, the callbacks are expected to return 0,
366 // otherwise CRT initialization fails.
367 static int call_asan_init() {
368 __asan_init();
369 return 0;
371 #pragma section(".CRT$XIB", long, read) // NOLINT
372 __declspec(allocate(".CRT$XIB")) int (*__asan_preinit)() = call_asan_init;
374 #endif // ASAN_DLL_THUNK