summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/process.cpp4
-rw-r--r--src/core/hle/kernel/vm_manager.cpp6
-rw-r--r--src/core/hle/kernel/vm_manager.h3
-rw-r--r--src/core/hle/service/ldr/ldr.cpp27
4 files changed, 27 insertions, 13 deletions
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index f06b6bb55..a257c3726 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -252,8 +252,8 @@ ResultCode Process::HeapFree(VAddr target, u32 size) {
252 return vm_manager.HeapFree(target, size); 252 return vm_manager.HeapFree(target, size);
253} 253}
254 254
255ResultCode Process::MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size) { 255ResultCode Process::MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, MemoryState state) {
256 return vm_manager.MirrorMemory(dst_addr, src_addr, size); 256 return vm_manager.MirrorMemory(dst_addr, src_addr, size, state);
257} 257}
258 258
259ResultCode Process::UnmapMemory(VAddr dst_addr, VAddr /*src_addr*/, u64 size) { 259ResultCode Process::UnmapMemory(VAddr dst_addr, VAddr /*src_addr*/, u64 size) {
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index ec7fd6150..100f8f6bf 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -298,7 +298,7 @@ ResultCode VMManager::HeapFree(VAddr target, u64 size) {
298 return RESULT_SUCCESS; 298 return RESULT_SUCCESS;
299} 299}
300 300
301ResultCode VMManager::MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size) { 301ResultCode VMManager::MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, MemoryState state) {
302 const auto vma = FindVMA(src_addr); 302 const auto vma = FindVMA(src_addr);
303 303
304 ASSERT_MSG(vma != vma_map.end(), "Invalid memory address"); 304 ASSERT_MSG(vma != vma_map.end(), "Invalid memory address");
@@ -312,8 +312,8 @@ ResultCode VMManager::MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
312 const std::shared_ptr<std::vector<u8>>& backing_block = vma->second.backing_block; 312 const std::shared_ptr<std::vector<u8>>& backing_block = vma->second.backing_block;
313 const std::size_t backing_block_offset = vma->second.offset + vma_offset; 313 const std::size_t backing_block_offset = vma->second.offset + vma_offset;
314 314
315 CASCADE_RESULT(auto new_vma, MapMemoryBlock(dst_addr, backing_block, backing_block_offset, size, 315 CASCADE_RESULT(auto new_vma,
316 MemoryState::Mapped)); 316 MapMemoryBlock(dst_addr, backing_block, backing_block_offset, size, state));
317 // Protect mirror with permissions from old region 317 // Protect mirror with permissions from old region
318 Reprotect(new_vma, vma->second.permissions); 318 Reprotect(new_vma, vma->second.permissions);
319 // Remove permissions from old region 319 // Remove permissions from old region
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index 248cc46dc..d522404fe 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -189,7 +189,8 @@ public:
189 ResultVal<VAddr> HeapAllocate(VAddr target, u64 size, VMAPermission perms); 189 ResultVal<VAddr> HeapAllocate(VAddr target, u64 size, VMAPermission perms);
190 ResultCode HeapFree(VAddr target, u64 size); 190 ResultCode HeapFree(VAddr target, u64 size);
191 191
192 ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size); 192 ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size,
193 MemoryState state = MemoryState::Mapped);
193 194
194 /** 195 /**
195 * Scans all VMAs and updates the page table range of any that use the given vector as backing 196 * Scans all VMAs and updates the page table range of any that use the given vector as backing
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index 5f020cbe0..b43f1f054 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -18,6 +18,7 @@ namespace Service::LDR {
18 18
19namespace ErrCodes { 19namespace ErrCodes {
20enum { 20enum {
21 InvalidMemoryState = 51,
21 InvalidNRO = 52, 22 InvalidNRO = 52,
22 InvalidNRR = 53, 23 InvalidNRR = 53,
23 MissingNRRHash = 54, 24 MissingNRRHash = 54,
@@ -32,6 +33,7 @@ enum {
32}; 33};
33} 34}
34 35
36constexpr ResultCode ERROR_INVALID_MEMORY_STATE(ErrorModule::Loader, ErrCodes::InvalidMemoryState);
35constexpr ResultCode ERROR_INVALID_NRO(ErrorModule::Loader, ErrCodes::InvalidNRO); 37constexpr ResultCode ERROR_INVALID_NRO(ErrorModule::Loader, ErrCodes::InvalidNRO);
36constexpr ResultCode ERROR_INVALID_NRR(ErrorModule::Loader, ErrCodes::InvalidNRR); 38constexpr ResultCode ERROR_INVALID_NRR(ErrorModule::Loader, ErrCodes::InvalidNRR);
37constexpr ResultCode ERROR_MISSING_NRR_HASH(ErrorModule::Loader, ErrCodes::MissingNRRHash); 39constexpr ResultCode ERROR_MISSING_NRR_HASH(ErrorModule::Loader, ErrCodes::MissingNRRHash);
@@ -120,7 +122,7 @@ public:
120 return; 122 return;
121 } 123 }
122 124
123 if (nro.size() >= MAXIMUM_LOADED_RO) { 125 if (nrr.size() >= MAXIMUM_LOADED_RO) {
124 LOG_ERROR(Service_LDR, "Loading new NRR would exceed the maximum number of loaded NRRs " 126 LOG_ERROR(Service_LDR, "Loading new NRR would exceed the maximum number of loaded NRRs "
125 "(0x40)! Failing..."); 127 "(0x40)! Failing...");
126 IPC::ResponseBuilder rb{ctx, 2}; 128 IPC::ResponseBuilder rb{ctx, 2};
@@ -178,10 +180,13 @@ public:
178 } 180 }
179 181
180 std::vector<SHA256Hash> hashes; 182 std::vector<SHA256Hash> hashes;
183
184 // Copy all hashes in the NRR (specified by hash count/hash offset) into vector.
181 for (std::size_t i = header.hash_offset; 185 for (std::size_t i = header.hash_offset;
182 i < (header.hash_offset + (header.hash_count << 5)); i += 8) { 186 i < (header.hash_offset + (header.hash_count * sizeof(SHA256Hash))); i += 8) {
183 hashes.emplace_back(); 187 SHA256Hash hash;
184 std::memcpy(hashes.back().data(), nrr_data.data() + i, sizeof(SHA256Hash)); 188 std::memcpy(hash.data(), nrr_data.data() + i, sizeof(SHA256Hash));
189 hashes.emplace_back(hash);
185 } 190 }
186 191
187 nrr.insert_or_assign(nrr_addr, std::move(hashes)); 192 nrr.insert_or_assign(nrr_addr, std::move(hashes));
@@ -258,8 +263,8 @@ public:
258 // NRO Size or BSS Size is zero or causes overflow 263 // NRO Size or BSS Size is zero or causes overflow
259 const auto nro_size_valid = 264 const auto nro_size_valid =
260 nro_size != 0 && nro_addr + nro_size > nro_addr && Common::Is4KBAligned(nro_size); 265 nro_size != 0 && nro_addr + nro_size > nro_addr && Common::Is4KBAligned(nro_size);
261 const auto bss_size_valid = std::numeric_limits<u64>::max() - nro_size >= bss_size && 266 const auto bss_size_valid =
262 (bss_size == 0 || bss_addr + bss_size > bss_addr); 267 nro_size + bss_size >= nro_size && (bss_size == 0 || bss_addr + bss_size > bss_addr);
263 268
264 if (!nro_size_valid || !bss_size_valid) { 269 if (!nro_size_valid || !bss_size_valid) {
265 LOG_ERROR(Service_LDR, 270 LOG_ERROR(Service_LDR,
@@ -313,7 +318,15 @@ public:
313 auto& vm_manager = process->VMManager(); 318 auto& vm_manager = process->VMManager();
314 auto map_address = vm_manager.FindFreeRegion(nro_size + bss_size); 319 auto map_address = vm_manager.FindFreeRegion(nro_size + bss_size);
315 320
316 ASSERT(map_address.Succeeded()); 321 if (!map_address.Succeeded() ||
322 *map_address + nro_size + bss_size > vm_manager.GetAddressSpaceEndAddress()) {
323
324 LOG_ERROR(Service_LDR,
325 "General error while allocation memory or no available memory to allocate!");
326 IPC::ResponseBuilder rb{ctx, 2};
327 rb.Push(ERROR_INVALID_MEMORY_STATE);
328 return;
329 }
317 330
318 ASSERT(process->MirrorMemory(*map_address, nro_addr, nro_size, 331 ASSERT(process->MirrorMemory(*map_address, nro_addr, nro_size,
319 Kernel::MemoryState::ModuleCodeStatic) == RESULT_SUCCESS); 332 Kernel::MemoryState::ModuleCodeStatic) == RESULT_SUCCESS);