(root)/
gcc-13.2.0/
libsanitizer/
sanitizer_common/
sanitizer_win_dll_thunk.h
       1  //===-- sanitizer_win_dll_thunk.h -----------------------------------------===//
       2  //
       3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
       4  // See https://llvm.org/LICENSE.txt for license information.
       5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
       6  //
       7  //===----------------------------------------------------------------------===//
       8  // This header provide helper macros to delegate calls to the shared runtime
       9  // that lives in the main executable. It should be included to dll_thunks that
      10  // will be linked to the dlls, when the sanitizer is a static library included
      11  // in the main executable.
      12  //===----------------------------------------------------------------------===//
      13  #ifndef SANITIZER_WIN_DLL_THUNK_H
      14  #define SANITIZER_WIN_DLL_THUNK_H
      15  #include "sanitizer_internal_defs.h"
      16  
      17  namespace __sanitizer {
      18  uptr dllThunkGetRealAddrOrDie(const char *name);
      19  
      20  int dllThunkIntercept(const char* main_function, uptr dll_function);
      21  
      22  int dllThunkInterceptWhenPossible(const char* main_function,
      23      const char* default_function, uptr dll_function);
      24  }
      25  
      26  extern "C" int __dll_thunk_init();
      27  
      28  // ----------------- Function interception helper macros -------------------- //
      29  // Override dll_function with main_function from main executable.
      30  #define INTERCEPT_OR_DIE(main_function, dll_function)                          \
      31    static int intercept_##dll_function() {                                      \
      32      return __sanitizer::dllThunkIntercept(main_function, (__sanitizer::uptr)   \
      33          dll_function);                                                         \
      34    }                                                                            \
      35    __pragma(section(".DLLTH$M", long, read))                                    \
      36    __declspec(allocate(".DLLTH$M")) int (*__dll_thunk_##dll_function)() =       \
      37      intercept_##dll_function;
      38  
      39  // Try to override dll_function with main_function from main executable.
      40  // If main_function is not present, override dll_function with default_function.
      41  #define INTERCEPT_WHEN_POSSIBLE(main_function, default_function, dll_function) \
      42    static int intercept_##dll_function() {                                      \
      43      return __sanitizer::dllThunkInterceptWhenPossible(main_function,           \
      44          default_function, (__sanitizer::uptr)dll_function);                    \
      45    }                                                                            \
      46    __pragma(section(".DLLTH$M", long, read))                                    \
      47    __declspec(allocate(".DLLTH$M")) int (*__dll_thunk_##dll_function)() =       \
      48      intercept_##dll_function;
      49  
      50  // -------------------- Function interception macros ------------------------ //
      51  // Special case of hooks -- ASan own interface functions.  Those are only called
      52  // after __asan_init, thus an empty implementation is sufficient.
      53  #define INTERCEPT_SANITIZER_FUNCTION(name)                                     \
      54    extern "C" __declspec(noinline) void name() {                                \
      55      volatile int prevent_icf = (__LINE__ << 8) ^ __COUNTER__;                  \
      56      static const char function_name[] = #name;                                 \
      57      for (const char* ptr = &function_name[0]; *ptr; ++ptr)                     \
      58        prevent_icf ^= *ptr;                                                     \
      59      (void)prevent_icf;                                                         \
      60      __debugbreak();                                                            \
      61    }                                                                            \
      62    INTERCEPT_OR_DIE(#name, name)
      63  
      64  // Special case of hooks -- Weak functions, could be redefined in the main
      65  // executable, but that is not necessary, so we shouldn't die if we can not find
      66  // a reference. Instead, when the function is not present in the main executable
      67  // we consider the default impl provided by asan library.
      68  #define INTERCEPT_SANITIZER_WEAK_FUNCTION(name)                                \
      69    extern "C" __declspec(noinline) void name() {                                \
      70      volatile int prevent_icf = (__LINE__ << 8) ^ __COUNTER__;                  \
      71      static const char function_name[] = #name;                                 \
      72      for (const char* ptr = &function_name[0]; *ptr; ++ptr)                     \
      73        prevent_icf ^= *ptr;                                                     \
      74      (void)prevent_icf;                                                         \
      75      __debugbreak();                                                            \
      76    }                                                                            \
      77    INTERCEPT_WHEN_POSSIBLE(#name, STRINGIFY(WEAK_EXPORT_NAME(name)), name)
      78  
      79  // We can't define our own version of strlen etc. because that would lead to
      80  // link-time or even type mismatch errors.  Instead, we can declare a function
      81  // just to be able to get its address.  Me may miss the first few calls to the
      82  // functions since it can be called before __dll_thunk_init, but that would lead
      83  // to false negatives in the startup code before user's global initializers,
      84  // which isn't a big deal.
      85  #define INTERCEPT_LIBRARY_FUNCTION(name)                                       \
      86    extern "C" void name();                                                      \
      87    INTERCEPT_OR_DIE(WRAPPER_NAME(name), name)
      88  
      89  // Use these macros for functions that could be called before __dll_thunk_init()
      90  // is executed and don't lead to errors if defined (free, malloc, etc).
      91  #define INTERCEPT_WRAP_V_V(name)                                               \
      92    extern "C" void name() {                                                     \
      93      typedef decltype(name) *fntype;                                            \
      94      static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name);   \
      95      fn();                                                                      \
      96    }                                                                            \
      97    INTERCEPT_OR_DIE(#name, name);
      98  
      99  #define INTERCEPT_WRAP_V_W(name)                                               \
     100    extern "C" void name(void *arg) {                                            \
     101      typedef decltype(name) *fntype;                                            \
     102      static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name);   \
     103      fn(arg);                                                                   \
     104    }                                                                            \
     105    INTERCEPT_OR_DIE(#name, name);
     106  
     107  #define INTERCEPT_WRAP_V_WW(name)                                              \
     108    extern "C" void name(void *arg1, void *arg2) {                               \
     109      typedef decltype(name) *fntype;                                            \
     110      static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name);   \
     111      fn(arg1, arg2);                                                            \
     112    }                                                                            \
     113    INTERCEPT_OR_DIE(#name, name);
     114  
     115  #define INTERCEPT_WRAP_V_WWW(name)                                             \
     116    extern "C" void name(void *arg1, void *arg2, void *arg3) {                   \
     117      typedef decltype(name) *fntype;                                            \
     118      static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name);   \
     119      fn(arg1, arg2, arg3);                                                      \
     120    }                                                                            \
     121    INTERCEPT_OR_DIE(#name, name);
     122  
     123  #define INTERCEPT_WRAP_W_V(name)                                               \
     124    extern "C" void *name() {                                                    \
     125      typedef decltype(name) *fntype;                                            \
     126      static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name);   \
     127      return fn();                                                               \
     128    }                                                                            \
     129    INTERCEPT_OR_DIE(#name, name);
     130  
     131  #define INTERCEPT_WRAP_W_W(name)                                               \
     132    extern "C" void *name(void *arg) {                                           \
     133      typedef decltype(name) *fntype;                                            \
     134      static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name);   \
     135      return fn(arg);                                                            \
     136    }                                                                            \
     137    INTERCEPT_OR_DIE(#name, name);
     138  
     139  #define INTERCEPT_WRAP_W_WW(name)                                              \
     140    extern "C" void *name(void *arg1, void *arg2) {                              \
     141      typedef decltype(name) *fntype;                                            \
     142      static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name);   \
     143      return fn(arg1, arg2);                                                     \
     144    }                                                                            \
     145    INTERCEPT_OR_DIE(#name, name);
     146  
     147  #define INTERCEPT_WRAP_W_WWW(name)                                             \
     148    extern "C" void *name(void *arg1, void *arg2, void *arg3) {                  \
     149      typedef decltype(name) *fntype;                                            \
     150      static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name);   \
     151      return fn(arg1, arg2, arg3);                                               \
     152    }                                                                            \
     153    INTERCEPT_OR_DIE(#name, name);
     154  
     155  #define INTERCEPT_WRAP_W_WWWW(name)                                            \
     156    extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4) {      \
     157      typedef decltype(name) *fntype;                                            \
     158      static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name);   \
     159      return fn(arg1, arg2, arg3, arg4);                                         \
     160    }                                                                            \
     161    INTERCEPT_OR_DIE(#name, name);
     162  
     163  #define INTERCEPT_WRAP_W_WWWWW(name)                                           \
     164    extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4,        \
     165                          void *arg5) {                                          \
     166      typedef decltype(name) *fntype;                                            \
     167      static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name);   \
     168      return fn(arg1, arg2, arg3, arg4, arg5);                                   \
     169    }                                                                            \
     170    INTERCEPT_OR_DIE(#name, name);
     171  
     172  #define INTERCEPT_WRAP_W_WWWWWW(name)                                          \
     173    extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4,        \
     174                          void *arg5, void *arg6) {                              \
     175      typedef decltype(name) *fntype;                                            \
     176      static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name);   \
     177      return fn(arg1, arg2, arg3, arg4, arg5, arg6);                             \
     178    }                                                                            \
     179    INTERCEPT_OR_DIE(#name, name);
     180  
     181  #endif // SANITIZER_WIN_DLL_THUNK_H