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