58 lines
2.0 KiB
C++

#pragma once
#include "log.h"
// Patching Functions
#ifndef REBORN_HAS_PATCH_CODE
#error "Missing Patching Functions"
#endif
// Init
void reborn_init_patch();
// Replace Call Located At start With A Call To target
void overwrite_call_manual(void *addr, void *new_target, bool force_b_instruction = false);
template <typename T>
void overwrite_call(void *addr, __attribute__((unused)) T *target_type, typename T::ptr_type new_target, const bool force_b_instruction = false) {
overwrite_call_manual(addr, (void *) new_target, force_b_instruction);
}
// Replace All Calls To Method start With target
void *overwrite_calls_manual(void *target, void *replacement, bool allow_no_callsites = false);
template <typename T>
void overwrite_calls(T *target, typename T::overwrite_type replacement) {
DEBUG("Overwriting Method: %s", target->name.c_str());
if (!target->overwrite(replacement)) {
ERR("Unable To Overwrite Method! Use patch_vtable() Instead!");
}
}
// Thunk Enabler
void *reborn_thunk_enabler(void *target, void *thunk);
// Replace All Calls To start With target Within [to, from)
void overwrite_calls_within_manual(void *from, void *to, const void *target, void *replacement);
template <typename T>
void overwrite_calls_within(void *from, void *to, T *target, typename T::ptr_type replacement) {
overwrite_calls_within_manual(from, to, (void *) target->get(), (void *) replacement);
}
// Get Target Address From BL Instruction
void *extract_from_bl_instruction(unsigned char *addr);
// Patch Instruction
void patch(void *addr, unsigned char patch[4]);
// Patch 4 Bytes Of Data
void patch_address(void *addr, void *target);
// Patch VTable Entry
// IMPORTANT NOTE: This does not affect subclasses.
template <typename T>
void patch_vtable(const T *target, typename T::ptr_type replacement) {
DEBUG("Patching VTable: %s", target->name.c_str());
if (target->enabled) {
WARN("Use overwrite_calls() Instead!");
}
patch_address((void *) target->get_vtable_addr(), (void *) replacement);
}