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 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 { 55 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> { 61 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. 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 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). 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. 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. 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