168cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov//===-- asan_dll_thunk.cc -------------------------------------------------===// 268cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// 368cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// The LLVM Compiler Infrastructure 468cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// 568cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// This file is distributed under the University of Illinois Open Source 668cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// License. See LICENSE.TXT for details. 768cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// 868cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov//===----------------------------------------------------------------------===// 968cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// 1068cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// This file is a part of AddressSanitizer, an address sanity checker. 1168cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// 1268cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// This file defines a family of thunks that should be statically linked into 1368cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// the DLLs that have ASan instrumentation in order to delegate the calls to the 1468cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// shared runtime that lives in the main binary. 1568cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// See https://code.google.com/p/address-sanitizer/issues/detail?id=209 for the 1668cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// details. 1768cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov//===----------------------------------------------------------------------===// 1868cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov 1968cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// Only compile this code when buidling asan_dll_thunk.lib 2068cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// Using #ifdef rather than relying on Makefiles etc. 2168cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// simplifies the build procedure. 2268cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov#ifdef ASAN_DLL_THUNK 235d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#include "asan_init_version.h" 242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_common/sanitizer_interception.h" 2568cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov 262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// ---------- Function interception helper functions and macros ----------- {{{1 2743e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanovextern "C" { 2843e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanovvoid *__stdcall GetModuleHandleA(const char *module_name); 2943e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanovvoid *__stdcall GetProcAddress(void *module, const char *proc_name); 3043e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanovvoid abort(); 3143e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov} 3268cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov 3343e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanovstatic void *getRealProcAddressOrDie(const char *name) { 3443e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov void *ret = GetProcAddress(GetModuleHandleA(0), name); 3568cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov if (!ret) 3668cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov abort(); 3768cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov return ret; 3868cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov} 3968cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov 402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// We need to intercept some functions (e.g. ASan interface, memory allocator -- 412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// let's call them "hooks") exported by the DLL thunk and forward the hooks to 422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// the runtime in the main module. 432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// However, we don't want to keep two lists of these hooks. 442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// To avoid that, the list of hooks should be defined using the 452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// INTERCEPT_WHEN_POSSIBLE macro. Then, all these hooks can be intercepted 462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// at once by calling INTERCEPT_HOOKS(). 472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Use macro+template magic to automatically generate the list of hooks. 492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Each hook at line LINE defines a template class with a static 502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// FunctionInterceptor<LINE>::Execute() method intercepting the hook. 512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// The default implementation of FunctionInterceptor<LINE> is to call 522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// the Execute() method corresponding to the previous line. 532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestemplate<int LINE> 542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstruct FunctionInterceptor { 552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines static void Execute() { FunctionInterceptor<LINE-1>::Execute(); } 562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}; 572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// There shouldn't be any hooks with negative definition line number. 592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestemplate<> 602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstruct FunctionInterceptor<0> { 612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines static void Execute() {} 622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}; 632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define INTERCEPT_WHEN_POSSIBLE(main_function, dll_function) \ 652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines template<> struct FunctionInterceptor<__LINE__> { \ 662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines static void Execute() { \ 672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void *wrapper = getRealProcAddressOrDie(main_function); \ 682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (!__interception::OverrideFunction((uptr)dll_function, \ 692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (uptr)wrapper, 0)) \ 702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines abort(); \ 712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines FunctionInterceptor<__LINE__-1>::Execute(); \ 722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } \ 732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines }; 742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Special case of hooks -- ASan own interface functions. Those are only called 762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// after __asan_init, thus an empty implementation is sufficient. 772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define INTERFACE_FUNCTION(name) \ 785d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines extern "C" void name() { \ 795d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines volatile int prevent_icf = (__LINE__ << 8); (void)prevent_icf; \ 805d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines __debugbreak(); \ 815d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines } \ 822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines INTERCEPT_WHEN_POSSIBLE(#name, name) 832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// INTERCEPT_HOOKS must be used after the last INTERCEPT_WHEN_POSSIBLE. 852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define INTERCEPT_HOOKS FunctionInterceptor<__LINE__>::Execute 862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// We can't define our own version of strlen etc. because that would lead to 882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// link-time or even type mismatch errors. Instead, we can declare a function 892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// just to be able to get its address. Me may miss the first few calls to the 902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// functions since it can be called before __asan_init, but that would lead to 912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// false negatives in the startup code before user's global initializers, which 922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// isn't a big deal. 932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define INTERCEPT_LIBRARY_FUNCTION(name) \ 942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines extern "C" void name(); \ 952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines INTERCEPT_WHEN_POSSIBLE(WRAPPER_NAME(name), name) 962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Disable compiler warnings that show up if we declare our own version 982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// of a compiler intrinsic (e.g. strlen). 992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#pragma warning(disable: 4391) 1002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#pragma warning(disable: 4392) 1012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void InterceptHooks(); 1032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// }}} 1042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// ---------- Function wrapping helpers ----------------------------------- {{{1 10643e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov#define WRAP_V_V(name) \ 10768cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov extern "C" void name() { \ 10868cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov typedef void (*fntype)(); \ 109a8b8e964d7b94cae465df77642465901b1b3079dTimur Iskhodzhanov static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ 11068cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov fn(); \ 1112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } \ 1122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines INTERCEPT_WHEN_POSSIBLE(#name, name); 11368cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov 11443e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov#define WRAP_V_W(name) \ 11568cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov extern "C" void name(void *arg) { \ 11668cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov typedef void (*fntype)(void *arg); \ 117a8b8e964d7b94cae465df77642465901b1b3079dTimur Iskhodzhanov static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ 11868cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov fn(arg); \ 1192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } \ 1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines INTERCEPT_WHEN_POSSIBLE(#name, name); 12168cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov 12243e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov#define WRAP_V_WW(name) \ 12368cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov extern "C" void name(void *arg1, void *arg2) { \ 12468cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov typedef void (*fntype)(void *, void *); \ 125a8b8e964d7b94cae465df77642465901b1b3079dTimur Iskhodzhanov static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ 12668cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov fn(arg1, arg2); \ 1272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } \ 1282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines INTERCEPT_WHEN_POSSIBLE(#name, name); 12943e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov 130c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov#define WRAP_V_WWW(name) \ 131c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov extern "C" void name(void *arg1, void *arg2, void *arg3) { \ 132c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov typedef void *(*fntype)(void *, void *, void *); \ 133a8b8e964d7b94cae465df77642465901b1b3079dTimur Iskhodzhanov static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ 134c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov fn(arg1, arg2, arg3); \ 1352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } \ 1362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines INTERCEPT_WHEN_POSSIBLE(#name, name); 137c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov 138c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov#define WRAP_W_V(name) \ 139c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov extern "C" void *name() { \ 140c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov typedef void *(*fntype)(); \ 141a8b8e964d7b94cae465df77642465901b1b3079dTimur Iskhodzhanov static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ 142c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov return fn(); \ 1432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } \ 1442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines INTERCEPT_WHEN_POSSIBLE(#name, name); 145c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov 14643e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov#define WRAP_W_W(name) \ 14743e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov extern "C" void *name(void *arg) { \ 14843e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov typedef void *(*fntype)(void *arg); \ 149a8b8e964d7b94cae465df77642465901b1b3079dTimur Iskhodzhanov static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ 15043e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov return fn(arg); \ 1512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } \ 1522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines INTERCEPT_WHEN_POSSIBLE(#name, name); 15343e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov 15443e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov#define WRAP_W_WW(name) \ 15543e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov extern "C" void *name(void *arg1, void *arg2) { \ 15643e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov typedef void *(*fntype)(void *, void *); \ 157a8b8e964d7b94cae465df77642465901b1b3079dTimur Iskhodzhanov static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ 15843e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov return fn(arg1, arg2); \ 1592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } \ 1602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines INTERCEPT_WHEN_POSSIBLE(#name, name); 16143e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov 16243e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov#define WRAP_W_WWW(name) \ 16343e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov extern "C" void *name(void *arg1, void *arg2, void *arg3) { \ 16443e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov typedef void *(*fntype)(void *, void *, void *); \ 165a8b8e964d7b94cae465df77642465901b1b3079dTimur Iskhodzhanov static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ 16643e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov return fn(arg1, arg2, arg3); \ 1672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } \ 1682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines INTERCEPT_WHEN_POSSIBLE(#name, name); 16943e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov 17043e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov#define WRAP_W_WWWW(name) \ 17143e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4) { \ 17243e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov typedef void *(*fntype)(void *, void *, void *, void *); \ 173a8b8e964d7b94cae465df77642465901b1b3079dTimur Iskhodzhanov static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ 17443e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov return fn(arg1, arg2, arg3, arg4); \ 1752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } \ 1762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines INTERCEPT_WHEN_POSSIBLE(#name, name); 17743e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov 17843e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov#define WRAP_W_WWWWW(name) \ 17943e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \ 18043e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov void *arg5) { \ 18143e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov typedef void *(*fntype)(void *, void *, void *, void *, void *); \ 182a8b8e964d7b94cae465df77642465901b1b3079dTimur Iskhodzhanov static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ 18343e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov return fn(arg1, arg2, arg3, arg4, arg5); \ 1842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } \ 1852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines INTERCEPT_WHEN_POSSIBLE(#name, name); 18643e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov 18743e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov#define WRAP_W_WWWWWW(name) \ 18843e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \ 18943e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov void *arg5, void *arg6) { \ 19043e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov typedef void *(*fntype)(void *, void *, void *, void *, void *, void *); \ 191a8b8e964d7b94cae465df77642465901b1b3079dTimur Iskhodzhanov static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ 19243e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov return fn(arg1, arg2, arg3, arg4, arg5, arg6); \ 1932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } \ 1942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines INTERCEPT_WHEN_POSSIBLE(#name, name); 19568cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// }}} 19668cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov 19743e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov// ----------------- ASan own interface functions -------------------- 1982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Don't use the INTERFACE_FUNCTION machinery for this function as we actually 1992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// want to call it in the __asan_init interceptor. 200c11fa095b344c1423ba76822d5bde122b1676223Timur IskhodzhanovWRAP_W_V(__asan_should_detect_stack_use_after_return) 201c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov 202c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanovextern "C" { 203c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov int __asan_option_detect_stack_use_after_return; 204c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov 205c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov // Manually wrap __asan_init as we need to initialize 206c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov // __asan_option_detect_stack_use_after_return afterwards. 2075d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines void __asan_init() { 208c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov typedef void (*fntype)(); 2092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines static fntype fn = 0; 2105d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines // __asan_init is expected to be called by only one thread. 2112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (fn) return; 2122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2135d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines fn = (fntype)getRealProcAddressOrDie(__asan_init_name); 214c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov fn(); 215c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov __asan_option_detect_stack_use_after_return = 216def895b9ed81b37a99660a2ddfc2c45d229000a4Timur Iskhodzhanov (__asan_should_detect_stack_use_after_return() != 0); 2172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines InterceptHooks(); 219c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov } 220c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov} 22168cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov 2222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_handle_no_return) 2232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_report_store1) 2252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_report_store2) 2262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_report_store4) 2272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_report_store8) 2282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_report_store16) 2292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_report_store_n) 2302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_report_load1) 2322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_report_load2) 2332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_report_load4) 2342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_report_load8) 2352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_report_load16) 2362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_report_load_n) 2372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_memcpy); 2392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_memset); 2402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_memmove); 2412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_register_globals) 2432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_unregister_globals) 2442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_before_dynamic_init) 2462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_after_dynamic_init) 2472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_poison_stack_memory) 2492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_unpoison_stack_memory) 2502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_poison_memory_region) 2522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_unpoison_memory_region) 2532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_get_current_fake_stack) 2552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_addr_is_in_fake_stack) 2562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_malloc_0) 2582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_malloc_1) 2592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_malloc_2) 2602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_malloc_3) 2612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_malloc_4) 2622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_malloc_5) 2632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_malloc_6) 2642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_malloc_7) 2652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_malloc_8) 2662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_malloc_9) 2672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_malloc_10) 2682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 2692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_free_0) 2702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_free_1) 2712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_free_2) 2722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_free_4) 2732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_free_5) 2742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_free_6) 2752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_free_7) 2762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_free_8) 2772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_free_9) 2782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERFACE_FUNCTION(__asan_stack_free_10) 279c11fa095b344c1423ba76822d5bde122b1676223Timur Iskhodzhanov 2805d71de26cedae3dafc17449fe0182045c0bd20e8Stephen HinesINTERFACE_FUNCTION(__sanitizer_cov_module_init) 2815d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines 28268cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov// TODO(timurrrr): Add more interface functions on the as-needed basis. 28368cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov 28443e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov// ----------------- Memory allocation functions --------------------- 28543e62df906327f6ffa492edb933af1195143d149Timur IskhodzhanovWRAP_V_W(free) 28643e62df906327f6ffa492edb933af1195143d149Timur IskhodzhanovWRAP_V_WW(_free_dbg) 28743e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov 28843e62df906327f6ffa492edb933af1195143d149Timur IskhodzhanovWRAP_W_W(malloc) 28943e62df906327f6ffa492edb933af1195143d149Timur IskhodzhanovWRAP_W_WWWW(_malloc_dbg) 29043e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov 29143e62df906327f6ffa492edb933af1195143d149Timur IskhodzhanovWRAP_W_WW(calloc) 29243e62df906327f6ffa492edb933af1195143d149Timur IskhodzhanovWRAP_W_WWWWW(_calloc_dbg) 29343e62df906327f6ffa492edb933af1195143d149Timur IskhodzhanovWRAP_W_WWW(_calloc_impl) 29443e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov 29543e62df906327f6ffa492edb933af1195143d149Timur IskhodzhanovWRAP_W_WW(realloc) 29643e62df906327f6ffa492edb933af1195143d149Timur IskhodzhanovWRAP_W_WWW(_realloc_dbg) 29743e62df906327f6ffa492edb933af1195143d149Timur IskhodzhanovWRAP_W_WWW(_recalloc) 29843e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov 29943e62df906327f6ffa492edb933af1195143d149Timur IskhodzhanovWRAP_W_W(_msize) 3002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesWRAP_W_W(_expand) 3012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesWRAP_W_W(_expand_dbg) 3022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 3032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// TODO(timurrrr): Might want to add support for _aligned_* allocation 3042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// functions to detect a bit more bugs. Those functions seem to wrap malloc(). 30543e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov 30643e62df906327f6ffa492edb933af1195143d149Timur Iskhodzhanov// TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cc). 30768cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov 3082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(atoi); 3092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(atol); 3102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(frexp); 3112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(longjmp); 3122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(memchr); 3132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(memcmp); 3142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(memcpy); 3152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(memmove); 3162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(memset); 3172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(strcat); // NOLINT 3182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(strchr); 3192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(strcmp); 3202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(strcpy); // NOLINT 3212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(strlen); 3222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(strncat); 3232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(strncmp); 3242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(strncpy); 3252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(strnlen); 3262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(strtol); 3272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesINTERCEPT_LIBRARY_FUNCTION(wcslen); 3282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 3295d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// Must be after all the interceptor declarations due to the way INTERCEPT_HOOKS 3305d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// is defined. 3312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid InterceptHooks() { 3322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines INTERCEPT_HOOKS(); 3332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 3342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 3355d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// We want to call __asan_init before C/C++ initializers/constructors are 3365d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// executed, otherwise functions like memset might be invoked. 3375d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// For some strange reason, merely linking in asan_preinit.cc doesn't work 3385d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// as the callback is never called... Is link.exe doing something too smart? 3395d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines 3405d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// In DLLs, the callbacks are expected to return 0, 3415d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines// otherwise CRT initialization fails. 3425d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hinesstatic int call_asan_init() { 3435d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines __asan_init(); 3445d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines return 0; 3455d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines} 3465d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#pragma section(".CRT$XIB", long, read) // NOLINT 3475d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines__declspec(allocate(".CRT$XIB")) int (*__asan_preinit)() = call_asan_init; 3485d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines 34968cd60c77470fd6e0f86bad1e4c68796d516cc06Timur Iskhodzhanov#endif // ASAN_DLL_THUNK 350