FindTrailingRelativeJumpTable accepted a jump table after a function's
code only when padding followed it up to the end of the inspected range.
A PS4 function's table can end past its FDE, be padded to the next
16-byte boundary and be followed by more code before the next FDE. The
table is now accepted when padding reaches that boundary; it then ends
there, so the code after it is still analysed as code.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
FreeBSD 11.4 kern_truncate returns EINVAL for a negative length before it
looks up the path, and getutimes rejects an out-of-range tv_usec before
namei in utimes and lutimes. The guest calls checked a NULL or empty path
first, so truncate(NULL, -1) and utimes("", {usec -1}) returned EFAULT or
ENOENT where FreeBSD returns EINVAL.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Since host imports group adjacent ranges into aligned blocks (#6457), an
import can span both 64 KiB blocks that an earlier import left unwatched
and the metadata of resident multisampled DCC targets.
ImportWatched with staysWatched took the whole import out of the write
watch when any part of it was not watched before. It now walks and
compares each run of watched blocks of the import on its own, and
unwatches only the blocks that were not watched or whose walk failed.
A resident DCC target took the generation of its metadata from a walk
of the metadata's pages alone. CPU stores to the rest of the metadata's
64 KiB block made before that walk were stamped later by the import's
walk, so the block read as written, and the import window marked the
metadata page as possibly stored over: the next draw refused the
target. The generations now come from a walk of the whole blocks.
agc_write_tracking and agc_driver_msaa_dcc_clear_* gain regression
tests for both.
Fixes#8103
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A --module-dir module that only the executable needs was initialized by
the Windows entry stub with no start arguments, so a later
sceKernelLoadStartModule with arguments found it started and its
module_start never saw them. Unity's mono-ps4.sprx keeps those
arguments for the plugins it loads. Such a module is now deferred like
any other runtime module: mapped at startup and started, with its
arguments, when the title loads it. Modules another guest module needs
are still started at startup, and Linux and macOS are unchanged.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
rename and sceKernelRename resolved "dir/." to "dir" and renamed the directory. FreeBSD 11.4's lookup fails a last component of "." for DELETE and RENAME with EINVAL, for the source and the destination alike. Check the guest string before it is resolved: a last component of "." (also under trailing slashes) fails with EINVAL when its parent exists, ENOENT when it does not and ENOTDIR when it is not a directory.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Return the handle of an event flag this process created under the
given name, or ENOENT. Twispero opens the shell's
SceShellCoreUtilAppFocus flag at start-up and treats a failed open as
unknown focus.
stat, open, mkdir, rename and the other calls that resolve a guest path answered ENOENT (or EIO for rename) for a name longer than 255 bytes or a path of 1024 bytes or more, because the host path just did not exist. FreeBSD 11.4's namei fails a component above NAME_MAX and a path of MAXPATHLEN bytes with ENAMETOOLONG. Check both limits on the guest string before it is resolved; FilesystemError already maps the error to 63.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
bind, listen, accept, connect, shutdown, getsockname, getsockopt, setsockopt, send, recv and the other calls that look up a guest socket answered EBADF for a descriptor that is open but not a socket, for example a pipe end. FreeBSD 11.4's getsock_cap fails these with ENOTSOCK and keeps EBADF for a closed or invalid descriptor.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The Windows build failed agc_performance_trace: ReplaceGzipFile made the
write fail by putting a directory at <name>.tmp, so the std::ios_base::failure
came out of libstdc++'s ofstream and could not unwind to the test's catch on
Windows.
The test now blocks the move instead, with a directory at the destination:
MoveFileExW (or rename) fails and ReplaceGzip throws std::system_error from
the driver's own code. ReplaceGzip also removes its temporary file when the
move fails, and the test checks that the blocked destination, the missing
temporary file and the other benchmark file are as expected.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
bind, connect and sendto answered EFAULT for an address length below 2 and EAFNOSUPPORT for an AF_INET address below 16 or an AF_INET6 address below 28 bytes. FreeBSD 11.4's getsockaddr fails a length below 2 with EINVAL and above SOCK_MAXADDRLEN (255) with ENAMETOOLONG, and the protocols compare the length with sizeof(struct sockaddr_in) or sockaddr_in6 and fail with EINVAL.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
sceNpGetAccountId and sceNpSetGamePresenceOnline report NP as signed
out, and sceNpUnregisterPlusEventCallback returns 0 like the premium
form.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A domain program that picks one of its patch's control points from data
(Onimusha: Way of the Sword, PPSA27836, selects a corner with v_cmp and
v_cndmask before a buffer_load from the off-chip ring) was refused with
"the tessellation ring or LDS address is not affine in the control point
and relative patch". Computed indices were accepted only for hull LDS
reads.
- The address evaluator gives off-chip EvaluationInput reads the same
dynamic term as hull LDS reads, and a value read from the patch's own
ring or LDS no longer counts as depending on the relative patch index,
since the lowered read takes the patch implicitly.
- When the program also uses its relative patch index as data, the
index is replaced by the grouped patch instead of 0, which left a
computed read's address pointing into another patch. Such reads now
subtract their relative patch term, for hull and domain reads alike;
reads in programs that do not use the index as data keep their address.
- The computed offset must be a whole number of control points, and the
backend clamps the domain gl_in index to the last output control point
as it already does for hull reads.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
strrchr passed its int argument to the host strrchr unchanged. On Windows the
host compares it with the signed char bytes of the string, so a byte of 0x80 to
0xFF passed as an unsigned value (0xE9) or a value above 255 (0x12F) was not
found, where FreeBSD converts the argument to char first.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The controller information reported 1920 by 943, the DualShock 4 height with
the DualSense pixel density, while the host controller's fingers were scaled to
1920 by 942 and the keyboard touch contacts sat on the 942 centre line. A title
that maps touch coordinates through the reported resolution lost the lower part
of the touchpad. The width and height now live beside the pad state and all
three places use them.
agc_trimmed_import fails on Windows with NVIDIA and AMD drivers at the
1440 KiB unmap case: after the pages are mapped again, the import of the
whole range has the same VkDeviceMemory handle as the first import.
In that case the first import is not kept: its kept side has a new backing
serial, so the trimmed memory is released and freed by the recorder syncs
of the checks that follow. The driver then hands the freed handle value to
the new import of the whole range, so the comparison with the first
import's handle fails even though that memory no longer exists.
Compare the remapped import with the kept side's import instead, which is
still alive or held by the recorder when the whole range is imported
again. In the cases that keep the trimmed import this is the first import,
as before.
AI-assisted: yes
socketpair accepted SOCK_CLOEXEC but left both descriptors out of the
close-on-exec set, so F_GETFD read 0 on them. FreeBSD 11's
kern_socketpair opens both files with O_CLOEXEC when the type carries
SOCK_CLOEXEC, as socket already does here.