mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-25 20:28:48 +08:00
* [Core/Dlsym] Restore normalize-dlsym-arguments and deferred bootstrap tracing from PR #94 PR #216 regressed two critical features from PR #94: 1. NormalizeKernelDynlibDlsymArguments — handles argument reordering when standalone bootstrap loaders call sceKernelDlsym through the bridge with (symbol_ptr, handle, out) instead of the standard (handle, symbol_ptr, out). Without this, payloads like elfldr-ps5 and websrv-ps5 fail with a deterministic UnmanagedCallersOnly fail-fast. 2. Deferred bootstrap tracing — ring-buffered import logging that drains after the hot path, avoiding per-call Console.Error I/O. Also restored: - CompleteKernelDynlibDlsymFailure — centralized error handling - IsPlausibleDynlibSymbolPointer — pointer bounds validation - COW snapshot of _importEntries in ProbeReturnRip - ResetLazyDlsymStubState and lazy-dlsym field infrastructure - DraftDrainDeferredBootstrapTraces in Execute() finally block Fixes #530, fixes #531 * fix: remove orphaned _importNidHashCache.Clear() reference The field _importNidHashCache no longer exists on main (removed post PR #94). The 3-way merge incorrectly restored the .Clear() call without the field declaration, causing a build failure on all platforms. --------- Co-authored-by: tru3 <tru3@tru3.com>
This commit is contained in:
@@ -91,6 +91,71 @@ 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()
|
||||||
{
|
{
|
||||||
var trace = _recentImportTrace;
|
var trace = _recentImportTrace;
|
||||||
@@ -268,14 +333,15 @@ 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}");
|
||||||
for (int importIndex = 0; importIndex < _importEntries.Length; importIndex++)
|
var importEntries = _importEntries;
|
||||||
|
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(
|
||||||
@@ -302,14 +368,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(
|
||||||
|
|||||||
@@ -2024,38 +2024,96 @@ public sealed partial class DirectExecutionBackend
|
|||||||
{
|
{
|
||||||
return OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;
|
return OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
ulong symbolNameAddress = cpuContext[CpuRegister.Rsi];
|
|
||||||
ulong outputAddress = cpuContext[CpuRegister.Rdx];
|
NormalizeKernelDynlibDlsymArguments(cpuContext, out var symbolNameAddress, out var outputAddress);
|
||||||
if (!TryReadAsciiZ(symbolNameAddress, 512, out var symbolName))
|
try
|
||||||
{
|
{
|
||||||
cpuContext[CpuRegister.Rax] = 18446744073709551615uL;
|
if (!TryReadAsciiZ(symbolNameAddress, 512, out var symbolName))
|
||||||
return OrbisGen2Result.ORBIS_GEN2_OK;
|
{
|
||||||
|
return CompleteKernelDynlibDlsymFailure(cpuContext, outputAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
var moduleHandle = unchecked((int)cpuContext[CpuRegister.Rdi]);
|
||||||
|
if (!TryResolveModuleSymbolAddress(moduleHandle, symbolName, out var resolvedAddress) &&
|
||||||
|
!TryResolveRuntimeSymbolAddress(symbolName, out resolvedAddress) &&
|
||||||
|
!TryResolveRuntimeSymbolAddress(ComputePsNid(symbolName), out resolvedAddress) &&
|
||||||
|
!TryResolveRuntimeSymbolAlias(symbolName, out resolvedAddress))
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine(
|
||||||
|
$"[LOADER][WARN] sceKernelDlsym failed: handle=0x{cpuContext[CpuRegister.Rdi]:X} symbol='{symbolName}'");
|
||||||
|
return CompleteKernelDynlibDlsymFailure(cpuContext, outputAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_DLSYM"), "1", StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine(
|
||||||
|
$"[LOADER][TRACE] sceKernelDlsym: handle=0x{moduleHandle:X} symbol='{symbolName}' -> 0x{resolvedAddress:X16}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outputAddress == 0L || !TryWriteUInt64Compat(outputAddress, resolvedAddress))
|
||||||
|
{
|
||||||
|
return CompleteKernelDynlibDlsymFailure(cpuContext, outputAddress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var moduleHandle = unchecked((int)cpuContext[CpuRegister.Rdi]);
|
catch
|
||||||
if (!TryResolveModuleSymbolAddress(moduleHandle, symbolName, out var resolvedAddress) &&
|
|
||||||
!TryResolveRuntimeSymbolAddress(symbolName, out resolvedAddress) &&
|
|
||||||
!TryResolveRuntimeSymbolAddress(ComputePsNid(symbolName), out resolvedAddress) &&
|
|
||||||
!TryResolveRuntimeSymbolAlias(symbolName, out resolvedAddress))
|
|
||||||
{
|
{
|
||||||
Console.Error.WriteLine(
|
return CompleteKernelDynlibDlsymFailure(cpuContext, outputAddress);
|
||||||
$"[LOADER][WARN] sceKernelDlsym failed: handle=0x{cpuContext[CpuRegister.Rdi]:X} symbol='{symbolName}'");
|
|
||||||
cpuContext[CpuRegister.Rax] = 18446744073709551615uL;
|
|
||||||
return OrbisGen2Result.ORBIS_GEN2_OK;
|
|
||||||
}
|
|
||||||
if (string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_DLSYM"), "1", StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine(
|
|
||||||
$"[LOADER][TRACE] sceKernelDlsym: handle=0x{moduleHandle:X} symbol='{symbolName}' -> 0x{resolvedAddress:X16}");
|
|
||||||
}
|
|
||||||
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 static bool TryResolveModuleSymbolAddress(int moduleHandle, string symbolName, out ulong address)
|
private static bool TryResolveModuleSymbolAddress(int moduleHandle, string symbolName, out ulong address)
|
||||||
{
|
{
|
||||||
if (KernelModuleRegistry.TryResolveModuleSymbol(moduleHandle, symbolName, out address))
|
if (KernelModuleRegistry.TryResolveModuleSymbol(moduleHandle, symbolName, out address))
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers.Binary;
|
using System.Buffers.Binary;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -88,6 +89,13 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
|
|||||||
ulong GuestThreadHandle,
|
ulong GuestThreadHandle,
|
||||||
int ManagedThreadId);
|
int ManagedThreadId);
|
||||||
|
|
||||||
|
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
|
||||||
{
|
{
|
||||||
@@ -303,7 +311,31 @@ 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 Dictionary<string, ulong> _runtimeSymbolsByName = new Dictionary<string, ulong>(StringComparer.Ordinal);
|
private readonly ConcurrentDictionary<string, ulong> _runtimeSymbolsByName =
|
||||||
|
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];
|
||||||
|
|
||||||
@@ -311,6 +343,14 @@ 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;
|
||||||
@@ -1140,8 +1180,14 @@ 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;
|
||||||
@@ -1224,6 +1270,7 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
|
|||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
HostSessionControl.SetShutdownHandler(null);
|
HostSessionControl.SetShutdownHandler(null);
|
||||||
|
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") + ") ===");
|
||||||
}
|
}
|
||||||
@@ -6680,13 +6727,14 @@ 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;
|
||||||
for (int i = 0; i < _importEntries.Length; i++)
|
var importEntries = _importEntries;
|
||||||
|
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}");
|
||||||
@@ -6979,6 +7027,7 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
|
|||||||
_importEntries = Array.Empty<ImportStubEntry>();
|
_importEntries = Array.Empty<ImportStubEntry>();
|
||||||
_runtimeSymbolsByName.Clear();
|
_runtimeSymbolsByName.Clear();
|
||||||
StopReadyThreadDispatcher();
|
StopReadyThreadDispatcher();
|
||||||
|
ResetLazyDlsymStubState();
|
||||||
StopStallWatchdog();
|
StopStallWatchdog();
|
||||||
if (_exceptionHandler != 0)
|
if (_exceptionHandler != 0)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user