The title-module variants of sceKernelGetModuleList and
sceKernelGetModuleInfo, following shadPS4: the list leaves out system
libraries and the info call answers EPERM for one. A system library is
a loaded .prx image that is not a relinked title module.
NHL 27 (PPSA34063) imports both and fails to load without them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The kernel #2081 matches stores each pattern dword with
buffer_store_format_x, so what lands in memory depends on the output
descriptor's FORMAT (bits 12-18 of user[3]). Only 32_UINT, 32_SINT and
32_FLOAT (20-22) store the dword unchanged. Other formats convert it,
and an 8- or 16-bit one writes 1 or 2 bytes of every 4-byte element, so
a buffer fill would also overwrite the bytes in between. Such a dispatch
now goes to the recompiler.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
referencedIds() took every operand word of every instruction as a
possible id, so a literal that happened to equal the id of a dead folded
constant or an unreachable block kept it: the OpTypeInt width 32 kept a
dead constant %32, LocalSize literals kept dead labels.
Visit only the <id> operands of each instruction. Literal operands are
skipped for the instructions that carry them: type widths, counts and
image parameters, constant values, storage classes, memory access and
image operand masks (their trailing ids still count), composite and
shuffle indices, OpArrayLength members, extended instruction numbers,
entry point names, execution modes, merge and function controls, branch
weights, OpSwitch case values (two words for a 64-bit selector) and
group operations. An instruction without a listed layout still counts
every word, so an unknown instruction can only keep debris, never drop
something in use.
The SpirvModule case now also folds a switch whose dead constant has id
32 and whose dead blocks' ids appear as LocalSize literals; it fails
without this change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
qsort was a heapsort. It sorted correctly, but elements that compare
equal ended in a different order from FreeBSD's Bentley-McIlroy qsort,
in 18947 of 20000 random arrays with repeated keys, and below 7
elements, where FreeBSD's insertion sort keeps equal elements in
place, a heapsort does not. qsort now follows FreeBSD 11 qsort.c,
including its comparator call sequence.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZWLdTjf1S57iLgn2rcaFb
On Linux with write watching (uffd write-protect), the first import asks the device whether a GPU
write clears the protection (ProbeImportWriteProtection): it records a vkCmdCopyBuffer and a
vkCmdFillBuffer on the import and submits them. The test's mock device records no commands, so
agc_host_import_retire failed with "missing Vulkan function: vkCmdCopyBuffer" before it reached
the retire (RADV, reported on #4515). The test now sets APS5_WRITE_WATCH_IMPORTS=unwatch, so its
imports are compared as on Windows and the probe, which a mock cannot answer, does not run.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PS4 executables keep their relocated read-only data, GOT and init/fini
arrays in a PT_SCE_RELRO segment outside every PT_LOAD. The segment filter
dropped it, so Windows and macOS output stopped at the first relocation
into it, and Linux output placed the relinker's extra block over its
addresses without an error. The ELF reader now reports such a segment as a
read-write PT_LOAD. A PT_SCE_RELRO inside a PT_LOAD keeps being skipped,
and one that partially overlaps a PT_LOAD throws.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Windows GUI build started without standard handles has no descriptor 2.
_dup(2) then reached the invalid-parameter handler, which aborts, before the
"cannot keep the host standard error" error could be thrown. It now goes
through WithoutParameterHandler like the other descriptor calls in this file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Guest descriptors are host descriptors, so a guest that moves standard
error with dup2 also moves the stream sceKernelDebugOutText writes to. A
title that forwards its standard error to the kernel log through a pipe
then reads its own debug output back and logs it again without end. Before
the guest's first dup2 onto descriptor 2, the host's standard error is kept,
and sceKernelDebugOutText writes there.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
EmitBdaWrite, used for buffer stores through GPU-selected descriptors, recorded an
Unaligned fault and dropped every 32-bit store whose address is not 4-byte aligned.
EmitBdaStore and the BDA reads already take the byte path for unaligned addresses, and
raw buffer accesses use the exact bytes, as RDNA does in unaligned mode. The unaligned
case now stores the four bytes one by one like the 8- and 16-bit stores of the same
function.
Sword of the Sea hit this about once per frame from one compute store, so four bytes
were lost and a fault was reported each time.
The BDA store execution table now also runs through EmitBdaWrite; its unaligned dword
cases failed before this change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Windows unwinder stopped at the first frame of a module without the
project's .ehmeta or .ehfram tables, so an exception could not cross
libstdc++-6.dll and libwinpthread-1.dll (std::call_once through
pthread_once) or system DLLs. For such a frame it now looks up the
function's PE unwind data with RtlLookupFunctionEntry and takes the
caller's registers, including the nonvolatile rsi, rdi and xmm6-xmm15,
from RtlVirtualUnwind. A frame whose unwind data has an exception or
termination handler still stops the walk, since those handlers are not
run.
windows_exceptions gets back the std::call_once case of #1423.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>