Commit Graph
14017 Commits
Author SHA1 Message Date
Yunus Shaikh f29ee47366 refactor(libkernel): record a host stack protect's guarded part on its own line
The stack branch now records the reserve and guard below a protected
range with a separate RecordProtection call, and keeps the call that
records the protected range itself as main has it. The ranges recorded
are the same: RecordProtection replaces what it covers, so the two calls
together record the whole requested range, as before. #6184 adds a line
next to that call, and the two no longer touch.
2026-10-15 08:52:21 -07:00
Yunus Shaikh fa9ac37ce7 feat(libc): ask whether any part of a range is write-watched
GuestWriteWatchCovers says whether a range is watched in full. The
Linux and macOS watches unregister page ranges, so a range can hold
watched pages between unwatched ones, and code that must act on every
watched byte of a store has had no way to find them short of asking
page by page. GuestWriteWatchOverlaps answers with one lookup in the
registered ranges, like Covers.

The macOS write-watch test and agc_write_tracking on Linux check it
around watched pages between unwatched ones, at both edges and for an
empty range.
2026-10-15 08:51:39 -07:00
JJenkx f5c420641e refactor(agc): limit failed-window checks to rejected imports 2026-10-15 11:48:13 -04:00
JJenkx aee2fe3b0f fix(agc): retain failed import windows across unrelated mappings 2026-10-15 11:48:12 -04:00
Claude 76cc70c245 fix(agc): overestimate single-sample draws with centroid inputs
A draw with PA_SC_CONSERVATIVE_RASTERIZATION_CNTL 0x6001 and
SPI_PS_INPUT_ENA.PERSP_CENTROID or LINEAR_CENTROID threw in DecodeState,
whatever its rasterized sample count. With PA_SC_AA_CONFIG.MSAA_NUM_SAMPLES
0 the single rasterized sample is the pixel centre, which is where the
recompiler already puts the centroid barycentrics, so such a draw now
decodes to overestimation. More rasterized samples, and a single-sample
draw raised to a multisampled color target, still throw.

Extends agc_driver_graphics and records the inference in the driver's
technical debt.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01XJ3RTcWpqBBdVE8QRtKxJD
2026-10-15 15:47:02 +00:00
CapibaraandClaude Sonnet 5 66b0a6082e docs(libSceRegMgr): match house style for the unknown-function debt entry
The entry described the NID as sourced from the community firmware dump
alongside the signature, but nid_patcher derives the NID from the export
name itself; only the signature is unverified. Rewrite the entry to match
the house style used by libSceHttp2.md and libSceContentDelete.md: NID
inline, the importing title named, and a pinned link to the one external
source instead of an unlinked claim.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Vb2m1o8ZDHARkX6FTP9xuJ
2026-10-15 12:43:59 -03:00
Yunus Shaikh 7fc9e201df test(agc): check the stamps of a store into partly watched memory
A driver store and an own store across a watched block and an unwatched
one must stamp the watched block and no other. On Linux, a store across
the halves of a split block must stamp it, and a store into its unwatched
half alone must not.
2026-10-15 08:42:52 -07:00
Yunus Shaikh ae920cb206 fix(agc): stamp the watched blocks of a partly watched store
MarkWritten and StoreOwnBytes return 0 for a range that is not wholly
watched, and they stamped none of its blocks. The watched blocks such a
store wrote kept their old stamps, so UnchangedSince and StoredOver over
them still read as unchanged after a GPU write that crossed into an
unwatched import. A vouched shader table column or a cached range then
kept bytes that had been replaced.

Both now stamp each block whose part of the store starts or ends in
watched memory, as the wholly watched path stamps every block. They still
return 0 and note the store as unstamped. This costs one or two coverage
lookups per block, and only on this path.
2026-10-15 08:42:41 -07:00
MarcZX100 68311f5824 fix(agc): size sampled MSAA surface footprints 2026-10-15 15:42:03 +00:00
Adrià 0c4816f611 Merge pull request #5753 from Tiberon-Kuiper/fix/macos-empty-write-watch-ranges
fix(libc): ignore empty macOS write-watch ranges
2026-10-15 17:39:52 +02:00
Adrià ce998f9a2c Merge pull request #5747 from fisherjoey/fix/gate-capture-gpu-indirect
fix(agc): keep the gate run going past indirect dispatches whose arguments stay on the GPU
2026-10-15 17:39:46 +02:00
Adrià a85a8d9548 Merge pull request #5739 from fogydes/fix/rtc-year-timezone-bounds-and-local-clock
fix(libSceRtc): checked tick addition in local clock, test coverage for current clock
2026-10-15 17:39:41 +02:00
Yunus Shaikh 4b15b702eb refactor(agc): expose the guest read guard as GuestMemory::GuardRead
Read, ReadCommitted and ReadCommittedUnsynced each loaded the installed
read guard and called it inline. GuardRead does that once, so code that
reads guest memory without going through those functions can run the
same check. No behaviour change.
2026-10-15 08:35:39 -07:00
SandstromPLandClaude Opus 5.5 716d811861 feat(libSceDiscMap): report no disc bitmap from the two disc map queries
Until Dawn (CUSA02636) bundles a libSceFios2.prx that imports two
libSceDiscMap functions, sceDiscMapIsRequestOnHDD (lbQKqsERhtE) and
ioKMruft1ek, and no host library exported them.

Both now return SCE_DISC_MAP_ERROR_NO_BITMAP_INFO (0x81100004) and
write nothing, as shadPS4 and fpPS4 do. That is the error the console
library returns while it has no disc bitmap loaded.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 20:54:46 +05:30
Yossi Yadgar a7ef31e103 docs(debt): note how closed standard descriptors are reopened 2026-10-15 18:19:21 +03:00
Yossi Yadgar 7c4400e926 test(libc): start a guest process with its standard descriptors closed 2026-10-15 18:19:05 +03:00
Yossi Yadgar 2852249eb9 fix(libc): open closed standard descriptors on /dev/null when libc loads 2026-10-15 18:19:05 +03:00
Yossi Yadgar 6473318a6b docs(debt): note which descriptors each LoadExec path passes on Linux 2026-10-15 18:17:21 +03:00
Yossi Yadgar c9ae2c4191 test(libSceSystemService): check stderr after LoadExec on both exec paths
The re-executed image is told apart by an environment variable. With an argument list (fexecve) it sees argc 1 and the marker as argv[0]; with a null list (execv) it sees only its path.
2026-10-15 18:17:21 +03:00
Yossi Yadgar 45cb1f91a0 fix(libSceSystemService): give the host standard error back before LoadExec's fexecve
A LoadExec with an argument list replaces the process through Replace (fexecve), which runs before StartHostExecutable, so the next image still wrote to the title's redirect. Descriptor 2 now gets the kept host descriptor there too, after the shutdown and the flush and before close_range closes it.
2026-10-15 18:17:21 +03:00
Yossi Yadgar 0d9af44626 docs(debt): note which descriptors LoadExec passes on Linux 2026-10-15 18:13:12 +03:00
Yossi Yadgar 67f08d9f27 test(libSceSystemService): check stderr after LoadExec of a redirected title
A forked child with stderr on a pipe moves the guest's descriptor 2 to a
second pipe with dup2, then starts itself again through
sceSystemServiceLoadExec("/app0/eboot.bin"). What the new image writes
to stderr must reach the first pipe and nothing the second. It fails
with the previous execv, where the text goes to the guest's pipe.
2026-10-15 18:13:12 +03:00
Yossi Yadgar c28e0ac370 fix(libSceSystemService): give LoadExec's next executable the host standard error
A guest dup2 onto descriptor 2 keeps a close-on-exec duplicate of the
host's standard error (#4792), so the runtime's own output stays on the
console while the title's stderr goes where the title pointed it. The
duplicate did not survive LoadExec's execv, and the next executable
started with descriptor 2 still on the title's redirect: its runtime
output, terminate report included, went there.

RetroArch (PPSA99169) points stderr at app0/trace.txt and then starts
its picker. The picker's [gpu] and sceKernelDebugOutText lines landed
in trace.txt, and its abort on an unconverted es-de.bin showed up
nowhere; the message was found only in the core dump.

Before execv, the kept descriptor now goes back onto descriptor 2.
2026-10-15 18:13:12 +03:00
fma-rc 451f11eafe fix(libkernel): report a 256 GiB AMM range starting on a 64 GiB boundary 2026-10-15 17:12:57 +02:00
Yunus Shaikh 5796ddfcfd fix(libkernel): commit a protect at the bottom of a host stack's reserve
HotSpot makes its stack guard zones with an RW protect of the lowest
pages of the thread's stack, then PROT_NONE, as it commits them on
native Windows (os::pd_create_stack_guard_pages, then os::guard_memory).
Below a host stack's guard page such a protect was only recorded, so the
pages stayed reserved: they could not be written after the RW protect,
and the zones never held.

A protect of reserved pages that starts at the bottom of the reserve and
stops short of the guard page now commits and protects them. The guard
page and the reserve above the range stay as they are, so the stack still
grows through the guard down to it, and the stack limit in the TEB still
follows the committed stack.

Windows moves the guard down by committing the pages below it as
read/write guard pages, committed or not. The zones therefore hold until
the stack is within one guard region of them (three pages on GitHub's
runners), and the pages the guard reaches then come in read/write. The
test checks both, and the debt entry says so.
2026-10-15 08:10:42 -07:00
Yunus Shaikh 56ed31b334 test(libkernel): protect the bottom of a reserved host stack, then make it inaccessible
HotSpot makes its stack guard zones this way: an RW protect of the
lowest 48 KiB of the thread's stack, then PROT_NONE. Both calls succeed,
the guard page stays above them, and the stack still grows through it.
Every case now also checks that the stack limit in the TEB follows the
committed stack.
2026-10-15 08:10:42 -07:00
Yunus Shaikh 3724c577d8 fix(libkernel): keep a host stack's guard page and reserve when protecting it on Windows
Committing the reserved pages of a host thread's stack before protecting
it, as the stack branch did for a range the arena doesn't own, also
cleared the guard page's PAGE_GUARD. The thread was left with no guard
and no reserve: an overflow ran into whatever lay below the stack instead
of raising a stack overflow, and the stack limit in the thread's TEB,
which Windows moves only when the guard page is hit, stopped following
the stack. A range that began inside the reserve also left the reserved
pages below it with no guard above them, so the stack could no longer
grow into them.

The stack branch now leaves the guard page and the reserved pages below
it as they are, and commits and protects only what lies above them;
reserved pages above the guard are still committed first. The protection
is recorded for the whole range, and a range of only reserved and guard
pages changes nothing on the host. The test protects the main thread's
whole stack and a reserved thread's whole stack and upper part, then
checks that the guard page is still there and that the stack grows
through it, also after a PROT_NONE protect of its lowest page. The debt
file records that those pages come in read/write as the stack grows.
2026-10-15 08:10:42 -07:00
Yunus Shaikh 877320a5cd test(libkernel): protect the whole main-thread stack on Linux too
ProtectWholeStack also runs on the Linux main thread, whose reported
stack is mostly not mapped yet.
2026-10-15 08:10:42 -07:00
Yunus Shaikh b5909a5ee0 fix(libkernel): map the unmapped pages of a host stack before protecting it on Linux
On Linux the guest's main runs on the host main thread's stack, which
the kernel maps only as it grows. sceKernelIsStack reports the whole
range that pthread_getattr_np gives, which is sized by RLIMIT_STACK and
is mostly not mapped yet. A protection of that range failed with ENOMEM,
so mprotect returned EINVAL and sceKernelMprotect stopped the title.

When the stack branch's mprotect fails with ENOMEM, the range's unmapped
pages are now mapped read-write at their own addresses
(MAP_FIXED_NOREPLACE) and the protection is applied again. This matches
how the reserved pages of a host stack are committed on Windows.
2026-10-15 08:10:42 -07:00
Adrià 92e50418f3 Merge pull request #5725 from GalaxyGamingFR/fix/stale-label-after-rebase
fix(ci): clear the stale label once a PR is rebased
2026-10-15 17:04:38 +02:00
Adrià d67b79a7e4 Merge pull request #5709 from fogydes/fix/libc-formatting-allocation-and-bounds
fix(libc): check allocation result in vasprintf and guard null pointer in strndup
2026-10-15 17:04:33 +02:00
Adrià 37e0f1688e Merge pull request #5708 from MarcZX100/codex/test-untracked-storage-repeat-5693
test(agc): cover repeated untracked storage writes after sampling
2026-10-15 17:04:27 +02:00
Adrià 0b5d774545 Merge pull request #5704 from fogydes/fix/libkernel-app-metadata-concurrency
fix(libkernel): protect app metadata state across threads and validate icon stream read
2026-10-15 17:04:22 +02:00
RickandClaude Opus 5.5 831c583003 fix(libkernel): refuse a closed loopback TCP port at once on Windows
Windows answers a SYN to a closed port with a RST and then retransmits
the SYN, so connect to a closed loopback port takes about 2 s before
ECONNREFUSED; FreeBSD fails at once. PS5VR (PPSA99177) makes about 33
such connects to 127.0.0.1:17600 and reaches its home screen 45 s late.

When no socket listens on the destination port (GetExtendedTcpTable),
a loopback connect now sets SIO_TCP_INITIAL_RTO with no SYN
retransmissions and fails at once. A port with a listener keeps the
retransmissions: Windows also answers a SYN to a full accept backlog
with a RST, and the retransmission connects once the server accepts,
as the console's does after FreeBSD drops the SYN.

guest_refused_connect requires ECONNREFUSED in under a second for a
closed port through libkernel connect and sceNetConnect, and a second
connect to a listener with backlog 1 to succeed once the server accepts
the first, through both.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-15 17:04:20 +02:00
Adrià d8862a63ba Merge pull request #5703 from EagleBearerYS/fix/libkernel-protect-reserved-host-stack
fix(libkernel): commit a reserved host stack before protecting it
2026-10-15 17:04:17 +02:00
Adrià 3751c55111 Merge pull request #5700 from specbug/fix/default-scope-guest-symbols
fix(libkernel): resolve renamed guest exports in the default scope
2026-10-15 17:04:10 +02:00
Adrià 0e6a5e7a5c Merge pull request #5690 from SandstromPL/fix/savedata-mount3-invalid-dir-name
fix(savedata): return a parameter error from sceSaveDataMount3 for an invalid directory name
2026-10-15 17:04:04 +02:00
Adrià 162adb9da8 Merge pull request #5669 from MarcZX100/codex/signal-mask-128
fix(libkernel): honor all guest signal mask words
2026-10-15 17:03:59 +02:00
Adrià 8a253707e6 Merge pull request #5663 from al3w0f205/feat/libkernel-munlockall
feat(libkernel): add munlockall export
2026-10-15 17:03:54 +02:00
Adrià f5a55a11d0 Merge pull request #5662 from Roojool/contrib/g15-libc-pending
feat(libc): implement collate<wchar_t>::_Getcat
2026-10-15 17:03:49 +02:00
Adrià 21ca964f3f Merge pull request #5632 from babyhuey/fix/libc-closed-stream-writes
fix(libc): fail stream calls on a stream that a failed freopen closed
2026-10-15 17:03:43 +02:00
Adrià 9490a6da68 Merge pull request #5617 from Dripl1x/feat/socket-timeouts
feat(libkernel): apply SO_RCVTIMEO and SO_SNDTIMEO on a guest socket
2026-10-15 17:03:37 +02:00
Adrià 63b377b51b Merge pull request #5612 from JJenkx/feat/private-mutex-sharing
fix(libkernel): store mutex process-sharing attributes
2026-10-15 17:03:30 +02:00
Adrià 51b1d4a3a0 Merge pull request #5611 from JJenkx/fix/kernel-virtual-query-layout
fix(libkernel): stabilize virtual-query layout across hosts
2026-10-15 17:03:24 +02:00
Adrià 08290338aa Merge pull request #5599 from JJenkx/feat/libc-isfinitel
feat(libc): implement x87 long-double finite classification
2026-10-15 17:03:18 +02:00
Adrià b4a4fcac0e Merge pull request #5254 from 0xRickx/fix/libsceaudiodec-heaac
fix(libSceAudiodec): decode HE-AAC as the console does
2026-10-15 16:59:46 +02:00
Adrià 120615bc73 Merge pull request #4927 from QRMOE/fix-libc-getcwd-allocated-size
fix(libc): ignore getcwd size when allocating a buffer
2026-10-15 16:59:41 +02:00
MrMha 8f89496766 fix: preserve strong references when grouping duplicate imports 2026-10-15 18:59:32 +04:00
MrMha 3929c9a49b fix: escape trace names in Markdown table cells 2026-10-15 18:59:10 +04:00
MrMha 03a9073104 fix: reject negative trace digest list limits 2026-10-15 18:58:49 +04:00