mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-10-13 15:43:09 +00:00
[patcher, ro] runtime tls patch (#4492) optimization
This commit is contained in:
@@ -45,6 +45,23 @@ Patcher::Patcher() : c(m_patch_instructions), c_pre(m_patch_instructions_pre) {
|
||||
WriteLoadContext(c_pre);
|
||||
}
|
||||
|
||||
Patcher::Patcher(std::span<const u8> text) : c(m_patch_instructions), c_pre(m_patch_instructions_pre) {
|
||||
modules.emplace_back();
|
||||
curr_patch = &modules.back();
|
||||
const auto words = std::span<const u32>{reinterpret_cast<const u32*>(text.data()), text.size() / sizeof(u32)};
|
||||
for (u32 i = ModuleCodeIndex; i < static_cast<u32>(words.size()); ++i) {
|
||||
const uintptr_t offset = i * sizeof(u32);
|
||||
if (auto mrs = MRS{words[i]}; mrs.Verify() && mrs.GetRt() != 31 && (mrs.GetSystemReg() == TpidrEl0 || mrs.GetSystemReg() == TpidrroEl0)) {
|
||||
BranchToPatch(offset);
|
||||
const auto src_reg = mrs.GetSystemReg() == TpidrroEl0 ? oaknut::SystemReg::TPIDRRO_EL0 : oaknut::SystemReg::TPIDR_EL0;
|
||||
WriteMrsHandler(offset + sizeof(u32), oaknut::XReg{static_cast<int>(mrs.GetRt())}, src_reg);
|
||||
} else if (auto msr = MSR{words[i]}; msr.Verify() && msr.GetSystemReg() == TpidrEl0) {
|
||||
BranchToPatch(offset);
|
||||
WriteMsrHandler(offset + sizeof(u32), oaknut::XReg{static_cast<int>(msr.GetRt())});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Patcher::~Patcher() = default;
|
||||
|
||||
bool Patcher::PatchText(std::span<const u8> program_image, const Kernel::CodeSet::Segment& code) {
|
||||
@@ -182,6 +199,31 @@ bool Patcher::PatchText(std::span<const u8> program_image, const Kernel::CodeSet
|
||||
return true;
|
||||
}
|
||||
|
||||
std::span<const u32> Patcher::RelocateRuntimeTls(
|
||||
s64 patch_offset, std::vector<InstructionPatch>& out_patches) {
|
||||
const auto& patch = modules.front();
|
||||
const auto can_branch = [](s64 offset) {
|
||||
return offset % 4 == 0 && offset >= -static_cast<s64>(MaxRelativeBranch) && offset < static_cast<s64>(MaxRelativeBranch);
|
||||
};
|
||||
out_patches.clear();
|
||||
out_patches.reserve(patch.m_branch_to_patch_relocations.size());
|
||||
for (const auto& rel : patch.m_branch_to_patch_relocations) {
|
||||
const s64 offset = patch_offset + rel.patch_offset - static_cast<s64>(rel.module_offset);
|
||||
if (!can_branch(offset)) {return {};}
|
||||
u32 replacement;
|
||||
oaknut::CodeGenerator rc{&replacement};
|
||||
rc.B(offset);
|
||||
out_patches.push_back({rel.module_offset, replacement});
|
||||
}
|
||||
for (const auto& rel : patch.m_branch_to_module_relocations) {
|
||||
const s64 offset = static_cast<s64>(rel.module_offset) - patch_offset - rel.patch_offset;
|
||||
if (!can_branch(offset)) {return {};}
|
||||
oaknut::CodeGenerator rc{m_patch_instructions.data() + rel.patch_offset / sizeof(u32)};
|
||||
rc.B(offset);
|
||||
}
|
||||
return m_patch_instructions;
|
||||
}
|
||||
|
||||
bool Patcher::RelocateAndCopy(Common::ProcessAddress load_base, const Kernel::CodeSet::Segment& code, std::vector<u8>& program_image, EntryTrampolines* out_trampolines) {
|
||||
const size_t patch_size = GetSectionSize();
|
||||
const size_t pre_patch_size = GetPreSectionSize();
|
||||
|
||||
Reference in New Issue
Block a user