1 //===-- asan_dll_thunk.cc -------------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of AddressSanitizer, an address sanity checker.
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
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.
21 #include "sanitizer_common/sanitizer_interception.h"
23 // ----------------- Helper functions and macros --------------------- {{{1
25 void *__stdcall
GetModuleHandleA(const char *module_name
);
26 void *__stdcall
GetProcAddress(void *module
, const char *proc_name
);
30 static void *getRealProcAddressOrDie(const char *name
) {
31 void *ret
= GetProcAddress(GetModuleHandleA(0), name
);
37 #define WRAP_V_V(name) \
38 extern "C" void name() { \
39 typedef void (*fntype)(); \
40 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
44 #define WRAP_V_W(name) \
45 extern "C" void name(void *arg) { \
46 typedef void (*fntype)(void *arg); \
47 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
51 #define WRAP_V_WW(name) \
52 extern "C" void name(void *arg1, void *arg2) { \
53 typedef void (*fntype)(void *, void *); \
54 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
58 #define WRAP_V_WWW(name) \
59 extern "C" void name(void *arg1, void *arg2, void *arg3) { \
60 typedef void *(*fntype)(void *, void *, void *); \
61 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
62 fn(arg1, arg2, arg3); \
65 #define WRAP_W_V(name) \
66 extern "C" void *name() { \
67 typedef void *(*fntype)(); \
68 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
72 #define WRAP_W_W(name) \
73 extern "C" void *name(void *arg) { \
74 typedef void *(*fntype)(void *arg); \
75 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
79 #define WRAP_W_WW(name) \
80 extern "C" void *name(void *arg1, void *arg2) { \
81 typedef void *(*fntype)(void *, void *); \
82 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
83 return fn(arg1, arg2); \
86 #define WRAP_W_WWW(name) \
87 extern "C" void *name(void *arg1, void *arg2, void *arg3) { \
88 typedef void *(*fntype)(void *, void *, void *); \
89 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
90 return fn(arg1, arg2, arg3); \
93 #define WRAP_W_WWWW(name) \
94 extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4) { \
95 typedef void *(*fntype)(void *, void *, void *, void *); \
96 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
97 return fn(arg1, arg2, arg3, arg4); \
100 #define WRAP_W_WWWWW(name) \
101 extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \
103 typedef void *(*fntype)(void *, void *, void *, void *, void *); \
104 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
105 return fn(arg1, arg2, arg3, arg4, arg5); \
108 #define WRAP_W_WWWWWW(name) \
109 extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \
110 void *arg5, void *arg6) { \
111 typedef void *(*fntype)(void *, void *, void *, void *, void *, void *); \
112 static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
113 return fn(arg1, arg2, arg3, arg4, arg5, arg6); \
117 // --------- Interface interception helper functions and macros ----------- {{{1
118 // We need to intercept the ASan interface exported by the DLL thunk and forward
119 // all the functions to the runtime in the main module.
120 // However, we don't want to keep two lists of interface functions.
121 // To avoid that, the list of interface functions should be defined using the
122 // INTERFACE_FUNCTION macro. Then, all the interface can be intercepted at once
123 // by calling INTERCEPT_ASAN_INTERFACE().
125 // Use macro+template magic to automatically generate the list of interface
126 // functions. Each interface function at line LINE defines a template class
127 // with a static InterfaceInteceptor<LINE>::Execute() method intercepting the
128 // function. The default implementation of InterfaceInteceptor<LINE> is to call
129 // the Execute() method corresponding to the previous line.
131 struct InterfaceInteceptor
{
132 static void Execute() { InterfaceInteceptor
<LINE
-1>::Execute(); }
135 // There shouldn't be any interface function with negative line number.
137 struct InterfaceInteceptor
<0> {
138 static void Execute() {}
141 #define INTERFACE_FUNCTION(name) \
142 extern "C" void name() { __debugbreak(); } \
143 template<> struct InterfaceInteceptor<__LINE__> { \
144 static void Execute() { \
145 void *wrapper = getRealProcAddressOrDie(#name); \
146 if (!__interception::OverrideFunction((uptr)name, (uptr)wrapper, 0)) \
148 InterfaceInteceptor<__LINE__-1>::Execute(); \
152 // INTERCEPT_ASAN_INTERFACE must be used after the last INTERFACE_FUNCTION.
153 #define INTERCEPT_ASAN_INTERFACE InterfaceInteceptor<__LINE__>::Execute
155 static void InterceptASanInterface();
158 // ----------------- ASan own interface functions --------------------
159 // Don't use the INTERFACE_FUNCTION machinery for this function as we actually
160 // want to call it in the __asan_init interceptor.
161 WRAP_W_V(__asan_should_detect_stack_use_after_return
)
164 int __asan_option_detect_stack_use_after_return
;
166 // Manually wrap __asan_init as we need to initialize
167 // __asan_option_detect_stack_use_after_return afterwards.
168 void __asan_init_v3() {
169 typedef void (*fntype
)();
170 static fntype fn
= 0;
173 fn
= (fntype
)getRealProcAddressOrDie("__asan_init_v3");
175 __asan_option_detect_stack_use_after_return
=
176 (__asan_should_detect_stack_use_after_return() != 0);
178 InterceptASanInterface();
182 INTERFACE_FUNCTION(__asan_handle_no_return
)
184 INTERFACE_FUNCTION(__asan_report_store1
)
185 INTERFACE_FUNCTION(__asan_report_store2
)
186 INTERFACE_FUNCTION(__asan_report_store4
)
187 INTERFACE_FUNCTION(__asan_report_store8
)
188 INTERFACE_FUNCTION(__asan_report_store16
)
189 INTERFACE_FUNCTION(__asan_report_store_n
)
191 INTERFACE_FUNCTION(__asan_report_load1
)
192 INTERFACE_FUNCTION(__asan_report_load2
)
193 INTERFACE_FUNCTION(__asan_report_load4
)
194 INTERFACE_FUNCTION(__asan_report_load8
)
195 INTERFACE_FUNCTION(__asan_report_load16
)
196 INTERFACE_FUNCTION(__asan_report_load_n
)
198 INTERFACE_FUNCTION(__asan_memcpy
);
199 INTERFACE_FUNCTION(__asan_memset
);
200 INTERFACE_FUNCTION(__asan_memmove
);
202 INTERFACE_FUNCTION(__asan_register_globals
)
203 INTERFACE_FUNCTION(__asan_unregister_globals
)
205 INTERFACE_FUNCTION(__asan_before_dynamic_init
)
206 INTERFACE_FUNCTION(__asan_after_dynamic_init
)
208 INTERFACE_FUNCTION(__asan_poison_stack_memory
)
209 INTERFACE_FUNCTION(__asan_unpoison_stack_memory
)
211 INTERFACE_FUNCTION(__asan_poison_memory_region
)
212 INTERFACE_FUNCTION(__asan_unpoison_memory_region
)
214 INTERFACE_FUNCTION(__asan_get_current_fake_stack
)
215 INTERFACE_FUNCTION(__asan_addr_is_in_fake_stack
)
217 INTERFACE_FUNCTION(__asan_stack_malloc_0
)
218 INTERFACE_FUNCTION(__asan_stack_malloc_1
)
219 INTERFACE_FUNCTION(__asan_stack_malloc_2
)
220 INTERFACE_FUNCTION(__asan_stack_malloc_3
)
221 INTERFACE_FUNCTION(__asan_stack_malloc_4
)
222 INTERFACE_FUNCTION(__asan_stack_malloc_5
)
223 INTERFACE_FUNCTION(__asan_stack_malloc_6
)
224 INTERFACE_FUNCTION(__asan_stack_malloc_7
)
225 INTERFACE_FUNCTION(__asan_stack_malloc_8
)
226 INTERFACE_FUNCTION(__asan_stack_malloc_9
)
227 INTERFACE_FUNCTION(__asan_stack_malloc_10
)
229 INTERFACE_FUNCTION(__asan_stack_free_0
)
230 INTERFACE_FUNCTION(__asan_stack_free_1
)
231 INTERFACE_FUNCTION(__asan_stack_free_2
)
232 INTERFACE_FUNCTION(__asan_stack_free_4
)
233 INTERFACE_FUNCTION(__asan_stack_free_5
)
234 INTERFACE_FUNCTION(__asan_stack_free_6
)
235 INTERFACE_FUNCTION(__asan_stack_free_7
)
236 INTERFACE_FUNCTION(__asan_stack_free_8
)
237 INTERFACE_FUNCTION(__asan_stack_free_9
)
238 INTERFACE_FUNCTION(__asan_stack_free_10
)
240 // TODO(timurrrr): Add more interface functions on the as-needed basis.
242 // ----------------- Memory allocation functions ---------------------
247 WRAP_W_WWWW(_malloc_dbg
)
250 WRAP_W_WWWWW(_calloc_dbg
)
251 WRAP_W_WWW(_calloc_impl
)
254 WRAP_W_WWW(_realloc_dbg
)
255 WRAP_W_WWW(_recalloc
)
259 WRAP_W_W(_expand_dbg
)
261 // TODO(timurrrr): Might want to add support for _aligned_* allocation
262 // functions to detect a bit more bugs. Those functions seem to wrap malloc().
264 // TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cc).
266 void InterceptASanInterface() {
267 INTERCEPT_ASAN_INTERFACE();
270 #endif // ASAN_DLL_THUNK