mirror of
https://github.com/yuzu-emu/yuzu-android.git
synced 2025-06-29 07:38:33 -05:00
Sources: Run clang-format on everything.
This commit is contained in:
@ -14,38 +14,29 @@
|
||||
namespace LDR_RO {
|
||||
|
||||
static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F
|
||||
ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument, ErrorLevel::Usage);
|
||||
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);
|
||||
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<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
|
||||
}};
|
||||
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);
|
||||
@ -63,7 +54,7 @@ VAddr CROHelper::SegmentTagToAddress(SegmentTag segment_tag) const {
|
||||
}
|
||||
|
||||
ResultCode CROHelper::ApplyRelocation(VAddr target_address, RelocationType relocation_type,
|
||||
u32 addend, u32 symbol_address, u32 target_future_address) {
|
||||
u32 addend, u32 symbol_address, u32 target_future_address) {
|
||||
|
||||
switch (relocation_type) {
|
||||
case RelocationType::Nothing:
|
||||
@ -124,7 +115,8 @@ ResultCode CROHelper::ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool
|
||||
return CROFormatError(0x12);
|
||||
}
|
||||
|
||||
ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend, symbol_address, relocation_target);
|
||||
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;
|
||||
@ -167,7 +159,7 @@ VAddr CROHelper::FindExportNamedSymbol(const std::string& name) const {
|
||||
|
||||
if (test_byte >= len) {
|
||||
next.raw = entry.left.raw;
|
||||
} else if((name[test_byte] >> test_bit_in_byte) & 1) {
|
||||
} else if ((name[test_byte] >> test_bit_in_byte) & 1) {
|
||||
next.raw = entry.right.raw;
|
||||
} else {
|
||||
next.raw = entry.left.raw;
|
||||
@ -212,26 +204,13 @@ ResultCode CROHelper::RebaseHeader(u32 cro_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
|
||||
}};
|
||||
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;
|
||||
@ -266,9 +245,9 @@ ResultCode CROHelper::RebaseHeader(u32 cro_size) {
|
||||
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) {
|
||||
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);
|
||||
@ -309,8 +288,8 @@ ResultCode CROHelper::RebaseExportNamedSymbolTable() {
|
||||
|
||||
if (entry.name_offset != 0) {
|
||||
entry.name_offset += module_address;
|
||||
if (entry.name_offset < export_strings_offset
|
||||
|| entry.name_offset >= export_strings_end) {
|
||||
if (entry.name_offset < export_strings_offset ||
|
||||
entry.name_offset >= export_strings_end) {
|
||||
return CROFormatError(0x11);
|
||||
}
|
||||
}
|
||||
@ -337,9 +316,13 @@ 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 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);
|
||||
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) {
|
||||
@ -348,24 +331,24 @@ ResultCode CROHelper::RebaseImportModuleTable() {
|
||||
|
||||
if (entry.name_offset != 0) {
|
||||
entry.name_offset += module_address;
|
||||
if (entry.name_offset < import_strings_offset
|
||||
|| entry.name_offset >= import_strings_end) {
|
||||
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) {
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -379,25 +362,27 @@ 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);
|
||||
VAddr external_relocation_table_end =
|
||||
external_relocation_table_offset +
|
||||
GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry);
|
||||
|
||||
u32 num = GetField(ImportNamedSymbolNum);
|
||||
for (u32 i = 0; i < num ; ++i) {
|
||||
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) {
|
||||
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) {
|
||||
if (entry.relocation_batch_offset < external_relocation_table_offset ||
|
||||
entry.relocation_batch_offset > external_relocation_table_end) {
|
||||
return CROFormatError(0x1B);
|
||||
}
|
||||
}
|
||||
@ -409,17 +394,19 @@ ResultCode CROHelper::RebaseImportNamedSymbolTable() {
|
||||
|
||||
ResultCode CROHelper::RebaseImportIndexedSymbolTable() {
|
||||
VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset);
|
||||
VAddr external_relocation_table_end = external_relocation_table_offset + GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry);
|
||||
VAddr external_relocation_table_end =
|
||||
external_relocation_table_offset +
|
||||
GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry);
|
||||
|
||||
u32 num = GetField(ImportIndexedSymbolNum);
|
||||
for (u32 i = 0; i < num ; ++i) {
|
||||
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) {
|
||||
if (entry.relocation_batch_offset < external_relocation_table_offset ||
|
||||
entry.relocation_batch_offset > external_relocation_table_end) {
|
||||
return CROFormatError(0x14);
|
||||
}
|
||||
}
|
||||
@ -431,17 +418,19 @@ ResultCode CROHelper::RebaseImportIndexedSymbolTable() {
|
||||
|
||||
ResultCode CROHelper::RebaseImportAnonymousSymbolTable() {
|
||||
VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset);
|
||||
VAddr external_relocation_table_end = external_relocation_table_offset + GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry);
|
||||
VAddr external_relocation_table_end =
|
||||
external_relocation_table_offset +
|
||||
GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry);
|
||||
|
||||
u32 num = GetField(ImportAnonymousSymbolNum);
|
||||
for (u32 i = 0; i < num ; ++i) {
|
||||
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) {
|
||||
if (entry.relocation_batch_offset < external_relocation_table_offset ||
|
||||
entry.relocation_batch_offset > external_relocation_table_end) {
|
||||
return CROFormatError(0x17);
|
||||
}
|
||||
}
|
||||
@ -475,7 +464,8 @@ ResultCode CROHelper::ResetExternalRelocations() {
|
||||
return CROFormatError(0x12);
|
||||
}
|
||||
|
||||
ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend, unresolved_symbol, relocation_target);
|
||||
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;
|
||||
@ -528,23 +518,27 @@ ResultCode CROHelper::ClearExternalRelocations() {
|
||||
|
||||
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);
|
||||
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);
|
||||
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) {
|
||||
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);
|
||||
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);
|
||||
@ -571,7 +565,8 @@ ResultCode CROHelper::ApplyInternalRelocations(u32 old_data_segment_address) {
|
||||
|
||||
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;
|
||||
target_address =
|
||||
old_data_segment_address + relocation.target_position.offset_into_segment;
|
||||
} else {
|
||||
target_address = target_addressB;
|
||||
}
|
||||
@ -582,8 +577,10 @@ ResultCode CROHelper::ApplyInternalRelocations(u32 old_data_segment_address) {
|
||||
|
||||
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);
|
||||
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;
|
||||
@ -734,25 +731,29 @@ ResultCode CROHelper::ApplyImportNamedSymbol(VAddr crs_address) {
|
||||
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);
|
||||
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());
|
||||
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;
|
||||
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>(false);
|
||||
}
|
||||
|
||||
return MakeResult<bool>(true);
|
||||
});
|
||||
return MakeResult<bool>(true);
|
||||
});
|
||||
if (result.IsError()) {
|
||||
return result;
|
||||
}
|
||||
@ -777,7 +778,6 @@ ResultCode CROHelper::ResetImportNamedSymbol() {
|
||||
LOG_ERROR(Service_LDR, "Error reseting relocation batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
@ -831,40 +831,47 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) {
|
||||
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;
|
||||
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;
|
||||
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>(false);
|
||||
}
|
||||
return MakeResult<bool>(true);
|
||||
});
|
||||
return MakeResult<bool>(true);
|
||||
});
|
||||
if (result.IsError()) {
|
||||
return result;
|
||||
}
|
||||
@ -873,8 +880,8 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) {
|
||||
}
|
||||
|
||||
ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) {
|
||||
LOG_DEBUG(Service_LDR, "CRO \"%s\" exports named symbols to \"%s\"",
|
||||
ModuleName().data(), target.ModuleName().data());
|
||||
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) {
|
||||
@ -885,7 +892,8 @@ ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) {
|
||||
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);
|
||||
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());
|
||||
@ -901,8 +909,8 @@ ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) {
|
||||
}
|
||||
|
||||
ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) {
|
||||
LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports named symbols to \"%s\"",
|
||||
ModuleName().data(), target.ModuleName().data());
|
||||
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);
|
||||
@ -914,11 +922,13 @@ ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) {
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
@ -940,8 +950,8 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) {
|
||||
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());
|
||||
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);
|
||||
@ -949,7 +959,8 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) {
|
||||
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);
|
||||
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;
|
||||
@ -957,13 +968,14 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) {
|
||||
}
|
||||
|
||||
LOG_INFO(Service_LDR, "CRO \"%s\" exports %d anonymous symbols to \"%s\"",
|
||||
module_name.data(), entry.import_anonymous_symbol_num, target.ModuleName().data());
|
||||
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);
|
||||
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;
|
||||
@ -987,12 +999,13 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) {
|
||||
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());
|
||||
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);
|
||||
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;
|
||||
@ -1000,11 +1013,12 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) {
|
||||
}
|
||||
|
||||
LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports anonymous symbols to \"%s\"",
|
||||
module_name.data(), target.ModuleName().data());
|
||||
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);
|
||||
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;
|
||||
@ -1025,25 +1039,27 @@ ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) {
|
||||
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 (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());
|
||||
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;
|
||||
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>(false);
|
||||
}
|
||||
|
||||
return MakeResult<bool>(true);
|
||||
});
|
||||
return MakeResult<bool>(true);
|
||||
});
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying exit relocation %08X", result.raw);
|
||||
return result;
|
||||
@ -1070,9 +1086,9 @@ static ResultCode VerifyStringTableLength(VAddr address, u32 size) {
|
||||
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 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()) {
|
||||
@ -1088,9 +1104,8 @@ ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size,
|
||||
|
||||
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);
|
||||
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();
|
||||
@ -1374,7 +1389,8 @@ void CROHelper::Unregister(VAddr 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) {
|
||||
if (module_address == next_head.module_address ||
|
||||
module_address == previous_head.module_address) {
|
||||
// removing head
|
||||
if (next.module_address) {
|
||||
// the next is new head
|
||||
@ -1400,7 +1416,8 @@ void CROHelper::Unregister(VAddr crs_address) {
|
||||
// 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) {
|
||||
} else if (previous_head.module_address &&
|
||||
previous_head.PreviousModule() == module_address) {
|
||||
previous_head.SetPreviousModule(previous.module_address);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
@ -1419,9 +1436,9 @@ u32 CROHelper::GetFixEnd(u32 fix_level) const {
|
||||
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]);
|
||||
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;
|
||||
|
@ -10,8 +10,8 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/swap.h"
|
||||
|
||||
#include "core/memory.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Namespace LDR_RO
|
||||
@ -21,14 +21,17 @@ namespace LDR_RO {
|
||||
// GCC versions < 5.0 do not implement std::is_trivially_copyable.
|
||||
// Excluding MSVC because it has weird behaviour for std::is_trivially_copyable.
|
||||
#if (__GNUC__ >= 5) || defined(__clang__)
|
||||
#define ASSERT_CRO_STRUCT(name, size) \
|
||||
static_assert(std::is_standard_layout<name>::value, "CRO structure " #name " doesn't use standard layout"); \
|
||||
static_assert(std::is_trivially_copyable<name>::value, "CRO structure " #name " isn't trivially copyable"); \
|
||||
static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name)
|
||||
#define ASSERT_CRO_STRUCT(name, size) \
|
||||
static_assert(std::is_standard_layout<name>::value, \
|
||||
"CRO structure " #name " doesn't use standard layout"); \
|
||||
static_assert(std::is_trivially_copyable<name>::value, \
|
||||
"CRO structure " #name " isn't trivially copyable"); \
|
||||
static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name)
|
||||
#else
|
||||
#define ASSERT_CRO_STRUCT(name, size) \
|
||||
static_assert(std::is_standard_layout<name>::value, "CRO structure " #name " doesn't use standard layout"); \
|
||||
static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name)
|
||||
#define ASSERT_CRO_STRUCT(name, size) \
|
||||
static_assert(std::is_standard_layout<name>::value, \
|
||||
"CRO structure " #name " doesn't use standard layout"); \
|
||||
static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name)
|
||||
#endif
|
||||
|
||||
static constexpr u32 CRO_HEADER_SIZE = 0x138;
|
||||
@ -59,9 +62,9 @@ public:
|
||||
* @param is_crs true if the module itself is the static module
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode 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 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);
|
||||
|
||||
/**
|
||||
* Unrebases the module.
|
||||
@ -148,8 +151,10 @@ private:
|
||||
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.
|
||||
* We don't directly use a struct here, to avoid GetPointer, reinterpret_cast, or Read/WriteBlock repeatedly.
|
||||
* Each item in this enum represents a u32 field in the header begin from address+0x80,
|
||||
* successively.
|
||||
* We don't directly use a struct here, to avoid GetPointer, reinterpret_cast, or
|
||||
* Read/WriteBlock repeatedly.
|
||||
*/
|
||||
enum HeaderField {
|
||||
Magic = 0,
|
||||
@ -208,18 +213,20 @@ private:
|
||||
Fix2Barrier = ImportModuleTableOffset,
|
||||
Fix1Barrier = StaticAnonymousSymbolTableOffset,
|
||||
};
|
||||
static_assert(Fix0Barrier == (CRO_HEADER_SIZE - CRO_HASH_SIZE) / 4, "CRO Header fields are wrong!");
|
||||
static_assert(Fix0Barrier == (CRO_HEADER_SIZE - CRO_HASH_SIZE) / 4,
|
||||
"CRO Header fields are wrong!");
|
||||
|
||||
enum class SegmentType : u32 {
|
||||
Code = 0,
|
||||
Code = 0,
|
||||
ROData = 1,
|
||||
Data = 2,
|
||||
BSS = 3,
|
||||
Data = 2,
|
||||
BSS = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* Identifies a program location inside of a segment.
|
||||
* Required to refer to program locations because individual segments may be relocated independently of each other.
|
||||
* Required to refer to program locations because individual segments may be relocated
|
||||
* independently of each other.
|
||||
*/
|
||||
union SegmentTag {
|
||||
u32_le raw;
|
||||
@ -227,7 +234,8 @@ private:
|
||||
BitField<4, 28, u32_le> offset_into_segment;
|
||||
|
||||
SegmentTag() = default;
|
||||
explicit SegmentTag(u32 raw_) : raw(raw_) {}
|
||||
explicit SegmentTag(u32 raw_) : raw(raw_) {
|
||||
}
|
||||
};
|
||||
|
||||
/// Information of a segment in this module.
|
||||
@ -282,7 +290,7 @@ private:
|
||||
|
||||
/// Identifies an indexed symbol imported from another module.
|
||||
struct ImportIndexedSymbolEntry {
|
||||
u32_le index; // index of an ExportIndexedSymbolEntry in the exporting module
|
||||
u32_le index; // index of an ExportIndexedSymbolEntry in the exporting module
|
||||
u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable
|
||||
|
||||
static constexpr HeaderField TABLE_OFFSET_FIELD = ImportIndexedSymbolTableOffset;
|
||||
@ -291,8 +299,8 @@ private:
|
||||
|
||||
/// Identifies an anonymous symbol imported from another module.
|
||||
struct ImportAnonymousSymbolEntry {
|
||||
SegmentTag symbol_position; // in the exporting segment
|
||||
u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable
|
||||
SegmentTag symbol_position; // in the exporting segment
|
||||
u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable
|
||||
|
||||
static constexpr HeaderField TABLE_OFFSET_FIELD = ImportAnonymousSymbolTableOffset;
|
||||
};
|
||||
@ -300,42 +308,47 @@ private:
|
||||
|
||||
/// Information of a imported module and symbols imported from it.
|
||||
struct ImportModuleEntry {
|
||||
u32_le name_offset; // pointing to a substring in ImportStrings
|
||||
u32_le import_indexed_symbol_table_offset; // pointing to a subtable in ImportIndexedSymbolTable
|
||||
u32_le name_offset; // pointing to a substring in ImportStrings
|
||||
u32_le import_indexed_symbol_table_offset; // pointing to a subtable in
|
||||
// ImportIndexedSymbolTable
|
||||
u32_le import_indexed_symbol_num;
|
||||
u32_le import_anonymous_symbol_table_offset; // pointing to a subtable in ImportAnonymousSymbolTable
|
||||
u32_le import_anonymous_symbol_table_offset; // pointing to a subtable in
|
||||
// ImportAnonymousSymbolTable
|
||||
u32_le import_anonymous_symbol_num;
|
||||
|
||||
static constexpr HeaderField TABLE_OFFSET_FIELD = ImportModuleTableOffset;
|
||||
|
||||
void GetImportIndexedSymbolEntry(u32 index, ImportIndexedSymbolEntry& entry) {
|
||||
Memory::ReadBlock(import_indexed_symbol_table_offset + index * sizeof(ImportIndexedSymbolEntry),
|
||||
&entry, sizeof(ImportIndexedSymbolEntry));
|
||||
Memory::ReadBlock(import_indexed_symbol_table_offset +
|
||||
index * sizeof(ImportIndexedSymbolEntry),
|
||||
&entry, sizeof(ImportIndexedSymbolEntry));
|
||||
}
|
||||
|
||||
void GetImportAnonymousSymbolEntry(u32 index, ImportAnonymousSymbolEntry& entry) {
|
||||
Memory::ReadBlock(import_anonymous_symbol_table_offset + index * sizeof(ImportAnonymousSymbolEntry),
|
||||
&entry, sizeof(ImportAnonymousSymbolEntry));
|
||||
Memory::ReadBlock(import_anonymous_symbol_table_offset +
|
||||
index * sizeof(ImportAnonymousSymbolEntry),
|
||||
&entry, sizeof(ImportAnonymousSymbolEntry));
|
||||
}
|
||||
};
|
||||
ASSERT_CRO_STRUCT(ImportModuleEntry, 20);
|
||||
|
||||
enum class RelocationType : u8 {
|
||||
Nothing = 0,
|
||||
AbsoluteAddress = 2,
|
||||
RelativeAddress = 3,
|
||||
ThumbBranch = 10,
|
||||
ArmBranch = 28,
|
||||
ModifyArmBranch = 29,
|
||||
AbsoluteAddress2 = 38,
|
||||
Nothing = 0,
|
||||
AbsoluteAddress = 2,
|
||||
RelativeAddress = 3,
|
||||
ThumbBranch = 10,
|
||||
ArmBranch = 28,
|
||||
ModifyArmBranch = 29,
|
||||
AbsoluteAddress2 = 38,
|
||||
AlignedRelativeAddress = 42,
|
||||
};
|
||||
|
||||
struct RelocationEntry {
|
||||
SegmentTag target_position; // to self's segment as an ExternalRelocationEntry; to static module segment as a StaticRelocationEntry
|
||||
SegmentTag target_position; // to self's segment as an ExternalRelocationEntry; to static
|
||||
// module segment as a StaticRelocationEntry
|
||||
RelocationType type;
|
||||
u8 is_batch_end;
|
||||
u8 is_batch_resolved; // set at a batch beginning if the batch is resolved
|
||||
u8 is_batch_resolved; // set at a batch beginning if the batch is resolved
|
||||
INSERT_PADDING_BYTES(1);
|
||||
u32_le addend;
|
||||
};
|
||||
@ -366,8 +379,8 @@ private:
|
||||
|
||||
/// Identifies a special static anonymous symbol (no game is known using this).
|
||||
struct StaticAnonymousSymbolEntry {
|
||||
SegmentTag symbol_position; // to self's segment
|
||||
u32_le relocation_batch_offset; // pointing to a relocation batch in StaticRelocationTable
|
||||
SegmentTag symbol_position; // to self's segment
|
||||
u32_le relocation_batch_offset; // pointing to a relocation batch in StaticRelocationTable
|
||||
|
||||
static constexpr HeaderField TABLE_OFFSET_FIELD = StaticAnonymousSymbolTableOffset;
|
||||
};
|
||||
@ -446,12 +459,15 @@ private:
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function iterating over all registered auto-link modules, including the static module.
|
||||
* A helper function iterating over all registered auto-link modules, including the static
|
||||
* module.
|
||||
* @param crs_address the virtual address of the static module
|
||||
* @param func a function object to operate on a module. It accepts one parameter
|
||||
* CROHelper and returns ResultVal<bool>. It should return true to continue the iteration,
|
||||
* CROHelper and returns ResultVal<bool>. It should return true to continue the
|
||||
* iteration,
|
||||
* false to stop the iteration, or an error code (which will also stop the iteration).
|
||||
* @returns ResultCode indicating the result of the operation, RESULT_SUCCESS if all iteration success,
|
||||
* @returns ResultCode indicating the result of the operation, RESULT_SUCCESS if all iteration
|
||||
* success,
|
||||
* otherwise error code of the last iteration.
|
||||
*/
|
||||
template <typename FunctionObject>
|
||||
@ -477,8 +493,8 @@ private:
|
||||
* Usually equals to target_address, but will be different for a target in .data segment
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode ApplyRelocation(VAddr target_address, RelocationType relocation_type,
|
||||
u32 addend, u32 symbol_address, u32 target_future_address);
|
||||
ResultCode ApplyRelocation(VAddr target_address, RelocationType relocation_type, u32 addend,
|
||||
u32 symbol_address, u32 target_future_address);
|
||||
|
||||
/**
|
||||
* Clears a relocation to zero
|
||||
@ -492,7 +508,8 @@ private:
|
||||
* Applies or resets a batch of relocations
|
||||
* @param batch the virtual address of the first relocation in the batch
|
||||
* @param symbol_address the symbol address to be relocated with
|
||||
* @param reset false to set the batch to resolved state, true to reset the batch to unresolved state
|
||||
* @param reset false to set the batch to resolved state, true to reset the batch to unresolved
|
||||
* state
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool reset = false);
|
||||
@ -507,7 +524,8 @@ private:
|
||||
/**
|
||||
* Rebases offsets in module header according to module address.
|
||||
* @param cro_size the size of the CRO file
|
||||
* @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code.
|
||||
* @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
|
||||
* code.
|
||||
*/
|
||||
ResultCode RebaseHeader(u32 cro_size);
|
||||
|
||||
@ -520,43 +538,49 @@ private:
|
||||
* @param bss_segment_size the buffer size for .bss segment
|
||||
* @returns ResultVal<VAddr> with the virtual address of .data segment in CRO.
|
||||
*/
|
||||
ResultVal<VAddr> RebaseSegmentTable(u32 cro_size,
|
||||
VAddr data_segment_address, u32 data_segment_size,
|
||||
VAddr bss_segment_address, u32 bss_segment_size);
|
||||
ResultVal<VAddr> RebaseSegmentTable(u32 cro_size, VAddr data_segment_address,
|
||||
u32 data_segment_size, VAddr bss_segment_address,
|
||||
u32 bss_segment_size);
|
||||
|
||||
/**
|
||||
* Rebases offsets in exported named symbol table according to module address.
|
||||
* @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code.
|
||||
* @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
|
||||
* code.
|
||||
*/
|
||||
ResultCode RebaseExportNamedSymbolTable();
|
||||
|
||||
/**
|
||||
* Verifies indices in export tree table.
|
||||
* @returns ResultCode RESULT_SUCCESS if all indices are verified as valid, otherwise error code.
|
||||
* @returns ResultCode RESULT_SUCCESS if all indices are verified as valid, otherwise error
|
||||
* code.
|
||||
*/
|
||||
ResultCode VerifyExportTreeTable() const;
|
||||
|
||||
/**
|
||||
* Rebases offsets in exported module table according to module address.
|
||||
* @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code.
|
||||
* @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
|
||||
* code.
|
||||
*/
|
||||
ResultCode RebaseImportModuleTable();
|
||||
|
||||
/**
|
||||
* Rebases offsets in imported named symbol table according to module address.
|
||||
* @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code.
|
||||
* @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
|
||||
* code.
|
||||
*/
|
||||
ResultCode RebaseImportNamedSymbolTable();
|
||||
|
||||
/**
|
||||
* Rebases offsets in imported indexed symbol table according to module address.
|
||||
* @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code.
|
||||
* @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
|
||||
* code.
|
||||
*/
|
||||
ResultCode RebaseImportIndexedSymbolTable();
|
||||
|
||||
/**
|
||||
* Rebases offsets in imported anonymous symbol table according to module address.
|
||||
* @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code.
|
||||
* @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
|
||||
* code.
|
||||
*/
|
||||
ResultCode RebaseImportAnonymousSymbolTable();
|
||||
|
||||
@ -621,7 +645,8 @@ private:
|
||||
void UnrebaseHeader();
|
||||
|
||||
/**
|
||||
* Looks up all imported named symbols of this module in all registered auto-link modules, and resolves them if found.
|
||||
* Looks up all imported named symbols of this module in all registered auto-link modules, and
|
||||
* resolves them if found.
|
||||
* @param crs_address the virtual address of the static module
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
@ -646,7 +671,8 @@ private:
|
||||
ResultCode ResetImportAnonymousSymbol();
|
||||
|
||||
/**
|
||||
* Finds registered auto-link modules that this module imports, and resolves indexed and anonymous symbols exported by them.
|
||||
* Finds registered auto-link modules that this module imports, and resolves indexed and
|
||||
* anonymous symbols exported by them.
|
||||
* @param crs_address the virtual address of the static module
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
@ -667,7 +693,8 @@ private:
|
||||
ResultCode ResetExportNamedSymbol(CROHelper target);
|
||||
|
||||
/**
|
||||
* Resolves imported indexed and anonymous symbols in the target module which imports this module.
|
||||
* Resolves imported indexed and anonymous symbols in the target module which imports this
|
||||
* module.
|
||||
* @param target the module to resolve.
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
|
@ -18,24 +18,33 @@
|
||||
|
||||
namespace LDR_RO {
|
||||
|
||||
static const ResultCode ERROR_ALREADY_INITIALIZED = // 0xD9612FF9
|
||||
ResultCode(ErrorDescription::AlreadyInitialized, ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Permanent);
|
||||
static const ResultCode ERROR_NOT_INITIALIZED = // 0xD9612FF8
|
||||
ResultCode(ErrorDescription::NotInitialized, ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Permanent);
|
||||
static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F
|
||||
ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument, ErrorLevel::Usage);
|
||||
static const ResultCode ERROR_MISALIGNED_ADDRESS = // 0xD9012FF1
|
||||
ResultCode(ErrorDescription::MisalignedAddress, ErrorModule::RO, ErrorSummary::WrongArgument, ErrorLevel::Permanent);
|
||||
static const ResultCode ERROR_MISALIGNED_SIZE = // 0xD9012FF2
|
||||
ResultCode(ErrorDescription::MisalignedSize, ErrorModule::RO, ErrorSummary::WrongArgument, ErrorLevel::Permanent);
|
||||
static const ResultCode ERROR_ILLEGAL_ADDRESS = // 0xE1612C0F
|
||||
ResultCode(static_cast<ErrorDescription>(15), ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Usage);
|
||||
static const ResultCode ERROR_INVALID_MEMORY_STATE = // 0xD8A12C08
|
||||
ResultCode(static_cast<ErrorDescription>(8), ErrorModule::RO, ErrorSummary::InvalidState, ErrorLevel::Permanent);
|
||||
static const ResultCode ERROR_NOT_LOADED = // 0xD8A12C0D
|
||||
ResultCode(static_cast<ErrorDescription>(13), ErrorModule::RO, ErrorSummary::InvalidState, ErrorLevel::Permanent);
|
||||
static const ResultCode ERROR_INVALID_DESCRIPTOR = // 0xD9001830
|
||||
ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent);
|
||||
static const ResultCode ERROR_ALREADY_INITIALIZED = // 0xD9612FF9
|
||||
ResultCode(ErrorDescription::AlreadyInitialized, ErrorModule::RO, ErrorSummary::Internal,
|
||||
ErrorLevel::Permanent);
|
||||
static const ResultCode ERROR_NOT_INITIALIZED = // 0xD9612FF8
|
||||
ResultCode(ErrorDescription::NotInitialized, ErrorModule::RO, ErrorSummary::Internal,
|
||||
ErrorLevel::Permanent);
|
||||
static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F
|
||||
ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument,
|
||||
ErrorLevel::Usage);
|
||||
static const ResultCode ERROR_MISALIGNED_ADDRESS = // 0xD9012FF1
|
||||
ResultCode(ErrorDescription::MisalignedAddress, ErrorModule::RO, ErrorSummary::WrongArgument,
|
||||
ErrorLevel::Permanent);
|
||||
static const ResultCode ERROR_MISALIGNED_SIZE = // 0xD9012FF2
|
||||
ResultCode(ErrorDescription::MisalignedSize, ErrorModule::RO, ErrorSummary::WrongArgument,
|
||||
ErrorLevel::Permanent);
|
||||
static const ResultCode ERROR_ILLEGAL_ADDRESS = // 0xE1612C0F
|
||||
ResultCode(static_cast<ErrorDescription>(15), ErrorModule::RO, ErrorSummary::Internal,
|
||||
ErrorLevel::Usage);
|
||||
static const ResultCode ERROR_INVALID_MEMORY_STATE = // 0xD8A12C08
|
||||
ResultCode(static_cast<ErrorDescription>(8), ErrorModule::RO, ErrorSummary::InvalidState,
|
||||
ErrorLevel::Permanent);
|
||||
static const ResultCode ERROR_NOT_LOADED = // 0xD8A12C0D
|
||||
ResultCode(static_cast<ErrorDescription>(13), ErrorModule::RO, ErrorSummary::InvalidState,
|
||||
ErrorLevel::Permanent);
|
||||
static const ResultCode ERROR_INVALID_DESCRIPTOR = // 0xD9001830
|
||||
ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS,
|
||||
ErrorSummary::WrongArgument, ErrorLevel::Permanent);
|
||||
|
||||
static MemorySynchronizer memory_synchronizer;
|
||||
|
||||
@ -44,10 +53,10 @@ static VAddr loaded_crs; ///< the virtual address of the static module
|
||||
|
||||
static bool VerifyBufferState(VAddr buffer_ptr, u32 size) {
|
||||
auto vma = Kernel::g_current_process->vm_manager.FindVMA(buffer_ptr);
|
||||
return vma != Kernel::g_current_process->vm_manager.vma_map.end()
|
||||
&& vma->second.base + vma->second.size >= buffer_ptr + size
|
||||
&& vma->second.permissions == Kernel::VMAPermission::ReadWrite
|
||||
&& vma->second.meminfo_state == Kernel::MemoryState::Private;
|
||||
return vma != Kernel::g_current_process->vm_manager.vma_map.end() &&
|
||||
vma->second.base + vma->second.size >= buffer_ptr + size &&
|
||||
vma->second.permissions == Kernel::VMAPermission::ReadWrite &&
|
||||
vma->second.meminfo_state == Kernel::MemoryState::Private;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,13 +75,14 @@ static bool VerifyBufferState(VAddr buffer_ptr, u32 size) {
|
||||
static void Initialize(Service::Interface* self) {
|
||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
||||
VAddr crs_buffer_ptr = cmd_buff[1];
|
||||
u32 crs_size = cmd_buff[2];
|
||||
VAddr crs_address = cmd_buff[3];
|
||||
u32 descriptor = cmd_buff[4];
|
||||
u32 process = cmd_buff[5];
|
||||
u32 crs_size = cmd_buff[2];
|
||||
VAddr crs_address = cmd_buff[3];
|
||||
u32 descriptor = cmd_buff[4];
|
||||
u32 process = cmd_buff[5];
|
||||
|
||||
LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, crs_address=0x%08X, crs_size=0x%X, descriptor=0x%08X, process=0x%08X",
|
||||
crs_buffer_ptr, crs_address, crs_size, descriptor, process);
|
||||
LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, crs_address=0x%08X, crs_size=0x%X, "
|
||||
"descriptor=0x%08X, process=0x%08X",
|
||||
crs_buffer_ptr, crs_address, crs_size, descriptor, process);
|
||||
|
||||
if (descriptor != 0) {
|
||||
LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
|
||||
@ -119,7 +129,8 @@ static void Initialize(Service::Interface* self) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (crs_address < Memory::PROCESS_IMAGE_VADDR || crs_address + crs_size > Memory::PROCESS_IMAGE_VADDR_END) {
|
||||
if (crs_address < Memory::PROCESS_IMAGE_VADDR ||
|
||||
crs_address + crs_size > Memory::PROCESS_IMAGE_VADDR_END) {
|
||||
LOG_ERROR(Service_LDR, "CRS mapping address is not in the process image region");
|
||||
cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw;
|
||||
return;
|
||||
@ -131,14 +142,17 @@ static void Initialize(Service::Interface* self) {
|
||||
// TODO(wwylele): should be memory aliasing
|
||||
std::shared_ptr<std::vector<u8>> crs_mem = std::make_shared<std::vector<u8>>(crs_size);
|
||||
Memory::ReadBlock(crs_buffer_ptr, crs_mem->data(), crs_size);
|
||||
result = Kernel::g_current_process->vm_manager.MapMemoryBlock(crs_address, crs_mem, 0, crs_size, Kernel::MemoryState::Code).Code();
|
||||
result = Kernel::g_current_process->vm_manager
|
||||
.MapMemoryBlock(crs_address, crs_mem, 0, crs_size, Kernel::MemoryState::Code)
|
||||
.Code();
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw);
|
||||
cmd_buff[1] = result.raw;
|
||||
return;
|
||||
}
|
||||
|
||||
result = Kernel::g_current_process->vm_manager.ReprotectRange(crs_address, crs_size, Kernel::VMAPermission::Read);
|
||||
result = Kernel::g_current_process->vm_manager.ReprotectRange(crs_address, crs_size,
|
||||
Kernel::VMAPermission::Read);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw);
|
||||
cmd_buff[1] = result.raw;
|
||||
@ -186,9 +200,9 @@ static void Initialize(Service::Interface* self) {
|
||||
static void LoadCRR(Service::Interface* self) {
|
||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
||||
u32 crr_buffer_ptr = cmd_buff[1];
|
||||
u32 crr_size = cmd_buff[2];
|
||||
u32 descriptor = cmd_buff[3];
|
||||
u32 process = cmd_buff[4];
|
||||
u32 crr_size = cmd_buff[2];
|
||||
u32 descriptor = cmd_buff[3];
|
||||
u32 process = cmd_buff[4];
|
||||
|
||||
if (descriptor != 0) {
|
||||
LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
|
||||
@ -200,7 +214,8 @@ static void LoadCRR(Service::Interface* self) {
|
||||
cmd_buff[0] = IPC::MakeHeader(2, 1, 0);
|
||||
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
|
||||
|
||||
LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, crr_size=0x%08X, descriptor=0x%08X, process=0x%08X",
|
||||
LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, crr_size=0x%08X, "
|
||||
"descriptor=0x%08X, process=0x%08X",
|
||||
crr_buffer_ptr, crr_size, descriptor, process);
|
||||
}
|
||||
|
||||
@ -218,8 +233,8 @@ static void LoadCRR(Service::Interface* self) {
|
||||
static void UnloadCRR(Service::Interface* self) {
|
||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
||||
u32 crr_buffer_ptr = cmd_buff[1];
|
||||
u32 descriptor = cmd_buff[2];
|
||||
u32 process = cmd_buff[3];
|
||||
u32 descriptor = cmd_buff[2];
|
||||
u32 process = cmd_buff[3];
|
||||
|
||||
if (descriptor != 0) {
|
||||
LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
|
||||
@ -231,7 +246,8 @@ static void UnloadCRR(Service::Interface* self) {
|
||||
cmd_buff[0] = IPC::MakeHeader(3, 1, 0);
|
||||
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
|
||||
|
||||
LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X",
|
||||
LOG_WARNING(Service_LDR,
|
||||
"(STUBBED) called, crr_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X",
|
||||
crr_buffer_ptr, descriptor, process);
|
||||
}
|
||||
|
||||
@ -263,27 +279,28 @@ static void UnloadCRR(Service::Interface* self) {
|
||||
*/
|
||||
static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
|
||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
||||
VAddr cro_buffer_ptr = cmd_buff[1];
|
||||
VAddr cro_address = cmd_buff[2];
|
||||
u32 cro_size = cmd_buff[3];
|
||||
VAddr cro_buffer_ptr = cmd_buff[1];
|
||||
VAddr cro_address = cmd_buff[2];
|
||||
u32 cro_size = cmd_buff[3];
|
||||
VAddr data_segment_address = cmd_buff[4];
|
||||
u32 zero = cmd_buff[5];
|
||||
u32 data_segment_size = cmd_buff[6];
|
||||
u32 bss_segment_address = cmd_buff[7];
|
||||
u32 bss_segment_size = cmd_buff[8];
|
||||
bool auto_link = (cmd_buff[9] & 0xFF) != 0;
|
||||
u32 fix_level = cmd_buff[10];
|
||||
VAddr crr_address = cmd_buff[11];
|
||||
u32 descriptor = cmd_buff[12];
|
||||
u32 process = cmd_buff[13];
|
||||
u32 zero = cmd_buff[5];
|
||||
u32 data_segment_size = cmd_buff[6];
|
||||
u32 bss_segment_address = cmd_buff[7];
|
||||
u32 bss_segment_size = cmd_buff[8];
|
||||
bool auto_link = (cmd_buff[9] & 0xFF) != 0;
|
||||
u32 fix_level = cmd_buff[10];
|
||||
VAddr crr_address = cmd_buff[11];
|
||||
u32 descriptor = cmd_buff[12];
|
||||
u32 process = cmd_buff[13];
|
||||
|
||||
LOG_DEBUG(Service_LDR, "called (%s), cro_buffer_ptr=0x%08X, cro_address=0x%08X, cro_size=0x%X, "
|
||||
"data_segment_address=0x%08X, zero=%d, data_segment_size=0x%X, bss_segment_address=0x%08X, bss_segment_size=0x%X, "
|
||||
"auto_link=%s, fix_level=%d, crr_address=0x%08X, descriptor=0x%08X, process=0x%08X",
|
||||
link_on_load_bug_fix ? "new" : "old", cro_buffer_ptr, cro_address, cro_size,
|
||||
data_segment_address, zero, data_segment_size, bss_segment_address, bss_segment_size,
|
||||
auto_link ? "true" : "false", fix_level, crr_address, descriptor, process
|
||||
);
|
||||
LOG_DEBUG(Service_LDR,
|
||||
"called (%s), cro_buffer_ptr=0x%08X, cro_address=0x%08X, cro_size=0x%X, "
|
||||
"data_segment_address=0x%08X, zero=%d, data_segment_size=0x%X, "
|
||||
"bss_segment_address=0x%08X, bss_segment_size=0x%X, "
|
||||
"auto_link=%s, fix_level=%d, crr_address=0x%08X, descriptor=0x%08X, process=0x%08X",
|
||||
link_on_load_bug_fix ? "new" : "old", cro_buffer_ptr, cro_address, cro_size,
|
||||
data_segment_address, zero, data_segment_size, bss_segment_address, bss_segment_size,
|
||||
auto_link ? "true" : "false", fix_level, crr_address, descriptor, process);
|
||||
|
||||
if (descriptor != 0) {
|
||||
LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
|
||||
@ -330,8 +347,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cro_address < Memory::PROCESS_IMAGE_VADDR
|
||||
|| cro_address + cro_size > Memory::PROCESS_IMAGE_VADDR_END) {
|
||||
if (cro_address < Memory::PROCESS_IMAGE_VADDR ||
|
||||
cro_address + cro_size > Memory::PROCESS_IMAGE_VADDR_END) {
|
||||
LOG_ERROR(Service_LDR, "CRO mapping address is not in the process image region");
|
||||
cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw;
|
||||
return;
|
||||
@ -339,7 +356,9 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
|
||||
|
||||
if (zero) {
|
||||
LOG_ERROR(Service_LDR, "Zero is not zero %d", zero);
|
||||
cmd_buff[1] = ResultCode(static_cast<ErrorDescription>(29), ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Usage).raw;
|
||||
cmd_buff[1] = ResultCode(static_cast<ErrorDescription>(29), ErrorModule::RO,
|
||||
ErrorSummary::Internal, ErrorLevel::Usage)
|
||||
.raw;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -349,14 +368,17 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
|
||||
// TODO(wwylele): should be memory aliasing
|
||||
std::shared_ptr<std::vector<u8>> cro_mem = std::make_shared<std::vector<u8>>(cro_size);
|
||||
Memory::ReadBlock(cro_buffer_ptr, cro_mem->data(), cro_size);
|
||||
result = Kernel::g_current_process->vm_manager.MapMemoryBlock(cro_address, cro_mem, 0, cro_size, Kernel::MemoryState::Code).Code();
|
||||
result = Kernel::g_current_process->vm_manager
|
||||
.MapMemoryBlock(cro_address, cro_mem, 0, cro_size, Kernel::MemoryState::Code)
|
||||
.Code();
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw);
|
||||
cmd_buff[1] = result.raw;
|
||||
return;
|
||||
}
|
||||
|
||||
result = Kernel::g_current_process->vm_manager.ReprotectRange(cro_address, cro_size, Kernel::VMAPermission::Read);
|
||||
result = Kernel::g_current_process->vm_manager.ReprotectRange(cro_address, cro_size,
|
||||
Kernel::VMAPermission::Read);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw);
|
||||
Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size);
|
||||
@ -384,7 +406,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
|
||||
return;
|
||||
}
|
||||
|
||||
result = cro.Rebase(loaded_crs, cro_size, data_segment_address, data_segment_size, bss_segment_address, bss_segment_size, false);
|
||||
result = cro.Rebase(loaded_crs, cro_size, data_segment_address, data_segment_size,
|
||||
bss_segment_address, bss_segment_size, false);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error rebasing CRO %08X", result.raw);
|
||||
Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size);
|
||||
@ -409,7 +432,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
|
||||
// TODO(wwylele): verify the behaviour when buffer_ptr == address
|
||||
if (cro_buffer_ptr != cro_address) {
|
||||
if (fix_size != cro_size) {
|
||||
result = Kernel::g_current_process->vm_manager.UnmapRange(cro_address + fix_size, cro_size - fix_size);
|
||||
result = Kernel::g_current_process->vm_manager.UnmapRange(cro_address + fix_size,
|
||||
cro_size - fix_size);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error unmapping memory block %08X", result.raw);
|
||||
Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size);
|
||||
@ -426,7 +450,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
|
||||
u32 exe_size;
|
||||
std::tie(exe_begin, exe_size) = cro.GetExecutablePages();
|
||||
if (exe_begin) {
|
||||
result = Kernel::g_current_process->vm_manager.ReprotectRange(exe_begin, exe_size, Kernel::VMAPermission::ReadExecute);
|
||||
result = Kernel::g_current_process->vm_manager.ReprotectRange(
|
||||
exe_begin, exe_size, Kernel::VMAPermission::ReadExecute);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw);
|
||||
Kernel::g_current_process->vm_manager.UnmapRange(cro_address, fix_size);
|
||||
@ -437,8 +462,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
|
||||
|
||||
Core::g_app_core->ClearInstructionCache();
|
||||
|
||||
LOG_INFO(Service_LDR, "CRO \"%s\" loaded at 0x%08X, fixed_end=0x%08X",
|
||||
cro.ModuleName().data(), cro_address, cro_address+fix_size);
|
||||
LOG_INFO(Service_LDR, "CRO \"%s\" loaded at 0x%08X, fixed_end=0x%08X", cro.ModuleName().data(),
|
||||
cro_address, cro_address + fix_size);
|
||||
|
||||
cmd_buff[1] = RESULT_SUCCESS.raw;
|
||||
cmd_buff[2] = fix_size;
|
||||
@ -464,14 +489,15 @@ static void LoadCRO(Service::Interface* self) {
|
||||
*/
|
||||
static void UnloadCRO(Service::Interface* self) {
|
||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
||||
VAddr cro_address = cmd_buff[1];
|
||||
u32 zero = cmd_buff[2];
|
||||
VAddr cro_buffer_ptr = cmd_buff[3];
|
||||
u32 descriptor = cmd_buff[4];
|
||||
u32 process = cmd_buff[5];
|
||||
VAddr cro_address = cmd_buff[1];
|
||||
u32 zero = cmd_buff[2];
|
||||
VAddr cro_buffer_ptr = cmd_buff[3];
|
||||
u32 descriptor = cmd_buff[4];
|
||||
u32 process = cmd_buff[5];
|
||||
|
||||
LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, zero=%d, cro_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X",
|
||||
cro_address, zero, cro_buffer_ptr, descriptor, process);
|
||||
LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, zero=%d, cro_buffer_ptr=0x%08X, "
|
||||
"descriptor=0x%08X, process=0x%08X",
|
||||
cro_address, zero, cro_buffer_ptr, descriptor, process);
|
||||
|
||||
if (descriptor != 0) {
|
||||
LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
|
||||
@ -558,11 +584,11 @@ static void UnloadCRO(Service::Interface* self) {
|
||||
static void LinkCRO(Service::Interface* self) {
|
||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
||||
VAddr cro_address = cmd_buff[1];
|
||||
u32 descriptor = cmd_buff[2];
|
||||
u32 process = cmd_buff[3];
|
||||
u32 descriptor = cmd_buff[2];
|
||||
u32 process = cmd_buff[3];
|
||||
|
||||
LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X",
|
||||
cro_address, descriptor, process);
|
||||
cro_address, descriptor, process);
|
||||
|
||||
if (descriptor != 0) {
|
||||
LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
|
||||
@ -620,11 +646,11 @@ static void LinkCRO(Service::Interface* self) {
|
||||
static void UnlinkCRO(Service::Interface* self) {
|
||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
||||
VAddr cro_address = cmd_buff[1];
|
||||
u32 descriptor = cmd_buff[2];
|
||||
u32 process = cmd_buff[3];
|
||||
u32 descriptor = cmd_buff[2];
|
||||
u32 process = cmd_buff[3];
|
||||
|
||||
LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X",
|
||||
cro_address, descriptor, process);
|
||||
cro_address, descriptor, process);
|
||||
|
||||
if (descriptor != 0) {
|
||||
LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
|
||||
@ -682,11 +708,11 @@ static void UnlinkCRO(Service::Interface* self) {
|
||||
static void Shutdown(Service::Interface* self) {
|
||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
||||
VAddr crs_buffer_ptr = cmd_buff[1];
|
||||
u32 descriptor = cmd_buff[2];
|
||||
u32 process = cmd_buff[3];
|
||||
u32 descriptor = cmd_buff[2];
|
||||
u32 process = cmd_buff[3];
|
||||
|
||||
LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X",
|
||||
crs_buffer_ptr, descriptor, process);
|
||||
crs_buffer_ptr, descriptor, process);
|
||||
|
||||
if (descriptor != 0) {
|
||||
LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
|
||||
@ -724,15 +750,11 @@ static void Shutdown(Service::Interface* self) {
|
||||
}
|
||||
|
||||
const Interface::FunctionInfo FunctionTable[] = {
|
||||
{0x000100C2, Initialize, "Initialize"},
|
||||
{0x00020082, LoadCRR, "LoadCRR"},
|
||||
{0x00030042, UnloadCRR, "UnloadCRR"},
|
||||
{0x000402C2, LoadCRO<false>, "LoadCRO"},
|
||||
{0x000500C2, UnloadCRO, "UnloadCRO"},
|
||||
{0x00060042, LinkCRO, "LinkCRO"},
|
||||
{0x00070042, UnlinkCRO, "UnlinkCRO"},
|
||||
{0x00080042, Shutdown, "Shutdown"},
|
||||
{0x000902C2, LoadCRO<true>, "LoadCRO_New"},
|
||||
{0x000100C2, Initialize, "Initialize"}, {0x00020082, LoadCRR, "LoadCRR"},
|
||||
{0x00030042, UnloadCRR, "UnloadCRR"}, {0x000402C2, LoadCRO<false>, "LoadCRO"},
|
||||
{0x000500C2, UnloadCRO, "UnloadCRO"}, {0x00060042, LinkCRO, "LinkCRO"},
|
||||
{0x00070042, UnlinkCRO, "UnlinkCRO"}, {0x00080042, Shutdown, "Shutdown"},
|
||||
{0x000902C2, LoadCRO<true>, "LoadCRO_New"},
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -14,9 +14,8 @@
|
||||
namespace LDR_RO {
|
||||
|
||||
auto MemorySynchronizer::FindMemoryBlock(VAddr mapping, VAddr original) {
|
||||
auto block = std::find_if(memory_blocks.begin(), memory_blocks.end(), [=](MemoryBlock& b){
|
||||
return b.original == original;
|
||||
});
|
||||
auto block = std::find_if(memory_blocks.begin(), memory_blocks.end(),
|
||||
[=](MemoryBlock& b) { return b.original == original; });
|
||||
ASSERT(block->mapping == mapping);
|
||||
return block;
|
||||
}
|
||||
|
Reference in New Issue
Block a user