Home | History | Annotate | Download | only in asan
      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