WindowsPageAllocator: Fix allocation issues on macOS

On macOS (if using e.g. Crossover), VirtualQuery can report a memory address as free but still fail to reserve the memory with VirtualAlloc (fails with error code 0x170C240 for some reason).

To fix this, memory is now reserved directly in the loop to ensure it can be reserved. If reservation fails, the next address is tried.
This commit is contained in:
ghorsington committed 2022-06-19 21:50:49 +03:00
1 parent fbb856702f
commit 3febd6a3ba
1 file changed
+12 -5
@@ -12,7 +12,7 @@ namespace BepInEx.IL2CPP.Hook.Allocator;
internal class WindowsPageAllocator : PageAllocator
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static nint RoundUp(nint num, nint unit) => (num + unit - 1) & ~ (unit - 1);
private static nint RoundUp(nint num, nint unit) => (num + unit - 1) & ~(unit - 1);
private static Win32Exception Win32Error(string message = null, int code = -1)
{
@@ -23,6 +23,7 @@ internal class WindowsPageAllocator : PageAllocator
protected override nint AllocateChunk(nint hint)
{
nint chunk;
while (true)
{
if (WinApi.VirtualQuery(hint, out var mbi) == 0)
@@ -38,7 +39,17 @@ internal class WindowsPageAllocator : PageAllocator
var d = nextAddress - mbi.BaseAddress;
if (d >= 0 && mbi.RegionSize - d >= ALLOCATION_UNIT)
{
Logger.Log(LogLevel.Debug, $"Found free chunk at 0x{(long) nextAddress:X8}");
hint = nextAddress;
chunk = WinApi.VirtualAlloc(hint, ALLOCATION_UNIT, WinApi.AllocationType.MEM_RESERVE,
WinApi.ProtectConstant.PAGE_NOACCESS);
if (chunk == 0)
{
Logger.Log(LogLevel.Debug, $"Failed to reserve address: 0x{(long) hint:X8}: {Win32Error()}");
goto next;
}
break;
}
}
@@ -47,10 +58,6 @@ internal class WindowsPageAllocator : PageAllocator
hint = mbi.BaseAddress + mbi.RegionSize;
}
var chunk = WinApi.VirtualAlloc(hint, ALLOCATION_UNIT, WinApi.AllocationType.MEM_RESERVE,
WinApi.ProtectConstant.PAGE_NOACCESS);
if (chunk == 0)
throw Win32Error($"Failed to reserve address: 0x{(long) hint:X8}");
var addr = WinApi.VirtualAlloc(chunk, PAGE_SIZE, WinApi.AllocationType.MEM_COMMIT,
WinApi.ProtectConstant.PAGE_READWRITE);
if (addr == 0)