mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 14:20:14 +00:00
LDR: implement unlink
This commit is contained in:
parent
bed5915f4f
commit
1e2bcb21f2
@ -1193,6 +1193,79 @@ class CROHelper final {
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all imported named symbols of this module to unresolved state.
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode ResetImportNamedSymbol() {
|
||||
u32 unresolved_symbol = SegmentTagToAddress(GetField(OnUnresolvedSegmentTag));
|
||||
|
||||
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));
|
||||
|
||||
ResultCode result = ApplyPatchBatch(patch_addr, unresolved_symbol, true);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error reseting patch batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all imported indexed symbols of this module to unresolved state.
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode ResetImportIndexedSymbol() {
|
||||
u32 unresolved_symbol = SegmentTagToAddress(GetField(OnUnresolvedSegmentTag));
|
||||
|
||||
u32 import_num = GetField(ImportIndexedSymbolNum);
|
||||
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));
|
||||
|
||||
ResultCode result = ApplyPatchBatch(patch_addr, unresolved_symbol, true);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error reseting patch batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all imported anonymous symbols of this module to unresolved state.
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode ResetImportAnonymousSymbol() {
|
||||
u32 unresolved_symbol = SegmentTagToAddress(GetField(OnUnresolvedSegmentTag));
|
||||
|
||||
u32 import_num = GetField(ImportAnonymousSymbolNum);
|
||||
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));
|
||||
|
||||
ResultCode result = ApplyPatchBatch(patch_addr, unresolved_symbol, true);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error reseting patch batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -1281,6 +1354,40 @@ class CROHelper final {
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets target's named symbols imported from this module to unresolved state.
|
||||
* @param target the module to reset.
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode ResetExportNamedSymbol(CROHelper target) {
|
||||
LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports named symbols to \"%s\"",
|
||||
ModuleName().data(), target.ModuleName().data());
|
||||
u32 unresolved_symbol = target.SegmentTagToAddress(target.GetField(OnUnresolvedSegmentTag));
|
||||
u32 target_import_strings_size = target.GetField(ImportStringsSize);
|
||||
u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum);
|
||||
for (u32 i = 0; i < target_symbol_import_num; ++i) {
|
||||
ImportNamedSymbolEntry entry;
|
||||
target.GetEntry(i, entry);
|
||||
VAddr patch_addr = entry.patch_batch_offset;
|
||||
ExternalPatchEntry patch_entry;
|
||||
Memory::ReadBlock(patch_addr, &patch_entry, sizeof(ExternalPatchEntry));
|
||||
|
||||
if (patch_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) {
|
||||
LOG_TRACE(Service_LDR, " unexports symbol \"%s\"", symbol_name.data());
|
||||
ResultCode result = target.ApplyPatchBatch(patch_addr, unresolved_symbol, true);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying patch batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves imported indexed and anonymous symbols in the target module which imports this module.
|
||||
* @param target the module to resolve.
|
||||
@ -1331,6 +1438,52 @@ class CROHelper final {
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets target's indexed and anonymous symbol imported from this module to unresolved state.
|
||||
* @param target the module to reset.
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode ResetModuleExport(CROHelper target) {
|
||||
u32 unresolved_symbol = target.SegmentTagToAddress(target.GetField(OnUnresolvedSegmentTag));
|
||||
|
||||
std::string module_name = ModuleName();
|
||||
u32 target_import_string_size = target.GetField(ImportStringsSize);
|
||||
u32 target_import_module_num = target.GetField(ImportModuleNum);
|
||||
for (u32 i = 0; i < target_import_module_num; ++i) {
|
||||
ImportModuleEntry entry;
|
||||
target.GetEntry(i, entry);
|
||||
|
||||
if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name)
|
||||
continue;
|
||||
|
||||
LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports indexed symbols to \"%s\"",
|
||||
module_name.data(), target.ModuleName().data());
|
||||
for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) {
|
||||
ImportIndexedSymbolEntry im;
|
||||
entry.GetImportIndexedSymbolEntry(j, im);
|
||||
ResultCode result = target.ApplyPatchBatch(im.patch_batch_offset, unresolved_symbol, true);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying patch batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports anonymous symbols to \"%s\"",
|
||||
module_name.data(), target.ModuleName().data());
|
||||
for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) {
|
||||
ImportAnonymousSymbolEntry im;
|
||||
entry.GetImportAnonymousSymbolEntry(j, im);
|
||||
ResultCode result = target.ApplyPatchBatch(im.patch_batch_offset, unresolved_symbol, true);
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error applying patch batch %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the exit function in this module
|
||||
* @param crs_address the virtual address of the static module.
|
||||
@ -1605,6 +1758,55 @@ public:
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlinks this module with other modules.
|
||||
* @param crs_address the virtual address of the static module
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
*/
|
||||
ResultCode Unlink(VAddr crs_address) {
|
||||
|
||||
// Resets all imported named symbols
|
||||
ResultCode result = ResetImportNamedSymbol();
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error resetting symbol import %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Resets all imported indexed symbols
|
||||
result = ResetImportIndexedSymbol();
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error resetting indexed import %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Resets all imported anonymous symbols
|
||||
result = ResetImportAnonymousSymbol();
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error resetting anonymous import %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Resets all symbols in other modules imported from this module
|
||||
// Note: the RO service seems only searching in auto-link modules
|
||||
result = ForEachAutoLinkCRO(crs_address, [this](CROHelper target) -> ResultVal<bool> {
|
||||
ResultCode result = ResetExportNamedSymbol(target);
|
||||
if (result.IsError())
|
||||
return result;
|
||||
|
||||
result = ResetModuleExport(target);
|
||||
if (result.IsError())
|
||||
return result;
|
||||
|
||||
return MakeResult<bool>(true);
|
||||
});
|
||||
if (result.IsError()) {
|
||||
LOG_ERROR(Service_LDR, "Error resetting export %08X", result.raw);
|
||||
return result;
|
||||
}
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all patches to zero.
|
||||
* @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
|
||||
|
Loading…
Reference in New Issue
Block a user