mirror of
https://github.com/gcc-mirror/gcc.git
synced 2024-11-21 13:40:47 +00:00
89 lines
4.6 KiB
C++
89 lines
4.6 KiB
C++
//===-- sanitizer_win_thunk_interception.h ------------------------- -----===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
// This header provide helper macros and functions to delegate calls to the
|
|
// shared runtime that lives in the sanitizer DLL.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SANITIZER_WIN_THUNK_INTERCEPTION_H
|
|
#define SANITIZER_WIN_THUNK_INTERCEPTION_H
|
|
#include <stdint.h>
|
|
|
|
#include "sanitizer_internal_defs.h"
|
|
|
|
extern "C" {
|
|
__declspec(dllimport) bool __cdecl __sanitizer_override_function(
|
|
const char *export_name, __sanitizer::uptr user_function,
|
|
__sanitizer::uptr *old_function = nullptr);
|
|
__declspec(dllimport) bool __cdecl __sanitizer_override_function_by_addr(
|
|
__sanitizer::uptr source_function, __sanitizer::uptr target_function,
|
|
__sanitizer::uptr *old_target_function = nullptr);
|
|
__declspec(dllimport) bool __cdecl __sanitizer_register_weak_function(
|
|
const char *export_name, __sanitizer::uptr user_function,
|
|
__sanitizer::uptr *old_function = nullptr);
|
|
}
|
|
|
|
using sanitizer_thunk = int (*)();
|
|
|
|
namespace __sanitizer {
|
|
int override_function(const char *export_name, uptr user_function);
|
|
int register_weak(const char *export_name, uptr user_function);
|
|
void initialize_thunks(const sanitizer_thunk *begin,
|
|
const sanitizer_thunk *end);
|
|
} // namespace __sanitizer
|
|
|
|
// -------------------- Function interception macros ------------------------ //
|
|
// We can't define our own version of strlen etc. because that would lead to
|
|
// link-time or even type mismatch errors. Instead, we can declare a function
|
|
// just to be able to get its address. Me may miss the first few calls to the
|
|
// functions since it can be called before __dll_thunk_init, but that would lead
|
|
// to false negatives in the startup code before user's global initializers,
|
|
// which isn't a big deal.
|
|
// Use .INTR segment to register function pointers that are iterated over during
|
|
// startup that will replace local_function with sanitizer_export.
|
|
|
|
#define INTERCEPT_LIBRARY_FUNCTION(local_function, sanitizer_export) \
|
|
extern "C" void local_function(); \
|
|
static int intercept_##local_function() { \
|
|
return __sanitizer::override_function( \
|
|
sanitizer_export, \
|
|
reinterpret_cast<__sanitizer::uptr>(local_function)); \
|
|
} \
|
|
__pragma(section(".INTR$M", long, read)) __declspec(allocate( \
|
|
".INTR$M")) int (*__sanitizer_static_thunk_##local_function)() = \
|
|
intercept_##local_function;
|
|
|
|
// ------------------ Weak symbol registration macros ---------------------- //
|
|
// Use .WEAK segment to register function pointers that are iterated over during
|
|
// startup that will replace sanitizer_export with local_function
|
|
#ifdef __clang__
|
|
# define REGISTER_WEAK_OPTNONE __attribute__((optnone))
|
|
# define REGISTER_WEAK_FUNCTION_ADDRESS(fn) __builtin_function_start(fn)
|
|
#else
|
|
# define REGISTER_WEAK_OPTNONE
|
|
# define REGISTER_WEAK_FUNCTION_ADDRESS(fn) &fn
|
|
#endif
|
|
|
|
#define REGISTER_WEAK_FUNCTION(local_function) \
|
|
extern "C" void local_function(); \
|
|
extern "C" void WEAK_EXPORT_NAME(local_function)(); \
|
|
WIN_WEAK_IMPORT_DEF(local_function) \
|
|
REGISTER_WEAK_OPTNONE static int register_weak_##local_function() { \
|
|
if ((uintptr_t)REGISTER_WEAK_FUNCTION_ADDRESS(local_function) != \
|
|
(uintptr_t)REGISTER_WEAK_FUNCTION_ADDRESS( \
|
|
WEAK_EXPORT_NAME(local_function))) { \
|
|
return __sanitizer::register_weak( \
|
|
SANITIZER_STRINGIFY(WEAK_EXPORT_NAME(local_function)), \
|
|
reinterpret_cast<__sanitizer::uptr>(local_function)); \
|
|
} \
|
|
return 0; \
|
|
} \
|
|
__pragma(section(".WEAK$M", long, read)) __declspec(allocate( \
|
|
".WEAK$M")) int (*__sanitizer_register_weak_##local_function)() = \
|
|
register_weak_##local_function;
|
|
#endif // SANITIZER_WIN_STATIC_RUNTIME_THUNK_H
|