From 3febd6a3ba4266fb996e81b27d18b2dcc82ac1e2 Mon Sep 17 00:00:00 2001 From: ghorsington Date: Sun, 19 Jun 2022 21:50:49 +0300 Subject: [PATCH] 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. --- .../Hook/Allocator/WindowsPageAllocator.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/BepInEx.IL2CPP/Hook/Allocator/WindowsPageAllocator.cs b/BepInEx.IL2CPP/Hook/Allocator/WindowsPageAllocator.cs index fc2c258..ba57ef8 100644 --- a/BepInEx.IL2CPP/Hook/Allocator/WindowsPageAllocator.cs +++ b/BepInEx.IL2CPP/Hook/Allocator/WindowsPageAllocator.cs @@ -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)