LDR fixup module_address

This commit is contained in:
wwylele 2016-08-16 10:53:53 +08:00
parent 663e38c142
commit 1fb62d3a90

View File

@ -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;
} }