diff options
author | bunnei <bunneidev@gmail.com> | 2017-10-10 23:32:14 +0200 |
---|---|---|
committer | bunnei <bunneidev@gmail.com> | 2017-10-10 23:32:14 +0200 |
commit | 0906de9a14b735d1d409290ca050eb7d2c2d3d84 (patch) | |
tree | 79bb57d3a4dc4ca377e7a62744c3941de29e785b /src/core/hle/service/ldr_ro/cro_helper.cpp | |
parent | Merge remote-tracking branch 'upstream/master' into nx (diff) | |
download | yuzu-0906de9a14b735d1d409290ca050eb7d2c2d3d84.tar yuzu-0906de9a14b735d1d409290ca050eb7d2c2d3d84.tar.gz yuzu-0906de9a14b735d1d409290ca050eb7d2c2d3d84.tar.bz2 yuzu-0906de9a14b735d1d409290ca050eb7d2c2d3d84.tar.lz yuzu-0906de9a14b735d1d409290ca050eb7d2c2d3d84.tar.xz yuzu-0906de9a14b735d1d409290ca050eb7d2c2d3d84.tar.zst yuzu-0906de9a14b735d1d409290ca050eb7d2c2d3d84.zip |
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/service/ldr_ro/cro_helper.cpp | 1495 |
1 files changed, 0 insertions, 1495 deletions
diff --git a/src/core/hle/service/ldr_ro/cro_helper.cpp b/src/core/hle/service/ldr_ro/cro_helper.cpp deleted file mode 100644 index 6128f8a6c..000000000 --- a/src/core/hle/service/ldr_ro/cro_helper.cpp +++ /dev/null @@ -1,1495 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/alignment.h" -#include "common/logging/log.h" -#include "common/scope_exit.h" -#include "core/hle/service/ldr_ro/cro_helper.h" - -namespace Service { -namespace LDR { - -static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F - ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument, - ErrorLevel::Usage); - -static ResultCode CROFormatError(u32 description) { - return ResultCode(static_cast<ErrorDescription>(description), ErrorModule::RO, - ErrorSummary::WrongArgument, ErrorLevel::Permanent); -} - -const std::array<int, 17> CROHelper::ENTRY_SIZE{{ - 1, // code - 1, // data - 1, // module name - sizeof(SegmentEntry), sizeof(ExportNamedSymbolEntry), sizeof(ExportIndexedSymbolEntry), - 1, // export strings - sizeof(ExportTreeEntry), sizeof(ImportModuleEntry), sizeof(ExternalRelocationEntry), - sizeof(ImportNamedSymbolEntry), sizeof(ImportIndexedSymbolEntry), - sizeof(ImportAnonymousSymbolEntry), - 1, // import strings - sizeof(StaticAnonymousSymbolEntry), sizeof(InternalRelocationEntry), - sizeof(StaticRelocationEntry), -}}; - -const std::array<CROHelper::HeaderField, 4> CROHelper::FIX_BARRIERS{{ - Fix0Barrier, Fix1Barrier, Fix2Barrier, Fix3Barrier, -}}; - -VAddr CROHelper::SegmentTagToAddress(SegmentTag segment_tag) const { - u32 segment_num = GetField(SegmentNum); - - if (segment_tag.segment_index >= segment_num) - return 0; - - SegmentEntry entry; - GetEntry(segment_tag.segment_index, entry); - - if (segment_tag.offset_into_segment >= entry.size) - return 0; - - return entry.offset + segment_tag.offset_into_segment; -} - -ResultCode CROHelper::ApplyRelocation(VAddr target_address, RelocationType relocation_type, - u32 addend, u32 symbol_address, u32 target_future_address) { - - switch (relocation_type) { - case RelocationType::Nothing: - break; - case RelocationType::AbsoluteAddress: - case RelocationType::AbsoluteAddress2: - Memory::Write32(target_address, symbol_address + addend); - break; - case RelocationType::RelativeAddress: - Memory::Write32(target_address, symbol_address + addend - target_future_address); - break; - case RelocationType::ThumbBranch: - case RelocationType::ArmBranch: - case RelocationType::ModifyArmBranch: - case RelocationType::AlignedRelativeAddress: - // TODO(wwylele): implement other types - UNIMPLEMENTED(); - break; - default: - return CROFormatError(0x22); - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ClearRelocation(VAddr target_address, RelocationType relocation_type) { - switch (relocation_type) { - case RelocationType::Nothing: - break; - case RelocationType::AbsoluteAddress: - case RelocationType::AbsoluteAddress2: - case RelocationType::RelativeAddress: - Memory::Write32(target_address, 0); - break; - case RelocationType::ThumbBranch: - case RelocationType::ArmBranch: - case RelocationType::ModifyArmBranch: - case RelocationType::AlignedRelativeAddress: - // TODO(wwylele): implement other types - UNIMPLEMENTED(); - break; - default: - return CROFormatError(0x22); - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool reset) { - if (symbol_address == 0 && !reset) - return CROFormatError(0x10); - - VAddr relocation_address = batch; - while (true) { - RelocationEntry relocation; - Memory::ReadBlock(relocation_address, &relocation, sizeof(RelocationEntry)); - - VAddr relocation_target = SegmentTagToAddress(relocation.target_position); - if (relocation_target == 0) { - return CROFormatError(0x12); - } - - ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend, - symbol_address, relocation_target); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); - return result; - } - - if (relocation.is_batch_end) - break; - - relocation_address += sizeof(RelocationEntry); - } - - RelocationEntry relocation; - Memory::ReadBlock(batch, &relocation, sizeof(RelocationEntry)); - relocation.is_batch_resolved = reset ? 0 : 1; - Memory::WriteBlock(batch, &relocation, sizeof(RelocationEntry)); - return RESULT_SUCCESS; -} - -VAddr CROHelper::FindExportNamedSymbol(const std::string& name) const { - if (!GetField(ExportTreeNum)) - return 0; - - std::size_t len = name.size(); - ExportTreeEntry entry; - GetEntry(0, entry); - ExportTreeEntry::Child next; - next.raw = entry.left.raw; - u32 found_id; - - while (true) { - GetEntry(next.next_index, entry); - - if (next.is_end) { - found_id = entry.export_table_index; - break; - } - - u16 test_byte = entry.test_bit >> 3; - u16 test_bit_in_byte = entry.test_bit & 7; - - if (test_byte >= len) { - next.raw = entry.left.raw; - } else if ((name[test_byte] >> test_bit_in_byte) & 1) { - next.raw = entry.right.raw; - } else { - next.raw = entry.left.raw; - } - } - - u32 export_named_symbol_num = GetField(ExportNamedSymbolNum); - - if (found_id >= export_named_symbol_num) - return 0; - - u32 export_strings_size = GetField(ExportStringsSize); - ExportNamedSymbolEntry symbol_entry; - GetEntry(found_id, symbol_entry); - - if (Memory::ReadCString(symbol_entry.name_offset, export_strings_size) != name) - return 0; - - return SegmentTagToAddress(symbol_entry.symbol_position); -} - -ResultCode CROHelper::RebaseHeader(u32 cro_size) { - ResultCode error = CROFormatError(0x11); - - // verifies magic - if (GetField(Magic) != MAGIC_CRO0) - return error; - - // verifies not registered - if (GetField(NextCRO) != 0 || GetField(PreviousCRO) != 0) - return error; - - // This seems to be a hard limit set by the RO module - if (GetField(FileSize) > 0x10000000 || GetField(BssSize) > 0x10000000) - return error; - - // verifies not fixed - if (GetField(FixedSize) != 0) - return error; - - if (GetField(CodeOffset) < CRO_HEADER_SIZE) - return error; - - // verifies that all offsets are in the correct order - constexpr std::array<HeaderField, 18> OFFSET_ORDER = {{ - CodeOffset, ModuleNameOffset, SegmentTableOffset, ExportNamedSymbolTableOffset, - ExportTreeTableOffset, ExportIndexedSymbolTableOffset, ExportStringsOffset, - ImportModuleTableOffset, ExternalRelocationTableOffset, ImportNamedSymbolTableOffset, - ImportIndexedSymbolTableOffset, ImportAnonymousSymbolTableOffset, ImportStringsOffset, - StaticAnonymousSymbolTableOffset, InternalRelocationTableOffset, - StaticRelocationTableOffset, DataOffset, FileSize, - }}; - - u32 prev_offset = GetField(OFFSET_ORDER[0]); - u32 cur_offset; - for (std::size_t i = 1; i < OFFSET_ORDER.size(); ++i) { - cur_offset = GetField(OFFSET_ORDER[i]); - if (cur_offset < prev_offset) - return error; - prev_offset = cur_offset; - } - - // rebases offsets - u32 offset = GetField(NameOffset); - if (offset != 0) - SetField(NameOffset, offset + module_address); - - for (int field = CodeOffset; field < Fix0Barrier; field += 2) { - HeaderField header_field = static_cast<HeaderField>(field); - offset = GetField(header_field); - if (offset != 0) - SetField(header_field, offset + module_address); - } - - // verifies everything is not beyond the buffer - u32 file_end = module_address + cro_size; - for (int field = CodeOffset, i = 0; field < Fix0Barrier; field += 2, ++i) { - HeaderField offset_field = static_cast<HeaderField>(field); - HeaderField size_field = static_cast<HeaderField>(field + 1); - if (GetField(offset_field) + GetField(size_field) * ENTRY_SIZE[i] > file_end) - return error; - } - - return RESULT_SUCCESS; -} - -ResultVal<VAddr> CROHelper::RebaseSegmentTable(u32 cro_size, VAddr data_segment_address, - u32 data_segment_size, VAddr bss_segment_address, - u32 bss_segment_size) { - - u32 prev_data_segment = 0; - u32 segment_num = GetField(SegmentNum); - for (u32 i = 0; i < segment_num; ++i) { - SegmentEntry segment; - GetEntry(i, segment); - if (segment.type == SegmentType::Data) { - if (segment.size != 0) { - if (segment.size > data_segment_size) - return ERROR_BUFFER_TOO_SMALL; - prev_data_segment = segment.offset; - segment.offset = data_segment_address; - } - } else if (segment.type == SegmentType::BSS) { - if (segment.size != 0) { - if (segment.size > bss_segment_size) - return ERROR_BUFFER_TOO_SMALL; - segment.offset = bss_segment_address; - } - } else if (segment.offset != 0) { - segment.offset += module_address; - if (segment.offset > module_address + cro_size) - return CROFormatError(0x19); - } - SetEntry(i, segment); - } - return MakeResult<VAddr>(prev_data_segment + module_address); -} - -ResultCode CROHelper::RebaseExportNamedSymbolTable() { - VAddr export_strings_offset = GetField(ExportStringsOffset); - VAddr export_strings_end = export_strings_offset + GetField(ExportStringsSize); - - 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 != 0) { - entry.name_offset += module_address; - if (entry.name_offset < export_strings_offset || - entry.name_offset >= export_strings_end) { - return CROFormatError(0x11); - } - } - - SetEntry(i, entry); - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::VerifyExportTreeTable() const { - u32 tree_num = GetField(ExportTreeNum); - for (u32 i = 0; i < tree_num; ++i) { - ExportTreeEntry entry; - GetEntry(i, entry); - - if (entry.left.next_index >= tree_num || entry.right.next_index >= tree_num) { - return CROFormatError(0x11); - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::RebaseImportModuleTable() { - VAddr import_strings_offset = GetField(ImportStringsOffset); - VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize); - VAddr import_indexed_symbol_table_offset = GetField(ImportIndexedSymbolTableOffset); - VAddr index_import_table_end = - import_indexed_symbol_table_offset + - GetField(ImportIndexedSymbolNum) * sizeof(ImportIndexedSymbolEntry); - VAddr import_anonymous_symbol_table_offset = GetField(ImportAnonymousSymbolTableOffset); - VAddr offset_import_table_end = - import_anonymous_symbol_table_offset + - GetField(ImportAnonymousSymbolNum) * sizeof(ImportAnonymousSymbolEntry); - - u32 module_num = GetField(ImportModuleNum); - for (u32 i = 0; i < module_num; ++i) { - ImportModuleEntry entry; - GetEntry(i, entry); - - if (entry.name_offset != 0) { - entry.name_offset += module_address; - if (entry.name_offset < import_strings_offset || - entry.name_offset >= import_strings_end) { - return CROFormatError(0x18); - } - } - - if (entry.import_indexed_symbol_table_offset != 0) { - entry.import_indexed_symbol_table_offset += module_address; - if (entry.import_indexed_symbol_table_offset < import_indexed_symbol_table_offset || - entry.import_indexed_symbol_table_offset > index_import_table_end) { - return CROFormatError(0x18); - } - } - - if (entry.import_anonymous_symbol_table_offset != 0) { - entry.import_anonymous_symbol_table_offset += module_address; - if (entry.import_anonymous_symbol_table_offset < import_anonymous_symbol_table_offset || - entry.import_anonymous_symbol_table_offset > offset_import_table_end) { - return CROFormatError(0x18); - } - } - - SetEntry(i, entry); - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::RebaseImportNamedSymbolTable() { - VAddr import_strings_offset = GetField(ImportStringsOffset); - VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize); - VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); - VAddr external_relocation_table_end = - external_relocation_table_offset + - GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); - - u32 num = GetField(ImportNamedSymbolNum); - for (u32 i = 0; i < num; ++i) { - ImportNamedSymbolEntry entry; - GetEntry(i, entry); - - if (entry.name_offset != 0) { - entry.name_offset += module_address; - if (entry.name_offset < import_strings_offset || - entry.name_offset >= import_strings_end) { - return CROFormatError(0x1B); - } - } - - if (entry.relocation_batch_offset != 0) { - entry.relocation_batch_offset += module_address; - if (entry.relocation_batch_offset < external_relocation_table_offset || - entry.relocation_batch_offset > external_relocation_table_end) { - return CROFormatError(0x1B); - } - } - - SetEntry(i, entry); - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::RebaseImportIndexedSymbolTable() { - VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); - VAddr external_relocation_table_end = - external_relocation_table_offset + - GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); - - u32 num = GetField(ImportIndexedSymbolNum); - for (u32 i = 0; i < num; ++i) { - ImportIndexedSymbolEntry entry; - GetEntry(i, entry); - - if (entry.relocation_batch_offset != 0) { - entry.relocation_batch_offset += module_address; - if (entry.relocation_batch_offset < external_relocation_table_offset || - entry.relocation_batch_offset > external_relocation_table_end) { - return CROFormatError(0x14); - } - } - - SetEntry(i, entry); - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::RebaseImportAnonymousSymbolTable() { - VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); - VAddr external_relocation_table_end = - external_relocation_table_offset + - GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); - - u32 num = GetField(ImportAnonymousSymbolNum); - for (u32 i = 0; i < num; ++i) { - ImportAnonymousSymbolEntry entry; - GetEntry(i, entry); - - if (entry.relocation_batch_offset != 0) { - entry.relocation_batch_offset += module_address; - if (entry.relocation_batch_offset < external_relocation_table_offset || - entry.relocation_batch_offset > external_relocation_table_end) { - return CROFormatError(0x17); - } - } - - SetEntry(i, entry); - } - return RESULT_SUCCESS; -} - -VAddr CROHelper::GetOnUnresolvedAddress() { - return SegmentTagToAddress(SegmentTag(GetField(OnUnresolvedSegmentTag))); -} - -ResultCode CROHelper::ResetExternalRelocations() { - u32 unresolved_symbol = GetOnUnresolvedAddress(); - u32 external_relocation_num = GetField(ExternalRelocationNum); - ExternalRelocationEntry relocation; - - // Verifies that the last relocation is the end of a batch - GetEntry(external_relocation_num - 1, relocation); - if (!relocation.is_batch_end) { - return CROFormatError(0x12); - } - - bool batch_begin = true; - for (u32 i = 0; i < external_relocation_num; ++i) { - GetEntry(i, relocation); - VAddr relocation_target = SegmentTagToAddress(relocation.target_position); - - if (relocation_target == 0) { - return CROFormatError(0x12); - } - - ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend, - unresolved_symbol, relocation_target); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); - return result; - } - - if (batch_begin) { - // resets to unresolved state - relocation.is_batch_resolved = 0; - SetEntry(i, relocation); - } - - // if current is an end, then the next is a beginning - batch_begin = relocation.is_batch_end != 0; - } - - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ClearExternalRelocations() { - u32 external_relocation_num = GetField(ExternalRelocationNum); - ExternalRelocationEntry relocation; - - bool batch_begin = true; - for (u32 i = 0; i < external_relocation_num; ++i) { - GetEntry(i, relocation); - VAddr relocation_target = SegmentTagToAddress(relocation.target_position); - - if (relocation_target == 0) { - return CROFormatError(0x12); - } - - ResultCode result = ClearRelocation(relocation_target, relocation.type); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error clearing relocation %08X", result.raw); - return result; - } - - if (batch_begin) { - // resets to unresolved state - relocation.is_batch_resolved = 0; - SetEntry(i, relocation); - } - - // if current is an end, then the next is a beginning - batch_begin = relocation.is_batch_end != 0; - } - - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ApplyStaticAnonymousSymbolToCRS(VAddr crs_address) { - VAddr static_relocation_table_offset = GetField(StaticRelocationTableOffset); - VAddr static_relocation_table_end = - static_relocation_table_offset + - GetField(StaticRelocationNum) * sizeof(StaticRelocationEntry); - - CROHelper crs(crs_address); - u32 offset_export_num = GetField(StaticAnonymousSymbolNum); - LOG_INFO(Service_LDR, "CRO \"%s\" exports %d static anonymous symbols", ModuleName().data(), - offset_export_num); - for (u32 i = 0; i < offset_export_num; ++i) { - StaticAnonymousSymbolEntry entry; - GetEntry(i, entry); - u32 batch_address = entry.relocation_batch_offset + module_address; - - if (batch_address < static_relocation_table_offset || - batch_address > static_relocation_table_end) { - return CROFormatError(0x16); - } - - u32 symbol_address = SegmentTagToAddress(entry.symbol_position); - LOG_TRACE(Service_LDR, "CRO \"%s\" exports 0x%08X to the static module", - ModuleName().data(), symbol_address); - ResultCode result = crs.ApplyRelocationBatch(batch_address, symbol_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); - return result; - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ApplyInternalRelocations(u32 old_data_segment_address) { - u32 segment_num = GetField(SegmentNum); - u32 internal_relocation_num = GetField(InternalRelocationNum); - for (u32 i = 0; i < internal_relocation_num; ++i) { - InternalRelocationEntry relocation; - GetEntry(i, relocation); - VAddr target_addressB = SegmentTagToAddress(relocation.target_position); - if (target_addressB == 0) { - return CROFormatError(0x15); - } - - VAddr target_address; - SegmentEntry target_segment; - GetEntry(relocation.target_position.segment_index, target_segment); - - if (target_segment.type == SegmentType::Data) { - // If the relocation is to the .data segment, we need to relocate it in the old buffer - target_address = - old_data_segment_address + relocation.target_position.offset_into_segment; - } else { - target_address = target_addressB; - } - - if (relocation.symbol_segment >= segment_num) { - return CROFormatError(0x15); - } - - SegmentEntry symbol_segment; - GetEntry(relocation.symbol_segment, symbol_segment); - LOG_TRACE(Service_LDR, "Internally relocates 0x%08X with 0x%08X", target_address, - symbol_segment.offset); - ResultCode result = ApplyRelocation(target_address, relocation.type, relocation.addend, - symbol_segment.offset, target_addressB); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); - return result; - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ClearInternalRelocations() { - u32 internal_relocation_num = GetField(InternalRelocationNum); - for (u32 i = 0; i < internal_relocation_num; ++i) { - InternalRelocationEntry relocation; - GetEntry(i, relocation); - VAddr target_address = SegmentTagToAddress(relocation.target_position); - - if (target_address == 0) { - return CROFormatError(0x15); - } - - ResultCode result = ClearRelocation(target_address, relocation.type); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error clearing relocation %08X", result.raw); - return result; - } - } - return RESULT_SUCCESS; -} - -void CROHelper::UnrebaseImportAnonymousSymbolTable() { - u32 num = GetField(ImportAnonymousSymbolNum); - for (u32 i = 0; i < num; ++i) { - ImportAnonymousSymbolEntry entry; - GetEntry(i, entry); - - if (entry.relocation_batch_offset != 0) { - entry.relocation_batch_offset -= module_address; - } - - SetEntry(i, entry); - } -} - -void CROHelper::UnrebaseImportIndexedSymbolTable() { - u32 num = GetField(ImportIndexedSymbolNum); - for (u32 i = 0; i < num; ++i) { - ImportIndexedSymbolEntry entry; - GetEntry(i, entry); - - if (entry.relocation_batch_offset != 0) { - entry.relocation_batch_offset -= module_address; - } - - SetEntry(i, entry); - } -} - -void CROHelper::UnrebaseImportNamedSymbolTable() { - u32 num = GetField(ImportNamedSymbolNum); - for (u32 i = 0; i < num; ++i) { - ImportNamedSymbolEntry entry; - GetEntry(i, entry); - - if (entry.name_offset != 0) { - entry.name_offset -= module_address; - } - - if (entry.relocation_batch_offset) { - entry.relocation_batch_offset -= module_address; - } - - SetEntry(i, entry); - } -} - -void CROHelper::UnrebaseImportModuleTable() { - u32 module_num = GetField(ImportModuleNum); - for (u32 i = 0; i < module_num; ++i) { - ImportModuleEntry entry; - GetEntry(i, entry); - - if (entry.name_offset != 0) { - entry.name_offset -= module_address; - } - - if (entry.import_indexed_symbol_table_offset) { - entry.import_indexed_symbol_table_offset -= module_address; - } - - if (entry.import_anonymous_symbol_table_offset) { - entry.import_anonymous_symbol_table_offset -= module_address; - } - - SetEntry(i, entry); - } -} - -void CROHelper::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 != 0) { - entry.name_offset -= module_address; - } - - SetEntry(i, entry); - } -} - -void CROHelper::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 != 0) { - segment.offset -= module_address; - } - - SetEntry(i, segment); - } -} - -void CROHelper::UnrebaseHeader() { - u32 offset = GetField(NameOffset); - if (offset != 0) - SetField(NameOffset, offset - module_address); - - for (int field = CodeOffset; field < Fix0Barrier; field += 2) { - HeaderField header_field = static_cast<HeaderField>(field); - offset = GetField(header_field); - if (offset != 0) - SetField(header_field, offset - module_address); - } -} - -ResultCode CROHelper::ApplyImportNamedSymbol(VAddr crs_address) { - u32 import_strings_size = GetField(ImportStringsSize); - u32 symbol_import_num = GetField(ImportNamedSymbolNum); - for (u32 i = 0; i < symbol_import_num; ++i) { - ImportNamedSymbolEntry entry; - GetEntry(i, entry); - VAddr relocation_addr = entry.relocation_batch_offset; - ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); - - if (!relocation_entry.is_batch_resolved) { - ResultCode result = - ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { - std::string symbol_name = - Memory::ReadCString(entry.name_offset, import_strings_size); - u32 symbol_address = source.FindExportNamedSymbol(symbol_name); - - if (symbol_address != 0) { - LOG_TRACE(Service_LDR, "CRO \"%s\" imports \"%s\" from \"%s\"", - ModuleName().data(), symbol_name.data(), - source.ModuleName().data()); - - ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", - result.raw); - return result; - } - - return MakeResult<bool>(false); - } - - return MakeResult<bool>(true); - }); - if (result.IsError()) { - return result; - } - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ResetImportNamedSymbol() { - u32 unresolved_symbol = GetOnUnresolvedAddress(); - - u32 symbol_import_num = GetField(ImportNamedSymbolNum); - for (u32 i = 0; i < symbol_import_num; ++i) { - ImportNamedSymbolEntry entry; - GetEntry(i, entry); - VAddr relocation_addr = entry.relocation_batch_offset; - ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); - - ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error reseting relocation batch %08X", result.raw); - return result; - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ResetImportIndexedSymbol() { - u32 unresolved_symbol = GetOnUnresolvedAddress(); - - u32 import_num = GetField(ImportIndexedSymbolNum); - for (u32 i = 0; i < import_num; ++i) { - ImportIndexedSymbolEntry entry; - GetEntry(i, entry); - VAddr relocation_addr = entry.relocation_batch_offset; - ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); - - ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error reseting relocation batch %08X", result.raw); - return result; - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ResetImportAnonymousSymbol() { - u32 unresolved_symbol = GetOnUnresolvedAddress(); - - u32 import_num = GetField(ImportAnonymousSymbolNum); - for (u32 i = 0; i < import_num; ++i) { - ImportAnonymousSymbolEntry entry; - GetEntry(i, entry); - VAddr relocation_addr = entry.relocation_batch_offset; - ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); - - ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error reseting relocation batch %08X", result.raw); - return result; - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) { - u32 import_strings_size = GetField(ImportStringsSize); - - u32 import_module_num = GetField(ImportModuleNum); - for (u32 i = 0; i < import_module_num; ++i) { - ImportModuleEntry entry; - GetEntry(i, entry); - std::string want_cro_name = Memory::ReadCString(entry.name_offset, import_strings_size); - - ResultCode result = - ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { - if (want_cro_name == source.ModuleName()) { - LOG_INFO(Service_LDR, "CRO \"%s\" imports %d indexed symbols from \"%s\"", - ModuleName().data(), entry.import_indexed_symbol_num, - source.ModuleName().data()); - for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { - ImportIndexedSymbolEntry im; - entry.GetImportIndexedSymbolEntry(j, im); - ExportIndexedSymbolEntry ex; - source.GetEntry(im.index, ex); - u32 symbol_address = source.SegmentTagToAddress(ex.symbol_position); - LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address); - ResultCode result = - ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", - result.raw); - return result; - } - } - LOG_INFO(Service_LDR, "CRO \"%s\" imports %d anonymous symbols from \"%s\"", - ModuleName().data(), entry.import_anonymous_symbol_num, - source.ModuleName().data()); - for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { - ImportAnonymousSymbolEntry im; - entry.GetImportAnonymousSymbolEntry(j, im); - u32 symbol_address = source.SegmentTagToAddress(im.symbol_position); - LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address); - ResultCode result = - ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", - result.raw); - return result; - } - } - return MakeResult<bool>(false); - } - return MakeResult<bool>(true); - }); - if (result.IsError()) { - return result; - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) { - LOG_DEBUG(Service_LDR, "CRO \"%s\" exports named symbols to \"%s\"", ModuleName().data(), - target.ModuleName().data()); - u32 target_import_strings_size = target.GetField(ImportStringsSize); - u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum); - for (u32 i = 0; i < target_symbol_import_num; ++i) { - ImportNamedSymbolEntry entry; - target.GetEntry(i, entry); - VAddr relocation_addr = entry.relocation_batch_offset; - ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); - - if (!relocation_entry.is_batch_resolved) { - std::string symbol_name = - Memory::ReadCString(entry.name_offset, target_import_strings_size); - u32 symbol_address = FindExportNamedSymbol(symbol_name); - if (symbol_address != 0) { - LOG_TRACE(Service_LDR, " exports symbol \"%s\"", symbol_name.data()); - ResultCode result = target.ApplyRelocationBatch(relocation_addr, symbol_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); - return result; - } - } - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) { - LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports named symbols to \"%s\"", ModuleName().data(), - target.ModuleName().data()); - u32 unresolved_symbol = target.GetOnUnresolvedAddress(); - u32 target_import_strings_size = target.GetField(ImportStringsSize); - u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum); - for (u32 i = 0; i < target_symbol_import_num; ++i) { - ImportNamedSymbolEntry entry; - target.GetEntry(i, entry); - VAddr relocation_addr = entry.relocation_batch_offset; - ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); - - if (relocation_entry.is_batch_resolved) { - std::string symbol_name = - Memory::ReadCString(entry.name_offset, target_import_strings_size); - u32 symbol_address = FindExportNamedSymbol(symbol_name); - if (symbol_address != 0) { - LOG_TRACE(Service_LDR, " unexports symbol \"%s\"", symbol_name.data()); - ResultCode result = - target.ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); - return result; - } - } - } - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ApplyModuleExport(CROHelper target) { - std::string module_name = ModuleName(); - u32 target_import_string_size = target.GetField(ImportStringsSize); - u32 target_import_module_num = target.GetField(ImportModuleNum); - for (u32 i = 0; i < target_import_module_num; ++i) { - ImportModuleEntry entry; - target.GetEntry(i, entry); - - if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name) - continue; - - LOG_INFO(Service_LDR, "CRO \"%s\" exports %d indexed symbols to \"%s\"", module_name.data(), - entry.import_indexed_symbol_num, target.ModuleName().data()); - for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { - ImportIndexedSymbolEntry im; - entry.GetImportIndexedSymbolEntry(j, im); - ExportIndexedSymbolEntry ex; - GetEntry(im.index, ex); - u32 symbol_address = SegmentTagToAddress(ex.symbol_position); - LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address); - ResultCode result = - target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); - return result; - } - } - - LOG_INFO(Service_LDR, "CRO \"%s\" exports %d anonymous symbols to \"%s\"", - module_name.data(), entry.import_anonymous_symbol_num, target.ModuleName().data()); - for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { - ImportAnonymousSymbolEntry im; - entry.GetImportAnonymousSymbolEntry(j, im); - u32 symbol_address = SegmentTagToAddress(im.symbol_position); - LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address); - ResultCode result = - target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); - return result; - } - } - } - - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ResetModuleExport(CROHelper target) { - u32 unresolved_symbol = target.GetOnUnresolvedAddress(); - - std::string module_name = ModuleName(); - u32 target_import_string_size = target.GetField(ImportStringsSize); - u32 target_import_module_num = target.GetField(ImportModuleNum); - for (u32 i = 0; i < target_import_module_num; ++i) { - ImportModuleEntry entry; - target.GetEntry(i, entry); - - if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name) - continue; - - LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports indexed symbols to \"%s\"", module_name.data(), - target.ModuleName().data()); - for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { - ImportIndexedSymbolEntry im; - entry.GetImportIndexedSymbolEntry(j, im); - ResultCode result = - target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); - return result; - } - } - - LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports anonymous symbols to \"%s\"", - module_name.data(), target.ModuleName().data()); - for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { - ImportAnonymousSymbolEntry im; - entry.GetImportAnonymousSymbolEntry(j, im); - ResultCode result = - target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); - return result; - } - } - } - - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) { - u32 import_strings_size = GetField(ImportStringsSize); - u32 symbol_import_num = GetField(ImportNamedSymbolNum); - for (u32 i = 0; i < symbol_import_num; ++i) { - ImportNamedSymbolEntry entry; - GetEntry(i, entry); - VAddr relocation_addr = entry.relocation_batch_offset; - ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); - - if (Memory::ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit") { - ResultCode result = - ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { - u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_"); - - if (symbol_address != 0) { - LOG_DEBUG(Service_LDR, "CRO \"%s\" import exit function from \"%s\"", - ModuleName().data(), source.ModuleName().data()); - - ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", - result.raw); - return result; - } - - return MakeResult<bool>(false); - } - - return MakeResult<bool>(true); - }); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying exit relocation %08X", result.raw); - return result; - } - } - } - return RESULT_SUCCESS; -} - -/** - * Verifies a string or a string table matching a predicted size (i.e. terminated by 0) - * if it is not empty. There can be many other nulls in the string table because - * they are composed by many sub strings. This function is to check whether the - * whole string (table) is terminated properly, despite that it is not actually one string. - * @param address the virtual address of the string (table) - * @param size the size of the string (table), including the terminating 0 - * @returns ResultCode RESULT_SUCCESS if the size matches, otherwise error code. - */ -static ResultCode VerifyStringTableLength(VAddr address, u32 size) { - if (size != 0) { - if (Memory::Read8(address + size - 1) != 0) - return CROFormatError(0x0B); - } - return RESULT_SUCCESS; -} - -ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment_addresss, - u32 data_segment_size, VAddr bss_segment_address, u32 bss_segment_size, - bool is_crs) { - - ResultCode result = RebaseHeader(cro_size); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error rebasing header %08X", result.raw); - return result; - } - - result = VerifyStringTableLength(GetField(ModuleNameOffset), GetField(ModuleNameSize)); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error verifying module name %08X", result.raw); - return result; - } - - u32 prev_data_segment_address = 0; - if (!is_crs) { - auto result_val = RebaseSegmentTable(cro_size, data_segment_addresss, data_segment_size, - bss_segment_address, bss_segment_size); - if (result_val.Failed()) { - LOG_ERROR(Service_LDR, "Error rebasing segment table %08X", result_val.Code().raw); - return result_val.Code(); - } - prev_data_segment_address = *result_val; - } - - result = RebaseExportNamedSymbolTable(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error rebasing symbol export table %08X", result.raw); - return result; - } - - result = VerifyExportTreeTable(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error verifying export tree %08X", result.raw); - return result; - } - - result = VerifyStringTableLength(GetField(ExportStringsOffset), GetField(ExportStringsSize)); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error verifying export strings %08X", result.raw); - return result; - } - - result = RebaseImportModuleTable(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error rebasing object table %08X", result.raw); - return result; - } - - result = ResetExternalRelocations(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error resetting all external relocations %08X", result.raw); - return result; - } - - result = RebaseImportNamedSymbolTable(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error rebasing symbol import table %08X", result.raw); - return result; - } - - result = RebaseImportIndexedSymbolTable(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error rebasing index import table %08X", result.raw); - return result; - } - - result = RebaseImportAnonymousSymbolTable(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error rebasing offset import table %08X", result.raw); - return result; - } - - result = VerifyStringTableLength(GetField(ImportStringsOffset), GetField(ImportStringsSize)); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error verifying import strings %08X", result.raw); - return result; - } - - if (!is_crs) { - result = ApplyStaticAnonymousSymbolToCRS(crs_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying offset export to CRS %08X", result.raw); - return result; - } - } - - result = ApplyInternalRelocations(prev_data_segment_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying internal relocations %08X", result.raw); - return result; - } - - if (!is_crs) { - result = ApplyExitRelocations(crs_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying exit relocations %08X", result.raw); - return result; - } - } - - return RESULT_SUCCESS; -} - -void CROHelper::Unrebase(bool is_crs) { - UnrebaseImportAnonymousSymbolTable(); - UnrebaseImportIndexedSymbolTable(); - UnrebaseImportNamedSymbolTable(); - UnrebaseImportModuleTable(); - UnrebaseExportNamedSymbolTable(); - - if (!is_crs) - UnrebaseSegmentTable(); - - SetNextModule(0); - SetPreviousModule(0); - - SetField(FixedSize, 0); - - UnrebaseHeader(); -} - -ResultCode CROHelper::VerifyHash(u32 cro_size, VAddr crr) const { - // TODO(wwylele): actually verify the hash - return RESULT_SUCCESS; -} - -ResultCode CROHelper::Link(VAddr crs_address, bool link_on_load_bug_fix) { - ResultCode result = RESULT_SUCCESS; - - { - VAddr data_segment_address; - if (link_on_load_bug_fix) { - // this is a bug fix introduced by 7.2.0-17's LoadCRO_New - // The bug itself is: - // If a relocation target is in .data segment, it will relocate to the - // user-specified buffer. But if this is linking during loading, - // the .data segment hasn't been transfer from CRO to the buffer, - // thus the relocation will be overwritten by data transfer. - // To fix this bug, we need temporarily restore the old .data segment - // offset and apply imported symbols. - - // RO service seems assuming segment_index == segment_type, - // so we do the same - if (GetField(SegmentNum) >= 2) { // means we have .data segment - SegmentEntry entry; - GetEntry(2, entry); - ASSERT(entry.type == SegmentType::Data); - data_segment_address = entry.offset; - entry.offset = GetField(DataOffset); - SetEntry(2, entry); - } - } - SCOPE_EXIT({ - // Restore the new .data segment address after importing - if (link_on_load_bug_fix) { - if (GetField(SegmentNum) >= 2) { - SegmentEntry entry; - GetEntry(2, entry); - entry.offset = data_segment_address; - SetEntry(2, entry); - } - } - }); - - // Imports named symbols from other modules - result = ApplyImportNamedSymbol(crs_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying symbol import %08X", result.raw); - return result; - } - - // Imports indexed and anonymous symbols from other modules - result = ApplyModuleImport(crs_address); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying module import %08X", result.raw); - return result; - } - } - - // Exports symbols to other modules - result = ForEachAutoLinkCRO(crs_address, [this](CROHelper target) -> ResultVal<bool> { - ResultCode result = ApplyExportNamedSymbol(target); - if (result.IsError()) - return result; - - result = ApplyModuleExport(target); - if (result.IsError()) - return result; - - return MakeResult<bool>(true); - }); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error applying export %08X", result.raw); - return result; - } - - return RESULT_SUCCESS; -} - -ResultCode CROHelper::Unlink(VAddr crs_address) { - - // Resets all imported named symbols - ResultCode result = ResetImportNamedSymbol(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error resetting symbol import %08X", result.raw); - return result; - } - - // Resets all imported indexed symbols - result = ResetImportIndexedSymbol(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error resetting indexed import %08X", result.raw); - return result; - } - - // Resets all imported anonymous symbols - result = ResetImportAnonymousSymbol(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error resetting anonymous import %08X", result.raw); - return result; - } - - // Resets all symbols in other modules imported from this module - // Note: the RO service seems only searching in auto-link modules - result = ForEachAutoLinkCRO(crs_address, [this](CROHelper target) -> ResultVal<bool> { - ResultCode result = ResetExportNamedSymbol(target); - if (result.IsError()) - return result; - - result = ResetModuleExport(target); - if (result.IsError()) - return result; - - return MakeResult<bool>(true); - }); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error resetting export %08X", result.raw); - return result; - } - - return RESULT_SUCCESS; -} - -ResultCode CROHelper::ClearRelocations() { - ResultCode result = ClearExternalRelocations(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error clearing external relocations %08X", result.raw); - return result; - } - - result = ClearInternalRelocations(); - if (result.IsError()) { - LOG_ERROR(Service_LDR, "Error clearing internal relocations %08X", result.raw); - return result; - } - return RESULT_SUCCESS; -} - -void CROHelper::InitCRS() { - SetNextModule(0); - SetPreviousModule(0); -} - -void CROHelper::Register(VAddr crs_address, bool auto_link) { - CROHelper crs(crs_address); - CROHelper head(auto_link ? crs.NextModule() : crs.PreviousModule()); - - if (head.module_address) { - // there are already CROs registered - // register as the new tail - CROHelper tail(head.PreviousModule()); - - // link with the old tail - ASSERT(tail.NextModule() == 0); - SetPreviousModule(tail.module_address); - tail.SetNextModule(module_address); - - // set previous of the head pointing to the new tail - head.SetPreviousModule(module_address); - } else { - // register as the first CRO - // set previous to self as tail - SetPreviousModule(module_address); - - // set self as head - if (auto_link) - crs.SetNextModule(module_address); - else - crs.SetPreviousModule(module_address); - } - - // the new one is the tail - SetNextModule(0); -} - -void CROHelper::Unregister(VAddr crs_address) { - CROHelper crs(crs_address); - CROHelper next_head(crs.NextModule()), previous_head(crs.PreviousModule()); - CROHelper next(NextModule()), previous(PreviousModule()); - - if (module_address == next_head.module_address || - module_address == previous_head.module_address) { - // removing head - if (next.module_address) { - // the next is new head - // let its previous point to the tail - next.SetPreviousModule(previous.module_address); - } - - // set new head - if (module_address == previous_head.module_address) { - crs.SetPreviousModule(next.module_address); - } else { - crs.SetNextModule(next.module_address); - } - } else if (next.module_address) { - // link previous and next - previous.SetNextModule(next.module_address); - next.SetPreviousModule(previous.module_address); - } else { - // removing tail - // set previous as new tail - previous.SetNextModule(0); - - // let head's previous point to the new tail - if (next_head.module_address && next_head.PreviousModule() == module_address) { - next_head.SetPreviousModule(previous.module_address); - } else if (previous_head.module_address && - previous_head.PreviousModule() == module_address) { - previous_head.SetPreviousModule(previous.module_address); - } else { - UNREACHABLE(); - } - } - - // unlink self - SetNextModule(0); - SetPreviousModule(0); -} - -u32 CROHelper::GetFixEnd(u32 fix_level) const { - u32 end = CRO_HEADER_SIZE; - end = std::max<u32>(end, GetField(CodeOffset) + GetField(CodeSize)); - - u32 entry_size_i = 2; - int field = ModuleNameOffset; - while (true) { - end = std::max<u32>(end, GetField(static_cast<HeaderField>(field)) + - GetField(static_cast<HeaderField>(field + 1)) * - ENTRY_SIZE[entry_size_i]); - - ++entry_size_i; - field += 2; - - if (field == FIX_BARRIERS[fix_level]) - return end; - } -} - -u32 CROHelper::Fix(u32 fix_level) { - u32 fix_end = GetFixEnd(fix_level); - - if (fix_level != 0) { - SetField(Magic, MAGIC_FIXD); - - for (int field = FIX_BARRIERS[fix_level]; field < Fix0Barrier; field += 2) { - SetField(static_cast<HeaderField>(field), fix_end); - SetField(static_cast<HeaderField>(field + 1), 0); - } - } - - fix_end = Common::AlignUp(fix_end, Memory::PAGE_SIZE); - - u32 fixed_size = fix_end - module_address; - SetField(FixedSize, fixed_size); - return fixed_size; -} - -bool CROHelper::IsLoaded() const { - u32 magic = GetField(Magic); - if (magic != MAGIC_CRO0 && magic != MAGIC_FIXD) - return false; - - // TODO(wwylele): verify memory state here after memory aliasing is implemented - - return true; -} - -std::tuple<VAddr, u32> CROHelper::GetExecutablePages() const { - u32 segment_num = GetField(SegmentNum); - for (u32 i = 0; i < segment_num; ++i) { - SegmentEntry entry; - GetEntry(i, entry); - if (entry.type == SegmentType::Code && entry.size != 0) { - VAddr begin = Common::AlignDown(entry.offset, Memory::PAGE_SIZE); - VAddr end = Common::AlignUp(entry.offset + entry.size, Memory::PAGE_SIZE); - return std::make_tuple(begin, end - begin); - } - } - return std::make_tuple(0, 0); -} - -} // namespace LDR -} // namespace Service |