mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 17:30:16 +00:00
LDR: implement unrebase
This commit is contained in:
parent
f3c452c562
commit
124abb9f96
@ -972,6 +972,148 @@ class CROHelper final {
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all internal patches to zero.
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode ClearInternalPatches() {
|
||||
u32 internal_patch_num = GetField(InternalPatchNum);
|
||||
for (u32 i = 0; i < internal_patch_num; ++i) {
|
||||
InternalPatchEntry patch;
|
||||
GetEntry(i, patch);
|
||||
VAddr target_address = SegmentTagToAddress(patch.target_position);
|
||||
|
||||
if (target_address == 0) {
|
||||
return CROFormatError(0x15);
|
||||
}
|
||||
|
||||
ResultCode result = ClearPatch(target_address, patch.type);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error clearing patch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/// Unrebases offsets in imported anonymous symbol table
|
||||
void UnrebaseImportAnonymousSymbolTable() {
|
||||
u32 num = GetField(ImportAnonymousSymbolNum);
|
||||
for (u32 i = 0; i < num; ++i) {
|
||||
ImportAnonymousSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
|
||||
if (entry.patch_batch_offset) {
|
||||
entry.patch_batch_offset -= address;
|
||||
}
|
||||
|
||||
SetEntry(i, entry);
|
||||
}
|
||||
}
|
||||
|
||||
/// Unrebases offsets in imported indexed symbol table
|
||||
void UnrebaseImportIndexedSymbolTable() {
|
||||
u32 num = GetField(ImportIndexedSymbolNum);
|
||||
for (u32 i = 0; i < num; ++i) {
|
||||
ImportIndexedSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
|
||||
if (entry.patch_batch_offset) {
|
||||
entry.patch_batch_offset -= address;
|
||||
}
|
||||
|
||||
SetEntry(i, entry);
|
||||
}
|
||||
}
|
||||
|
||||
/// Unrebases offsets in imported named symbol table
|
||||
void UnrebaseImportNamedSymbolTable() {
|
||||
u32 num = GetField(ImportNamedSymbolNum);
|
||||
for (u32 i = 0; i < num; ++i) {
|
||||
ImportNamedSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
|
||||
if (entry.name_offset) {
|
||||
entry.name_offset -= address;
|
||||
}
|
||||
|
||||
if (entry.patch_batch_offset) {
|
||||
entry.patch_batch_offset -= address;
|
||||
}
|
||||
|
||||
SetEntry(i, entry);
|
||||
}
|
||||
}
|
||||
|
||||
/// Unrebases offsets in imported module table
|
||||
void UnrebaseImportModuleTable() {
|
||||
u32 module_num = GetField(ImportModuleNum);
|
||||
for (u32 i = 0; i < module_num; ++i) {
|
||||
ImportModuleEntry entry;
|
||||
GetEntry(i, entry);
|
||||
|
||||
if (entry.name_offset) {
|
||||
entry.name_offset -= address;
|
||||
}
|
||||
|
||||
if (entry.import_indexed_symbol_table_offset) {
|
||||
entry.import_indexed_symbol_table_offset -= address;
|
||||
}
|
||||
|
||||
if (entry.import_anonymous_symbol_table_offset) {
|
||||
entry.import_anonymous_symbol_table_offset -= address;
|
||||
}
|
||||
|
||||
SetEntry(i, entry);
|
||||
}
|
||||
}
|
||||
|
||||
/// Unrebases offsets in exported named symbol table
|
||||
void UnrebaseExportNamedSymbolTable() {
|
||||
u32 export_named_symbol_num = GetField(ExportNamedSymbolNum);
|
||||
for (u32 i = 0; i < export_named_symbol_num; ++i) {
|
||||
ExportNamedSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
|
||||
if (entry.name_offset) {
|
||||
entry.name_offset -= address;
|
||||
}
|
||||
|
||||
SetEntry(i, entry);
|
||||
}
|
||||
}
|
||||
|
||||
/// Unrebases offsets in segment table
|
||||
void UnrebaseSegmentTable() {
|
||||
u32 segment_num = GetField(SegmentNum);
|
||||
for (u32 i = 0; i < segment_num; ++i) {
|
||||
SegmentEntry segment;
|
||||
GetEntry(i, segment);
|
||||
|
||||
if (segment.type == SegmentType::BSS) {
|
||||
segment.offset = 0;
|
||||
} else if (segment.offset) {
|
||||
segment.offset -= address;
|
||||
}
|
||||
|
||||
SetEntry(i, segment);
|
||||
}
|
||||
}
|
||||
|
||||
/// Unrebases offsets in module header
|
||||
void UnrebaseHeader() {
|
||||
u32 offset = GetField(NameOffset);
|
||||
if (offset)
|
||||
SetField(NameOffset, offset - address);
|
||||
|
||||
for (int field = CodeOffset; field < Fix0Barrier; field += 2) {
|
||||
HeaderField header_field = static_cast<HeaderField>(field);
|
||||
offset = GetField(header_field);
|
||||
if (offset)
|
||||
SetField(header_field, offset - address);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the exit function in this module
|
||||
* @param crs_address the virtual address of the static module.
|
||||
@ -1145,6 +1287,28 @@ public:
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unrebases the module.
|
||||
* @param is_crs true if the module itself is the static module
|
||||
*/
|
||||
void Unrebase(bool is_crs) {
|
||||
UnrebaseImportAnonymousSymbolTable();
|
||||
UnrebaseImportIndexedSymbolTable();
|
||||
UnrebaseImportNamedSymbolTable();
|
||||
UnrebaseImportModuleTable();
|
||||
UnrebaseExportNamedSymbolTable();
|
||||
|
||||
if (!is_crs)
|
||||
UnrebaseSegmentTable();
|
||||
|
||||
SetNext(0);
|
||||
SetPrevious(0);
|
||||
|
||||
SetField(FixedSize, 0);
|
||||
|
||||
UnrebaseHeader();
|
||||
}
|
||||
|
||||
void InitCRS() {
|
||||
SetNext(0);
|
||||
SetPrevious(0);
|
||||
|
Loading…
Reference in New Issue
Block a user