mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-10 14:07:25 +00:00
[nce] add split patch mode to support modules bigger than 128MB (#3489)
nce patcher was extended to support modules larger than 128MB due to ARM64 branch limit. now added a pre-patch and (existing) post-patch module code. Allowwing MRS/MSR/SVC handler to remain within branch branch range Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3489 Reviewed-by: MaranBr <maranbr@eden-emu.dev> Reviewed-by: CamilleLaVey <camillelavey99@gmail.com> Co-authored-by: Maufeat <sahyno1996@gmail.com> Co-committed-by: Maufeat <sahyno1996@gmail.com>
This commit is contained in:
+44
-10
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
@@ -41,6 +41,7 @@ enum class PatchMode : u32 {
|
||||
None,
|
||||
PreText, ///< Patch section is inserted before .text
|
||||
PostData, ///< Patch section is inserted after .data
|
||||
Split, ///< Patch sections are inserted before .text and after .data
|
||||
};
|
||||
|
||||
using ModuleTextAddress = u64;
|
||||
@@ -63,6 +64,7 @@ public:
|
||||
bool RelocateAndCopy(Common::ProcessAddress load_base, const Kernel::CodeSet::Segment& code,
|
||||
Kernel::PhysicalMemory& program_image, EntryTrampolines* out_trampolines);
|
||||
size_t GetSectionSize() const noexcept;
|
||||
size_t GetPreSectionSize() const noexcept;
|
||||
|
||||
[[nodiscard]] PatchMode GetPatchMode() const noexcept {
|
||||
return mode;
|
||||
@@ -76,15 +78,25 @@ private:
|
||||
uintptr_t module_offset;
|
||||
};
|
||||
|
||||
void WriteLoadContext();
|
||||
void WriteSaveContext();
|
||||
void LockContext();
|
||||
void UnlockContext();
|
||||
void WriteSvcTrampoline(ModuleDestLabel module_dest, u32 svc_id);
|
||||
void WriteMrsHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg,
|
||||
oaknut::SystemReg src_reg);
|
||||
void WriteMsrHandler(ModuleDestLabel module_dest, oaknut::XReg src_reg);
|
||||
void WriteCntpctHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg);
|
||||
// Core implementations with explicit code generator
|
||||
void WriteLoadContext(oaknut::VectorCodeGenerator& code);
|
||||
void WriteSaveContext(oaknut::VectorCodeGenerator& code);
|
||||
void LockContext(oaknut::VectorCodeGenerator& code);
|
||||
void UnlockContext(oaknut::VectorCodeGenerator& code);
|
||||
void WriteSvcTrampoline(ModuleDestLabel module_dest, u32 svc_id, oaknut::VectorCodeGenerator& code, oaknut::Label& save_ctx, oaknut::Label& load_ctx);
|
||||
void WriteMrsHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg, oaknut::SystemReg src_reg, oaknut::VectorCodeGenerator& code);
|
||||
void WriteMsrHandler(ModuleDestLabel module_dest, oaknut::XReg src_reg, oaknut::VectorCodeGenerator& code);
|
||||
void WriteCntpctHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg, oaknut::VectorCodeGenerator& code);
|
||||
|
||||
// Convenience wrappers using default code generator
|
||||
void WriteLoadContext() { WriteLoadContext(c); }
|
||||
void WriteSaveContext() { WriteSaveContext(c); }
|
||||
void LockContext() { LockContext(c); }
|
||||
void UnlockContext() { UnlockContext(c); }
|
||||
void WriteSvcTrampoline(ModuleDestLabel module_dest, u32 svc_id) { WriteSvcTrampoline(module_dest, svc_id, c, m_save_context, m_load_context); }
|
||||
void WriteMrsHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg, oaknut::SystemReg src_reg) { WriteMrsHandler(module_dest, dest_reg, src_reg, c); }
|
||||
void WriteMsrHandler(ModuleDestLabel module_dest, oaknut::XReg src_reg) { WriteMsrHandler(module_dest, src_reg, c); }
|
||||
void WriteCntpctHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg) { WriteCntpctHandler(module_dest, dest_reg, c); }
|
||||
|
||||
private:
|
||||
static constexpr size_t CACHE_SIZE = 16384; // Cache size for patch entries
|
||||
@@ -111,19 +123,34 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void BranchToPatchPre(uintptr_t module_dest) {
|
||||
curr_patch->m_branch_to_pre_patch_relocations.push_back({c_pre.offset(), module_dest});
|
||||
}
|
||||
|
||||
void BranchToModule(uintptr_t module_dest) {
|
||||
curr_patch->m_branch_to_module_relocations.push_back({c.offset(), module_dest});
|
||||
c.dw(0);
|
||||
}
|
||||
|
||||
void BranchToModulePre(uintptr_t module_dest) {
|
||||
curr_patch->m_branch_to_module_relocations_pre.push_back({c_pre.offset(), module_dest});
|
||||
c_pre.dw(0);
|
||||
}
|
||||
|
||||
void WriteModulePc(uintptr_t module_dest) {
|
||||
curr_patch->m_write_module_pc_relocations.push_back({c.offset(), module_dest});
|
||||
c.dx(0);
|
||||
}
|
||||
|
||||
void WriteModulePcPre(uintptr_t module_dest) {
|
||||
curr_patch->m_write_module_pc_relocations_pre.push_back({c_pre.offset(), module_dest});
|
||||
c_pre.dx(0);
|
||||
}
|
||||
|
||||
private:
|
||||
// List of patch instructions we have generated.
|
||||
std::vector<u32> m_patch_instructions{};
|
||||
std::vector<u32> m_patch_instructions_pre{};
|
||||
|
||||
// Relocation type for relative branch from module to patch.
|
||||
struct Relocation {
|
||||
@@ -133,15 +160,22 @@ private:
|
||||
|
||||
struct ModulePatch {
|
||||
std::vector<Trampoline> m_trampolines;
|
||||
std::vector<Trampoline> m_trampolines_pre;
|
||||
std::vector<Relocation> m_branch_to_patch_relocations{};
|
||||
std::vector<Relocation> m_branch_to_pre_patch_relocations{};
|
||||
std::vector<Relocation> m_branch_to_module_relocations{};
|
||||
std::vector<Relocation> m_branch_to_module_relocations_pre{};
|
||||
std::vector<Relocation> m_write_module_pc_relocations{};
|
||||
std::vector<Relocation> m_write_module_pc_relocations_pre{};
|
||||
std::vector<ModuleTextAddress> m_exclusives{};
|
||||
};
|
||||
|
||||
oaknut::VectorCodeGenerator c;
|
||||
oaknut::VectorCodeGenerator c_pre;
|
||||
oaknut::Label m_save_context{};
|
||||
oaknut::Label m_load_context{};
|
||||
oaknut::Label m_save_context_pre{};
|
||||
oaknut::Label m_load_context_pre{};
|
||||
PatchMode mode{PatchMode::None};
|
||||
size_t total_program_size{};
|
||||
size_t m_relocate_module_index{};
|
||||
|
||||
Reference in New Issue
Block a user