mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-25 20:28:48 +08:00
[Loader] Fall back to fixed-range backfill when main image base is occupied (#493)
When TryAllocateAtExact fails for the main image base (0x800000000 for PS5, 0x400000 for PS4), the loader previously threw a fatal InvalidOperationException with no recovery path. This happens when the host OS has already claimed part of that address range — common under Rosetta 2, with aggressive ASLR, or when another process maps into the guest address space. Instead of failing immediately, attempt TryBackFixedRange which backs the range page by page, claiming any free gaps. If the backfill also fails, Clear() rolls back partial allocations and the exception now includes platform-specific recovery advice. This prevents the most common emulator startup crash on affected hosts. Co-authored-by: tru3 <tru3@tru3.com>
This commit is contained in:
@@ -199,9 +199,32 @@ public sealed class SelfLoader : ISelfLoader
|
||||
{
|
||||
if (!physicalVm.TryAllocateAtExact(imageBase, totalImageSize, executable: true, out var allocatedBase))
|
||||
{
|
||||
var reason = physicalVm.DescribeAddressForDiagnostics(imageBase);
|
||||
throw new InvalidOperationException(
|
||||
$"Could not allocate main image at required base 0x{imageBase:X16} (size=0x{totalImageSize:X}): {reason}.");
|
||||
// Exact allocation failed — the host may have already claimed
|
||||
// part of this range (ASLR, Rosetta 2, or another process).
|
||||
// Try backing the fixed range page by page to claim whatever
|
||||
// free gaps exist. If the whole range is occupied the backfill
|
||||
// returns false and we surface the original failure reason.
|
||||
Console.Error.WriteLine(
|
||||
$"[LOADER] Exact allocation at main image base 0x{imageBase:X16} " +
|
||||
$"(size=0x{totalImageSize:X}) failed; attempting fixed-range backfill.");
|
||||
if (!physicalVm.TryBackFixedRange(imageBase, totalImageSize, executable: true))
|
||||
{
|
||||
// TryBackFixedRange may have partially backed pages before
|
||||
// failing. The earlier Clear() already reset all regions, so
|
||||
// this second Clear() is idempotent for everything except the
|
||||
// partial backfill — it frees only those orphaned pages.
|
||||
physicalVm.Clear();
|
||||
var reason = physicalVm.DescribeAddressForDiagnostics(imageBase);
|
||||
throw new InvalidOperationException(
|
||||
$"Could not allocate main image at required base 0x{imageBase:X16} " +
|
||||
$"(size=0x{totalImageSize:X}): {reason}. " +
|
||||
"Try closing other applications, rebooting, or " +
|
||||
(OperatingSystem.IsWindows()
|
||||
? "setting SHARPEMU_DISABLE_MITIGATION_RELAUNCH=1."
|
||||
: "ensuring no other process maps into this address range."));
|
||||
}
|
||||
|
||||
allocatedBase = imageBase;
|
||||
}
|
||||
|
||||
imageBase = allocatedBase;
|
||||
|
||||
Reference in New Issue
Block a user