mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-06-10 12:43:15 +00:00
memory: Implement protecting multiple VMAs (#2484)
* Implement protecting multiple VMAs A handful of games expect this to work, and updated versions of Grand Theft Auto V crash if it doesn't work. * Clang
This commit is contained in:
parent
14717b8ecb
commit
54a1694a2b
2 changed files with 31 additions and 16 deletions
|
@ -481,19 +481,14 @@ int MemoryManager::QueryProtection(VAddr addr, void** start, void** end, u32* pr
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MemoryManager::Protect(VAddr addr, size_t size, MemoryProt prot) {
|
s64 MemoryManager::ProtectBytes(VAddr addr, VirtualMemoryArea vma_base, size_t size,
|
||||||
std::scoped_lock lk{mutex};
|
MemoryProt prot) {
|
||||||
|
const auto start_in_vma = addr - vma_base.base;
|
||||||
|
const auto adjusted_size =
|
||||||
|
vma_base.size - start_in_vma < size ? vma_base.size - start_in_vma : size;
|
||||||
|
|
||||||
// Find the virtual memory area that contains the specified address range.
|
if (vma_base.type == VMAType::Free) {
|
||||||
auto it = FindVMA(addr);
|
LOG_ERROR(Kernel_Vmm, "Cannot change protection on free memory region");
|
||||||
if (it == vma_map.end() || !it->second.Contains(addr, size)) {
|
|
||||||
LOG_ERROR(Core, "Address range not mapped");
|
|
||||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
VirtualMemoryArea& vma = it->second;
|
|
||||||
if (vma.type == VMAType::Free) {
|
|
||||||
LOG_ERROR(Core, "Cannot change protection on free memory region");
|
|
||||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,13 +499,13 @@ int MemoryManager::Protect(VAddr addr, size_t size, MemoryProt prot) {
|
||||||
|
|
||||||
MemoryProt invalid_flags = prot & ~valid_flags;
|
MemoryProt invalid_flags = prot & ~valid_flags;
|
||||||
if (u32(invalid_flags) != 0 && u32(invalid_flags) != u32(MemoryProt::NoAccess)) {
|
if (u32(invalid_flags) != 0 && u32(invalid_flags) != u32(MemoryProt::NoAccess)) {
|
||||||
LOG_ERROR(Core, "Invalid protection flags: prot = {:#x}, invalid flags = {:#x}", u32(prot),
|
LOG_ERROR(Kernel_Vmm, "Invalid protection flags: prot = {:#x}, invalid flags = {:#x}",
|
||||||
u32(invalid_flags));
|
u32(prot), u32(invalid_flags));
|
||||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change protection
|
// Change protection
|
||||||
vma.prot = prot;
|
vma_base.prot = prot;
|
||||||
|
|
||||||
// Set permissions
|
// Set permissions
|
||||||
Core::MemoryPermission perms{};
|
Core::MemoryPermission perms{};
|
||||||
|
@ -533,6 +528,24 @@ int MemoryManager::Protect(VAddr addr, size_t size, MemoryProt prot) {
|
||||||
|
|
||||||
impl.Protect(addr, size, perms);
|
impl.Protect(addr, size, perms);
|
||||||
|
|
||||||
|
return adjusted_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 MemoryManager::Protect(VAddr addr, size_t size, MemoryProt prot) {
|
||||||
|
std::scoped_lock lk{mutex};
|
||||||
|
s64 protected_bytes = 0;
|
||||||
|
do {
|
||||||
|
auto it = FindVMA(addr + protected_bytes);
|
||||||
|
auto& vma_base = it->second;
|
||||||
|
auto result = 0;
|
||||||
|
result = ProtectBytes(addr + protected_bytes, vma_base, size - protected_bytes, prot);
|
||||||
|
if (result < 0) {
|
||||||
|
// ProtectBytes returned an error, return it
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
protected_bytes += result;
|
||||||
|
} while (protected_bytes < size);
|
||||||
|
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -198,7 +198,9 @@ public:
|
||||||
|
|
||||||
int QueryProtection(VAddr addr, void** start, void** end, u32* prot);
|
int QueryProtection(VAddr addr, void** start, void** end, u32* prot);
|
||||||
|
|
||||||
int Protect(VAddr addr, size_t size, MemoryProt prot);
|
s32 Protect(VAddr addr, size_t size, MemoryProt prot);
|
||||||
|
|
||||||
|
s64 ProtectBytes(VAddr addr, VirtualMemoryArea vma_base, size_t size, MemoryProt prot);
|
||||||
|
|
||||||
int VirtualQuery(VAddr addr, int flags, ::Libraries::Kernel::OrbisVirtualQueryInfo* info);
|
int VirtualQuery(VAddr addr, int flags, ::Libraries::Kernel::OrbisVirtualQueryInfo* info);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue