Repository navigation
fix(relinker): stop module syscall scans at the PLT and skip the PS4 loader path - #5994
Conversation
…loader path OpenOrbis modules keep read-only data after their code, as executables do. The syscall scan of sce_module modules decoded it, and the module of the OpenOrbis library sample (libExample.prx) failed with "Forbidden syscall instruction". For modules with a PT_SCE_DYNLIBDATA segment, the scan now stops at the end of the PLT after the last unwind function, found by FindSceCodeEnd as for executables. The same modules begin their executable segment with the /libexec/ld-elf.so.1 string but have no PT_INTERP header, so code analysis decoded the string and failed with "Unsupported Windows guest TLS instruction (bytes: 64 2d 65 6c 66 2e)", which is the text "d-elf.". When no PT_INTERP header covers the start of a PS4 code segment, code analysis now starts after that exact string.
jotitadev
left a comment
There was a problem hiding this comment.
macOS data point: the --macos target hits the same loader-path failure, and this PR fixes it there too.
Apple M2 Max, macOS 27.2 (26B5091g), AppleClang, Ninja Release, relinker-only. Head 8997cac1b merged without conflicts into main c26982f63.
- arm64: ctest 164/164.
- x86_64 under Rosetta 2 (
-DCMAKE_OSX_ARCHITECTURES=x86_64, Python 3.9.6): 160/164; the 4 failures (pr_overlap_encoding,stubgen_stdout_newlines,release_package,linux_fixed_base) fail the same way on unmodifiedmainhere. sce_module_code_extentwith only the test applied onmainfails on both builds withUnsupported Windows guest TLS instruction (bytes: 64 2d 65 6c 66 2e) (offset 0x100a); with the PR it passes.
The test converts both fixtures with --windows only. I ran the same two fixtures (fixture(rodata_address=False, interp_header=False) and sce_module() from the test) through every target, same results on the arm64 and x86_64 binaries:
| Target | Fixture | main |
This PR |
|---|---|---|---|
| Linux (default) | loader path, no PT_INTERP |
converts | converts |
| Linux (default) | module with data after code | Forbidden syscall instruction at code offset 0x1020 |
converts |
--macos |
loader path, no PT_INTERP |
Unsupported macOS guest TLS instruction (bytes: 64 2d 65 6c 66 2e) (offset 0x100a) |
converts |
--macos |
module with data after code | Forbidden syscall instruction at code offset 0x1020 |
converts |
--windows |
loader path, no PT_INTERP |
Unsupported Windows guest TLS instruction ... |
converts |
--windows |
module with data after code | Forbidden syscall instruction at code offset 0x1020 |
converts |
So the syscall-scan part matters on all three targets and the loader-path part on macOS and Windows; this covers conversion on the Linux and macOS hosts the description lists as untested. Running the fixtures with --macos as well would keep the macOS TLS path under test.
Written with AI assistance (Claude Code). I ran the builds and tests above on my machine.
|
Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
The two fixtures were converted for Windows only. They now run for Linux, Windows and macOS. The syscall scan of a module with data after its code fails on all three without the fix, and the loader path without PT_INTERP fails on Windows and macOS, so the macOS code analysis stays under test.
|
@jotitadev Thanks for running it on macOS. I followed your suggestion: Get-fix/AnyPS5@f7ec358ec converts both fixtures for Linux, Windows and macOS. I checked each target without each part of the fix, using
The relinker-only ctest passes (165/165). I checked the overlap the bot lists. I fetched each listed pull request and, for every file it shares with this one, merged its change with The bot lists 24 pull requests, with 45 shared files between them. This pull request adds a conflict in three:
Combined build: I built
AI-assisted: yes (Claude Code). I ran these checks myself on Windows 11. 🤖 Generated with Claude Code |
|
Checked on the head merged onto current main: relinker-scope build and ctest (137 tests) pass, and |
Resolve the docs/dev/debt/relinker.md conflict with boykopovar#5994: keep its sce_module syscall-scan entry, which now also stops at the end of the last unwind function when the PLT comes before the code (it calls the same FindSceCodeEnd), and its /libexec/ld-elf.so.1 start in the code analysis entry, with this PR's end for a PLT before the code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What
OpenOrbis modules (
sce_module/*.prx) stop in the relinker at two places after #5138, which makes their section-symbol relocations convertible. Both are about where a module's code is, so they are one change.sce_modulemodules decoded that data, and the library sample'slibExample.prxfailed withFAIL: Forbidden syscall instruction at code offset 0xd016e. For modules with aPT_SCE_DYNLIBDATAsegment, the scan now stops at the end of the PLT after the last unwind function, found byFindSceCodeEndas for executables (fix(relinker): keep code analysis inside the code extent of PS4 executables #5195)./libexec/ld-elf.so.1string but have noPT_INTERPheader, so code analysis decoded the string and failed withFAIL: Unsupported Windows guest TLS instruction (bytes: 64 2d 65 6c 66 2e) (offset 0x400a), which is the textd-elf.. When noPT_INTERPcovers the start of a PS4 code segment and the segment begins with exactly that string, code analysis starts after it.The relinker debt file records that code after the PLT is not scanned. Part of the PS4 homebrew work tracked in #3093.
Tested
Windows 11 Pro 26200, WinLibs GCC 15.2.0 r7, Release, on
maine442f4c2e:sce_module_code_extenttest builds two modules: one whose text starts with the loader path and has noPT_INTERP, and one with data after the code. Both fail onmainand pass with this change. Reverting either part makes it fail.main.using_librarywith fix(relinker): accept section-relative guest module relocations #5138 merged:mainwith fix(relinker): accept section-relative guest module relocations #5138 stops at the syscall scan; with this change and without the loader-path part, it stops at the TLS instruction above. With both, the program converts, starts and calls into the module (onmaine442f4c2ewith the other changes listed in Relinker rejects PS4 executables: SCE dynamic tables and data in the code segment (two ready branches) + remaining PS4 work #3093):test string: Hi I'm from the library! You passed: 13371338 | rv = 0x00000000.tools/check_conventions.py --base origin/mainpasses.Not tested on Linux or macOS.
Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)using_librarysample also needs fix(relinker): accept section-relative guest module relocations #5138using_library), Relinker rejects PS4 executables: SCE dynamic tables and data in the code segment (two ready branches) + remaining PS4 work #3093🤖 Generated with Claude Code