1 //===-- sanitizer_win_thunk_interception.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 and functions to delegate calls to the 9 // shared runtime that lives in the sanitizer DLL. 10 //===----------------------------------------------------------------------===// 11 12 #ifndef SANITIZER_WIN_THUNK_INTERCEPTION_H 13 #define SANITIZER_WIN_THUNK_INTERCEPTION_H 14 #include <stdint.h> 15 16 #include "sanitizer_internal_defs.h" 17 18 extern "C" { 19 __declspec(dllimport) bool __cdecl __sanitizer_override_function( 20 const char *export_name, __sanitizer::uptr user_function, 21 __sanitizer::uptr *old_function = nullptr); 22 __declspec(dllimport) bool __cdecl __sanitizer_override_function_by_addr( 23 __sanitizer::uptr source_function, __sanitizer::uptr target_function, 24 __sanitizer::uptr *old_target_function = nullptr); 25 __declspec(dllimport) bool __cdecl __sanitizer_register_weak_function( 26 const char *export_name, __sanitizer::uptr user_function, 27 __sanitizer::uptr *old_function = nullptr); 28 } 29 30 using sanitizer_thunk = int (*)(); 31 32 namespace __sanitizer { 33 int override_function(const char *export_name, uptr user_function); 34 int register_weak(const char *export_name, uptr user_function); 35 void initialize_thunks(const sanitizer_thunk *begin, 36 const sanitizer_thunk *end); 37 } // namespace __sanitizer 38 39 // -------------------- Function interception macros ------------------------ // 40 // We can't define our own version of strlen etc. because that would lead to 41 // link-time or even type mismatch errors. Instead, we can declare a function 42 // just to be able to get its address. Me may miss the first few calls to the 43 // functions since it can be called before __dll_thunk_init, but that would lead 44 // to false negatives in the startup code before user's global initializers, 45 // which isn't a big deal. 46 // Use .INTR segment to register function pointers that are iterated over during 47 // startup that will replace local_function with sanitizer_export. 48 49 #define INTERCEPT_LIBRARY_FUNCTION(local_function, sanitizer_export) \ 50 extern "C" void local_function(); \ 51 static int intercept_##local_function() { \ 52 return __sanitizer::override_function( \ 53 sanitizer_export, \ 54 reinterpret_cast<__sanitizer::uptr>(local_function)); \ 55 } \ 56 __pragma(section(".INTR$M", long, read)) __declspec(allocate( \ 57 ".INTR$M")) int (*__sanitizer_static_thunk_##local_function)() = \ 58 intercept_##local_function; 59 60 // ------------------ Weak symbol registration macros ---------------------- // 61 // Use .WEAK segment to register function pointers that are iterated over during 62 // startup that will replace sanitizer_export with local_function 63 #ifdef __clang__ 64 # define REGISTER_WEAK_OPTNONE __attribute__((optnone)) 65 # define REGISTER_WEAK_FUNCTION_ADDRESS(fn) __builtin_function_start(fn) 66 #else 67 # define REGISTER_WEAK_OPTNONE 68 # define REGISTER_WEAK_FUNCTION_ADDRESS(fn) &fn 69 #endif 70 71 #define REGISTER_WEAK_FUNCTION(local_function) \ 72 extern "C" void local_function(); \ 73 extern "C" void WEAK_EXPORT_NAME(local_function)(); \ 74 WIN_WEAK_IMPORT_DEF(local_function) \ 75 REGISTER_WEAK_OPTNONE static int register_weak_##local_function() { \ 76 if ((uintptr_t)REGISTER_WEAK_FUNCTION_ADDRESS(local_function) != \ 77 (uintptr_t)REGISTER_WEAK_FUNCTION_ADDRESS( \ 78 WEAK_EXPORT_NAME(local_function))) { \ 79 return __sanitizer::register_weak( \ 80 SANITIZER_STRINGIFY(WEAK_EXPORT_NAME(local_function)), \ 81 reinterpret_cast<__sanitizer::uptr>(local_function)); \ 82 } \ 83 return 0; \ 84 } \ 85 __pragma(section(".WEAK$M", long, read)) __declspec(allocate( \ 86 ".WEAK$M")) int (*__sanitizer_register_weak_##local_function)() = \ 87 register_weak_##local_function; 88 #endif // SANITIZER_WIN_STATIC_RUNTIME_THUNK_H 89