mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-28 05:30:57 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b522776988 |
@@ -38,71 +38,6 @@ public sealed partial class DirectExecutionBackend
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecordDeferredBootstrapTrace(
|
|
||||||
long dispatchIndex,
|
|
||||||
ulong op,
|
|
||||||
ulong symbolPointer,
|
|
||||||
ulong outputPointer,
|
|
||||||
ulong returnRip)
|
|
||||||
{
|
|
||||||
lock (_deferredBootstrapTraceGate)
|
|
||||||
{
|
|
||||||
_deferredBootstrapTrace[_deferredBootstrapTraceWriteIndex] = new DeferredBootstrapTraceEntry(
|
|
||||||
dispatchIndex,
|
|
||||||
op,
|
|
||||||
symbolPointer,
|
|
||||||
outputPointer,
|
|
||||||
returnRip);
|
|
||||||
_deferredBootstrapTraceWriteIndex =
|
|
||||||
(_deferredBootstrapTraceWriteIndex + 1) % _deferredBootstrapTrace.Length;
|
|
||||||
if (_deferredBootstrapTraceCount < _deferredBootstrapTrace.Length)
|
|
||||||
{
|
|
||||||
_deferredBootstrapTraceCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrainDeferredBootstrapTraces()
|
|
||||||
{
|
|
||||||
if (!_logBootstrap)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeferredBootstrapTraceEntry[] pending;
|
|
||||||
lock (_deferredBootstrapTraceGate)
|
|
||||||
{
|
|
||||||
if (_deferredBootstrapTraceCount == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pending = new DeferredBootstrapTraceEntry[_deferredBootstrapTraceCount];
|
|
||||||
var readIndex = (_deferredBootstrapTraceWriteIndex - _deferredBootstrapTraceCount +
|
|
||||||
_deferredBootstrapTrace.Length) % _deferredBootstrapTrace.Length;
|
|
||||||
for (var i = 0; i < _deferredBootstrapTraceCount; i++)
|
|
||||||
{
|
|
||||||
pending[i] = _deferredBootstrapTrace[(readIndex + i) % _deferredBootstrapTrace.Length];
|
|
||||||
}
|
|
||||||
|
|
||||||
_deferredBootstrapTraceCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var entry in pending)
|
|
||||||
{
|
|
||||||
var symbolText = "<unreadable>";
|
|
||||||
if (TryReadAsciiZ(entry.SymbolPointer, 256, out var sym))
|
|
||||||
{
|
|
||||||
symbolText = sym;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.Error.WriteLine(
|
|
||||||
$"[LOADER][TRACE] bootstrap_call#{entry.DispatchIndex}: op=0x{entry.Op:X16} " +
|
|
||||||
$"sym_ptr=0x{entry.SymbolPointer:X16} sym='{symbolText}' " +
|
|
||||||
$"out_ptr=0x{entry.OutputPointer:X16} ret=0x{entry.ReturnRip:X16}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DumpRecentImportTrace()
|
private void DumpRecentImportTrace()
|
||||||
{
|
{
|
||||||
if (_recentImportTraceCount == 0)
|
if (_recentImportTraceCount == 0)
|
||||||
@@ -235,15 +170,14 @@ public sealed partial class DirectExecutionBackend
|
|||||||
ulong callRip = returnRip + (ulong)i;
|
ulong callRip = returnRip + (ulong)i;
|
||||||
ulong target = unchecked((ulong)((long)(callRip + 5) + rel32));
|
ulong target = unchecked((ulong)((long)(callRip + 5) + rel32));
|
||||||
Log.Debug($"Import#{dispatchIndex} near-call @{callRip:X16}: target=0x{target:X16}");
|
Log.Debug($"Import#{dispatchIndex} near-call @{callRip:X16}: target=0x{target:X16}");
|
||||||
var importEntries = _importEntries;
|
for (int importIndex = 0; importIndex < _importEntries.Length; importIndex++)
|
||||||
for (int importIndex = 0; importIndex < importEntries.Length; importIndex++)
|
|
||||||
{
|
{
|
||||||
if (importEntries[importIndex].Address != target)
|
if (_importEntries[importIndex].Address != target)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
string nid = importEntries[importIndex].Nid;
|
string nid = _importEntries[importIndex].Nid;
|
||||||
if (_moduleManager.TryGetExport(nid, out var export))
|
if (_moduleManager.TryGetExport(nid, out var export))
|
||||||
{
|
{
|
||||||
Log.Debug(
|
Log.Debug(
|
||||||
@@ -270,14 +204,14 @@ public sealed partial class DirectExecutionBackend
|
|||||||
{
|
{
|
||||||
Log.Debug(
|
Log.Debug(
|
||||||
$"Import#{dispatchIndex} near-call PLT slot: [0x{slot:X16}] = 0x{slotTarget:X16}");
|
$"Import#{dispatchIndex} near-call PLT slot: [0x{slot:X16}] = 0x{slotTarget:X16}");
|
||||||
for (int importIndex = 0; importIndex < importEntries.Length; importIndex++)
|
for (int importIndex = 0; importIndex < _importEntries.Length; importIndex++)
|
||||||
{
|
{
|
||||||
if (importEntries[importIndex].Address != slotTarget)
|
if (_importEntries[importIndex].Address != slotTarget)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
string nid = importEntries[importIndex].Nid;
|
string nid = _importEntries[importIndex].Nid;
|
||||||
if (_moduleManager.TryGetExport(nid, out var export))
|
if (_moduleManager.TryGetExport(nid, out var export))
|
||||||
{
|
{
|
||||||
Log.Debug(
|
Log.Debug(
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ using System.Linq;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using SharpEmu.Core.Cpu;
|
using SharpEmu.Core.Cpu;
|
||||||
using SharpEmu.Core.Loader;
|
|
||||||
using SharpEmu.HLE;
|
using SharpEmu.HLE;
|
||||||
|
|
||||||
namespace SharpEmu.Core.Cpu.Native;
|
namespace SharpEmu.Core.Cpu.Native;
|
||||||
@@ -111,13 +110,12 @@ public sealed partial class DirectExecutionBackend
|
|||||||
LastError = "Import dispatch called without active CPU context";
|
LastError = "Import dispatch called without active CPU context";
|
||||||
return 18446744071562199298uL;
|
return 18446744071562199298uL;
|
||||||
}
|
}
|
||||||
var importEntries = _importEntries;
|
if ((uint)importIndex >= (uint)_importEntries.Length)
|
||||||
if ((uint)importIndex >= (uint)importEntries.Length)
|
|
||||||
{
|
{
|
||||||
LastError = $"Import dispatch index out of range: {importIndex}";
|
LastError = $"Import dispatch index out of range: {importIndex}";
|
||||||
return 18446744071562199042uL;
|
return 18446744071562199042uL;
|
||||||
}
|
}
|
||||||
ImportStubEntry importStubEntry = importEntries[importIndex];
|
ImportStubEntry importStubEntry = _importEntries[importIndex];
|
||||||
int num2 = Volatile.Read(in _rawSentinelRecoveries);
|
int num2 = Volatile.Read(in _rawSentinelRecoveries);
|
||||||
if (num2 != _lastReportedRawSentinelRecoveries)
|
if (num2 != _lastReportedRawSentinelRecoveries)
|
||||||
{
|
{
|
||||||
@@ -161,14 +159,6 @@ public sealed partial class DirectExecutionBackend
|
|||||||
*(ulong*)(xmmSlot + 8));
|
*(ulong*)(xmmSlot + 8));
|
||||||
}
|
}
|
||||||
cpuContext[CpuRegister.Rsp] = (ulong)argPackPtr + 96uL;
|
cpuContext[CpuRegister.Rsp] = (ulong)argPackPtr + 96uL;
|
||||||
if (string.Equals(importStubEntry.Nid, RuntimeStubNids.BootstrapBridge, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
NormalizeKernelDynlibDlsymArguments(cpuContext, out _, out _);
|
|
||||||
*(ulong*)argPackPtr = cpuContext[CpuRegister.Rdi];
|
|
||||||
*(ulong*)(argPackPtr + 8) = cpuContext[CpuRegister.Rsi];
|
|
||||||
*(ulong*)(argPackPtr + 16) = cpuContext[CpuRegister.Rdx];
|
|
||||||
}
|
|
||||||
|
|
||||||
ulong value = cpuContext[CpuRegister.Rdi];
|
ulong value = cpuContext[CpuRegister.Rdi];
|
||||||
ulong value2 = cpuContext[CpuRegister.Rsi];
|
ulong value2 = cpuContext[CpuRegister.Rsi];
|
||||||
ulong num3 = cpuContext[CpuRegister.Rdx];
|
ulong num3 = cpuContext[CpuRegister.Rdx];
|
||||||
@@ -219,6 +209,16 @@ public sealed partial class DirectExecutionBackend
|
|||||||
TraceGuestContext(
|
TraceGuestContext(
|
||||||
$"import dispatch={num} nid={importStubEntry.Nid} ret=0x{num7:X16} managed={Environment.CurrentManagedThreadId} guest=0x{GuestThreadExecution.CurrentGuestThreadHandle:X16} fiber=0x{GuestThreadExecution.CurrentFiberAddress:X16} active={HasActiveExecutionThread}");
|
$"import dispatch={num} nid={importStubEntry.Nid} ret=0x{num7:X16} managed={Environment.CurrentManagedThreadId} guest=0x{GuestThreadExecution.CurrentGuestThreadHandle:X16} fiber=0x{GuestThreadExecution.CurrentFiberAddress:X16} active={HasActiveExecutionThread}");
|
||||||
}
|
}
|
||||||
|
if (_logBootstrap && string.Equals(importStubEntry.Nid, RuntimeStubNids.BootstrapBridge, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
string symbolText = "<unreadable>";
|
||||||
|
if (TryReadAsciiZ(value2, 256, out var sym))
|
||||||
|
{
|
||||||
|
symbolText = sym;
|
||||||
|
}
|
||||||
|
Console.Error.WriteLine(
|
||||||
|
$"[LOADER][TRACE] bootstrap_call#{num}: op=0x{value:X16} sym_ptr=0x{value2:X16} sym='{symbolText}' out_ptr=0x{num3:X16} ret=0x{num7:X16}");
|
||||||
|
}
|
||||||
if (!isGuestWorker &&
|
if (!isGuestWorker &&
|
||||||
!ActiveForcedGuestExit &&
|
!ActiveForcedGuestExit &&
|
||||||
ShouldForceGuestExitOnImportLoop(importStubEntry.Nid, num7, num, value, value2) &&
|
ShouldForceGuestExitOnImportLoop(importStubEntry.Nid, num7, num, value, value2) &&
|
||||||
@@ -383,11 +383,6 @@ public sealed partial class DirectExecutionBackend
|
|||||||
{
|
{
|
||||||
if (string.Equals(importStubEntry.Nid, RuntimeStubNids.BootstrapBridge, StringComparison.Ordinal))
|
if (string.Equals(importStubEntry.Nid, RuntimeStubNids.BootstrapBridge, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
if (_logBootstrap)
|
|
||||||
{
|
|
||||||
RecordDeferredBootstrapTrace(num, value, value2, num3, num7);
|
|
||||||
}
|
|
||||||
|
|
||||||
orbisGen2Result = DispatchBootstrapBridge();
|
orbisGen2Result = DispatchBootstrapBridge();
|
||||||
}
|
}
|
||||||
else if (string.Equals(importStubEntry.Nid, RuntimeStubNids.KernelDynlibDlsym, StringComparison.Ordinal) ||
|
else if (string.Equals(importStubEntry.Nid, RuntimeStubNids.KernelDynlibDlsym, StringComparison.Ordinal) ||
|
||||||
@@ -550,7 +545,6 @@ public sealed partial class DirectExecutionBackend
|
|||||||
cpuContext.GetXmmRegister(0, out var returnXmm0Low, out var returnXmm0High);
|
cpuContext.GetXmmRegister(0, out var returnXmm0Low, out var returnXmm0High);
|
||||||
*(ulong*)(argPackPtr - 0x80) = returnXmm0Low;
|
*(ulong*)(argPackPtr - 0x80) = returnXmm0Low;
|
||||||
*(ulong*)(argPackPtr - 0x80 + 8) = returnXmm0High;
|
*(ulong*)(argPackPtr - 0x80 + 8) = returnXmm0High;
|
||||||
DrainDeferredBootstrapTraces();
|
|
||||||
return cpuContext[CpuRegister.Rax];
|
return cpuContext[CpuRegister.Rax];
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -559,7 +553,6 @@ public sealed partial class DirectExecutionBackend
|
|||||||
Console.Error.WriteLine($"[LOADER][ERROR] {LastError}");
|
Console.Error.WriteLine($"[LOADER][ERROR] {LastError}");
|
||||||
Console.Error.WriteLine($"[LOADER][ERROR] {ex.StackTrace}");
|
Console.Error.WriteLine($"[LOADER][ERROR] {ex.StackTrace}");
|
||||||
cpuContext[CpuRegister.Rax] = 18446744071562199298uL;
|
cpuContext[CpuRegister.Rax] = 18446744071562199298uL;
|
||||||
DrainDeferredBootstrapTraces();
|
|
||||||
return 18446744071562199298uL;
|
return 18446744071562199298uL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1318,485 +1311,30 @@ public sealed partial class DirectExecutionBackend
|
|||||||
{
|
{
|
||||||
return OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;
|
return OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
ulong symbolNameAddress = cpuContext[CpuRegister.Rsi];
|
||||||
NormalizeKernelDynlibDlsymArguments(cpuContext, out var symbolNameAddress, out var outputAddress);
|
ulong outputAddress = cpuContext[CpuRegister.Rdx];
|
||||||
try
|
if (!TryReadAsciiZ(symbolNameAddress, 512, out var symbolName))
|
||||||
{
|
{
|
||||||
if (!TryReadAsciiZ(symbolNameAddress, 512, out var symbolName) ||
|
cpuContext[CpuRegister.Rax] = 18446744073709551615uL;
|
||||||
!TryResolveDlsymGuestAddress(symbolName, out var resolvedAddress) ||
|
return OrbisGen2Result.ORBIS_GEN2_OK;
|
||||||
outputAddress == 0 ||
|
|
||||||
!TryWriteUInt64Compat(outputAddress, resolvedAddress))
|
|
||||||
{
|
|
||||||
return CompleteKernelDynlibDlsymFailure(cpuContext, outputAddress);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch
|
if (!TryResolveRuntimeSymbolAddress(symbolName, out var resolvedAddress) &&
|
||||||
|
!TryResolveRuntimeSymbolAlias(symbolName, out resolvedAddress))
|
||||||
{
|
{
|
||||||
return CompleteKernelDynlibDlsymFailure(cpuContext, outputAddress);
|
Console.Error.WriteLine(
|
||||||
|
$"[LOADER][WARN] sceKernelDlsym failed: handle=0x{cpuContext[CpuRegister.Rdi]:X} symbol='{symbolName}'");
|
||||||
|
cpuContext[CpuRegister.Rax] = 18446744073709551615uL;
|
||||||
|
return OrbisGen2Result.ORBIS_GEN2_OK;
|
||||||
|
}
|
||||||
|
if (outputAddress == 0L || !TryWriteUInt64Compat(outputAddress, resolvedAddress))
|
||||||
|
{
|
||||||
|
cpuContext[CpuRegister.Rax] = 18446744073709551615uL;
|
||||||
|
return OrbisGen2Result.ORBIS_GEN2_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpuContext[CpuRegister.Rax] = 0uL;
|
cpuContext[CpuRegister.Rax] = 0uL;
|
||||||
return OrbisGen2Result.ORBIS_GEN2_OK;
|
return OrbisGen2Result.ORBIS_GEN2_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void NormalizeKernelDynlibDlsymArguments(
|
|
||||||
CpuContext cpuContext,
|
|
||||||
out ulong symbolNameAddress,
|
|
||||||
out ulong outputAddress)
|
|
||||||
{
|
|
||||||
var handle = cpuContext[CpuRegister.Rdi];
|
|
||||||
symbolNameAddress = cpuContext[CpuRegister.Rsi];
|
|
||||||
outputAddress = cpuContext[CpuRegister.Rdx];
|
|
||||||
|
|
||||||
// Standalone bootstrap loaders sometimes call through the bridge with
|
|
||||||
// (symbol_ptr, handle, out) while sceKernelDlsym is (handle, symbol_ptr, out).
|
|
||||||
// Heuristic only: valid when RSI looks like a small handle and RDI is a guest pointer.
|
|
||||||
if (symbolNameAddress < 0x10000 &&
|
|
||||||
IsPlausibleDynlibSymbolPointer(handle))
|
|
||||||
{
|
|
||||||
symbolNameAddress = handle;
|
|
||||||
handle = cpuContext[CpuRegister.Rsi];
|
|
||||||
cpuContext[CpuRegister.Rdi] = handle;
|
|
||||||
cpuContext[CpuRegister.Rsi] = symbolNameAddress;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsPlausibleDynlibSymbolPointer(ulong address)
|
|
||||||
{
|
|
||||||
return address >= 0x10000 && address < 0x0000_8000_0000_0000UL;
|
|
||||||
}
|
|
||||||
|
|
||||||
private OrbisGen2Result CompleteKernelDynlibDlsymFailure(CpuContext cpuContext, ulong outputAddress)
|
|
||||||
{
|
|
||||||
if (outputAddress != 0)
|
|
||||||
{
|
|
||||||
_ = TryWriteUInt64Compat(outputAddress, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
cpuContext[CpuRegister.Rax] = ulong.MaxValue;
|
|
||||||
return OrbisGen2Result.ORBIS_GEN2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ResetLazyDlsymStubState()
|
|
||||||
{
|
|
||||||
lock (_lazyDlsymStubGate)
|
|
||||||
{
|
|
||||||
_lazyDlsymStubCache.Clear();
|
|
||||||
_lazyImportStubPoolMapped = false;
|
|
||||||
_lazyImportStubPoolBase = 0;
|
|
||||||
_lazyImportStubNextSlot = 0;
|
|
||||||
_lazyImportStubPoolLimit = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool TryResolveDlsymGuestAddress(string symbolName, out ulong guestAddress)
|
|
||||||
{
|
|
||||||
guestAddress = 0;
|
|
||||||
if (string.IsNullOrWhiteSpace(symbolName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tier 0: ELF runtime symbols and aliases.
|
|
||||||
if (TryResolveRuntimeSymbolAddress(symbolName, out guestAddress) ||
|
|
||||||
TryResolveRuntimeSymbolAlias(symbolName, out guestAddress))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tier 1: existing import stub entries (duplicate prevention).
|
|
||||||
if (TryFindImportStubGuestAddress(symbolName, out guestAddress))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var hasAerolibSymbol = Aerolib.Instance.TryGetByExportName(symbolName, out var hleSymbol);
|
|
||||||
if (hasAerolibSymbol)
|
|
||||||
{
|
|
||||||
if (HleDataSymbols.TryGetAddress(hleSymbol.Nid, out _))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TryResolveRuntimeSymbolAddress(hleSymbol.Nid, out guestAddress) ||
|
|
||||||
TryResolveRuntimeSymbolAddress(hleSymbol.ExportName, out guestAddress) ||
|
|
||||||
TryFindImportStubGuestAddress(hleSymbol.Nid, out guestAddress) ||
|
|
||||||
TryFindImportStubGuestAddress(hleSymbol.ExportName, out guestAddress))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (Aerolib.Instance.TryGetByNid(symbolName, out hleSymbol))
|
|
||||||
{
|
|
||||||
if (HleDataSymbols.TryGetAddress(hleSymbol.Nid, out _))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TryFindImportStubGuestAddress(hleSymbol.Nid, out guestAddress) ||
|
|
||||||
TryFindImportStubGuestAddress(hleSymbol.ExportName, out guestAddress))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
hasAerolibSymbol = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tier 3: lazy materialization for callable HLE symbols missing from ELF imports.
|
|
||||||
if (!TryResolveLazyDispatchTarget(symbolName, hasAerolibSymbol, in hleSymbol, out var dispatchNid, out var export))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TryGetOrCreateLazyImportStub(
|
|
||||||
dispatchNid,
|
|
||||||
symbolName,
|
|
||||||
hasAerolibSymbol ? hleSymbol : null,
|
|
||||||
export,
|
|
||||||
out guestAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool TryFindImportStubGuestAddress(string identifier, out ulong guestAddress)
|
|
||||||
{
|
|
||||||
guestAddress = 0;
|
|
||||||
if (string.IsNullOrWhiteSpace(identifier))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var importEntries = _importEntries;
|
|
||||||
for (var i = 0; i < importEntries.Length; i++)
|
|
||||||
{
|
|
||||||
var entry = importEntries[i];
|
|
||||||
if (!ImportStubEntryMatchesIdentifier(entry, identifier))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry.Address >= 0x10000)
|
|
||||||
{
|
|
||||||
guestAddress = entry.Address;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool ImportStubEntryMatchesIdentifier(in ImportStubEntry entry, string identifier)
|
|
||||||
{
|
|
||||||
if (string.Equals(entry.Nid, identifier, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry.Export is not { } export)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Equals(export.Name, identifier, StringComparison.Ordinal) ||
|
|
||||||
string.Equals(export.Nid, identifier, StringComparison.Ordinal);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsKernelDynlibDlsymIdentifier(string identifier)
|
|
||||||
{
|
|
||||||
return string.Equals(identifier, "sceKernelDlsym", StringComparison.Ordinal) ||
|
|
||||||
string.Equals(identifier, KernelDynlibDlsymAerolibNid, StringComparison.Ordinal) ||
|
|
||||||
string.Equals(identifier, RuntimeStubNids.KernelDynlibDlsym, StringComparison.Ordinal);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool TryResolveLazyDispatchTarget(
|
|
||||||
string symbolName,
|
|
||||||
bool hasAerolibSymbol,
|
|
||||||
in SysAbiSymbol hleSymbol,
|
|
||||||
out string dispatchNid,
|
|
||||||
out ExportedFunction? export)
|
|
||||||
{
|
|
||||||
export = null;
|
|
||||||
dispatchNid = string.Empty;
|
|
||||||
|
|
||||||
if (IsKernelDynlibDlsymIdentifier(symbolName))
|
|
||||||
{
|
|
||||||
dispatchNid = KernelDynlibDlsymAerolibNid;
|
|
||||||
_ = _moduleManager.TryGetExport(dispatchNid, out export);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasAerolibSymbol)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HleDataSymbols.TryGetAddress(hleSymbol.Nid, out _))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_moduleManager.TryGetExport(hleSymbol.Nid, out export))
|
|
||||||
{
|
|
||||||
dispatchNid = hleSymbol.Nid;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool TryGetOrCreateLazyImportStub(
|
|
||||||
string dispatchNid,
|
|
||||||
string symbolName,
|
|
||||||
SysAbiSymbol? hleSymbol,
|
|
||||||
ExportedFunction? export,
|
|
||||||
out ulong guestAddress)
|
|
||||||
{
|
|
||||||
guestAddress = 0;
|
|
||||||
if (string.IsNullOrWhiteSpace(dispatchNid))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lazyDlsymStubGate)
|
|
||||||
{
|
|
||||||
if (TryGetCachedLazyDlsymAddress(dispatchNid, symbolName, out guestAddress))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!EnsureLazyImportStubPoolMapped())
|
|
||||||
{
|
|
||||||
LogLazyImportStubMaterializationFailure(
|
|
||||||
"import stub region unresolved",
|
|
||||||
dispatchNid,
|
|
||||||
symbolName);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!TryAllocateLazyImportStubSlot(out guestAddress))
|
|
||||||
{
|
|
||||||
LogLazyImportStubMaterializationFailure(
|
|
||||||
"lazy import stub pool exhausted",
|
|
||||||
dispatchNid,
|
|
||||||
symbolName);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var previousEntries = _importEntries;
|
|
||||||
var importIndex = previousEntries.Length;
|
|
||||||
var newEntries = new ImportStubEntry[importIndex + 1];
|
|
||||||
if (importIndex > 0)
|
|
||||||
{
|
|
||||||
Array.Copy(previousEntries, newEntries, importIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
newEntries[importIndex] = new ImportStubEntry(guestAddress, dispatchNid, export);
|
|
||||||
|
|
||||||
var hostTrampoline = CreateImportHandlerTrampoline(importIndex);
|
|
||||||
if (hostTrampoline == 0 ||
|
|
||||||
!PatchImportStub((nint)(long)guestAddress, hostTrampoline))
|
|
||||||
{
|
|
||||||
guestAddress = 0;
|
|
||||||
LogLazyImportStubMaterializationFailure(
|
|
||||||
"failed to patch lazy import stub trampoline",
|
|
||||||
dispatchNid,
|
|
||||||
symbolName);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_importEntries = newEntries;
|
|
||||||
|
|
||||||
RegisterDlsymRuntimeSymbolKeys(symbolName, dispatchNid, hleSymbol, guestAddress);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool TryGetCachedLazyDlsymAddress(string dispatchNid, string symbolName, out ulong guestAddress)
|
|
||||||
{
|
|
||||||
if (_lazyDlsymStubCache.TryGetValue(dispatchNid, out guestAddress) ||
|
|
||||||
_lazyDlsymStubCache.TryGetValue(symbolName, out guestAddress))
|
|
||||||
{
|
|
||||||
return guestAddress >= 0x10000;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RegisterDlsymRuntimeSymbolKeys(
|
|
||||||
string symbolName,
|
|
||||||
string dispatchNid,
|
|
||||||
SysAbiSymbol? hleSymbol,
|
|
||||||
ulong guestAddress)
|
|
||||||
{
|
|
||||||
RegisterDlsymRuntimeSymbolKey(symbolName, guestAddress);
|
|
||||||
RegisterDlsymRuntimeSymbolKey(dispatchNid, guestAddress);
|
|
||||||
|
|
||||||
if (IsKernelDynlibDlsymIdentifier(symbolName) || IsKernelDynlibDlsymIdentifier(dispatchNid))
|
|
||||||
{
|
|
||||||
RegisterDlsymRuntimeSymbolKey(RuntimeStubNids.KernelDynlibDlsym, guestAddress);
|
|
||||||
RegisterDlsymRuntimeSymbolKey(KernelDynlibDlsymAerolibNid, guestAddress);
|
|
||||||
RegisterDlsymRuntimeSymbolKey("sceKernelDlsym", guestAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hleSymbol.HasValue)
|
|
||||||
{
|
|
||||||
RegisterDlsymRuntimeSymbolKey(hleSymbol.Value.Nid, guestAddress);
|
|
||||||
RegisterDlsymRuntimeSymbolKey(hleSymbol.Value.ExportName, guestAddress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RegisterDlsymRuntimeSymbolKey(string key, ulong guestAddress)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(key) || !IsRuntimeSymbolAddressUsable(guestAddress))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_runtimeSymbolsByName[key] = guestAddress;
|
|
||||||
_lazyDlsymStubCache[key] = guestAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LogLazyImportStubMaterializationFailure(string reason, string dispatchNid, string symbolName)
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine(
|
|
||||||
$"[LOADER][WARN] Lazy import stub materialization failed ({reason}): " +
|
|
||||||
$"nid={dispatchNid} symbol='{symbolName}'");
|
|
||||||
}
|
|
||||||
|
|
||||||
private unsafe bool TryResolveImportStubRegionBounds(
|
|
||||||
ImportStubEntry[] importEntries,
|
|
||||||
out ulong regionBase,
|
|
||||||
out ulong regionLimit)
|
|
||||||
{
|
|
||||||
regionBase = 0;
|
|
||||||
regionLimit = 0;
|
|
||||||
|
|
||||||
for (var candidateIndex = 0; candidateIndex < 64; candidateIndex++)
|
|
||||||
{
|
|
||||||
var candidateBase = ImportStubRegionCanonicalBase -
|
|
||||||
(ulong)candidateIndex * ImportStubRegionAddressStride;
|
|
||||||
if (VirtualQuery((void*)candidateBase, out var memoryInfo, (nuint)sizeof(MEMORY_BASIC_INFORMATION64)) == 0 ||
|
|
||||||
memoryInfo.RegionSize == 0 ||
|
|
||||||
memoryInfo.State != 4096)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var candidateLimit = candidateBase + memoryInfo.RegionSize;
|
|
||||||
var hasStub = false;
|
|
||||||
for (var i = 0; i < importEntries.Length; i++)
|
|
||||||
{
|
|
||||||
var entryAddress = importEntries[i].Address;
|
|
||||||
if (entryAddress < candidateBase || entryAddress >= candidateLimit)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((entryAddress - candidateBase) % LazyImportStubSlotSize != 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
hasStub = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasStub)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
regionBase = candidateBase;
|
|
||||||
regionLimit = candidateLimit;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ulong maxStubEnd = 0;
|
|
||||||
for (var i = 0; i < importEntries.Length; i++)
|
|
||||||
{
|
|
||||||
var entryAddress = importEntries[i].Address;
|
|
||||||
if (entryAddress < ImportStubRegionCanonicalBase)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((entryAddress - ImportStubRegionCanonicalBase) % LazyImportStubSlotSize != 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var entryEnd = entryAddress + LazyImportStubSlotSize;
|
|
||||||
if (entryEnd > maxStubEnd)
|
|
||||||
{
|
|
||||||
maxStubEnd = entryEnd;
|
|
||||||
regionBase = ImportStubRegionCanonicalBase;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (regionBase == 0 || maxStubEnd <= regionBase)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var spanBytes = maxStubEnd - regionBase;
|
|
||||||
regionLimit = regionBase + AlignUp(spanBytes, ImportStubRegionPageSize);
|
|
||||||
return regionLimit > regionBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool EnsureLazyImportStubPoolMapped()
|
|
||||||
{
|
|
||||||
if (_lazyImportStubPoolMapped && _lazyImportStubPoolBase != 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var importEntries = _importEntries;
|
|
||||||
if (!TryResolveImportStubRegionBounds(importEntries, out var importStubRegionBase, out var importStubRegionLimit))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ulong nextSlot = importStubRegionBase;
|
|
||||||
for (var i = 0; i < importEntries.Length; i++)
|
|
||||||
{
|
|
||||||
var entryAddress = importEntries[i].Address;
|
|
||||||
if (entryAddress < importStubRegionBase || entryAddress >= importStubRegionLimit)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var entryEnd = entryAddress + LazyImportStubSlotSize;
|
|
||||||
if (entryEnd > nextSlot)
|
|
||||||
{
|
|
||||||
nextSlot = entryEnd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextSlot >= importStubRegionLimit)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_lazyImportStubPoolBase = importStubRegionBase;
|
|
||||||
_lazyImportStubNextSlot = nextSlot;
|
|
||||||
_lazyImportStubPoolLimit = importStubRegionLimit;
|
|
||||||
_lazyImportStubPoolMapped = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool TryAllocateLazyImportStubSlot(out ulong guestAddress)
|
|
||||||
{
|
|
||||||
guestAddress = 0;
|
|
||||||
if (!_lazyImportStubPoolMapped ||
|
|
||||||
_lazyImportStubNextSlot < _lazyImportStubPoolBase ||
|
|
||||||
_lazyImportStubNextSlot + LazyImportStubSlotSize > _lazyImportStubPoolLimit)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
guestAddress = _lazyImportStubNextSlot;
|
|
||||||
_lazyImportStubNextSlot += LazyImportStubSlotSize;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool TryResolveRuntimeSymbolAlias(string symbolName, out ulong address)
|
private bool TryResolveRuntimeSymbolAlias(string symbolName, out ulong address)
|
||||||
{
|
{
|
||||||
address = 0;
|
address = 0;
|
||||||
@@ -1861,20 +1399,29 @@ public sealed partial class DirectExecutionBackend
|
|||||||
return OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;
|
return OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ulong bridgeHandle = cpuContext[CpuRegister.Rdi];
|
||||||
|
ulong symbolNameAddress = cpuContext[CpuRegister.Rsi];
|
||||||
ulong outputAddress = cpuContext[CpuRegister.Rdx];
|
ulong outputAddress = cpuContext[CpuRegister.Rdx];
|
||||||
try
|
_ = TryReadAsciiZ(symbolNameAddress, 512, out var symbolName);
|
||||||
|
|
||||||
|
OrbisGen2Result result = DispatchKernelDynlibDlsym();
|
||||||
|
if (result != OrbisGen2Result.ORBIS_GEN2_OK)
|
||||||
{
|
{
|
||||||
OrbisGen2Result result = DispatchKernelDynlibDlsym();
|
return result;
|
||||||
if (result != OrbisGen2Result.ORBIS_GEN2_OK)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch
|
if (_logBootstrap)
|
||||||
{
|
{
|
||||||
return CompleteKernelDynlibDlsymFailure(cpuContext, outputAddress);
|
Console.Error.WriteLine(
|
||||||
|
$"[LOADER][TRACE] bootstrap_dispatch: handle=0x{bridgeHandle:X16} symbol='{symbolName}' out=0x{outputAddress:X16} rax=0x{cpuContext[CpuRegister.Rax]:X16}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cpuContext[CpuRegister.Rax] == 0uL)
|
||||||
|
{
|
||||||
|
return OrbisGen2Result.ORBIS_GEN2_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.Error.WriteLine(
|
||||||
|
$"[LOADER][WARN] bootstrap_bridge unresolved: handle=0x{bridgeHandle:X} symbol='{symbolName}' out=0x{outputAddress:X16}");
|
||||||
return OrbisGen2Result.ORBIS_GEN2_OK;
|
return OrbisGen2Result.ORBIS_GEN2_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1915,7 +1462,6 @@ public sealed partial class DirectExecutionBackend
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<byte> list = new List<byte>(Math.Min(maxLength, 256));
|
List<byte> list = new List<byte>(Math.Min(maxLength, 256));
|
||||||
Span<byte> destination = stackalloc byte[1];
|
Span<byte> destination = stackalloc byte[1];
|
||||||
for (int i = 0; i < maxLength; i++)
|
for (int i = 0; i < maxLength; i++)
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -49,13 +48,6 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
|
|||||||
ulong Arg1,
|
ulong Arg1,
|
||||||
ulong Arg2);
|
ulong Arg2);
|
||||||
|
|
||||||
private readonly record struct DeferredBootstrapTraceEntry(
|
|
||||||
long DispatchIndex,
|
|
||||||
ulong Op,
|
|
||||||
ulong SymbolPointer,
|
|
||||||
ulong OutputPointer,
|
|
||||||
ulong ReturnRip);
|
|
||||||
|
|
||||||
#pragma warning disable CS0649
|
#pragma warning disable CS0649
|
||||||
private struct EXCEPTION_POINTERS
|
private struct EXCEPTION_POINTERS
|
||||||
{
|
{
|
||||||
@@ -240,31 +232,7 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
|
|||||||
|
|
||||||
private KeyValuePair<string, ulong>[] _runtimeSymbolsByAddress = Array.Empty<KeyValuePair<string, ulong>>();
|
private KeyValuePair<string, ulong>[] _runtimeSymbolsByAddress = Array.Empty<KeyValuePair<string, ulong>>();
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<string, ulong> _runtimeSymbolsByName =
|
private readonly Dictionary<string, ulong> _runtimeSymbolsByName = new Dictionary<string, ulong>(StringComparer.Ordinal);
|
||||||
new(StringComparer.Ordinal);
|
|
||||||
|
|
||||||
// Keep in sync with SelfLoader import-stub mapping constants.
|
|
||||||
private const ulong ImportStubRegionCanonicalBase = 0x0000_7000_0000_0000UL;
|
|
||||||
|
|
||||||
private const ulong ImportStubRegionAddressStride = 0x0000_0000_0100_0000UL;
|
|
||||||
|
|
||||||
private const ulong LazyImportStubSlotSize = 0x10;
|
|
||||||
|
|
||||||
private const ulong ImportStubRegionPageSize = 0x1000UL;
|
|
||||||
|
|
||||||
private const string KernelDynlibDlsymAerolibNid = "LwG8g3niqwA";
|
|
||||||
|
|
||||||
private readonly object _lazyDlsymStubGate = new();
|
|
||||||
|
|
||||||
private readonly Dictionary<string, ulong> _lazyDlsymStubCache = new(StringComparer.Ordinal);
|
|
||||||
|
|
||||||
private ulong _lazyImportStubPoolBase;
|
|
||||||
|
|
||||||
private ulong _lazyImportStubNextSlot;
|
|
||||||
|
|
||||||
private ulong _lazyImportStubPoolLimit;
|
|
||||||
|
|
||||||
private bool _lazyImportStubPoolMapped;
|
|
||||||
|
|
||||||
private readonly RecentImportTraceEntry[] _recentImportTrace = new RecentImportTraceEntry[64];
|
private readonly RecentImportTraceEntry[] _recentImportTrace = new RecentImportTraceEntry[64];
|
||||||
|
|
||||||
@@ -272,14 +240,6 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
|
|||||||
|
|
||||||
private int _recentImportTraceWriteIndex;
|
private int _recentImportTraceWriteIndex;
|
||||||
|
|
||||||
private readonly DeferredBootstrapTraceEntry[] _deferredBootstrapTrace = new DeferredBootstrapTraceEntry[32];
|
|
||||||
|
|
||||||
private int _deferredBootstrapTraceCount;
|
|
||||||
|
|
||||||
private int _deferredBootstrapTraceWriteIndex;
|
|
||||||
|
|
||||||
private readonly object _deferredBootstrapTraceGate = new();
|
|
||||||
|
|
||||||
private readonly string[] _distinctImportNidHistory = new string[128];
|
private readonly string[] _distinctImportNidHistory = new string[128];
|
||||||
|
|
||||||
private int _distinctImportNidHistoryCount;
|
private int _distinctImportNidHistoryCount;
|
||||||
@@ -895,14 +855,8 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
|
|||||||
result = OrbisGen2Result.ORBIS_GEN2_OK;
|
result = OrbisGen2Result.ORBIS_GEN2_OK;
|
||||||
LastError = null;
|
LastError = null;
|
||||||
InitializeRuntimeSymbolIndex(runtimeSymbols);
|
InitializeRuntimeSymbolIndex(runtimeSymbols);
|
||||||
ResetLazyDlsymStubState();
|
|
||||||
_recentImportTraceCount = 0;
|
_recentImportTraceCount = 0;
|
||||||
_recentImportTraceWriteIndex = 0;
|
_recentImportTraceWriteIndex = 0;
|
||||||
lock (_deferredBootstrapTraceGate)
|
|
||||||
{
|
|
||||||
_deferredBootstrapTraceCount = 0;
|
|
||||||
_deferredBootstrapTraceWriteIndex = 0;
|
|
||||||
}
|
|
||||||
_distinctImportNidHistoryCount = 0;
|
_distinctImportNidHistoryCount = 0;
|
||||||
_distinctImportNidHistoryWriteIndex = 0;
|
_distinctImportNidHistoryWriteIndex = 0;
|
||||||
_lastDistinctImportNid = string.Empty;
|
_lastDistinctImportNid = string.Empty;
|
||||||
@@ -976,7 +930,6 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
DrainDeferredBootstrapTraces();
|
|
||||||
GuestThreadExecution.Scheduler = previousGuestThreadScheduler;
|
GuestThreadExecution.Scheduler = previousGuestThreadScheduler;
|
||||||
Console.Error.WriteLine("[LOADER][INFO] === Execute END (LastError: " + (LastError ?? "null") + ") ===");
|
Console.Error.WriteLine("[LOADER][INFO] === Execute END (LastError: " + (LastError ?? "null") + ") ===");
|
||||||
}
|
}
|
||||||
@@ -4503,14 +4456,13 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
|
|||||||
ulong rsp = cpuContext[CpuRegister.Rsp];
|
ulong rsp = cpuContext[CpuRegister.Rsp];
|
||||||
Console.Error.WriteLine($"[LOADER][ERROR] Stall snapshot: rip=0x{cpuContext.Rip:X16} rsp=0x{rsp:X16} rbp=0x{cpuContext[CpuRegister.Rbp]:X16} rax=0x{cpuContext[CpuRegister.Rax]:X16} rbx=0x{cpuContext[CpuRegister.Rbx]:X16} rcx=0x{cpuContext[CpuRegister.Rcx]:X16} rdx=0x{cpuContext[CpuRegister.Rdx]:X16} rsi=0x{cpuContext[CpuRegister.Rsi]:X16} rdi=0x{cpuContext[CpuRegister.Rdi]:X16}");
|
Console.Error.WriteLine($"[LOADER][ERROR] Stall snapshot: rip=0x{cpuContext.Rip:X16} rsp=0x{rsp:X16} rbp=0x{cpuContext[CpuRegister.Rbp]:X16} rax=0x{cpuContext[CpuRegister.Rax]:X16} rbx=0x{cpuContext[CpuRegister.Rbx]:X16} rcx=0x{cpuContext[CpuRegister.Rcx]:X16} rdx=0x{cpuContext[CpuRegister.Rdx]:X16} rsi=0x{cpuContext[CpuRegister.Rsi]:X16} rdi=0x{cpuContext[CpuRegister.Rdi]:X16}");
|
||||||
ulong num = cpuContext.Rip & 0xFFFFFFFFFFFFFFF0uL;
|
ulong num = cpuContext.Rip & 0xFFFFFFFFFFFFFFF0uL;
|
||||||
var importEntries = _importEntries;
|
for (int i = 0; i < _importEntries.Length; i++)
|
||||||
for (int i = 0; i < importEntries.Length; i++)
|
|
||||||
{
|
{
|
||||||
if (importEntries[i].Address != num)
|
if (_importEntries[i].Address != num)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
string text = importEntries[i].Nid;
|
string text = _importEntries[i].Nid;
|
||||||
if (_moduleManager.TryGetExport(text, out ExportedFunction export))
|
if (_moduleManager.TryGetExport(text, out ExportedFunction export))
|
||||||
{
|
{
|
||||||
Console.Error.WriteLine($"[LOADER][ERROR] Stall import-stub: rip=0x{num:X16} nid={text} -> {export.LibraryName}:{export.Name}");
|
Console.Error.WriteLine($"[LOADER][ERROR] Stall import-stub: rip=0x{num:X16} nid={text} -> {export.LibraryName}:{export.Name}");
|
||||||
@@ -4701,7 +4653,6 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
|
|||||||
ClearImportHandlerTrampolines();
|
ClearImportHandlerTrampolines();
|
||||||
_importEntries = Array.Empty<ImportStubEntry>();
|
_importEntries = Array.Empty<ImportStubEntry>();
|
||||||
_runtimeSymbolsByName.Clear();
|
_runtimeSymbolsByName.Clear();
|
||||||
ResetLazyDlsymStubState();
|
|
||||||
_importNidHashCache.Clear();
|
_importNidHashCache.Clear();
|
||||||
StopStallWatchdog();
|
StopStallWatchdog();
|
||||||
if (_exceptionHandler != 0)
|
if (_exceptionHandler != 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user