mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-29 07:20:04 +00:00
LDR fixup relocation
This commit is contained in:
parent
f1f940d8d7
commit
1ddbb7f6df
@ -99,8 +99,8 @@ class CROHelper final {
|
||||
|
||||
ImportModuleTableOffset,
|
||||
ImportModuleNum,
|
||||
ExternalPatchTableOffset,
|
||||
ExternalPatchNum,
|
||||
ExternalRelocationTableOffset,
|
||||
ExternalRelocationNum,
|
||||
ImportNamedSymbolTableOffset,
|
||||
ImportNamedSymbolNum,
|
||||
ImportIndexedSymbolTableOffset,
|
||||
@ -112,10 +112,10 @@ class CROHelper final {
|
||||
|
||||
StaticAnonymousSymbolTableOffset,
|
||||
StaticAnonymousSymbolNum,
|
||||
InternalPatchTableOffset,
|
||||
InternalPatchNum,
|
||||
StaticPatchTableOffset,
|
||||
StaticPatchNum,
|
||||
InternalRelocationTableOffset,
|
||||
InternalRelocationNum,
|
||||
StaticRelocationTableOffset,
|
||||
StaticRelocationNum,
|
||||
Fix0Barrier,
|
||||
|
||||
Fix3Barrier = ExportNamedSymbolTableOffset,
|
||||
@ -187,8 +187,8 @@ class CROHelper final {
|
||||
|
||||
/// Identifies a named symbol imported from another module.
|
||||
struct ImportNamedSymbolEntry {
|
||||
u32_le name_offset; // pointing to a substring in ImportStrings
|
||||
u32_le patch_batch_offset; // pointing to a patch batch in ExternalPatchTable
|
||||
u32_le name_offset; // pointing to a substring in ImportStrings
|
||||
u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable
|
||||
|
||||
static constexpr HeaderField TABLE_OFFSET_FIELD = ImportNamedSymbolTableOffset;
|
||||
};
|
||||
@ -196,8 +196,8 @@ class CROHelper final {
|
||||
|
||||
/// Identifies an indexed symbol imported from another module.
|
||||
struct ImportIndexedSymbolEntry {
|
||||
u32_le index; // index of an ExportIndexedSymbolEntry in the exporting module
|
||||
u32_le patch_batch_offset; // pointing to a patch batch in ExternalPatchTable
|
||||
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;
|
||||
};
|
||||
@ -205,8 +205,8 @@ class CROHelper final {
|
||||
|
||||
/// Identifies an anonymous symbol imported from another module.
|
||||
struct ImportAnonymousSymbolEntry {
|
||||
SegmentTag symbol_position; // in the exporting segment
|
||||
u32_le patch_batch_offset; // pointing to a patch batch in ExternalPatchTable
|
||||
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;
|
||||
};
|
||||
@ -234,7 +234,7 @@ class CROHelper final {
|
||||
};
|
||||
ASSERT_CRO_STRUCT(ImportModuleEntry, 20);
|
||||
|
||||
enum class PatchType : u8 {
|
||||
enum class RelocationType : u8 {
|
||||
Nothing = 0,
|
||||
AbsoluteAddress = 2,
|
||||
RelativeAddress = 3,
|
||||
@ -245,50 +245,50 @@ class CROHelper final {
|
||||
AlignedRelativeAddress = 42,
|
||||
};
|
||||
|
||||
struct PatchEntry {
|
||||
SegmentTag target_position; // to self's segment as an ExternalPatchEntry; to static module segment as a StaticPatchEntry
|
||||
PatchType type;
|
||||
struct RelocationEntry {
|
||||
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
|
||||
INSERT_PADDING_BYTES(1);
|
||||
u32_le shift;
|
||||
u32_le addend;
|
||||
};
|
||||
|
||||
/// Identifies a normal cross-module patch.
|
||||
struct ExternalPatchEntry : PatchEntry {
|
||||
static constexpr HeaderField TABLE_OFFSET_FIELD = ExternalPatchTableOffset;
|
||||
/// Identifies a normal cross-module relocation.
|
||||
struct ExternalRelocationEntry : RelocationEntry {
|
||||
static constexpr HeaderField TABLE_OFFSET_FIELD = ExternalRelocationTableOffset;
|
||||
};
|
||||
ASSERT_CRO_STRUCT(ExternalPatchEntry, 12);
|
||||
ASSERT_CRO_STRUCT(ExternalRelocationEntry, 12);
|
||||
|
||||
/// Identifies a special static patch (no game is known using this).
|
||||
struct StaticPatchEntry : PatchEntry {
|
||||
static constexpr HeaderField TABLE_OFFSET_FIELD = StaticPatchTableOffset;
|
||||
/// Identifies a special static relocation (no game is known using this).
|
||||
struct StaticRelocationEntry : RelocationEntry {
|
||||
static constexpr HeaderField TABLE_OFFSET_FIELD = StaticRelocationTableOffset;
|
||||
};
|
||||
ASSERT_CRO_STRUCT(StaticPatchEntry, 12);
|
||||
ASSERT_CRO_STRUCT(StaticRelocationEntry, 12);
|
||||
|
||||
/// Identifies a in-module patch.
|
||||
struct InternalPatchEntry {
|
||||
/// Identifies a in-module relocation.
|
||||
struct InternalRelocationEntry {
|
||||
SegmentTag target_position; // to self's segment
|
||||
PatchType type;
|
||||
RelocationType type;
|
||||
u8 symbol_segment;
|
||||
INSERT_PADDING_BYTES(2);
|
||||
u32_le shift;
|
||||
u32_le addend;
|
||||
|
||||
static constexpr HeaderField TABLE_OFFSET_FIELD = InternalPatchTableOffset;
|
||||
static constexpr HeaderField TABLE_OFFSET_FIELD = InternalRelocationTableOffset;
|
||||
};
|
||||
ASSERT_CRO_STRUCT(InternalPatchEntry, 12);
|
||||
ASSERT_CRO_STRUCT(InternalRelocationEntry, 12);
|
||||
|
||||
/// Identifies a special static anonymous symbol (no game is known using this).
|
||||
struct StaticAnonymousSymbolEntry {
|
||||
SegmentTag symbol_position; // to self's segment
|
||||
u32_le patch_batch_offset; // pointing to a patch batch in StaticPatchTable
|
||||
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;
|
||||
};
|
||||
ASSERT_CRO_STRUCT(StaticAnonymousSymbolEntry, 8);
|
||||
|
||||
/**
|
||||
* Entry size of each table, from Code to StaticPatchTable.
|
||||
* Entry size of each table, from Code to StaticRelocationTable.
|
||||
* Byte string contents (such as Code) are treated with entries of size 1.
|
||||
* This is used for verifying the size of each table and calculating the fix end.
|
||||
*/
|
||||
@ -395,30 +395,30 @@ class CROHelper final {
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a patch
|
||||
* @param target_address where to apply the patch
|
||||
* @param patch_type the type of the patch
|
||||
* @param shift address shift apply to the patched symbol
|
||||
* @param symbol_address the symbol address to be patched with
|
||||
* Applies a relocation
|
||||
* @param target_address where to apply the relocation
|
||||
* @param relocation_type the type of the relocation
|
||||
* @param addend address addend applied to the relocated symbol
|
||||
* @param symbol_address the symbol address to be relocated with
|
||||
* @param target_future_address the future address of the target.
|
||||
* 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 ApplyPatch(VAddr target_address, PatchType patch_type, u32 shift, u32 symbol_address, u32 target_future_address) {
|
||||
switch (patch_type) {
|
||||
case PatchType::Nothing:
|
||||
ResultCode ApplyRelocation(VAddr target_address, RelocationType relocation_type, u32 addend, u32 symbol_address, u32 target_future_address) {
|
||||
switch (relocation_type) {
|
||||
case RelocationType::Nothing:
|
||||
break;
|
||||
case PatchType::AbsoluteAddress:
|
||||
case PatchType::AbsoluteAddress2:
|
||||
Memory::Write32(target_address, symbol_address + shift);
|
||||
case RelocationType::AbsoluteAddress:
|
||||
case RelocationType::AbsoluteAddress2:
|
||||
Memory::Write32(target_address, symbol_address + addend);
|
||||
break;
|
||||
case PatchType::RelativeAddress:
|
||||
Memory::Write32(target_address, symbol_address + shift - target_future_address);
|
||||
case RelocationType::RelativeAddress:
|
||||
Memory::Write32(target_address, symbol_address + addend - target_future_address);
|
||||
break;
|
||||
case PatchType::ThumbBranch:
|
||||
case PatchType::ArmBranch:
|
||||
case PatchType::ModifyArmBranch:
|
||||
case PatchType::AlignedRelativeAddress:
|
||||
case RelocationType::ThumbBranch:
|
||||
case RelocationType::ArmBranch:
|
||||
case RelocationType::ModifyArmBranch:
|
||||
case RelocationType::AlignedRelativeAddress:
|
||||
// TODO(wwylele): implement other types
|
||||
UNIMPLEMENTED();
|
||||
break;
|
||||
@ -429,24 +429,24 @@ class CROHelper final {
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears a patch to zero
|
||||
* @param target_address where to apply the patch
|
||||
* @param patch_type the type of the patch
|
||||
* Clears a relocation to zero
|
||||
* @param target_address where to apply the relocation
|
||||
* @param relocation_type the type of the relocation
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode ClearPatch(VAddr target_address, PatchType patch_type) {
|
||||
switch (patch_type) {
|
||||
case PatchType::Nothing:
|
||||
ResultCode ClearRelocation(VAddr target_address, RelocationType relocation_type) {
|
||||
switch (relocation_type) {
|
||||
case RelocationType::Nothing:
|
||||
break;
|
||||
case PatchType::AbsoluteAddress:
|
||||
case PatchType::AbsoluteAddress2:
|
||||
case PatchType::RelativeAddress:
|
||||
case RelocationType::AbsoluteAddress:
|
||||
case RelocationType::AbsoluteAddress2:
|
||||
case RelocationType::RelativeAddress:
|
||||
Memory::Write32(target_address, 0);
|
||||
break;
|
||||
case PatchType::ThumbBranch:
|
||||
case PatchType::ArmBranch:
|
||||
case PatchType::ModifyArmBranch:
|
||||
case PatchType::AlignedRelativeAddress:
|
||||
case RelocationType::ThumbBranch:
|
||||
case RelocationType::ArmBranch:
|
||||
case RelocationType::ModifyArmBranch:
|
||||
case RelocationType::AlignedRelativeAddress:
|
||||
// TODO(wwylele): implement other types
|
||||
UNIMPLEMENTED();
|
||||
break;
|
||||
@ -457,42 +457,42 @@ class CROHelper final {
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies or resets a batch of patch
|
||||
* @param batch the virtual address of the first patch in the batch
|
||||
* @param symbol_address the symbol address to be patched with
|
||||
* 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
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode ApplyPatchBatch(VAddr batch, u32 symbol_address, bool reset = false) {
|
||||
ResultCode ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool reset = false) {
|
||||
if (symbol_address == 0 && !reset)
|
||||
return CROFormatError(0x10);
|
||||
|
||||
VAddr patch_address = batch;
|
||||
VAddr relocation_address = batch;
|
||||
while (true) {
|
||||
PatchEntry patch;
|
||||
Memory::ReadBlock(patch_address, &patch, sizeof(PatchEntry));
|
||||
RelocationEntry relocation;
|
||||
Memory::ReadBlock(relocation_address, &relocation, sizeof(RelocationEntry));
|
||||
|
||||
VAddr patch_target = SegmentTagToAddress(patch.target_position);
|
||||
if (patch_target == 0) {
|
||||
VAddr relocation_target = SegmentTagToAddress(relocation.target_position);
|
||||
if (relocation_target == 0) {
|
||||
return CROFormatError(0x12);
|
||||
}
|
||||
|
||||
ResultCode result = ApplyPatch(patch_target, patch.type, patch.shift, symbol_address, patch_target);
|
||||
ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend, symbol_address, relocation_target);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying patch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (patch.is_batch_end)
|
||||
if (relocation.is_batch_end)
|
||||
break;
|
||||
|
||||
patch_address += sizeof(PatchEntry);
|
||||
relocation_address += sizeof(RelocationEntry);
|
||||
}
|
||||
|
||||
PatchEntry patch;
|
||||
Memory::ReadBlock(batch, &patch, sizeof(PatchEntry));
|
||||
patch.is_batch_resolved = reset ? 0 : 1;
|
||||
Memory::WriteBlock(batch, &patch, sizeof(PatchEntry));
|
||||
RelocationEntry relocation;
|
||||
Memory::ReadBlock(batch, &relocation, sizeof(RelocationEntry));
|
||||
relocation.is_batch_resolved = reset ? 0 : 1;
|
||||
Memory::WriteBlock(batch, &relocation, sizeof(RelocationEntry));
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -584,14 +584,14 @@ class CROHelper final {
|
||||
ExportIndexedSymbolTableOffset,
|
||||
ExportStringsOffset,
|
||||
ImportModuleTableOffset,
|
||||
ExternalPatchTableOffset,
|
||||
ExternalRelocationTableOffset,
|
||||
ImportNamedSymbolTableOffset,
|
||||
ImportIndexedSymbolTableOffset,
|
||||
ImportAnonymousSymbolTableOffset,
|
||||
ImportStringsOffset,
|
||||
StaticAnonymousSymbolTableOffset,
|
||||
InternalPatchTableOffset,
|
||||
StaticPatchTableOffset,
|
||||
InternalRelocationTableOffset,
|
||||
StaticRelocationTableOffset,
|
||||
DataOffset,
|
||||
FileSize
|
||||
}};
|
||||
@ -780,8 +780,8 @@ class CROHelper final {
|
||||
ResultCode RebaseImportNamedSymbolTable() {
|
||||
VAddr import_strings_offset = GetField(ImportStringsOffset);
|
||||
VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize);
|
||||
VAddr external_patch_table_offset = GetField(ExternalPatchTableOffset);
|
||||
VAddr external_patch_table_end = external_patch_table_offset + GetField(ExternalPatchNum) * sizeof(ExternalPatchEntry);
|
||||
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) {
|
||||
@ -796,10 +796,10 @@ class CROHelper final {
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.patch_batch_offset != 0) {
|
||||
entry.patch_batch_offset += module_address;
|
||||
if (entry.patch_batch_offset < external_patch_table_offset
|
||||
|| entry.patch_batch_offset > external_patch_table_end) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -814,18 +814,18 @@ class CROHelper final {
|
||||
* @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code.
|
||||
*/
|
||||
ResultCode RebaseImportIndexedSymbolTable() {
|
||||
VAddr external_patch_table_offset = GetField(ExternalPatchTableOffset);
|
||||
VAddr external_patch_table_end = external_patch_table_offset + GetField(ExternalPatchNum) * sizeof(ExternalPatchEntry);
|
||||
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.patch_batch_offset != 0) {
|
||||
entry.patch_batch_offset += module_address;
|
||||
if (entry.patch_batch_offset < external_patch_table_offset
|
||||
|| entry.patch_batch_offset > external_patch_table_end) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -840,18 +840,18 @@ class CROHelper final {
|
||||
* @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code.
|
||||
*/
|
||||
ResultCode RebaseImportAnonymousSymbolTable() {
|
||||
VAddr external_patch_table_offset = GetField(ExternalPatchTableOffset);
|
||||
VAddr external_patch_table_end = external_patch_table_offset + GetField(ExternalPatchNum) * sizeof(ExternalPatchEntry);
|
||||
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.patch_batch_offset != 0) {
|
||||
entry.patch_batch_offset += module_address;
|
||||
if (entry.patch_batch_offset < external_patch_table_offset
|
||||
|| entry.patch_batch_offset > external_patch_table_end) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -863,7 +863,7 @@ class CROHelper final {
|
||||
|
||||
/**
|
||||
* Gets the address of OnUnresolved function in this module.
|
||||
* Used as the applied symbol for reset patch.
|
||||
* Used as the applied symbol for reset relocation.
|
||||
* @returns the virtual address of OnUnresolved. 0 if not provided.
|
||||
*/
|
||||
VAddr GetOnUnresolvedAddress() {
|
||||
@ -871,79 +871,79 @@ class CROHelper final {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all external patches to unresolved state.
|
||||
* Resets all external relocations to unresolved state.
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode ResetExternalPatches() {
|
||||
ResultCode ResetExternalRelocations() {
|
||||
u32 unresolved_symbol = GetOnUnresolvedAddress();
|
||||
u32 external_patch_num = GetField(ExternalPatchNum);
|
||||
ExternalPatchEntry patch;
|
||||
u32 external_relocation_num = GetField(ExternalRelocationNum);
|
||||
ExternalRelocationEntry relocation;
|
||||
|
||||
// Verifies that the last patch is the end of a batch
|
||||
GetEntry(external_patch_num - 1, patch);
|
||||
if (!patch.is_batch_end) {
|
||||
// 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_patch_num; ++i) {
|
||||
GetEntry(i, patch);
|
||||
VAddr patch_target = SegmentTagToAddress(patch.target_position);
|
||||
for (u32 i = 0; i < external_relocation_num; ++i) {
|
||||
GetEntry(i, relocation);
|
||||
VAddr relocation_target = SegmentTagToAddress(relocation.target_position);
|
||||
|
||||
if (patch_target == 0) {
|
||||
if (relocation_target == 0) {
|
||||
return CROFormatError(0x12);
|
||||
}
|
||||
|
||||
ResultCode result = ApplyPatch(patch_target, patch.type, patch.shift, unresolved_symbol, patch_target);
|
||||
ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend, unresolved_symbol, relocation_target);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying patch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (batch_begin) {
|
||||
// resets to unresolved state
|
||||
patch.is_batch_resolved = 0;
|
||||
SetEntry(i, patch);
|
||||
relocation.is_batch_resolved = 0;
|
||||
SetEntry(i, relocation);
|
||||
}
|
||||
|
||||
// if current is an end, then the next is a beginning
|
||||
batch_begin = patch.is_batch_end != 0;
|
||||
batch_begin = relocation.is_batch_end != 0;
|
||||
}
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all external patches to zero.
|
||||
* Clears all external relocations to zero.
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode ClearExternalPatches() {
|
||||
u32 external_patch_num = GetField(ExternalPatchNum);
|
||||
ExternalPatchEntry patch;
|
||||
ResultCode ClearExternalRelocations() {
|
||||
u32 external_relocation_num = GetField(ExternalRelocationNum);
|
||||
ExternalRelocationEntry relocation;
|
||||
|
||||
bool batch_begin = true;
|
||||
for (u32 i = 0; i < external_patch_num; ++i) {
|
||||
GetEntry(i, patch);
|
||||
VAddr patch_target = SegmentTagToAddress(patch.target_position);
|
||||
for (u32 i = 0; i < external_relocation_num; ++i) {
|
||||
GetEntry(i, relocation);
|
||||
VAddr relocation_target = SegmentTagToAddress(relocation.target_position);
|
||||
|
||||
if (patch_target == 0) {
|
||||
if (relocation_target == 0) {
|
||||
return CROFormatError(0x12);
|
||||
}
|
||||
|
||||
ResultCode result = ClearPatch(patch_target, patch.type);
|
||||
ResultCode result = ClearRelocation(relocation_target, relocation.type);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error clearing patch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error clearing relocation %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (batch_begin) {
|
||||
// resets to unresolved state
|
||||
patch.is_batch_resolved = 0;
|
||||
SetEntry(i, patch);
|
||||
relocation.is_batch_resolved = 0;
|
||||
SetEntry(i, relocation);
|
||||
}
|
||||
|
||||
// if current is an end, then the next is a beginning
|
||||
batch_begin = patch.is_batch_end != 0;
|
||||
batch_begin = relocation.is_batch_end != 0;
|
||||
}
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
@ -955,8 +955,8 @@ class CROHelper final {
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode ApplyStaticAnonymousSymbolToCRS(VAddr crs_address) {
|
||||
VAddr static_patch_table_offset = GetField(StaticPatchTableOffset);
|
||||
VAddr static_patch_table_end = static_patch_table_offset + GetField(StaticPatchNum) * sizeof(StaticPatchEntry);
|
||||
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);
|
||||
@ -964,18 +964,18 @@ class CROHelper final {
|
||||
for (u32 i = 0; i < offset_export_num; ++i) {
|
||||
StaticAnonymousSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
u32 batch_address = entry.patch_batch_offset + module_address;
|
||||
u32 batch_address = entry.relocation_batch_offset + module_address;
|
||||
|
||||
if (batch_address < static_patch_table_offset
|
||||
|| batch_address > static_patch_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);
|
||||
ResultCode result = crs.ApplyPatchBatch(batch_address, symbol_address);
|
||||
ResultCode result = crs.ApplyRelocationBatch(batch_address, symbol_address);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying patch batch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -983,42 +983,42 @@ class CROHelper final {
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies all internal patches to the module itself.
|
||||
* Applies all internal relocations to the module itself.
|
||||
* @param old_data_segment_address the virtual address of data segment in CRO buffer
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode ApplyInternalPatches(u32 old_data_segment_address) {
|
||||
ResultCode ApplyInternalRelocations(u32 old_data_segment_address) {
|
||||
u32 segment_num = GetField(SegmentNum);
|
||||
u32 internal_patch_num = GetField(InternalPatchNum);
|
||||
for (u32 i = 0; i < internal_patch_num; ++i) {
|
||||
InternalPatchEntry patch;
|
||||
GetEntry(i, patch);
|
||||
VAddr target_addressB = SegmentTagToAddress(patch.target_position);
|
||||
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(patch.target_position.segment_index, target_segment);
|
||||
GetEntry(relocation.target_position.segment_index, target_segment);
|
||||
|
||||
if (target_segment.type == SegmentType::Data) {
|
||||
// If the patch is to the .data segment, we need to patch it in the old buffer
|
||||
target_address = old_data_segment_address + patch.target_position.offset_into_segment;
|
||||
// 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 (patch.symbol_segment >= segment_num) {
|
||||
if (relocation.symbol_segment >= segment_num) {
|
||||
return CROFormatError(0x15);
|
||||
}
|
||||
|
||||
SegmentEntry symbol_segment;
|
||||
GetEntry(patch.symbol_segment, symbol_segment);
|
||||
LOG_TRACE(Service_LDR, "Internally patches 0x%08X with 0x%08X", target_address, symbol_segment.offset);
|
||||
ResultCode result = ApplyPatch(target_address, patch.type, patch.shift, symbol_segment.offset, target_addressB);
|
||||
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 patch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1026,23 +1026,23 @@ class CROHelper final {
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all internal patches to zero.
|
||||
* Clears all internal relocations to zero.
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode ClearInternalPatches() {
|
||||
u32 internal_patch_num = GetField(InternalPatchNum);
|
||||
for (u32 i = 0; i < internal_patch_num; ++i) {
|
||||
InternalPatchEntry patch;
|
||||
GetEntry(i, patch);
|
||||
VAddr target_address = SegmentTagToAddress(patch.target_position);
|
||||
ResultCode 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 = ClearPatch(target_address, patch.type);
|
||||
ResultCode result = ClearRelocation(target_address, relocation.type);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error clearing patch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error clearing relocation %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1056,8 +1056,8 @@ class CROHelper final {
|
||||
ImportAnonymousSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
|
||||
if (entry.patch_batch_offset != 0) {
|
||||
entry.patch_batch_offset -= module_address;
|
||||
if (entry.relocation_batch_offset != 0) {
|
||||
entry.relocation_batch_offset -= module_address;
|
||||
}
|
||||
|
||||
SetEntry(i, entry);
|
||||
@ -1071,8 +1071,8 @@ class CROHelper final {
|
||||
ImportIndexedSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
|
||||
if (entry.patch_batch_offset != 0) {
|
||||
entry.patch_batch_offset -= module_address;
|
||||
if (entry.relocation_batch_offset != 0) {
|
||||
entry.relocation_batch_offset -= module_address;
|
||||
}
|
||||
|
||||
SetEntry(i, entry);
|
||||
@ -1090,8 +1090,8 @@ class CROHelper final {
|
||||
entry.name_offset -= module_address;
|
||||
}
|
||||
|
||||
if (entry.patch_batch_offset) {
|
||||
entry.patch_batch_offset -= module_address;
|
||||
if (entry.relocation_batch_offset) {
|
||||
entry.relocation_batch_offset -= module_address;
|
||||
}
|
||||
|
||||
SetEntry(i, entry);
|
||||
@ -1178,11 +1178,11 @@ class CROHelper final {
|
||||
for (u32 i = 0; i < symbol_import_num; ++i) {
|
||||
ImportNamedSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
VAddr patch_addr = entry.patch_batch_offset;
|
||||
ExternalPatchEntry patch_entry;
|
||||
Memory::ReadBlock(patch_addr, &patch_entry, sizeof(ExternalPatchEntry));
|
||||
VAddr relocation_addr = entry.relocation_batch_offset;
|
||||
ExternalRelocationEntry relocation_entry;
|
||||
Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry));
|
||||
|
||||
if (!patch_entry.is_batch_resolved) {
|
||||
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);
|
||||
@ -1191,9 +1191,9 @@ class CROHelper final {
|
||||
LOG_TRACE(Service_LDR, "CRO \"%s\" imports \"%s\" from \"%s\"",
|
||||
ModuleName().data(), symbol_name.data(), source.ModuleName().data());
|
||||
|
||||
ResultCode result = ApplyPatchBatch(patch_addr, symbol_address);
|
||||
ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying patch batch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1221,13 +1221,13 @@ class CROHelper final {
|
||||
for (u32 i = 0; i < symbol_import_num; ++i) {
|
||||
ImportNamedSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
VAddr patch_addr = entry.patch_batch_offset;
|
||||
ExternalPatchEntry patch_entry;
|
||||
Memory::ReadBlock(patch_addr, &patch_entry, sizeof(ExternalPatchEntry));
|
||||
VAddr relocation_addr = entry.relocation_batch_offset;
|
||||
ExternalRelocationEntry relocation_entry;
|
||||
Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry));
|
||||
|
||||
ResultCode result = ApplyPatchBatch(patch_addr, unresolved_symbol, true);
|
||||
ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error reseting patch batch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error reseting relocation batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1246,13 +1246,13 @@ class CROHelper final {
|
||||
for (u32 i = 0; i < import_num; ++i) {
|
||||
ImportIndexedSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
VAddr patch_addr = entry.patch_batch_offset;
|
||||
ExternalPatchEntry patch_entry;
|
||||
Memory::ReadBlock(patch_addr, &patch_entry, sizeof(ExternalPatchEntry));
|
||||
VAddr relocation_addr = entry.relocation_batch_offset;
|
||||
ExternalRelocationEntry relocation_entry;
|
||||
Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry));
|
||||
|
||||
ResultCode result = ApplyPatchBatch(patch_addr, unresolved_symbol, true);
|
||||
ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error reseting patch batch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error reseting relocation batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1270,13 +1270,13 @@ class CROHelper final {
|
||||
for (u32 i = 0; i < import_num; ++i) {
|
||||
ImportAnonymousSymbolEntry entry;
|
||||
GetEntry(i, entry);
|
||||
VAddr patch_addr = entry.patch_batch_offset;
|
||||
ExternalPatchEntry patch_entry;
|
||||
Memory::ReadBlock(patch_addr, &patch_entry, sizeof(ExternalPatchEntry));
|
||||
VAddr relocation_addr = entry.relocation_batch_offset;
|
||||
ExternalRelocationEntry relocation_entry;
|
||||
Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry));
|
||||
|
||||
ResultCode result = ApplyPatchBatch(patch_addr, unresolved_symbol, true);
|
||||
ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error reseting patch batch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error reseting relocation batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1308,9 +1308,9 @@ class CROHelper final {
|
||||
source.GetEntry(im.index, ex);
|
||||
u32 symbol_address = source.SegmentTagToAddress(ex.symbol_position);
|
||||
LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address);
|
||||
ResultCode result = ApplyPatchBatch(im.patch_batch_offset, symbol_address);
|
||||
ResultCode result = ApplyRelocationBatch(im.relocation_batch_offset, symbol_address);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying patch batch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1321,9 +1321,9 @@ class CROHelper final {
|
||||
entry.GetImportAnonymousSymbolEntry(j, im);
|
||||
u32 symbol_address = source.SegmentTagToAddress(im.symbol_position);
|
||||
LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address);
|
||||
ResultCode result = ApplyPatchBatch(im.patch_batch_offset, symbol_address);
|
||||
ResultCode result = ApplyRelocationBatch(im.relocation_batch_offset, symbol_address);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying patch batch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1351,18 +1351,18 @@ class CROHelper final {
|
||||
for (u32 i = 0; i < target_symbol_import_num; ++i) {
|
||||
ImportNamedSymbolEntry entry;
|
||||
target.GetEntry(i, entry);
|
||||
VAddr patch_addr = entry.patch_batch_offset;
|
||||
ExternalPatchEntry patch_entry;
|
||||
Memory::ReadBlock(patch_addr, &patch_entry, sizeof(ExternalPatchEntry));
|
||||
VAddr relocation_addr = entry.relocation_batch_offset;
|
||||
ExternalRelocationEntry relocation_entry;
|
||||
Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry));
|
||||
|
||||
if (!patch_entry.is_batch_resolved) {
|
||||
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.ApplyPatchBatch(patch_addr, symbol_address);
|
||||
ResultCode result = target.ApplyRelocationBatch(relocation_addr, symbol_address);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying patch batch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1385,18 +1385,18 @@ class CROHelper final {
|
||||
for (u32 i = 0; i < target_symbol_import_num; ++i) {
|
||||
ImportNamedSymbolEntry entry;
|
||||
target.GetEntry(i, entry);
|
||||
VAddr patch_addr = entry.patch_batch_offset;
|
||||
ExternalPatchEntry patch_entry;
|
||||
Memory::ReadBlock(patch_addr, &patch_entry, sizeof(ExternalPatchEntry));
|
||||
VAddr relocation_addr = entry.relocation_batch_offset;
|
||||
ExternalRelocationEntry relocation_entry;
|
||||
Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry));
|
||||
|
||||
if (patch_entry.is_batch_resolved) {
|
||||
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.ApplyPatchBatch(patch_addr, unresolved_symbol, true);
|
||||
ResultCode result = target.ApplyRelocationBatch(relocation_addr, unresolved_symbol, true);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying patch batch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1430,9 +1430,9 @@ class CROHelper final {
|
||||
GetEntry(im.index, ex);
|
||||
u32 symbol_address = SegmentTagToAddress(ex.symbol_position);
|
||||
LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address);
|
||||
ResultCode result = target.ApplyPatchBatch(im.patch_batch_offset, symbol_address);
|
||||
ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying patch batch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1444,9 +1444,9 @@ class CROHelper final {
|
||||
entry.GetImportAnonymousSymbolEntry(j, im);
|
||||
u32 symbol_address = SegmentTagToAddress(im.symbol_position);
|
||||
LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address);
|
||||
ResultCode result = target.ApplyPatchBatch(im.patch_batch_offset, symbol_address);
|
||||
ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying patch batch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1478,9 +1478,9 @@ class CROHelper final {
|
||||
for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) {
|
||||
ImportIndexedSymbolEntry im;
|
||||
entry.GetImportIndexedSymbolEntry(j, im);
|
||||
ResultCode result = target.ApplyPatchBatch(im.patch_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 patch batch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1490,9 +1490,9 @@ class CROHelper final {
|
||||
for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) {
|
||||
ImportAnonymousSymbolEntry im;
|
||||
entry.GetImportAnonymousSymbolEntry(j, im);
|
||||
ResultCode result = target.ApplyPatchBatch(im.patch_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 patch batch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1506,15 +1506,15 @@ class CROHelper final {
|
||||
* @param crs_address the virtual address of the static module.
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode ApplyExitPatches(VAddr crs_address) {
|
||||
ResultCode 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 patch_addr = entry.patch_batch_offset;
|
||||
ExternalPatchEntry patch_entry;
|
||||
Memory::ReadBlock(patch_addr, &patch_entry, sizeof(ExternalPatchEntry));
|
||||
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> {
|
||||
@ -1524,9 +1524,9 @@ class CROHelper final {
|
||||
LOG_DEBUG(Service_LDR, "CRO \"%s\" import exit function from \"%s\"",
|
||||
ModuleName().data(), source.ModuleName().data());
|
||||
|
||||
ResultCode result = ApplyPatchBatch(patch_addr, symbol_address);
|
||||
ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying patch batch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1536,7 +1536,7 @@ class CROHelper final {
|
||||
return MakeResult<bool>(true);
|
||||
});
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying exit patch %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error applying exit relocation %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1618,9 +1618,9 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
result = ResetExternalPatches();
|
||||
result = ResetExternalRelocations();
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error resetting all external patches %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error resetting all external relocations %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1656,16 +1656,16 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
result = ApplyInternalPatches(prev_data_segment_address);
|
||||
result = ApplyInternalRelocations(prev_data_segment_address);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying internal patches %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error applying internal relocations %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!is_crs) {
|
||||
result = ApplyExitPatches(crs_address);
|
||||
result = ApplyExitRelocations(crs_address);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying exit patches %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error applying exit relocations %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1720,10 +1720,10 @@ public:
|
||||
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 patch target is in .data segment, it will patch to the
|
||||
// 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 tranfer from CRO to the buffer,
|
||||
// thus the patch will be overwritten by data transfer.
|
||||
// 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.
|
||||
|
||||
@ -1835,19 +1835,19 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all patches to zero.
|
||||
* Clears all relocations to zero.
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode ClearPatches() {
|
||||
ResultCode result = ClearExternalPatches();
|
||||
ResultCode ClearRelocations() {
|
||||
ResultCode result = ClearExternalRelocations();
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error clearing external patches %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error clearing external relocations %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = ClearInternalPatches();
|
||||
result = ClearInternalRelocations();
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error clearing internal patches %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error clearing internal relocations %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
@ -2037,14 +2037,14 @@ const std::array<int, 17> CROHelper::ENTRY_SIZE {{
|
||||
1, // export strings
|
||||
sizeof(ExportTreeEntry),
|
||||
sizeof(ImportModuleEntry),
|
||||
sizeof(ExternalPatchEntry),
|
||||
sizeof(ExternalRelocationEntry),
|
||||
sizeof(ImportNamedSymbolEntry),
|
||||
sizeof(ImportIndexedSymbolEntry),
|
||||
sizeof(ImportAnonymousSymbolEntry),
|
||||
1, // import strings
|
||||
sizeof(StaticAnonymousSymbolEntry),
|
||||
sizeof(InternalPatchEntry),
|
||||
sizeof(StaticPatchEntry)
|
||||
sizeof(InternalRelocationEntry),
|
||||
sizeof(StaticRelocationEntry)
|
||||
}};
|
||||
|
||||
const std::array<CROHelper::HeaderField, 4> CROHelper::FIX_BARRIERS {{
|
||||
@ -2576,12 +2576,12 @@ static void UnloadCRO(Service::Interface* self) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the module is not fixed, clears all external/internal patches
|
||||
// If the module is not fixed, clears all external/internal relocations
|
||||
// to restore the state before loading, so that it can be loaded again(?)
|
||||
if (!cro.IsFixed()) {
|
||||
result = cro.ClearPatches();
|
||||
result = cro.ClearRelocations();
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error clearing patches %08X", result.raw);
|
||||
LOG_ERROR(Service_LDR, "Error clearing relocations %08X", result.raw);
|
||||
cmd_buff[1] = result.raw;
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user