[rpcsx-os] implement sys_query_memory_protection

This commit is contained in:
DH 2023-08-01 15:40:35 +03:00
parent 5edfdb037c
commit 0c59167c38
8 changed files with 95 additions and 11 deletions

View file

@ -20,8 +20,6 @@ struct HostFile : orbis::File {
int hostFd = -1;
~HostFile() {
std::printf("Destroying host file\n");
if (hostFd > 0) {
::close(hostFd);
}

View file

@ -12,6 +12,7 @@
#include "orbis/umtx.hpp"
#include "orbis/utils/Logs.hpp"
#include "orbis/utils/Rc.hpp"
#include "orbis/vm.hpp"
#include "thread.hpp"
#include "vfs.hpp"
#include "vm.hpp"
@ -247,6 +248,16 @@ orbis::SysResult virtual_query(orbis::Thread *thread,
return {};
}
orbis::SysResult
query_memory_protection(orbis::Thread *thread, orbis::ptr<void> address,
orbis::ptr<MemoryProtection> protection) {
if (rx::vm::queryProtection(address, &protection->startAddress,
&protection->endAddress, &protection->prot)) {
return {};
}
return ErrorCode::INVAL;
}
orbis::SysResult open(orbis::Thread *thread, orbis::ptr<const char> path,
orbis::sint flags, orbis::sint mode,
orbis::Ref<orbis::File> *file) {
@ -588,6 +599,7 @@ ProcessOps rx::procOpsTable = {
.munlockall = munlockall,
.munlock = munlock,
.virtual_query = virtual_query,
.query_memory_protection = query_memory_protection,
.open = open,
.shm_open = shm_open,
.blockpool_open = blockpool_open,

View file

@ -4,6 +4,7 @@
#include <bit>
#include <cassert>
#include <cinttypes>
#include <cstdint>
#include <cstring>
#include <fcntl.h>
#include <map>
@ -915,10 +916,60 @@ bool rx::vm::protect(void *addr, std::uint64_t size, std::int32_t prot) {
return ::mprotect(addr, size, prot & kMapProtCpuAll) == 0;
}
static std::int32_t getPageProtectionImpl(std::uint64_t address) {
return gBlocks[(address >> kBlockShift) - kFirstBlock].getProtection(
(address & kBlockMask) >> rx::vm::kPageShift);
}
bool rx::vm::queryProtection(const void *addr, std::uint64_t *startAddress,
std::uint64_t *endAddress, std::int64_t *prot) {
// TODO
return false;
std::uint64_t *endAddress, std::int32_t *prot) {
auto address = reinterpret_cast<std::uintptr_t>(addr);
if (address < kMinAddress || address >= kMaxAddress) {
return false;
}
std::uint64_t start = address & ~kPageMask;
std::uint64_t end = start + kPageSize;
std::lock_guard lock(g_mtx);
auto resultProt = getPageProtectionImpl(address);
while (true) {
auto testAddr = start - kPageSize;
if (testAddr < kMinAddress) {
break;
}
auto testProt = getPageProtectionImpl(testAddr);
if (resultProt != testProt) {
break;
}
start = testAddr;
}
while (true) {
auto testAddr = end;
if (testAddr >= kMaxAddress) {
break;
}
auto testProt = getPageProtectionImpl(testAddr);
if (resultProt != testProt) {
break;
}
end = testAddr + kPageSize;
}
*startAddress = start;
*endAddress = end;
*prot = resultProt;
return true;
}
unsigned rx::vm::getPageProtection(std::uint64_t address) {
@ -929,8 +980,7 @@ unsigned rx::vm::getPageProtection(std::uint64_t address) {
std::lock_guard lock(g_mtx);
return gBlocks[(address >> kBlockShift) - kFirstBlock].getProtection(
(address & kBlockMask) >> kPageShift);
return getPageProtectionImpl(address);
}
bool rx::vm::virtualQuery(const void *addr, std::int32_t flags,

View file

@ -75,6 +75,6 @@ bool protect(void *addr, std::uint64_t size, std::int32_t prot);
bool virtualQuery(const void *addr, std::int32_t flags, VirtualQueryInfo *info);
bool queryProtection(const void *addr, std::uint64_t *startAddress,
std::uint64_t *endAddress, std::int64_t *prot);
std::uint64_t *endAddress, std::int32_t *prot);
unsigned getPageProtection(std::uint64_t address);
} // namespace rx::vm