Register copied the protection it had recorded for pages it already
watched over the protection the kernel had just reported. A guest that
reserves address space, which registers it as PROT_NONE, then maps
direct memory over it read-write and registers it again kept the stale
PROT_NONE. Collect only write-protects pages with PROT_WRITE, so writes
to that memory were reported once and never again. With PPSA12544 on
the macOS port, the title menu text blinked and glyphs went missing.
Register now keeps a recorded protection only where its own write
protection explains what the kernel reports, and takes the kernel's
protection otherwise. A protected page that was mapped again also loses
its protected mark, so erase no longer restores the old protection over
the new mapping. The kernel is read under the lock, so a concurrent
Collect cannot protect a page between the read and the merge.
Test write_watch_mapped: a reservation, a mapping over it and a second
registration keep reporting writes, and a protected page reserved again
stays PROT_NONE.
AI-assisted: yes
GuestMemory.cpp reads PROCMAP_QUERY_VMA_READABLE and PROCMAP_QUERY_VMA_WRITABLE from the query result. The fallback for kernel headers without PROCMAP_QUERY now defines them too, so GuestMemory can use this header instead of its own copy.
GuestAllocationsUnmap took the piece containing the cursor from the
allocation's original extent. After part of an allocation was unmapped,
a later unmap or fixed map starting in that hole still matched the
allocation, and replaceRange threw on the hole. Match against the
registered range itself and end each piece at its end. RIDE 4
(PPSA01599) maps fixed over a partly unmapped direct memory range.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FreeBSD fchdir(2) changes the working directory to the directory referenced by a descriptor. The guest imports fchdir from libkernel_sys (PPSA99764, issue #1578) and the module did not export it.
The descriptor's directory is resolved from the path recorded when the directory was opened on Windows, and from the /proc/self/fd link target on Linux. The guest working directory is then set through the libc routine shared with chdir. A descriptor that is not open returns EBADF and one that is not a directory returns ENOTDIR.
AI-assisted: yes
(cherry picked from commit 76329cbb08781e13d757c3ff955acf71f8bd506f)
hypot(inf, NaN) returned a NaN on main. C Annex F returns +inf when
either operand is infinite, even if the other is a NaN, and FreeBSD
msun (lib/msun/src/e_hypot.c) does so for a signalling NaN too. The
infinite case is now checked before std::hypot; other inputs do not
change.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
C17 7.21.6.2p16 returns EOF only if input fails before the first conversion completes, and a suppressed conversion completes. FreeBSD counts it in nconversions (vfscanf.c, releng/11.4, lines 799-805). The host scanf returned EOF there, so sscanf("12", "%*d%d", &v) reported EOF instead of 0. Each suppressed conversion now records its end with a %n and a result of EOF becomes 0 when one was recorded.
PSXS5, SwanStationPS5 and Nuvio stop at start-up on setcontext on main,
and EVO Player and ProsperoStore do on Windows. The three are imported
by the statically linked OpenSSL's ASYNC code.
The three use FreeBSD 11's amd64 ucontext_t (mcontext at 0x10, mc_len
800, uc_link at 0x330, 0x370 bytes), which the titles are built
against: EVO Player's ASYNC_is_capable captures into a 0x370-byte stack
buffer, and async_fibre_makecontext sets uc_link at 0x330 and uc_stack
at 0x338. getcontext saves every register at its call in assembly and
stores the context as FreeBSD's sys_getcontext does: rax and rdx as 0,
the carry flag clear, the FXSAVE image and the signal mask, and nothing
from uc_link on. setcontext checks mc_len and mc_flags as set_mcontext
does, installs the signal mask, masks MXCSR with the host's MXCSR_MASK
and returns through iretq, so every general register and the flags are
restored and nothing is written below the target stack pointer.
makecontext follows FreeBSD 11's amd64 libc.
Windows checks guard-page growth and exception unwinding against the
stack bounds in the TEB. setcontext and longjmp now set them to the
stack they switch to, which makecontext registers and pins writable as
libSceFiber does for fiber stacks. OpenSSL enters a context with
setcontext and then switches with _setjmp and _longjmp.
Use unlocked POSIX EOF/error queries after unlocked byte operations so status synchronization cannot reacquire the stream lock. Keep the verified UCRT status calls on Windows, and cover byte, status, error, and held-lock behavior.
Co-authored-by: MarcZX100 <marczxrr@gmail.com>
On Windows every unwind step called VirtualQuery to find the frame's
module, and a module with a plain .eh_frame (libstdc++, libgcc, libwinpthread)
was searched by decoding each FDE in turn. A C++ exception crossing those
frames cost about a millisecond. Look the module up with RtlPcToFileHeader
first, falling back to VirtualQuery for images the loader does not know,
and binary-search a per-module index of FDE start addresses built on first
use.
The Windows formatter passed %p to the host CRT, which prints 16
zero-padded digits without a prefix. FreeBSD prints 0x followed by the
lowercase hex digits (0x0 for a null pointer), as if by %#lx.
Add standard quiet NaN generators nanf (DZU+K1wozGI) and nan (zck+6bVj5pA) to libc.
Resolves startup failure in VLC for PS5 (PPSA85300) where execution halts at nanf on Linux once strsep is available.
VLC (PPSA85300) imports daemon (Wn6I3wVATUE) and fails to load because
no library exports it. Forking into the background is not supported,
so it throws if called. VLC 3.0 calls daemon only when its daemon
option is set, and the title starts libVLC with --ignore-config and
without --daemon.