mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 18:20:14 +00:00
LDR fixup module_address
This commit is contained in:
parent
663e38c142
commit
1fb62d3a90
@ -59,7 +59,7 @@ static ResultCode CROFormatError(u32 description) {
|
|||||||
|
|
||||||
/// Represents a loaded module (CRO) with interfaces manipulating it.
|
/// Represents a loaded module (CRO) with interfaces manipulating it.
|
||||||
class CROHelper final {
|
class CROHelper final {
|
||||||
const VAddr address; ///< the virtual address of this module
|
const VAddr module_address; ///< the virtual address of this module
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each item in this enum represents a u32 field in the header begin from address+0x80, successively.
|
* Each item in this enum represents a u32 field in the header begin from address+0x80, successively.
|
||||||
@ -294,7 +294,7 @@ class CROHelper final {
|
|||||||
static constexpr u32 MAGIC_FIXD = 0x44584946;
|
static constexpr u32 MAGIC_FIXD = 0x44584946;
|
||||||
|
|
||||||
VAddr Field(HeaderField field) const {
|
VAddr Field(HeaderField field) const {
|
||||||
return address + CRO_HASH_SIZE + field * 4;
|
return module_address + CRO_HASH_SIZE + field * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetField(HeaderField field) const {
|
u32 GetField(HeaderField field) const {
|
||||||
@ -601,17 +601,17 @@ class CROHelper final {
|
|||||||
// rebases offsets
|
// rebases offsets
|
||||||
u32 offset = GetField(NameOffset);
|
u32 offset = GetField(NameOffset);
|
||||||
if (offset)
|
if (offset)
|
||||||
SetField(NameOffset, offset + address);
|
SetField(NameOffset, offset + module_address);
|
||||||
|
|
||||||
for (int field = CodeOffset; field < Fix0Barrier; field += 2) {
|
for (int field = CodeOffset; field < Fix0Barrier; field += 2) {
|
||||||
HeaderField header_field = static_cast<HeaderField>(field);
|
HeaderField header_field = static_cast<HeaderField>(field);
|
||||||
offset = GetField(header_field);
|
offset = GetField(header_field);
|
||||||
if (offset)
|
if (offset)
|
||||||
SetField(header_field, offset + address);
|
SetField(header_field, offset + module_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
// verifies everything is not beyond the buffer
|
// verifies everything is not beyond the buffer
|
||||||
u32 file_end = address + cro_size;
|
u32 file_end = module_address + cro_size;
|
||||||
for (int field = CodeOffset, i = 0; field < Fix0Barrier; field += 2, ++i) {
|
for (int field = CodeOffset, i = 0; field < Fix0Barrier; field += 2, ++i) {
|
||||||
HeaderField offset_field = static_cast<HeaderField>(field);
|
HeaderField offset_field = static_cast<HeaderField>(field);
|
||||||
HeaderField size_field = static_cast<HeaderField>(field + 1);
|
HeaderField size_field = static_cast<HeaderField>(field + 1);
|
||||||
@ -667,8 +667,8 @@ class CROHelper final {
|
|||||||
segment.offset = bss_segment_address;
|
segment.offset = bss_segment_address;
|
||||||
}
|
}
|
||||||
} else if (segment.offset) {
|
} else if (segment.offset) {
|
||||||
segment.offset += address;
|
segment.offset += module_address;
|
||||||
if (segment.offset > address + cro_size)
|
if (segment.offset > module_address + cro_size)
|
||||||
return CROFormatError(0x19);
|
return CROFormatError(0x19);
|
||||||
}
|
}
|
||||||
SetEntry(i, segment);
|
SetEntry(i, segment);
|
||||||
@ -690,7 +690,7 @@ class CROHelper final {
|
|||||||
GetEntry(i, entry);
|
GetEntry(i, entry);
|
||||||
|
|
||||||
if (entry.name_offset) {
|
if (entry.name_offset) {
|
||||||
entry.name_offset += address;
|
entry.name_offset += module_address;
|
||||||
if (entry.name_offset < export_strings_offset
|
if (entry.name_offset < export_strings_offset
|
||||||
|| entry.name_offset >= export_strings_end) {
|
|| entry.name_offset >= export_strings_end) {
|
||||||
return CROFormatError(0x11);
|
return CROFormatError(0x11);
|
||||||
@ -737,7 +737,7 @@ class CROHelper final {
|
|||||||
GetEntry(i, entry);
|
GetEntry(i, entry);
|
||||||
|
|
||||||
if (entry.name_offset) {
|
if (entry.name_offset) {
|
||||||
entry.name_offset += address;
|
entry.name_offset += module_address;
|
||||||
if (entry.name_offset < import_strings_offset
|
if (entry.name_offset < import_strings_offset
|
||||||
|| entry.name_offset >= import_strings_end) {
|
|| entry.name_offset >= import_strings_end) {
|
||||||
return CROFormatError(0x18);
|
return CROFormatError(0x18);
|
||||||
@ -745,7 +745,7 @@ class CROHelper final {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (entry.import_indexed_symbol_table_offset) {
|
if (entry.import_indexed_symbol_table_offset) {
|
||||||
entry.import_indexed_symbol_table_offset += address;
|
entry.import_indexed_symbol_table_offset += module_address;
|
||||||
if (entry.import_indexed_symbol_table_offset < import_indexed_symbol_table_offset
|
if (entry.import_indexed_symbol_table_offset < import_indexed_symbol_table_offset
|
||||||
|| entry.import_indexed_symbol_table_offset > index_import_table_end) {
|
|| entry.import_indexed_symbol_table_offset > index_import_table_end) {
|
||||||
return CROFormatError(0x18);
|
return CROFormatError(0x18);
|
||||||
@ -753,7 +753,7 @@ class CROHelper final {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (entry.import_anonymous_symbol_table_offset) {
|
if (entry.import_anonymous_symbol_table_offset) {
|
||||||
entry.import_anonymous_symbol_table_offset += address;
|
entry.import_anonymous_symbol_table_offset += module_address;
|
||||||
if (entry.import_anonymous_symbol_table_offset < import_anonymous_symbol_table_offset
|
if (entry.import_anonymous_symbol_table_offset < import_anonymous_symbol_table_offset
|
||||||
|| entry.import_anonymous_symbol_table_offset > offset_import_table_end) {
|
|| entry.import_anonymous_symbol_table_offset > offset_import_table_end) {
|
||||||
return CROFormatError(0x18);
|
return CROFormatError(0x18);
|
||||||
@ -781,7 +781,7 @@ class CROHelper final {
|
|||||||
GetEntry(i, entry);
|
GetEntry(i, entry);
|
||||||
|
|
||||||
if (entry.name_offset) {
|
if (entry.name_offset) {
|
||||||
entry.name_offset += address;
|
entry.name_offset += module_address;
|
||||||
if (entry.name_offset < import_strings_offset
|
if (entry.name_offset < import_strings_offset
|
||||||
|| entry.name_offset >= import_strings_end) {
|
|| entry.name_offset >= import_strings_end) {
|
||||||
return CROFormatError(0x1B);
|
return CROFormatError(0x1B);
|
||||||
@ -789,7 +789,7 @@ class CROHelper final {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (entry.patch_batch_offset) {
|
if (entry.patch_batch_offset) {
|
||||||
entry.patch_batch_offset += address;
|
entry.patch_batch_offset += module_address;
|
||||||
if (entry.patch_batch_offset < external_patch_table_offset
|
if (entry.patch_batch_offset < external_patch_table_offset
|
||||||
|| entry.patch_batch_offset > external_patch_table_end) {
|
|| entry.patch_batch_offset > external_patch_table_end) {
|
||||||
return CROFormatError(0x1B);
|
return CROFormatError(0x1B);
|
||||||
@ -815,7 +815,7 @@ class CROHelper final {
|
|||||||
GetEntry(i, entry);
|
GetEntry(i, entry);
|
||||||
|
|
||||||
if (entry.patch_batch_offset) {
|
if (entry.patch_batch_offset) {
|
||||||
entry.patch_batch_offset += address;
|
entry.patch_batch_offset += module_address;
|
||||||
if (entry.patch_batch_offset < external_patch_table_offset
|
if (entry.patch_batch_offset < external_patch_table_offset
|
||||||
|| entry.patch_batch_offset > external_patch_table_end) {
|
|| entry.patch_batch_offset > external_patch_table_end) {
|
||||||
return CROFormatError(0x14);
|
return CROFormatError(0x14);
|
||||||
@ -841,7 +841,7 @@ class CROHelper final {
|
|||||||
GetEntry(i, entry);
|
GetEntry(i, entry);
|
||||||
|
|
||||||
if (entry.patch_batch_offset) {
|
if (entry.patch_batch_offset) {
|
||||||
entry.patch_batch_offset += address;
|
entry.patch_batch_offset += module_address;
|
||||||
if (entry.patch_batch_offset < external_patch_table_offset
|
if (entry.patch_batch_offset < external_patch_table_offset
|
||||||
|| entry.patch_batch_offset > external_patch_table_end) {
|
|| entry.patch_batch_offset > external_patch_table_end) {
|
||||||
return CROFormatError(0x17);
|
return CROFormatError(0x17);
|
||||||
@ -947,7 +947,7 @@ class CROHelper final {
|
|||||||
for (u32 i = 0; i < offset_export_num; ++i) {
|
for (u32 i = 0; i < offset_export_num; ++i) {
|
||||||
StaticAnonymousSymbolEntry entry;
|
StaticAnonymousSymbolEntry entry;
|
||||||
GetEntry(i, entry);
|
GetEntry(i, entry);
|
||||||
u32 batch_address = entry.patch_batch_offset + address;
|
u32 batch_address = entry.patch_batch_offset + module_address;
|
||||||
|
|
||||||
if (batch_address < static_patch_table_offset
|
if (batch_address < static_patch_table_offset
|
||||||
|| batch_address > static_patch_table_end) {
|
|| batch_address > static_patch_table_end) {
|
||||||
@ -1040,7 +1040,7 @@ class CROHelper final {
|
|||||||
GetEntry(i, entry);
|
GetEntry(i, entry);
|
||||||
|
|
||||||
if (entry.patch_batch_offset) {
|
if (entry.patch_batch_offset) {
|
||||||
entry.patch_batch_offset -= address;
|
entry.patch_batch_offset -= module_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetEntry(i, entry);
|
SetEntry(i, entry);
|
||||||
@ -1055,7 +1055,7 @@ class CROHelper final {
|
|||||||
GetEntry(i, entry);
|
GetEntry(i, entry);
|
||||||
|
|
||||||
if (entry.patch_batch_offset) {
|
if (entry.patch_batch_offset) {
|
||||||
entry.patch_batch_offset -= address;
|
entry.patch_batch_offset -= module_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetEntry(i, entry);
|
SetEntry(i, entry);
|
||||||
@ -1070,11 +1070,11 @@ class CROHelper final {
|
|||||||
GetEntry(i, entry);
|
GetEntry(i, entry);
|
||||||
|
|
||||||
if (entry.name_offset) {
|
if (entry.name_offset) {
|
||||||
entry.name_offset -= address;
|
entry.name_offset -= module_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.patch_batch_offset) {
|
if (entry.patch_batch_offset) {
|
||||||
entry.patch_batch_offset -= address;
|
entry.patch_batch_offset -= module_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetEntry(i, entry);
|
SetEntry(i, entry);
|
||||||
@ -1089,15 +1089,15 @@ class CROHelper final {
|
|||||||
GetEntry(i, entry);
|
GetEntry(i, entry);
|
||||||
|
|
||||||
if (entry.name_offset) {
|
if (entry.name_offset) {
|
||||||
entry.name_offset -= address;
|
entry.name_offset -= module_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.import_indexed_symbol_table_offset) {
|
if (entry.import_indexed_symbol_table_offset) {
|
||||||
entry.import_indexed_symbol_table_offset -= address;
|
entry.import_indexed_symbol_table_offset -= module_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.import_anonymous_symbol_table_offset) {
|
if (entry.import_anonymous_symbol_table_offset) {
|
||||||
entry.import_anonymous_symbol_table_offset -= address;
|
entry.import_anonymous_symbol_table_offset -= module_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetEntry(i, entry);
|
SetEntry(i, entry);
|
||||||
@ -1112,7 +1112,7 @@ class CROHelper final {
|
|||||||
GetEntry(i, entry);
|
GetEntry(i, entry);
|
||||||
|
|
||||||
if (entry.name_offset) {
|
if (entry.name_offset) {
|
||||||
entry.name_offset -= address;
|
entry.name_offset -= module_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetEntry(i, entry);
|
SetEntry(i, entry);
|
||||||
@ -1129,7 +1129,7 @@ class CROHelper final {
|
|||||||
if (segment.type == SegmentType::BSS) {
|
if (segment.type == SegmentType::BSS) {
|
||||||
segment.offset = 0;
|
segment.offset = 0;
|
||||||
} else if (segment.offset) {
|
} else if (segment.offset) {
|
||||||
segment.offset -= address;
|
segment.offset -= module_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetEntry(i, segment);
|
SetEntry(i, segment);
|
||||||
@ -1140,13 +1140,13 @@ class CROHelper final {
|
|||||||
void UnrebaseHeader() {
|
void UnrebaseHeader() {
|
||||||
u32 offset = GetField(NameOffset);
|
u32 offset = GetField(NameOffset);
|
||||||
if (offset)
|
if (offset)
|
||||||
SetField(NameOffset, offset - address);
|
SetField(NameOffset, offset - module_address);
|
||||||
|
|
||||||
for (int field = CodeOffset; field < Fix0Barrier; field += 2) {
|
for (int field = CodeOffset; field < Fix0Barrier; field += 2) {
|
||||||
HeaderField header_field = static_cast<HeaderField>(field);
|
HeaderField header_field = static_cast<HeaderField>(field);
|
||||||
offset = GetField(header_field);
|
offset = GetField(header_field);
|
||||||
if (offset)
|
if (offset)
|
||||||
SetField(header_field, offset - address);
|
SetField(header_field, offset - module_address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1528,7 +1528,7 @@ class CROHelper final {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CROHelper(VAddr cro_address) : address(cro_address) {
|
explicit CROHelper(VAddr cro_address) : module_address(cro_address) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ModuleName() const {
|
std::string ModuleName() const {
|
||||||
@ -1576,7 +1576,7 @@ public:
|
|||||||
}
|
}
|
||||||
prev_data_segment_address = *result_val;
|
prev_data_segment_address = *result_val;
|
||||||
}
|
}
|
||||||
prev_data_segment_address += address;
|
prev_data_segment_address += module_address;
|
||||||
|
|
||||||
result = RebaseExportNamedSymbolTable();
|
result = RebaseExportNamedSymbolTable();
|
||||||
if (result.IsError()) {
|
if (result.IsError()) {
|
||||||
@ -1851,28 +1851,28 @@ public:
|
|||||||
CROHelper crs(crs_address);
|
CROHelper crs(crs_address);
|
||||||
CROHelper head(auto_link ? crs.Next() : crs.Previous());
|
CROHelper head(auto_link ? crs.Next() : crs.Previous());
|
||||||
|
|
||||||
if (head.address) {
|
if (head.module_address) {
|
||||||
// there are already CROs registered
|
// there are already CROs registered
|
||||||
// register as the new tail
|
// register as the new tail
|
||||||
CROHelper tail(head.Previous());
|
CROHelper tail(head.Previous());
|
||||||
|
|
||||||
// link with the old tail
|
// link with the old tail
|
||||||
ASSERT(tail.Next() == 0);
|
ASSERT(tail.Next() == 0);
|
||||||
SetPrevious(tail.address);
|
SetPrevious(tail.module_address);
|
||||||
tail.SetNext(address);
|
tail.SetNext(module_address);
|
||||||
|
|
||||||
// set previous of the head pointing to the new tail
|
// set previous of the head pointing to the new tail
|
||||||
head.SetPrevious(address);
|
head.SetPrevious(module_address);
|
||||||
} else {
|
} else {
|
||||||
// register as the first CRO
|
// register as the first CRO
|
||||||
// set previous to self as tail
|
// set previous to self as tail
|
||||||
SetPrevious(address);
|
SetPrevious(module_address);
|
||||||
|
|
||||||
// set self as head
|
// set self as head
|
||||||
if (auto_link)
|
if (auto_link)
|
||||||
crs.SetNext(address);
|
crs.SetNext(module_address);
|
||||||
else
|
else
|
||||||
crs.SetPrevious(address);
|
crs.SetPrevious(module_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
// the new one is the tail
|
// the new one is the tail
|
||||||
@ -1888,34 +1888,34 @@ public:
|
|||||||
CROHelper next_head(crs.Next()), previous_head(crs.Previous());
|
CROHelper next_head(crs.Next()), previous_head(crs.Previous());
|
||||||
CROHelper next(Next()), previous(Previous());
|
CROHelper next(Next()), previous(Previous());
|
||||||
|
|
||||||
if (address == next_head.address || address == previous_head.address) {
|
if (module_address == next_head.module_address || module_address == previous_head.module_address) {
|
||||||
// removing head
|
// removing head
|
||||||
if (next.address) {
|
if (next.module_address) {
|
||||||
// the next is new head
|
// the next is new head
|
||||||
// let its previous point to the tail
|
// let its previous point to the tail
|
||||||
next.SetPrevious(previous.address);
|
next.SetPrevious(previous.module_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set new head
|
// set new head
|
||||||
if (address == previous_head.address) {
|
if (module_address == previous_head.module_address) {
|
||||||
crs.SetPrevious(next.address);
|
crs.SetPrevious(next.module_address);
|
||||||
} else {
|
} else {
|
||||||
crs.SetNext(next.address);
|
crs.SetNext(next.module_address);
|
||||||
}
|
}
|
||||||
} else if (next.address) {
|
} else if (next.module_address) {
|
||||||
// link previous and next
|
// link previous and next
|
||||||
previous.SetNext(next.address);
|
previous.SetNext(next.module_address);
|
||||||
next.SetPrevious(previous.address);
|
next.SetPrevious(previous.module_address);
|
||||||
} else {
|
} else {
|
||||||
// removing tail
|
// removing tail
|
||||||
// set previous as new tail
|
// set previous as new tail
|
||||||
previous.SetNext(0);
|
previous.SetNext(0);
|
||||||
|
|
||||||
// let head's previous point to the new tail
|
// let head's previous point to the new tail
|
||||||
if (next_head.address && next_head.Previous() == address) {
|
if (next_head.module_address && next_head.Previous() == module_address) {
|
||||||
next_head.SetPrevious(previous.address);
|
next_head.SetPrevious(previous.module_address);
|
||||||
} else if (previous_head.address && previous_head.Previous() == address) {
|
} else if (previous_head.module_address && previous_head.Previous() == module_address) {
|
||||||
previous_head.SetPrevious(previous.address);
|
previous_head.SetPrevious(previous.module_address);
|
||||||
} else {
|
} else {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
@ -1969,7 +1969,7 @@ public:
|
|||||||
|
|
||||||
fix_end = Common::AlignUp(fix_end, Memory::PAGE_SIZE);
|
fix_end = Common::AlignUp(fix_end, Memory::PAGE_SIZE);
|
||||||
|
|
||||||
u32 fixed_size = fix_end - address;
|
u32 fixed_size = fix_end - module_address;
|
||||||
SetField(FixedSize, fixed_size);
|
SetField(FixedSize, fixed_size);
|
||||||
return fixed_size;
|
return fixed_size;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user