summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/ldr/ldr.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/service/ldr/ldr.cpp45
1 files changed, 33 insertions, 12 deletions
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index 5af925515..3164ca26e 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -78,7 +78,7 @@ public:
class RelocatableObject final : public ServiceFramework<RelocatableObject> {
public:
- explicit RelocatableObject() : ServiceFramework{"ldr:ro"} {
+ explicit RelocatableObject(Core::System& system) : ServiceFramework{"ldr:ro"}, system(system) {
// clang-format off
static const FunctionInfo functions[] = {
{0, &RelocatableObject::LoadNro, "LoadNro"},
@@ -310,7 +310,7 @@ public:
if (!IsValidNROHash(hash)) {
LOG_ERROR(Service_LDR,
"NRO hash is not present in any currently loaded NRRs (hash={})!",
- Common::HexArrayToString(hash));
+ Common::HexToString(hash));
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERROR_MISSING_NRR_HASH);
return;
@@ -345,14 +345,16 @@ public:
vm_manager
.MirrorMemory(*map_address, nro_address, nro_size, Kernel::MemoryState::ModuleCode)
.IsSuccess());
- ASSERT(vm_manager.UnmapRange(nro_address, nro_size).IsSuccess());
+ ASSERT(vm_manager.ReprotectRange(nro_address, nro_size, Kernel::VMAPermission::None)
+ .IsSuccess());
if (bss_size > 0) {
ASSERT(vm_manager
.MirrorMemory(*map_address + nro_size, bss_address, bss_size,
Kernel::MemoryState::ModuleCode)
.IsSuccess());
- ASSERT(vm_manager.UnmapRange(bss_address, bss_size).IsSuccess());
+ ASSERT(vm_manager.ReprotectRange(bss_address, bss_size, Kernel::VMAPermission::None)
+ .IsSuccess());
}
vm_manager.ReprotectRange(*map_address, header.text_size,
@@ -362,9 +364,10 @@ public:
vm_manager.ReprotectRange(*map_address + header.rw_offset, header.rw_size,
Kernel::VMAPermission::ReadWrite);
- Core::System::GetInstance().InvalidateCpuInstructionCaches();
+ system.InvalidateCpuInstructionCaches();
- nro.insert_or_assign(*map_address, NROInfo{hash, nro_size + bss_size});
+ nro.insert_or_assign(*map_address,
+ NROInfo{hash, nro_address, nro_size, bss_address, bss_size});
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
@@ -409,11 +412,25 @@ public:
}
auto& vm_manager = Core::CurrentProcess()->VMManager();
- const auto& nro_size = iter->second.size;
+ const auto& nro_info = iter->second;
- ASSERT(vm_manager.UnmapRange(nro_address, nro_size).IsSuccess());
+ // Unmap the mirrored memory
+ ASSERT(
+ vm_manager.UnmapRange(nro_address, nro_info.nro_size + nro_info.bss_size).IsSuccess());
+
+ // Reprotect the source memory
+ ASSERT(vm_manager
+ .ReprotectRange(nro_info.nro_address, nro_info.nro_size,
+ Kernel::VMAPermission::ReadWrite)
+ .IsSuccess());
+ if (nro_info.bss_size > 0) {
+ ASSERT(vm_manager
+ .ReprotectRange(nro_info.bss_address, nro_info.bss_size,
+ Kernel::VMAPermission::ReadWrite)
+ .IsSuccess());
+ }
- Core::System::GetInstance().InvalidateCpuInstructionCaches();
+ system.InvalidateCpuInstructionCaches();
nro.erase(iter);
IPC::ResponseBuilder rb{ctx, 2};
@@ -473,7 +490,10 @@ private:
struct NROInfo {
SHA256Hash hash;
- u64 size;
+ VAddr nro_address;
+ u64 nro_size;
+ VAddr bss_address;
+ u64 bss_size;
};
bool initialized = false;
@@ -496,13 +516,14 @@ private:
Common::Is4KBAligned(header.text_size) && Common::Is4KBAligned(header.ro_size) &&
Common::Is4KBAligned(header.rw_size);
}
+ Core::System& system;
};
-void InstallInterfaces(SM::ServiceManager& sm) {
+void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
std::make_shared<DebugMonitor>()->InstallAsService(sm);
std::make_shared<ProcessManager>()->InstallAsService(sm);
std::make_shared<Shell>()->InstallAsService(sm);
- std::make_shared<RelocatableObject>()->InstallAsService(sm);
+ std::make_shared<RelocatableObject>(system)->InstallAsService(sm);
}
} // namespace Service::LDR