Repository navigation
fix(libkernel): read and write guest sockets - #6
Merged
Merged
Conversation
Read the module layout from the PE image that holds the address. A relinked image reports its .elf sections as segments and the eh_frame_hdr recorded in .ehmeta; any other image reports its sections with memory access and its .ehfram section. The eh_frame_hdr and eh_frame helpers are shared with the Linux path, and the guest module info test now also runs on Windows. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…alls sceKernelGetModuleInfoForUnwind and sceKernelGetModuleInfoFromAddr each parsed .ehmeta and the eh_frame_hdr it names. Both now read them through Module/EhFrame.hpp, so a bad table fails the same way in both: an eh_frame_hdr version other than 1, an indirect or non-absptr/pcrel encoding, a 64-bit record length or anything outside the image throws. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JkiyF6p7oDAaTtVe8ci5zP
Add sigemptyset, sigfillset, sigaddset, sigdelset and sigismember with FreeBSD 11 semantics (lib/libc/gen/sigsetops.c): a 128-bit set of four 32-bit words, signal n at bit n - 1, signals 1 to 128 valid. sigfillset sets every bit. An invalid signal returns -1 with errno EINVAL and leaves the set untouched; sigismember returns 1 or 0. A null set throws. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ScreenTester5 (PPSA69420) stops at start-up on the unresolved sysctlbyname import and also imports sysctl. hw.ncpu (CTL_HW.HW_NCPU) reports the same processor count as sysconf(_SC_NPROCESSORS_ONLN). Other names and MIBs throw.
Three homebrew titles from boykopovar#1578 import it and stop at start-up without it: ps5-opengl (PPSA99005), EVO-PLAYER-PS5 (PPSA99039) and ProsperoRadio (PPSA99001). It reports the port's resolution as the full and pane size and the refresh rate ID as sceVideoOutGetOutputStatus does. The 48-byte layout follows the declarations in ps5-opengl and EVO-PLAYER-PS5, which agree; the screen size is 0 and the flags are 0. An invalid handle or a null status throws, as in the other status getters. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eNgs2 does The PS4 firmware 11.00 libSceNgs2.sprx stores matrix levels clamped to -4..4, keeps NaN, and rejects a level count of 0. Levels were stored unclamped, so a level of 8 played twice as loud as on the console, and a count of 0 cleared the matrix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hades (PPSA03355) stops at load on main with "undefined symbol: 9HzfhdtESio", the NID of pthread_getname_np, which it calls on pthread_self() with a 32-byte buffer. Measured on a PS5 (firmware 13.60) through dlopen of libkernel: the function takes (thread, buffer), copies the name and its terminator, returns an empty name for an unnamed thread, ESRCH for a null or joined thread and EFAULT for a null buffer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Returns the name of the directory under which a title's sandbox exposes system files, which homebrew SDKs splice into paths such as /<name>/common/cert/CA_LIST.cer and /<name>/common/lib/libc.sprx. The name is fixed here; recorded in TechnicalDebt together with the fact that nothing is mounted under it. Registers guest_sandbox_random_word. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
PICO-8 for PS5 (PPSA99808) stops at start-up on the unresolved import a7ToDPsIQrc from libSceLibcInternal. The parser follows FreeBSD's inet_aton (lib/libc/inet/inet_addr.c): one to four parts in decimal, octal or hex, the last part filling the remaining bytes, input ending at a NUL or whitespace, and a null address only validating. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Record the tessellation factor ring that sceAgcDriverSetTFRing receives and report it from sceAgcDriverGetTFRing, with the console's default of 0xFF00000000 and 128 KiB before a title sets one. VITA5 (PPSA39410) and Homebrew UI Lab (PPSA99050) stop on this import once sceVideoOutGetResolutionStatus resolves.
The hardware findings give 0xF_F000_0000, which is 0xFF0000000, not 0xFF00000000. Check the ring across threads, at ps5-opengl's size of 0x1b000 and with a canary after the outputs, and say in the debt entry that nothing is written to the ring.
sceSystemServiceLaunchWebBrowser fails with the kernel's EOPNOTSUPP: there is no web browser to open. RommPS PPSA76677 stops on main at this import and shows a QR code instead when the browser does not open.
…st any arguments The param is void*, as RommPS declares it. The test also passes a null and an empty URI and a param that must stay untouched, and compares against 0x8002002D itself. The debt entries now say the error is returned for any arguments and that the param layout and the console's argument checks are unknown.
CachedPipeline keeps at most 256 pipelines. A level with a larger working set thrashes the LRU: every miss creates a new VkPipeline (modules, layout, render pass and a driver compile from the pipeline cache). The bound is now 1024. A cached pipeline is a pure function of its key, so the bound changes only memory and time.
…iew adjustment A draw's guest buffer region inside a host import at an offset off minStorageBufferOffsetAlignment was copied per build (a new buffer, an input snapshot, a vkCmdCopyBuffer that ends the open render pass), and DirectRegions refused such builds as templates. Descriptor already binds any DWORD-aligned view from the aligned offset below it and passes the remainder through the shader's memory offset slot. A draw build that is not address-based and whose every guest buffer element has such a slot (a push constant byte, or a shader data byte inside its data buffer) now binds a region whose offset in its import is DWORD aligned in place, like an aligned one: its read-only views are snapshotted per draw by PrepareDrawBindings at address - adjustment, the import serial keys the template, and Revalidate proves it per use. Dispatches keep the copy (they read in-place inputs at execution, not at record). agc_driver_recorder_tests misalignedRegionTests: a misaligned read-only draw region is read in place, the build is reusable, the push constant carries the adjustment, and the per-draw snapshot starts at the aligned offset below the view.
PS5 titles pass a 0x230-byte SceAvPlayerInitDataEx: auto start is the byte after debug_level at 0x74, nine 0x30-byte thread parameter blocks fill 0x78-0x228 and the output video frame buffer count is at 0x228. sceAvPlayerInitEx read both fields at their PS4 offsets: auto start at 0xa8 is the video decoder thread priority and the buffer count at 0xa4 lies in the audio decoder block. PPSA25063 (Poppy Playtime: Chapter 4) sets every thread priority to 700, so its intro video started on its own and stopped at once; it writes auto start 0 and starts playback itself. With this_size 0x230 or more both fields are read at the PS5 offsets; smaller structures are read as before. The layout follows KytyPS5, prosper, SharpProspero and sharpemu and is recorded in TechnicalDebt. guest_avplayer builds a 0x230-byte structure with auto start 0 and nonzero thread parameters, then with auto start 1, and checks when playback starts and how many video buffers are allocated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
llvmpipe builds the high dword of the shader clock with a left shift by 32 (emit_clock in Mesa's lp_bld_nir_soa.c), so it is always 0 and s_memtime and s_memrealtime wrap every 2^32 ns. A pass of agc_driver_shader_clock whose two reads straddle a wrap failed with "memtime: lane N went back from 4294921902 to 3823"; dispatching right before the boundary fails every lane of that pass. On llvmpipe compare the low dwords modulo 2^32, which stays correct if Mesa fixes the shift. Other devices keep the 64-bit comparison. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
On a host without IPv6, socket(AF_INET6) fails with EAFNOSUPPORT, so guest_sce_net aborted at its first IPv6 socket and never ran the TCP, UDP, epoll, sendmsg/recvmsg, resolver and NetCtl checks after it. When sceNetSocket reports guest EAFNOSUPPORT (47) for the IPv6 socket, skip those socket checks, run the rest of the test, and exit with 77, which ctest reports as skipped. Hosts with IPv6 run every check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
libstdc++ already defines NOMINMAX on MinGW, so the unguarded define warned on every Windows build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
libSceVdecsw is the software H.264 decoder interface PPSA05684 uses for its movies. Decoder creation, compute queues, memory queries, decode input and output, AVC picture info, reset and finalize are implemented with the layouts of shadPS4's vdecsw.h, checked against the title's movie decoder, and decode through libSceVideodec2. The H.264 stream the Videodec2 test uses moves to a shared fixture, and a guest test decodes it through Vdecsw. Uncharted: Legacy of Thieves Collection (PPSA05684) plays its movies through libSceVdecsw and stopped at sceVdecswQueryComputeMemoryInfo.
…needs The built Windows libraries import libgcc_s_seh-1.dll, libstdc++-6.dll and libwinpthread-1.dll, and the entry stub loads them without searching PATH. The release archives ship the DLLs in libs/, but the runtime layout only told self-builders to copy the .prx files, which ends in error 126. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…aths with spaces MinGW windres passes -I paths to cc1 with backslash-escaped spaces and parentheses, so compiling 3rdparty/freetype/src/base/ftver.rc fails when the checkout or build path contains them. FreeType is linked as a static library and the resource object is never pulled into an output, so it is removed from the target's sources on Windows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t-runtime test(agc): bound the storage cache budget regression workload
…dit-exit-two fix(tools): exit 2 when import_audit cannot read an input or write --json
…nmax-kernel-sync build(windows): guard NOMINMAX in the kernel sync test
…-dlls docs(usage): list the MinGW runtime DLLs a self-built libs directory needs
build: skip the FreeType version resource so Windows builds work in paths with spaces
…no-error-dialog test(libs): report patched libraries that fail to load instead of a loader dialog
…-utf8 fix(tools): preserve UTF-8 in progress comparisons
…-ipv6 test(net): skip only the IPv6 socket checks on a host without IPv6
…tivirus docs(build): note antivirus quarantine of relinker test executables on Windows
…c-timezone-bounds fix(rtc): validate ticks before timezone conversion
…unread-close test(net): reset the closed peer with unread data so the send fails at once
feat(libc): implement syslog and vsyslog
feat(libkernel): implement tcgetattr and tcsetattr
…-regions perf(agc): bind misaligned draw buffer regions in place through the view adjustment
…sync feat(libkernel): implement fdatasync
…tats-debt docs: drop the stale unknown-signature entries for the memory pool stats
…s-event feat(libSceVideoOut): register the VRR status event and accept the VRR status call
…thread-getname-np feat(libkernel): implement pthread_getname_np
feat(libkernel): implement lstat
…eadlink feat(libkernel_sys): implement readlink
…ox-random-word feat(libkernel): implement sceKernelGetFsSandboxRandomWord
feat(libc): implement __fpclassifyf
feat(agc): implement sceAgcDriverGetTFRing
feat(libc): implement __inet_aton
…tion-status feat(videoout): implement sceVideoOutGetResolutionStatus
…rnel-system feat(libkernel): implement system
read, write, _read and _write on a guest socket descriptor went to the host, which has no such descriptor, so sceKernelRead and sceKernelWrite threw. They now reach the socket as recv and send without flags, with the socket layer's errno (EAGAIN 35, EPIPE 32, EBADF 9), a zero-length read returns 0 as dofileread does, and the two sceKernel forms return the kernel error for the same cases. The host's SIGPIPE on EPIPE, a write above INT_MAX bytes, readv, writev and the positioned forms are recorded in TechnicalDebt. OpenSSL's QUIC notifier signals its socketpair with write and read. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
SleglJan
force-pushed
the
feat/libkernel-socket-read-write
branch
from
October 9, 2026 21:59
62aa3af to
9d0b105
Compare
SleglJan
pushed a commit
that referenced
this pull request
Oct 16, 2026
…ll or crash A GPU hang or a crash in a title leaves no record of what the queues were last given: APS5_TRACE_GPU prints every submission (too much to leave on), and the WAIT_REG_MEM timeout message shows only the packet before the wait on the waiting queue. Each queue now keeps a ring of its last 16 submissions (APS5_PM4_RING=<n>, 0 to 4096, 0 disables): the TraceMs time in tenths of a millisecond, serial, size, guest address and a copy of the first 512 dwords after indirect buffers are inlined, recorded under the driver lock next to the serial, REWIND tails included. The ring of a queue and the failure report registration are set up at the top of Submit, before any output is reserved, so recording under the lock does not allocate. Disabled, Submit only tests a static flag; enabled, it costs one bounded copy per submission. DumpSubmissionRings decodes the kept dwords with Pm4::PacketWords and the new Pm4::KnownName, which returns the decoder's names as views of static strings (empty for an unknown opcode, printed as UNKNOWN_0x%02x); Pm4::Name now builds its std::string from it. Every line is formatted with integer and string conversions only into a 512-byte stack buffer and written with one WriteFile / write(2) on the stderr handle, so the dump does not allocate from the C runtime heap, lines from other threads do not interleave and the CRT stream lock is not taken (the rule of boykopovar#3871). The header gives the number of queues and the ring size, and each queue line the submissions recorded and kept. libc gets a small registry of failure reports (LibcRegisterFailureReport_nid_no_patch, Unregister, Run); Run runs the registered reports the first time it is called and returns at once after that. The Windows crash report runs it after the thread dump of an unhandled exception, after SIGABRT (which also covers the APS5_HANG_DUMP_SECS timed dump, since it aborts) and after an invalid CRT parameter, so an abort after a reported exception does not print the rings twice. The driver registers its dump at the first submission and unregisters at static destruction; the dump there waits a bounded time for each ring lock. What the crash-path dump cannot do (a ring held by the crashed thread, rings corrupted by the crash, Linux) is recorded in technical debt. APS5_STALL_WATCHDOG_SECS=<n> (0 to 86400, 0 disables) makes a waiter that has not progressed for n seconds dump the rings once per wait: a WAIT_REG_MEM (progress as for APS5_GPU_WAIT_TIMEOUT_MS: another packet runs or completes), a REWIND waiting for the title, and a compute submission held behind queue 0. The last one prints under the driver lock, so submissions and the other queues wait for it (USAGE.md says so). Both variables are read at the top of Submit, so an invalid value of either throws at the first submission and never later inside a GPU worker. The order wait behind queue 0 releases its order hold on scope exit, so a throwing dump cannot leave it counted. No packet semantics change; packet sizes and names are those of the existing decoder (PM4 type-3 header layout as in Mesa src/amd/common/sid.h). The queue bound of Submit and of the rings is one constant, SubmissionQueueEnd. Tests: agc_driver_pm4_tests gets ten modes, each its own ctest: agc_driver_pm4_ring (APS5_PM4_RING=4, six submissions on queue 0 and two on 0x20: the dump holds #3..#6 and #1..#2 in order, nothing older), agc_driver_pm4_ring_empty (one line), _ring_disabled (one line), _ring_invalid and agc_driver_pm4_stall_watchdog_invalid (APS5_STALL_WATCHDOG_SECS=1x: the submission throws and is not executed), _ring_report (LibcRunFailureReports_nid_no_patch dumps the rings), _ring_report_heap (Windows: with ucrtbase.dll's HeapAlloc and HeapReAlloc imports counting calls from the reporting thread, the failure report of a submission holding INDEX_BUFFER_SIZE names it and allocates nothing, while Pm4::Name of the same header is seen allocating), and with APS5_STALL_WATCHDOG_SECS=1 a WAIT_REG_MEM (agc_driver_pm4_stall_watchdog), a REWIND (_stall_watchdog_rewind) and a compute submission held behind a queue 0 rendering wait (_stall_watchdog_order), each held for about 2.5 s, dump once and complete when released. The PM4 catalog test checks KnownName against every opcode and custom name. windows_backtrace_failure_report checks that abort() runs the registered reports once and not an unregistered one; windows_backtrace_failure_report_once that abort() does not run them again after an earlier run. With the dump decoding through Pm4::Name, agc_driver_pm4_ring_report_heap fails with "the failure report allocated from the C runtime heap"; with Run resetting its flag, windows_backtrace_failure_report_once prints the report twice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
read,write,_readand_writeon a guest socket descriptor (0x10000000 and up) went to the host as if the number were a host descriptor, sosceKernelReadandsceKernelWritethrew (sceKernelWrite: write failed, fd=…, errno=9) on the first byte a title moved through a socket that way. On the console both are the socket'srecvandsendwithout flags (soo_read/soo_write).GuestSockets::ReadandGuestSockets::Writein the socket runtime forward torecvandsendwith flags 0, so the socket layer's errno applies:EAGAIN(35) on an empty non-blocking socket,EPIPE(32) after the peer closed,EBADF(9) on a closed descriptor. A zero-lengthreadreturns 0 without touching the socket, asdofilereaddoes, and a read longer thanINT_MAXis clamped.read,write,_readand_writeroute descriptors at or aboveGuestSockets::FirstDescriptorto them;sceKernelReadandsceKernelWritedo the same, before their null-buffer check, and return the kernel error (0x80020023forEAGAIN,0x80020009forEBADF) instead of throwing.EPIPEraises the host'sSIGPIPEon Linux, which the guest can neither ignore nor suppress, and nothing on Windows (the console raises it unlessSO_NOSIGPIPE); awriteaboveINT_MAXbytes isEMSGSIZE;readv,writev,pread,pwrite, theirsceKernelforms and AIO on a guest socket still go to the host.The 15 catalog titles whose OpenSSL QUIC notifier creates a
socketpair(boykopovar#1711, open) signal it withwriteand drain it withread(rio_notifier.cthroughwritesocket/readsocket); the same applies to any TCP socket a title reads withread.Overlap: boykopovar#1307 rewrites the four wrappers in
Stdio.cpp(the socket branch has to stay first); boykopovar#1711 and boykopovar#1708 insert a TechnicalDebt line at the same place; boykopovar#1091 and boykopovar#1738 add declarations toSocketRuntime.hpp, and boykopovar#1091 code toUdp.cppnear the table, where this adds two declarations and two functions at the end. Whichever merges second rebases. The pr-overlap report's__error_nid_postfixrows (boykopovar#1613, boykopovar#1616, boykopovar#1627, boykopovar#1675) are the sharedextern "C"declaration of the errno accessor thatOpen.cppnow adds, not an export.Tested
BUILD_TESTING=ONandANYPS5_ENABLE_SPIRV_TOOLS=ONon this branch (based onmainb83e849):ctest --repeat until-fail:3467/467;tools/check_test_registration.pyandtools/check_conventions.py --base upstream/mainpass.guest_socket_read_writetest over a TCP loopback pair:write/read,_write/_readandsceKernelWrite/sceKernelReadcarrying data both ways;EAGAINand0x80020023on an empty non-blocking socket; zero-length reads returning 0; 0 from both forms after the peer closed; (Linux)EPIPEonwriteafter the peer closed, with the host'sSIGPIPEignored by the test since a title cannot;EBADFand0x80020009from every entry point on a closed descriptor. Each receive waits withpollfirst, acceptingPOLLHUPafter the close. Written before the change: onmainit aborts with thesceKernelWritethrow above; it passes with the change.EPIPEcase there, likeguest_tcp.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)🤖 Generated with Claude Code