autorun_exit_tests built its own path from argv[0] and
windows_dependency_diagnostics_tests from GetModuleFileNameA. Both are in
the ANSI code page on Windows, but MinGW's std::filesystem::path reads a
narrow string as UTF-8, so in a build directory with characters such as
"ü" both tests stopped with "Cannot convert character sequence: Illegal
byte sequence" before testing anything (windows_diagnostic_fixture_isolation
runs the second one).
Take the path from GetModuleFileNameW on Windows. The relinker and the
generated diagnostic runner already use UTF-8 and wide APIs, so nothing
else changes.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Resolves the conflict with #8867 in EntryStubTests.cpp: keep its two
kernel-variant tests and the BufferUtils include, and this branch's
libSceAmpr-to-libc fallback test, with all three called from main.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
windows_import_identity generates two probes with the entry stub builder, as the diagnostics
test does, and runs them next to the patched libraries: same.exe imports the three locale objects
of #8875 twice, qualified to libSceAmpr.prx and to libc.prx, and exits 0 only if each pair
resolved to one address; different.exe compares the first with libkernel's getpagesize and must
exit 1. That pins the fallback from a host module to libc at run time, independently of how the
stub builds its search order.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
windows_dependency_diagnostics rewrites the fixture images right after the
diagnostic runner exits. The runner ends with an unhandled RaiseException of
STATUS_DLL_NOT_FOUND, and Windows fault handling keeps the exited process's
image files open for a short time after its handle is signaled: on Windows 11
22621 the Restart Manager names the exited runner as the holder and the file
opens 37 to 153 ms later. The rewrite then fails with ERROR_SHARING_VIOLATION,
and the final removal of the fixtures with access denied. Retry opening a
fixture while it fails with a sharing violation and the removal while it fails
with access denied, for at most 10 s each; every other failure still fails the
test at once.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Outputs whose input carries no PT_GNU_STACK get one appended with
PF_R|PF_W and alignment 16 so the kernel does not fall back to an
executable stack marking.
RequiredProgramHeaderCount and WriteLayout now derive from one shared
header list, so the reserved slot and the written header cannot
disagree at any PhNum boundary, when a free input slot should be
reused, or when the RELRO coverage guard reduces the kept count.
Space exhaustion beyond the 16-bit header limit fails loudly instead
of silently skipping the header.
On Linux the kernel maps each PT_LOAD from the start of its first page.
When a segment begins inside the page that holds the end of the previous
segment's zero-filled memory, that page is mapped again from the file, and
the bss tail reads whatever bytes precede the segment in the file. Nuvio
Max'd 0.5.27 (PPSA99288) keeps a mutex there and crashes at launch.
A segment whose page would read wrong bytes is now appended to the output
with that page prefix rebuilt from the segments below it. Outputs whose
pages already read right are unchanged.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
AnyPS5 exports some libkernel functions, such as __error, from
libc.prx, which libkernel.prx links. On Linux they resolve through that
dependency. On Windows, the import stubs search only the listed
modules, and libc.prx was listed only when libSceLibcInternal.prx was
needed. A PS4 homebrew that needs libkernel.prx but no C library (the
OpenOrbis graphics sample) failed with "unresolved ELF import
9BcDykPmo1I". libc.prx is now also listed when libkernel.prx is needed.
PS5 executables need libSceLibcInternal.prx and convert unchanged.
When a relinked executable fails to load a staged module, the dependency
diagnostics routine maps the same path as an image resource to walk its
imports. If that mapping failed it printed only "FAIL: dependency
diagnostics Windows API failed". The log then did not say whether the
staged module itself (libs\libSceRegMgr.prx in #4720) was absent or was
not a Windows image, and a module reached through another module's
imports was not named at all.
The register routine now reads GetLastError when LoadLibraryExW fails.
ERROR_FILE_NOT_FOUND and ERROR_PATH_NOT_FOUND print "dependency module
not found", ERROR_BAD_EXE_FORMAT prints "dependency module is not a
Windows PE image"; both name the module path, its importer and the
chain from the executable, like the existing missing-module report.
Other errors keep the generic message. An API set contract that
LoadLibraryExA reports as ERROR_MOD_NOT_FOUND now gets the
missing-module report too.
Refs #4720
Co-Authored-By: Claude Opus 5.5 <[email protected]>
ComputeExtraBlockVaddr kept the ELF congruence p_vaddr == p_offset (mod 0x1000)
and bumped the result by one page only when it fell below the highest guest
load end as a byte address. When that end is not page aligned and the extra
block's file offset remainder reaches it, the extra RWX PT_LOAD landed in the
same 4 KiB page that holds the tail of the highest guest segment. The kernel
maps each PT_LOAD page by page with MAP_FIXED in program-header order, so the
extra block's file page replaced the guest's .data tail and zero-filled .bss
there.
Round the highest kept PT_LOAD end up to the page before adding the offset
remainder, which is the placement GuestModuleWriter::WriteLinux already uses
for the guest module. Only the overlapping case changes; an end that is page
aligned or a remainder below it yields the same address as before.
The extra PT_LOAD now also spans to the end of its own page in p_memsz, so the
page it takes over is fully covered, and its vaddr is derived in WriteLayout
instead of being taken from the request. The header block load carries the
same flags as before.