The PE writer marked relocatable executables HIGH_ENTROPY_VA. Windows
then places the main thread stack, TEB, PEB and the loader threads'
stacks, which exist before libc reserves the guest arena from
0x2_0000_0000, anywhere in the first TiB. Nearly half the time they
land inside the arena and stay there as holes that fixed guest
mappings cannot use.
DllCharacteristics is now 0x140 (DYNAMIC_BASE, NX_COMPAT). The image
is still relocated and bottom-up allocations keep the 8-bit
randomization, but they start near the bottom of the address space,
far below the arena. DLL placement does not depend on this flag.
windows_address_space checks the flags and, on Windows, runs a
relinked guest that returns the high dword of its stack pointer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A title that ships sce_module/libc.prx makes addHost drop the host
libc.prx from the executable's dependencies. Every host prx needs it, but
their DT_RUNPATH is empty, so loading fails with "libc.prx: cannot open
shared object file".
Mirror the Windows rule from WindowsImportBuilder: when libSceLibcInternal.prx
is a host dependency and no host libc.prx remains, append libc.prx as the
last host dependency. The title's own imports still bind to the guest
modules first.
Refs #476
Preserve each bundled module directory under app0 and resolve Linux dependencies across directories. Add integration coverage for both output formats and Windows startup. Refs #556; duplicate-export rejection remains unchanged.
SHA1RNDS4/NEXTE/MSG1/MSG2 with a memory source made `--to-intel` fail
the whole relink. The stub now spills a scratch xmm, loads the operand
into it with the unaligned load already used for SHA-256 and runs the
register-form lowering. The SHA1RNDS4 immediate is read after the SIB
byte and displacement. RIP-relative operands still fail: the stub runs
at a different address.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The unsupported-instruction error now lists the instruction bytes, and the relink failure names the input file, the main executable or the guest module, on an extra Input: line.
Loads at fs:1 through fs:0x27 read tcb_dtv and tcb_thread on the FreeBSD layout, which the Windows thread control block does not model, so they returned zero. Accept only the TLS block, fs:0 and the stack guard at fs:0x28, and fail the relink for the rest.
SHA256RNDS2/MSG1/MSG2 with a memory source made `--to-intel` fail the
whole relink. The stub now spills a scratch xmm, loads the operand into
it with MOVDQU (AMD does not fault on a misaligned SHA operand, so the
unaligned load keeps that behaviour) and runs the register-form
lowering. RSP-based operands get the spill depth added to their
displacement. RIP-relative operands still fail: the stub runs at a
different address.
Co-Authored-By: Claude <noreply@anthropic.com>
RSQRTPS and RCPPS are approximations whose low bits differ between Intel
and AMD. Intel returns 0x3F7FF000 for 1/sqrt(1.0), and two Newton-Raphson
steps on it settle on 0.99999994 instead of 1.0. PPSA21564 renormalises
its spring quaternions that way: an identity quaternion keeps w at
0.99999994 with a zero axis, its axis-angle conversion then normalises the
zero axis into NaNs, and the NaN bone poses reach keyframed physics bodies.
A NaN body later moves to an invalid broadphase cell and the game crashes
a few seconds into its hub level.
--to-intel now replaces the VEX.128 register forms with an out-of-line stub
that computes 1/sqrt(x) with SQRTPS and DIVPS (1/x with DIVPS), keeping
the upper half of the destination cleared and the scratch register intact.
A site with no room for the jump, including one followed by a branch
target or a RIP-relative instruction, keeps the native instruction and is
reported as kept instead of failing the relink.
The APM leaves bits 127:64 of the destination undefined after EXTRQ and
INSERTQ, but hardware zeroes them, and the register-form INSERTQ stub
already does the same (#185). The other paths kept the old high qword, so
a following register-form INSERTQ that reads its length and index from
that qword computed the wrong low qword too.
Every stub path that left the high qword now ends with movq dst, dst.
The in-place PSRLQ, PMOVZX and PBLENDW forms leave it non-zero and have
no room for the movq, so those sites now take a stub. The two in-place
forms that emitted nothing now emit movq dst, dst.
Co-Authored-By: Claude <noreply@anthropic.com>
DecodeInstruction returned before the ModRM byte for VEX and EVEX and
read the third opcode byte of 0F 38/0F 3A as ModRM, so their
RIP-relative operands were never reported. --to-intel then moved such an
instruction after a short EXTRQ/INSERTQ into the stub with its
displacement unchanged, and the strict unused-import filter missed its
references.
Co-Authored-By: Claude <noreply@anthropic.com>
SHA1RNDS4, SHA1NEXTE, SHA1MSG1 and SHA1MSG2 passed through --to-intel
unchanged, so a relinked title that executes them faults on Intel CPUs
without SHA-NI. Their register forms are now lowered out of line with
SSE2 only through the shared stub builder; short sites share stubs via
MatchSequence. Memory forms fail the relink with the file offset, as for
SHA-256.
Co-Authored-By: Claude <noreply@anthropic.com>
The Linux entry stub built a copy of the entry parameter block holding
argc and a pointer to the host argv array, so the guest read that pointer
as argv[0] and uninitialised stack as argv[1..]. The process stack at
entry already has the guest's layout (argc as a qword, then the argv
pointers and a null), so pass rsp itself.
Test: linux_entry_argv relinks a fixture whose entry checks argc and
argv and runs the output on Linux x86-64.
In 64-bit mode a REX prefix only takes effect when it immediately
precedes the opcode; a REX followed by a legacy prefix or another REX is
ignored. The instruction decoder, the rewriter's reference classifier,
DecodedInstruction and the SSE4a, SHA-256 and CLZERO operand decoders
read legacy prefixes and then at most one REX. `48 F3 0F 2B 00`
(MOVNTSS) was therefore scanned as `[48 F3][0F 2B 00]` and kept, and
`48 67 0F 01 FC` lost its address-size prefix.
All of them now accept REX bytes among the prefixes and keep only one
that directly precedes the opcode. The converter's guard against
prefix-only fragments is removed, since the decoder no longer produces
them, and the TechnicalDebt entry describing the split is dropped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lower CLZERO out of line instead of failing the relink: the 64-byte line
containing rAX (EAX with 67h) is cleared with four MOVNTDQ stores of
zero, the same non-temporal, weakly ordered store. The line address is
masked in xmm0 so RFLAGS stays untouched; xmm0 and rcx are spilled below
the red zone. Short sites share stubs through MatchSequence. CLZERO with
LOCK, an FS/GS override, a 66/F2/F3 prefix or longer than 15 bytes fails
the relink.
The decoder splits a REX followed by another prefix into a separate
instruction, which would hide a prefix that changes what CLZERO or the
next instruction does. The converter now fails the relink when such a
prefix-only fragment directly precedes an AMD-only instruction or would
be moved into a stub as a trailing instruction.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refactor/split libs tests cmake
- Moved test inclusions from `core/libs/CMakeLists.txt` to local library CMakeLists.txt files.
- Created CMakeLists.txt files for `libSceSystemService, libSceContentExport, libSceNet, libSceNetCtl, libSceRandom, libSceRtc, libSceJson2, and libSceFiber`.
- The shared libSceNet/libSceNetCtl test is included in libSceNet.
- Added the shared function add_test_executable for hosting test executables.
- Added add_png_decoder(target runtimeTarget) and add_jpeg_decoder(target runtimeTarget). The runtimeTarget parameter is required; libc is currently passed. A non-existent target causes a CMake error. - The decoder is used by the PRX libraries, meaning exceptions from there should be thrown through our libc.prx.
Changed file locations relative to the build folder (previously they were stored in core/libs):
- tests/ - all test executables
- `core/libs/libs/implib/` - PRX import libraries (*.dll.a)
The number of tests found has not changed (88)
Replace MONITORX with a NOP and MWAITX with PAUSE in place, padded with
NOPs to the original length, instead of failing the relink. MWAITX may
return before its timer or a store to the monitored line, and without an
armed monitor it does not wait, so callers already re-check their
condition; the replacement takes that path every time.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>