mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-31 06:59:45 +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:
@@ -2024,38 +2024,96 @@ public sealed partial class DirectExecutionBackend
|
||||
{
|
||||
return OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
ulong symbolNameAddress = cpuContext[CpuRegister.Rsi];
|
||||
ulong outputAddress = cpuContext[CpuRegister.Rdx];
|
||||
if (!TryReadAsciiZ(symbolNameAddress, 512, out var symbolName))
|
||||
|
||||
NormalizeKernelDynlibDlsymArguments(cpuContext, out var symbolNameAddress, out var outputAddress);
|
||||
try
|
||||
{
|
||||
cpuContext[CpuRegister.Rax] = 18446744073709551615uL;
|
||||
return OrbisGen2Result.ORBIS_GEN2_OK;
|
||||
if (!TryReadAsciiZ(symbolNameAddress, 512, out var symbolName))
|
||||
{
|
||||
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]);
|
||||
if (!TryResolveModuleSymbolAddress(moduleHandle, symbolName, out var resolvedAddress) &&
|
||||
!TryResolveRuntimeSymbolAddress(symbolName, out resolvedAddress) &&
|
||||
!TryResolveRuntimeSymbolAddress(ComputePsNid(symbolName), out resolvedAddress) &&
|
||||
!TryResolveRuntimeSymbolAlias(symbolName, out resolvedAddress))
|
||||
catch
|
||||
{
|
||||
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 (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;
|
||||
return CompleteKernelDynlibDlsymFailure(cpuContext, outputAddress);
|
||||
}
|
||||
|
||||
cpuContext[CpuRegister.Rax] = 0uL;
|
||||
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)
|
||||
{
|
||||
if (KernelModuleRegistry.TryResolveModuleSymbol(moduleHandle, symbolName, out address))
|
||||
|
||||
Reference in New Issue
Block a user