#include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/GuestAllocations.hpp" #include #include #include #include extern "C" { void* APS5_VABI mmap_nid_postfix(void*, std::size_t, int, int, int, std::int64_t) noexcept; int APS5_VABI munmap_nid_postfix(void*, std::size_t) noexcept; int* APS5_VABI __error_nid_postfix(); } static void Require(bool condition) { if (!condition) { std::fputs("Guest memory check failed\n", stderr); std::abort(); } } int main() { constexpr std::size_t page = 0x4000; const auto failed = reinterpret_cast(static_cast(-1)); const auto reject = [&](std::size_t length, int protection, int flags, int fd, std::int64_t offset, int error) { *__error_nid_postfix() = 0; Require(mmap_nid_postfix(nullptr, length, protection, flags, fd, offset) == failed); Require(*__error_nid_postfix() == error); }; reject(0, 3, 0x1002, -1, 0, 22); reject(std::numeric_limits::max(), 3, 0x1002, -1, 0, 22); reject(page, 8, 0x1002, -1, 0, 22); reject(page, 3, 0x1002, 0, 0, 22); reject(page, 3, 0x1002, -1, 1, 22); reject(page, 3, 0x1001, -1, 0, 45); // shared reject(page, 3, 0x1012, -1, 0, 45); // fixed reject(page, 3, 0x2, 0, 0, 45); // file-backed reject(page, 3, 0x22, -1, 0, 45); // Linux MAP_ANON is not guest MAP_ANON auto* memory = static_cast(mmap_nid_postfix(nullptr, page * 3 - 1, 3, 0x1002, -1, 0)); Require(memory != failed && (reinterpret_cast(memory) & (page - 1)) == 0); for (std::size_t i = 0; i < page * 3; ++i) Require(memory[i] == 0); memory[0] = 42; memory[page * 2] = 73; { GuestAllocations::Mutation mutation; const auto range = mutation.Find(memory); Require(range.bytes == page * 3 && range.readable && range.writable); } Require(munmap_nid_postfix(memory + 1, page) == -1 && *__error_nid_postfix() == 22); Require(munmap_nid_postfix(memory, 0) == -1 && *__error_nid_postfix() == 22); Require(memory[0] == 42); Require(munmap_nid_postfix(memory + page, 1) == 0); // round to one guest page Require(memory[0] == 42 && memory[page * 2] == 73); Require(munmap_nid_postfix(memory, page) == 0); Require(memory[page * 2] == 73); Require(munmap_nid_postfix(memory + page * 2, page) == 0); Require(munmap_nid_postfix(memory, page) == -1); for (int protection : {0, 1, 3, 5}) { void* mapped = mmap_nid_postfix(memory, 1, protection, 0x1002, -1, 0); Require(mapped != failed); { GuestAllocations::Mutation mutation; const auto range = mutation.Find(mapped); Require(range.readable == ((protection & 3) != 0)); Require(range.writable == ((protection & 2) != 0)); } Require(munmap_nid_postfix(mapped, 1) == 0); } }