remove readback hacks, allows to read/write guest memory directly

This commit is contained in:
nmzik
2026-07-17 05:16:00 +02:00
parent 013e9a4485
commit e903c93848
27 changed files with 522 additions and 1228 deletions
+12 -71
View File
@@ -1,23 +1,10 @@
#include "graphics/shader/shaderVertexMetadata.h"
#include <algorithm>
#include <array>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#undef min
#undef max
#elif KYTY_PLATFORM == KYTY_PLATFORM_LINUX
#include <sys/mman.h>
#include <unistd.h>
#endif
namespace {
using namespace Libs::Graphics;
@@ -60,7 +47,7 @@ void CheckRejected(const ShaderMappedData& data, const char* text) {
"metadata rejection changed the prior output");
}
void TestValidAndHostileMetadata() {
void TestValidAndInvalidMetadata() {
Fixture fixture;
ShaderVertexMetadata output;
std::string error;
@@ -70,9 +57,13 @@ void TestValidAndHostileMetadata() {
output.input_semantics_count == 1,
"valid AGC vertex metadata was decoded incorrectly");
auto unreadable = fixture.mapped;
unreadable.user_data = reinterpret_cast<ShaderUserData*>(uintptr_t {1});
CheckRejected(unreadable, "unreadable AGC user-data header was accepted");
auto missing_header = fixture.mapped;
missing_header.user_data = nullptr;
CheckRejected(missing_header, "missing AGC user-data header was accepted");
Fixture missing_offsets;
missing_offsets.user_data.direct_resource_offset = nullptr;
CheckRejected(missing_offsets.mapped, "missing direct-resource offsets were accepted");
Fixture excessive_resources;
excessive_resources.user_data.direct_resource_count =
@@ -88,65 +79,15 @@ void TestValidAndHostileMetadata() {
static_cast<size_t>(AgcDirectResourceType::PtrVertexBufferTable)] = 63;
CheckRejected(excessive_register.mapped, "out-of-domain vertex table SGPR was accepted");
Fixture bad_semantics;
bad_semantics.mapped.input_semantics =
reinterpret_cast<ShaderSemantic*>(uintptr_t {1});
CheckRejected(bad_semantics.mapped, "unreadable vertex semantic array was accepted");
}
void TestCrossPageMetadata() {
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
SYSTEM_INFO system_info {};
GetSystemInfo(&system_info);
const auto page_size = static_cast<uint64_t>(system_info.dwPageSize);
auto* pages = static_cast<uint8_t*>(
VirtualAlloc(nullptr, page_size * 2, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));
Check(pages != nullptr, "failed to allocate metadata test pages");
DWORD old_protect = 0;
Check(VirtualProtect(pages + page_size, page_size, PAGE_NOACCESS, &old_protect) != 0,
"failed to protect metadata test page");
#elif KYTY_PLATFORM == KYTY_PLATFORM_LINUX
const auto native_page_size = sysconf(_SC_PAGESIZE);
Check(native_page_size > 0, "failed to query page size");
const auto page_size = static_cast<uint64_t>(native_page_size);
auto* pages = static_cast<uint8_t*>(
mmap(nullptr, page_size * 2, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
Check(pages != MAP_FAILED, "failed to allocate metadata test pages");
Check(mprotect(pages + page_size, page_size, PROT_NONE) == 0,
"failed to protect metadata test page");
#else
return;
#endif
Fixture fixture;
auto header_crossing = fixture.mapped;
header_crossing.user_data = reinterpret_cast<ShaderUserData*>(
pages + page_size - sizeof(ShaderUserData) + 1);
CheckRejected(header_crossing, "cross-page AGC user-data header was accepted");
auto offsets_crossing = fixture.mapped;
fixture.user_data.direct_resource_offset =
reinterpret_cast<uint16_t*>(pages + page_size - sizeof(uint16_t));
CheckRejected(offsets_crossing, "cross-page direct-resource offsets were accepted");
fixture.user_data.direct_resource_offset = fixture.offsets.data();
auto semantics_crossing = fixture.mapped;
semantics_crossing.input_semantics =
reinterpret_cast<ShaderSemantic*>(pages + page_size - sizeof(uint16_t));
CheckRejected(semantics_crossing, "cross-page vertex semantics were accepted");
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
Check(VirtualFree(pages, 0, MEM_RELEASE) != 0, "failed to free metadata test pages");
#elif KYTY_PLATFORM == KYTY_PLATFORM_LINUX
Check(munmap(pages, page_size * 2) == 0, "failed to free metadata test pages");
#endif
Fixture missing_semantics;
missing_semantics.mapped.input_semantics = nullptr;
CheckRejected(missing_semantics.mapped, "missing vertex semantic array was accepted");
}
} // namespace
int main() {
TestValidAndHostileMetadata();
TestCrossPageMetadata();
TestValidAndInvalidMetadata();
std::puts("ShaderVertexMetadataTests: all cases passed");
return 0;
}