Repository navigation
fix(relinker): find the PLT before the code in PS4 modules - #6354
Open
SandstromPL wants to merge 2 commits into
Open
SandstromPL wants to merge 2 commits into
SandstromPL wants to merge 2 commits into
Conversation
This was referenced Oct 15, 2026
|
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.
|
This was referenced Oct 15, 2026
This was referenced Oct 15, 2026
FindSceCodeEnd looked for the PLT only after the last function of the unwind table and failed with "PLT not found after the last unwind function" otherwise. The libSceFios2.prx and libc.prx that Until Dawn (CUSA02636) bundles have their PLT at 0xc8, at the start of the text segment, before the code. In both, the last unwind function is followed by the module's DT_FINI routine, which has no unwind entry, and then by read-only data. When no PLT follows the last unwind function, the search now also looks before it. A PLT found there must not overlap an unwind function, and the code extent then ends at the last unwind function, so what follows it stays out of the scans and the code analysis, including code without an unwind entry such as the DT_FINI routine of both modules (recorded in the debt file). A missing PLT now fails with "PLT not found before or after the unwind functions". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
12 tasks done
SandstromPL
force-pushed
the
fix/relinker-plt-before-code
branch
from
October 16, 2026 04:40
b5b4617 to
051dac9
Compare
10 of 11 tasks
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>
|
Windows check of 8156186 merged onto current Windows 11 Pro 26200, WinLibs GCC 15.2.0 r7 UCRT, Ninja, Release,
Negative control: with Not run: titles or homebrew. AI-assisted: yes |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Until Dawn (CUSA02636) bundles
libSceFios2.prxandlibc.prx(01.00). Their conversion stops in the code analysis, forlibSceFios2.prxwith:SuperCatElvis reported it on #3093 as stop 9 of the title's conversion, on
maind92a8da. They reached it after #5138 and scratch fixes for the other stops before it. Both modules have their PLT at 0xc8, at the start of the text segment, before the code. InlibSceFios2.prxthe last unwind function ends at 0x3d033, and what follows is the module'sDT_FINIroutine at 0x3d040, 0x7d bytes without an unwind entry, then read-only data that includes the zlib CRC-32 table.libc.prxhas the same layout: itsDT_FINIroutine at 0x828a0 follows its last unwind function [0x82890, 0x82896), and about 213 KiB of read-only data follow the routine.#3142 (Get-fix's commit, carried by MarcZX100) stopped the pipeline's syscall and call-site scans of executables at the end of the PLT that follows the last unwind function, so that the read-only data after the code is not decoded as code. My #5195 moved that search into
FindSceCodeEndand applied the same end to the code analysis of the Windows and macOS outputs, for executables and guest modules. The search only looks after the last unwind function, so these two modules fail there.When no PLT follows the last unwind function,
FindSceCodeEndnow also looks before it:push [GOT+8]; jmp [GOT+16]) anywhere from the start of the segment up to the end of the last unwind function.DT_SCE_PLTRELSZentry) must not overlap an unwind function. Otherwise the conversion fails withPLT overlaps an unwind function.overlapping instruction boundaries (offset 0x3d1fe)inside the CRC-32 table.PLT not found before or after the unwind functions.A PLT after the code, as in the executables converted so far, is found first, with the same result as before. That includes #5195's case of code without unwind entries between the last function and the PLT.
When the PLT comes first, there is no PLT after the code to bound the extent. The end of the last unwind function is then the only bound that doesn't guess the length of code without an unwind entry. #3093 ruled this bound out for the PLT-after layout because code without unwind entries can sit before the PLT, and that layout is unchanged. The cost: when the PLT comes before the code, code after the last unwind function that has no unwind entry is not analysed, and nothing reports it. An entry point, a branch target or an
fs:access found there is dropped without an error; the debt entry records this.DT_FINIroutine, which the Windows and macOS outputs call when the program exits (WindowsGuestStartup::Finalize, and the fini stub thatMacOsImage.cppregisters with__cxa_atexit). The code analysis starts fromDT_FINIonly inside the extent, so both routines are dropped, and anfs:access in one would run unchanged on the host.libSceFios2.prxroutine makes nofs:access, and that thelibc.prxone reads the pointer at 0xbc880 and calls 0x2fa50 through it; I've asked whether that one has anfs:access. The code analysis rewrites no indirect call: the relocation sets the pointer, and 0x2fa50 is already a root as a function symbol (symbol 1411 in SuperCatElvis's table), and with fix(relinker): accept matching defined relative symbols #6357 also as a relocation target.libc.prx's RELATIVE relocation with a symbol, which MarcZX100's fix(relinker): accept matching defined relative symbols #6357 handles.libc.prx, and [0xc8, 0x5d8) before 0x5e0 inlibSceFios2.prx, each followed by 8 zero bytes.Tested
Ubuntu 24.04, GCC 13.3, Release with
BUILD_TESTING=ON, onmain71bd287. Locally the libusb submodule isn't checked out, so I removed its two lines fromCMakeLists.txt.libSceUsbdthen fails to compile, andninja -k 0built everything that does not depend on it.sce_code_extent(relinker/tests/test_sce_code_extent.py) can now put the PLT before the code: at 0x180, before the unwind function at 0x200, with the data right after the function. It can also add a second unwind function before the PLT, and put an unsupported TLS instruction in the function. As in #5195, the fixture is converted as the main executable (--skip-sce-module), so each case goes through both callers. No case converts ansce_modulemodule. A module likelibSceFios2.prxreaches the sameFindSceCodeEndonly through the code analysis, which the Windows and macOS guest module writers run on the module's own bytes and program headers.leain the function pointing into the data after it, atfs-prefixed overlapping bytes (the shape of stop 10)Unsupported ... guest TLS instruction, so the function after the PLT is still analysedPLT overlaps an unwind functionPLT not found before or after the unwind functions(renamed)On
mainall 15 cases fail withPLT not found after the last unwind function. With the change they pass, 5 runs out of 5. The test also fails if:Cannot decode instruction);invalid function range).The registry check in the test now compares call sites case-insensitively: the relinker writes
0x1F0, and earlier PLT addresses happened to have no hex letters.Other checks:
cteston the RTX 3050 Ti: 1,243 of 1,248 pass, and all relinker tests pass.agc_driver_stencil_ref_exporton this GPU, and the VideoOut flip and frame-dump tests, which need a display.patched_librariesandguest_usbdare Not Run, because the libusb submodule isn't checked out.agc_pending_key_storesfails onmainsince perf(agc): clear a register fast clear without waiting for a known key store #6247, as reported there.agc_driver_store_over_untrackedfails 6 runs out of 10 when run alone here.guest_kernel_fcntlaborted once underctest -j10, and then passed 10 runs out of 10 when run alone.main5d9dcc4. 28 open PRs touch these files, all throughdocs/dev/debt/relinker.md; 19 of them are yabanana's stacked AOT PRs, which already conflict withmainin other files, and this branch adds no conflict to them. Only fix(relinker): stop module syscall scans at the PLT and skip the PS4 loader path #5994 (Get-fix) gets a new conflict, in the one debt line both rewrite.mainf03a2da (8156186), resolving that hunk as planned. fix(relinker): stop module syscall scans at the PLT and skip the PS4 loader path #5994'ssce_modulesyscall-scan line now says the scan stops "at the same end, or, when the PLT comes before the code, at the end of the last function of the unwind table", because its scan callsFindSceCodeEnd. The collector line keeps fix(relinker): stop module syscall scans at the PLT and skip the PS4 loader path #5994's/libexec/ld-elf.so.1start with this PR's end.sce_module_code_extentand this PR'ssce_code_extent.tools/check_conventions.pyfrommainpasses with this title and body.@SuperCatElvis, thanks for the answers on #3093. If you can, could you swap this in for your stop-9 change and check that both modules get past stops 9 and 10?
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)libc.prxandlibSceFios2.prx); CUSA03312 Hasbro Family Fun Pack (CUSA03312) #7198 (Hasbro Family Fun Pack: stop 8 in savvaniss's conversion); CUSA02636 (no Game bring-up discussion): stops 9 and 10 of SuperCatElvis's conversion on Relinker rejects PS4 executables: SCE dynamic tables and data in the code segment (two ready branches) + remaining PS4 work #3093, in the bundledlibSceFios2.prxandlibc.prx. They were reached after fix(relinker): accept section-relative guest module relocations #5138 and scratch fixes for the other stops from 1 to 8; stop 1, the eboot's jump tables, still stops the title onmain, and stop 11 (fix(relinker): accept matching defined relative symbols #6357) follows. Not rerun here.cteston NVIDIA GeForce RTX 3050 Ti Laptop GPU, driver 580.178.04, Ubuntu 24.04🤖 Generated with Claude Code