sharpemu/tests/SharpEmu.Libs.Tests/Memory/HostMemoryQueryRunTests.cs

54 lines
2.4 KiB
C#

// Copyright (C) 2026 SharpEmu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
using SharpEmu.HLE;
using Xunit;
namespace SharpEmu.Libs.Tests.Memory;
// A POSIX query reports the run of pages sharing the queried page's protection, ending at the
// next protection change, as Win32 VirtualQuery does.
public sealed unsafe class HostMemoryQueryRunTests
{
[Fact]
public void QueryRunsEndAtTheNextProtectionChange()
{
if (OperatingSystem.IsWindows()) return;
var page = (ulong)Environment.SystemPageSize;
var memory = (byte*)HostMemory.Alloc(null, (nuint)(page * 16), HostMemory.MEM_RESERVE | HostMemory.MEM_COMMIT, HostMemory.PAGE_READWRITE);
Assert.True(memory != null);
var start = (ulong)memory;
try
{
Assert.True(HostMemory.Protect((void*)(start + 3 * page), (nuint)(3 * page), HostMemory.PAGE_READONLY, out _));
Assert.True(HostMemory.Protect((void*)(start + 9 * page), (nuint)page, HostMemory.PAGE_NOACCESS, out _));
Assert.True(HostMemory.Protect((void*)(start + 15 * page), (nuint)page, HostMemory.PAGE_READONLY, out _));
AssertRun(start, 0, 3, HostMemory.PAGE_READWRITE);
AssertRun(start, 3, 3, HostMemory.PAGE_READONLY);
AssertRun(start, 4, 2, HostMemory.PAGE_READONLY);
AssertRun(start, 6, 3, HostMemory.PAGE_READWRITE);
AssertRun(start, 9, 1, HostMemory.PAGE_NOACCESS);
AssertRun(start, 10, 5, HostMemory.PAGE_READWRITE);
// A run at the last page of the mapping.
AssertRun(start, 15, 1, HostMemory.PAGE_READONLY);
// Restoring the default protection removes the overrides from the run.
Assert.True(HostMemory.Protect((void*)(start + 3 * page), (nuint)(7 * page), HostMemory.PAGE_READWRITE, out _));
AssertRun(start, 0, 15, HostMemory.PAGE_READWRITE);
}
finally
{
Assert.True(HostMemory.Free(memory, 0, HostMemory.MEM_RELEASE));
}
void AssertRun(ulong baseAddress, ulong firstPage, ulong pages, uint protect)
{
Assert.NotEqual(0u, (uint)HostMemory.Query((void*)(baseAddress + firstPage * page + 8), out var info));
Assert.Equal(baseAddress + firstPage * page, info.BaseAddress);
Assert.Equal(pages * page, info.RegionSize);
Assert.Equal(protect, info.Protect);
}
}
}