On Windows the UCRT does not switch an r+, w+ or a+ stream from writing
to reading without fflush or fseek: fread after fwrite returned bytes of
the write buffer and the next flush wrote them over the file, and ungetc
failed on an update stream that was not already reading. On Linux glibc
does not switch either for ungetc, which pushes the byte back over the
pending write, drops the write and can corrupt the heap on the next read,
or for an fread of at least the buffer size, which drops the write and
reads from the old offset.
fread, fgetc, getc_unlocked, fgets, ungetc, ungetwc and fscanf now flush
pending output and mark the stream as reading first, as FreeBSD 11.4's
__srefill and __ungetc do, through _IO_switch_to_get_mode on glibc.
Writes directly after reads still go through the UCRT on Windows; the
gap is recorded in the libc technical debt.
A guest wave's lanes see each other's LDS writes without a barrier, so
the recompiler adds a subgroup-scope OpControlBarrier between an LDS
write and the next LDS access when the guest wave is one host subgroup
(WaveLdsScope). AMD's proprietary Windows driver 32.0.21042.62 (Vulkan
driver 2.0.353, "AMD proprietary shader compiler", Radeon 0x13c0)
compiles that barrier to s_barrier, as the pipeline's internal ISA
shows (26 s_barrier for the guest's 9 in a small LDS reduction). In a
workgroup of several waves, the waves that enter a branch holding LDS
accesses then execute extra s_barriers, which pair with the other
waves' barriers, and those waves read LDS before it is written. LLPC
compiles a subgroup-scope control barrier to a wave barrier instead.
PS5LM Plus (PPSA99581) answered with garbage on that driver: the first
compute dispatch of its first graph, an RMS norm with a 512-thread
wave32 LDS tree reduction, scaled every row except its first 32
elements by a partial sum, while NVIDIA matched a NumPy reference and
the inputs were identical.
On that driver the barrier is now a subgroup-scope OpMemoryBarrier,
which it compiles to no instruction. A 32-lane subgroup is one hardware
wave there, which runs its lanes in lockstep and issues its LDS
instructions in order; Vulkan does not guarantee that, so it is
recorded as debt. Other drivers keep the control barrier. The flag is
part of the shader cache key, and agc_shader_replay takes
--wave-lds-memory-barriers to replay a request the way that driver
compiles it.
agc_driver_lds_tree_reduction sums over eight wave32 waves the way the
guest does, with its last four steps inside one wave and no s_barrier
between them: before, thread 32 read 1936 instead of 32896 on the AMD
driver; it passes on AMD and NVIDIA now. agc_subgroup_barrier checks
the driver quirk and the emitted barriers on every runner. PS5LM Plus
now answers " Paris. It is the largest city in Europe ..." on the AMD
iGPU without flash attention, as on NVIDIA and the CPU.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
lstat and readlink threw NotImplemented for every Windows reparse point
other than a symbolic link or a drive junction. A tag without the name
surrogate bit (cloud files, deduplication) does not stand for another path,
so lstat now answers as stat does and readlink returns EINVAL, as FreeBSD
does for a file that is not a link and as CPython's os.lstat and os.readlink
do (bpo-37834). A name surrogate that is neither a symbolic link nor a
junction (a mounted volume, a WSL link) is reported as the reparse point
itself with the mode of its attributes, and readlink returns EINVAL.
The tests set reparse tags with FSCTL_SET_REPARSE_POINT, one without the
name surrogate bit and one with it. A compact /exe (WOF) file cannot serve
as the fixture: on Windows 11 24H2 the WOF filter hides the reparse point
from GetFileAttributesW and FileAttributeTagInfo alike. Windows refuses
every open of an unhandled tag without FILE_FLAG_OPEN_REPARSE_POINT, so the
test requires lstat to agree with stat rather than to succeed.
mashingaan's boykopovar/AnyPS5#6447 returned EINVAL for other reparse
points without the tag check.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Fable 5.1 <[email protected]>
When the graph is built without the wave size and the return address
escapes under only one of wave32 and wave64, the graph records that size
and its error instead of throwing, and translation throws it only at
that size. A wave64 program that reads a compare mask written over a
call's link pair from a scalar instruction is now recompiled, while the
same program at wave32, where the high dword still holds the return
address, is refused.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The raw-byte check that runs before a syscall pattern between PS4 unwind
functions is skipped now also accepts mov rax, imm64, merges a following
mov al, imm8 or mov ax, imm16 into the earlier constant, and walks back
over any number of register moves or zeroings that leave rax alone
instead of at most seven. Visited states keep the walk linear in the
bytes it covers.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A voice callback runs during its system's render. A rack or system
destroyed from that callback was freed while the render still walked
it, which corrupted the heap. sceNgs2RackDestroy and
sceNgs2SystemDestroy now throw when the calling thread is rendering
that system; the console's behaviour there is not measured.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Say that 0x80bc0002 is this library's sceImeDialogTerm result rather
than a SharpProspero claim, and that the exports still throwing are
declared with shadPS4's parameters except sceImeDialogForTestFunction.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Arbzg9c2DA4DEFKVSvRgYv
A registered type-3 hull program holds the local and the hull part of a
tessellation draw in one binary, addressed through SPI_SHADER_PGM_LO_LS
(SH 0x148) with no SPI_SHADER_PGM_LO_HS: the local part runs on the lanes
below s3[7:0] and writes LDS, an s_barrier follows, and the hull part runs
on the lanes below s3[15:8] and may store the registers the local part
filled. The draw decode asked 0x148 for a type-5 local half, and
PPSA11386 (007 First Light) stopped in its level load with "registered
program refers to an incompatible shader binary type".
The draw decode now gives a registered type-3 program both the local and
the hull role and marks the tessellation configuration mergedHull. The
local stage only passes gl_VertexIndex and gl_InstanceIndex in a 16-byte
record. The hull stage runs the whole program, one invocation per output
control point: v2 and v5 come from the record of control point
min(gl_InvocationID, inputs - 1), v3 is the relative vertex id, and the
LDS becomes a per-control-point output array that a control point writes
in its own record and reads in any record of its patch after the barrier.
Registers live across the barrier stay in the invocation.
The hull stage of a merged program runs at one lane per invocation on
every device (HostSubgroupSize 1). Its lanes are gl_InvocationID, not host
subgroup invocations, so the s_cbranch_execz around the local part tests
the invocation's own lane. With the device's subgroup it took a subgroup
ballot, and lavapipe, whose subgroup stages lack the tessellation control
stage, rejected the draw ("subgroup capability 61 is unsupported for
shader stage 2").
The lowering refuses more input than output control points, LDS writes
outside the own record, reads outside the patch's records, barriers that
some invocations do not reach or that sit in a loop, reads or writes of
another lane's register, outputs beyond the device limits, and fetch
subroutines. Type 3 is prepared with its stage group like type 5 and
takes its float mode from RSRC1_HS. The hull user-data address (SH
0x102/0x103) is optional for a merged program: s[0:1] take it, unchecked,
when the draw sets it and are zero otherwise.
Both stages refer to one binary, so a draw lists each code and header
region once (AppendProgramMemory); a request's memory regions must not
overlap. An indirect draw's record words go into every program whose user
data holds the register, so the hull stage of a merged program reads
them too.
mergedHull is part of the recompile cache key, the draw decode comparison
and the request serialization (version 39).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
sceImeDialogForceClose threw. It now closes a running or finished
dialog the way sceImeDialogTerm does, without writing the typed text to
the title's buffer, and returns NOT_IN_USE (0x80bc0107) when no dialog
is open. The behaviour follows shadPS4 and the error code is the one
SharpProspero lists for PS5. The ImeDialog guest test covers each case.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Arbzg9c2DA4DEFKVSvRgYv
The hmd2s and hmd2n sweeps left 19 libSceHmd2 exports that either write
into their arguments or take a slot number rather than a pointer first.
A third probe called the writers with zero-filled and with 0xAA-filled
buffers, dumping every byte that changed, and the slot exports with a
first argument of 0, 1, 2, 3, 4, 5, 8, 16, 255 and -1. Before
sceHmd2Initialize, six writers put fixed bytes in their output (a 2 and
a zero byte; 0x2000 and 0x100 as 64-bit sizes; four floats; six or
twelve floats of 0 and 0.5 followed by 0x8a720003), and twelve exports
accept a slot of 0 to 1, 2 or 3 and answer 0x8a720009 above it, with
0, -1, 0x8a721002, 0x8a721003, 0x8a72002c or 0x8a72100f for a valid
slot. They are bound here, by NID, to 14 handlers with the measured
checks, returning their value while the library is not initialized and
throwing if sceHmd2Initialize ever succeeds.
The one export whose answer depends on the contents of an in-out
structure stays unimplemented and is described in the debt file.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
The hmd2s sweep left 81 libSceHmd2 exports that answer 0x8a720008 to
all-null arguments but something else to zeroed buffers. A second probe
called each of them six times before sceHmd2Initialize, every argument
pointing at a zeroed 16 KiB buffer except one, to find which arguments
are the checked pointers. 62 exports answer 0x8a720008 exactly when one
of a fixed set of arguments is null and their all-present code otherwise:
48 check the first argument, 10 the second, 6 the first two, 2 the first
and third, 2 all six. They are bound here, by NID, to 18 handlers with
that many pointer parameters, each returning ParameterNull for a null
checked pointer and otherwise the measured code (0x8a720004 for 20 of
them, 0 for 11, 0x8a721002 for 10, -1 for 5, 0x8a720009 for 7,
0x8a72002c for 3, and 0x8a720003, 0x8a721003, 0x8a721010 and 0x800d0203
for the rest) while the library is not initialized, throwing if
sceHmd2Initialize ever succeeds.
Left out: 7 exports that write output and 12 whose first argument is a
handle or slot number rather than a pointer. The debt entries list every
NID with its aerolib name where one exists.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
A sweep of the 281 libSceHmd2 exports on a PS5 (firmware 13.60), each
called from a payload before sceHmd2Initialize once with every argument
null and once with every argument pointing at a zeroed 16 KiB buffer,
found 127 that answer the same code both ways and write nothing. 125 of
them are bound here, by NID, to one handler per answer: 45 return 0, 16
return 0x8a720008, 15 return 0x8a720004, 12 return -1, 10 reprojection
exports return 0x8a72000b, 9 return 0x8a720002, 9 return 0x8a720009, 5
return 0x8a721002 and one each returns 0x8a72002c, 0x8a721003, 0x400 and
0x20000. Each handler returns its measured value while the library is not
initialized and throws if sceHmd2Initialize ever succeeds, because the
initialized behaviour is not measured; since b378541e79 it fails with
UnsupportedFeature here, so these are the answers titles get.
Left out: the export that returns a pointer-like value, the one answering
0x8a72000a (which sceHmd2Initialize also returns for some applications),
the exports that answer differently to null and to zeroed arguments or
write output, the 16 that crashed the probe, and the exports that main,
its aerolib name where one exists.
Co-Authored-By: Claude Fable 5.1 <[email protected]>