Repository navigation
fix(relinker): skip jump tables placed right after a function's unwind range - #7620
Closed
DealPotato wants to merge 2 commits into
Closed
DealPotato wants to merge 2 commits into
DealPotato wants to merge 2 commits into
Conversation
PS4 titles built with Sony's toolchain place a switch statement's jump
table in the code segment, after the last instruction of the function
that indexes it and inside the function's unwind range:
lea rcx, [rip + table]
movsxd rax, dword ptr [rcx + rax*4]
add rax, rcx
jmp rax
Code analysis decodes each function range from start to end, so it read
the table as instructions; the syscall scan and the call-site resolver
sweep the whole segment and lost their instruction boundaries there.
Limbo (CUSA01664) stopped at "Unsupported Windows guest TLS instruction
(bytes: 65 f9)" and Bloodborne (CUSA00900) at "Instruction exceeds 15
bytes".
FindInlineJumpTables decodes a function range, follows the table
address of each RIP-relative lea through 64-bit register moves, and
records the address a movsxd with scale 4 indexes when it lies later
in the same function. When decoding reaches the first such address and
every dword from there to the end of the function is an offset, from
the nearest table before it, to code before the first table, the rest
of the function is taken as tables. Anything else is decoded as before.
Code analysis stops each function there and keeps the control-flow
pass out of the tables; the pipeline fills them with nops in the copies
the syscall scan and the call-site resolver read.
…d range Some PS4 executables place a switch table after the FDE of the function that reads it. The function ends in a call to a noreturn function, and the table follows immediately. inFAMOUS Second Son (CUSA00004) does this at 0x64d0c4, right after a function whose unwind range ends at 0x64d0c3. The function's lea of the table base was added as a code root, so code analysis decoded the table entries, and the conversion stopped with "Unsupported Windows guest TLS instruction (bytes: 65 ff ff)". FindTrailingJumpTables tracks the same lea and movsxd table loads as FindInlineJumpTables, but for bases between the function's end and the next function. A table ends at the first entry whose target falls outside the function. The code collector treats such tables as inline data, and the pipeline fills them with nops before the syscall scan, as it already does for tables inside the function. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
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.
|
12 tasks done
Contributor
Author
|
Closing in favour of #6595, which handles the same case and converts the Second Son eboot that motivated this PR. |
11 tasks done
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
Some PS4 executables put a switch jump table right after the FDE of the function that reads it. #6618 only finds tables inside the function's unwind range, so code analysis decodes such a table's entries as instructions and the conversion stops.
inFAMOUS Second Son (CUSA00004) does this:
0x64c870has an FDE ending at0x64d0c3. It ends with a call to a noreturn function (call 0x984360) and anop.0x64d0c4:lea rcx, [rip+0x6dd]at0x64c9e0, thenmovslq (%rcx,%rax,4),%rax.leaadds0x64d0c4as a code root, and the conversion fails:The change:
FindTrailingJumpTablestracks the sameleaandmovsxdtable loads asFindInlineJumpTables, now shared through one helper. It does this for table bases between the function's end and the next function, or the end of the code segment.CodeInstructionCollectoradds these tables toinlineData, so the CFG neither enters them as roots nor reaches them by fall-through.RelinkerPipelinefills them withnopbefore the syscall scan, as it already does for tables inside the function.test_sce_inline_jump_tables.pygains atrailingfixture: theplaintable with the FDE ending at the table. Without the change, it fails withCannot decode instructionat the table.Tested
--windows --skip-sce-module. On this branch without the last commit, i.e.main+ fix(relinker): skip jump tables placed after a function's code #6618, it fails with the error above. With it, it converts.libc.prxandlibSceFios2.prxconvert.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 (none added).mdfiles or images added to the repository