89 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8// This header provide helper macros and functions to delegate calls to the9// shared runtime that lives in the sanitizer DLL.10//===----------------------------------------------------------------------===//11 12#ifndef SANITIZER_WIN_THUNK_INTERCEPTION_H13#define SANITIZER_WIN_THUNK_INTERCEPTION_H14#include <stdint.h>15 16#include "sanitizer_internal_defs.h"17 18extern "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 30using sanitizer_thunk = int (*)();31 32namespace __sanitizer {33int override_function(const char *export_name, uptr user_function);34int register_weak(const char *export_name, uptr user_function);35void initialize_thunks(const sanitizer_thunk *begin,36 const sanitizer_thunk *end);37} // namespace __sanitizer38 39// -------------------- Function interception macros ------------------------ //40// We can't define our own version of strlen etc. because that would lead to41// link-time or even type mismatch errors. Instead, we can declare a function42// just to be able to get its address. Me may miss the first few calls to the43// functions since it can be called before __dll_thunk_init, but that would lead44// 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 during47// 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 during62// startup that will replace sanitizer_export with local_function63#ifdef __clang__64# define REGISTER_WEAK_OPTNONE __attribute__((optnone))65# define REGISTER_WEAK_FUNCTION_ADDRESS(fn) __builtin_function_start(fn)66#else67# define REGISTER_WEAK_OPTNONE68# define REGISTER_WEAK_FUNCTION_ADDRESS(fn) &fn69#endif70 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_H89