diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/vm_manager.cpp | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/vm_manager.h | 3 | ||||
| -rw-r--r-- | src/core/hle/service/ldr/ldr.cpp | 27 |
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 | ||
| 255 | ResultCode Process::MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size) { | 255 | ResultCode 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 | ||
| 259 | ResultCode Process::UnmapMemory(VAddr dst_addr, VAddr /*src_addr*/, u64 size) { | 259 | ResultCode 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 | ||
| 301 | ResultCode VMManager::MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size) { | 301 | ResultCode 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 | ||
| 19 | namespace ErrCodes { | 19 | namespace ErrCodes { |
| 20 | enum { | 20 | enum { |
| 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 | ||
| 36 | constexpr ResultCode ERROR_INVALID_MEMORY_STATE(ErrorModule::Loader, ErrCodes::InvalidMemoryState); | ||
| 35 | constexpr ResultCode ERROR_INVALID_NRO(ErrorModule::Loader, ErrCodes::InvalidNRO); | 37 | constexpr ResultCode ERROR_INVALID_NRO(ErrorModule::Loader, ErrCodes::InvalidNRO); |
| 36 | constexpr ResultCode ERROR_INVALID_NRR(ErrorModule::Loader, ErrCodes::InvalidNRR); | 38 | constexpr ResultCode ERROR_INVALID_NRR(ErrorModule::Loader, ErrCodes::InvalidNRR); |
| 37 | constexpr ResultCode ERROR_MISSING_NRR_HASH(ErrorModule::Loader, ErrCodes::MissingNRRHash); | 39 | constexpr 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); |