FreeBSD 11.4 kern_mmap maps anonymous memory whenever MAP_ANON is set, with
or without MAP_PRIVATE (sys/vm/vm_mmap.c:339), and fails with EINVAL when
both MAP_SHARED and MAP_PRIVATE are set (vm_mmap.c:252). The guest failed
the first with ENOTSUP (45) and the second with ENOTSUP as well.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Rack locks and renders were tracked per system, so a voice callback
that locked a rack of another system could deadlock with that system's
render, or with a thread holding rack locks in both systems. Rack locks
and renders now exclude each other across threads and systems, as the
single internal lock did, while a thread nests them and other calls go
ahead.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The browser converter treats sce_module as a runtime directory, so the
Windows deferral of runtime modules the executable needs also deferred
libc.prx and libSceFios2.prx, which titles never load themselves.
Modules in sce_module, sce_modules and prx that the executable needs
are started at startup again, as the Linux deferral of #6586 keeps
them.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Check padding up to the end of the inspected range first, as before, and
use the 16-byte boundary rule only when that fails, so a long NOP that
crosses the boundary no longer rejects the table. Check the bytes the
function's own unwind range still covers after the table, so a table cut
short inside its function is rejected again.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The rename source is now resolved before the destination argument, as in
FreeBSD kern_renameat, so sceKernelRename("src", nullptr) fails with ENOENT
when src does not exist. GuestPosixScalarIo still expected EFAULT.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
FreeBSD 11.4 raise is thr_kill(thr_self(), sig) (lib/libc/gen/raise.c:52),
and thr_kill with a thread id treats signal 0 as a pure existence check
that returns 0 (sys/kern/kern_thr.c:425). The guest returned EINVAL.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The code analysis of the Windows and macOS outputs followed every
relocation and lea target inside the code range as code. PS4 images keep
read-only data between unwind functions, and strings and tables there
decoded into garbage, failing the conversion. Outside the unwind functions
such a target is now code only when it is 16-byte aligned, starts less
than 256 bytes after an unwind function and decodes to a jump, return or
trap; lea targets go through the same rule instead of the graph's own.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Between the unwind functions of a PS4 image the bytes are not known to be
code, and read-only tables there can hold 0f 05. Outside the unwind
functions a syscall, sysenter, int 0x80 or sysret pattern now fails the
relink only when a constant syscall number is loaded right before it; the
others are skipped and counted in one message. Inside the unwind functions
and in other images every such instruction still fails.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Rename of file/. fails with ENOTDIR and of loop/. with ELOOP on Linux, where
status() of the parent reports the error instead of "not found"; the test also
runs the file case on Windows, where it passes with and without the change.
The loop case needs a symbolic link and runs on Linux only.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
FreeBSD 11.4 kern_sigaction fails with EINVAL when a handler other than
SIG_DFL and SIG_IGN comes with flags outside SA_ONSTACK, SA_RESTART,
SA_RESETHAND, SA_NOCLDSTOP, SA_NODEFER, SA_NOCLDWAIT and SA_SIGINFO
(sys/kern/kern_sig.c:691-695). The guest accepted any flag word.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
libc.prx did not export wcstombs_s (sZLrjx-yEx4); only libSceAmpr did.
Ghost of Yotei imports it from libc.prx and stops at symbol resolution.
Move the implementation to libc next to wcsrtombs_s. libSceAmpr keeps
its export through an explicit-NID wrapper, because the NID patcher
leaves symbols that libc exports unrenamed in other libraries.
RenameDotError looked at the parent of a dot component with exists() and
is_directory(), so a stat failure other than a missing path, such as
permission denied, answered ENOENT or ENOTDIR. The parent is now read with
status(): a missing path is ENOENT (ENOTDIR when a component is a file), any
other error is mapped through FilesystemError, and only a successful status
decides between a directory (EINVAL) and a non-directory (ENOTDIR).
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
FreeBSD 11.4 kern_sigprocmask applies SIG_CANTMASK to the set for SIG_BLOCK
and SIG_SETMASK (sys/kern/kern_sig.c:1056, 1067), and sigsuspend sets its
mask through the same call (kern_sig.c:1534). The guest mask kept both bits,
so sigprocmask(SIG_BLOCK, {SIGKILL}) read back as blocked.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Windows APR reads are staged through a 64 KiB std::array on the stack of
the thread that submits them (f7953ecac). Titles submit reads from fibers
whose stacks they allocate themselves, which can be smaller than that and
have no guard page, so the array runs past the bottom of the fiber stack
and the file data lands on whatever lies below it. Demon's Souls
(PPSA01341) then crashes in scePthreadMutexLock about half a second after
start, on a mutex that holds bytes of playgo-chunkdefs.xml.
The staging buffer is now allocated for each read, at most 64 KiB. The
new guest_apr_read_stack test reads on a thread with a 64 KiB stack; with
the stack array it ends in a stack overflow.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
#7652 made raises wait for host code to leave, adding ~3 s to a test that
already took ~16 s on a fast machine. Main run 39414828108 timed out at 30 s
on windows. Round counts halved; every scenario still runs.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The console's strtof, strtod and strtold set ERANGE only when a
conversion underflows to zero; a non-zero subnormal result leaves errno
unchanged, while the host's sets it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RbLgECLQ2bpDM7oe2urGZK
In a payload process on a PS5 (firmware 12.70), sysctlbyname returns -1
with ENOENT for thirteen names that threw here, and leaves the buffer and
the length alone, for a read, a size query, a null length and a null
buffer with a null length. sysctl does the same for the fixed MIBs of
seven of them. sysctlnametomib gives those seven MIBs and returns ENOENT
for hw.cacheline_size and hw.usermem, which threw too.
machdep.cacheline_size already returned ENOENT and is now tested with
the others. A write to the new names and MIBs throws, as the console's
answer to a write was not tried. The hw.realmem and vm.overcommit debt
entries now say that a payload process gets ENOENT for them as well.
AI-assisted: yes
Co-Authored-By: Claude Opus 5.5 <[email protected]>
lseek on a descriptor that is not open with an invalid whence answered EINVAL.
FreeBSD 11.4 kern_lseek looks the descriptor up first and only then lets the
file's seek operation judge the whence, so the answer is EBADF.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
An ulthread runs on its own guest thread, so it remembers its object for sceUltUlthreadGetSelf, yields that thread, and exits it with the status sceUltUlthreadJoin and sceUltUlthreadTryJoin return. Outside an ulthread the three return ULT_ERROR_STATE.
Readers share the lock while no writer holds it and a writer waits until it is free. Destroying a held or waited-on lock and destroying the waiting-queue pool of a lock a thread waits on return ULT_ERROR_BUSY, and sceUltFinalize wakes waiters with ULT_ERROR_STATE, as for the mutex.
It takes a free mutex or relocks one the caller holds, as sceUltMutexLock does, and returns ULT_ERROR_BUSY instead of waiting when another thread holds it.
kevent threw for EVFILT_WRITE on any descriptor that is not a socket. On the write end of a pipe it now follows FreeBSD 11's filt_pipewrite: data is the free buffer space, and once the read end is closed the event reports EV_EOF with data 0. Adding the event after the read end is closed fails with EPIPE, as in pipe_kqfilter. EVFILT_WRITE on the read end still throws, because FreeBSD's pipe ends are bidirectional and host pipes are not.
GuestSockets::Ready only knew the read end of a pipe, and WaitAny asked the host for POLLIN on every descriptor that is not a socket, so a write interest on a pipe could never be reported or wake a wait. PipeWriteState gives the free space of the host buffer (F_GETPIPE_SZ less FIONREAD on Linux, the write quota on Windows), EOF once the read end is closed, and whether the host takes a write now; Ready reports the write end when it is writable or at EOF, and WaitAny asks for POLLOUT on it. macOS has no call for the capacity of a pipe and throws.
A voice callback runs with the internal lock released, so another
thread could lock the rack being rendered and the render then finished
it under that lock. sceNgs2RackLock now also waits while another thread
renders the rack's system, as it did when the rack lock was the
internal lock.
Co-Authored-By: Claude Opus 5.5 <[email protected]>