110 lines · cpp
1//===-- sanitizer_win_thunk_interception.cpp ----------------------- -----===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines things that need to be present in the application modules10// to interact with sanitizer DLL correctly and cannot be implemented using the11// default "import library" generated when linking the DLL.12//13// This includes the common infrastructure required to intercept local functions14// that must be replaced with sanitizer-aware versions, as well as the15// registration of weak functions with the sanitizer DLL. With this in-place,16// other sanitizer components can simply write to the .INTR and .WEAK sections.17//18//===----------------------------------------------------------------------===//19 20#if defined(SANITIZER_STATIC_RUNTIME_THUNK) || \21 defined(SANITIZER_DYNAMIC_RUNTIME_THUNK)22# include "sanitizer_win_thunk_interception.h"23 24extern "C" void abort();25 26namespace __sanitizer {27 28int override_function(const char *export_name, const uptr user_function) {29 if (!__sanitizer_override_function(export_name, user_function)) {30 abort();31 }32 33 return 0;34}35 36int register_weak(const char *export_name, const uptr user_function) {37 if (!__sanitizer_register_weak_function(export_name, user_function)) {38 abort();39 }40 41 return 0;42}43 44void initialize_thunks(const sanitizer_thunk *first,45 const sanitizer_thunk *last) {46 for (const sanitizer_thunk *it = first; it < last; ++it) {47 if (*it) {48 (*it)();49 }50 }51}52} // namespace __sanitizer53 54# define INTERFACE_FUNCTION(Name)55# define INTERFACE_WEAK_FUNCTION(Name) REGISTER_WEAK_FUNCTION(Name)56# include "sanitizer_common_interface.inc"57 58# pragma section(".INTR$A", read) // intercept begin59# pragma section(".INTR$Z", read) // intercept end60# pragma section(".WEAK$A", read) // weak begin61# pragma section(".WEAK$Z", read) // weak end62 63extern "C" {64__declspec(allocate(65 ".INTR$A")) sanitizer_thunk __sanitizer_intercept_thunk_begin;66__declspec(allocate(".INTR$Z")) sanitizer_thunk __sanitizer_intercept_thunk_end;67 68__declspec(allocate(69 ".WEAK$A")) sanitizer_thunk __sanitizer_register_weak_thunk_begin;70__declspec(allocate(71 ".WEAK$Z")) sanitizer_thunk __sanitizer_register_weak_thunk_end;72}73 74extern "C" int __sanitizer_thunk_init() {75 // __sanitizer_static_thunk_init is expected to be called by only one thread.76 static bool flag = false;77 if (flag) {78 return 0;79 }80 flag = true;81 82 __sanitizer::initialize_thunks(&__sanitizer_intercept_thunk_begin,83 &__sanitizer_intercept_thunk_end);84 __sanitizer::initialize_thunks(&__sanitizer_register_weak_thunk_begin,85 &__sanitizer_register_weak_thunk_end);86 87 // In DLLs, the callbacks are expected to return 0,88 // otherwise CRT initialization fails.89 return 0;90}91 92// We want to call dll_thunk_init before C/C++ initializers / constructors are93// executed, otherwise functions like memset might be invoked.94# pragma section(".CRT$XIB", long, read)95__declspec(allocate(".CRT$XIB")) int (*__sanitizer_thunk_init_ptr)() =96 __sanitizer_thunk_init;97 98static void WINAPI sanitizer_thunk_thread_init(void *mod, unsigned long reason,99 void *reserved) {100 if (reason == /*DLL_PROCESS_ATTACH=*/1)101 __sanitizer_thunk_init();102}103 104# pragma section(".CRT$XLAB", long, read)105__declspec(allocate(".CRT$XLAB")) void(106 WINAPI *__sanitizer_thunk_thread_init_ptr)(void *, unsigned long, void *) =107 sanitizer_thunk_thread_init;108 109#endif // defined(SANITIZER_STATIC_RUNTIME_THUNK) ||110 // defined(SANITIZER_DYNAMIC_RUNTIME_THUNK)