fix(recomp): register resume points for standalone entry_* functions - #271
Open
drakolordx7 wants to merge 1 commit into
Open
drakolordx7 wants to merge 1 commit into
drakolordx7 wants to merge 1 commit into
Conversation
discoverAdditionalEntryPoints() skipped every function whose name starts with "entry_" when collecting resume targets, on the assumption that they are synthetic wrappers that live inside a real function (the ones DiscoverAdditionalEntryPoints() itself creates for mid-function targets). Their owner then supplies the resume points. That does not hold for entry_* labels that come from a symbol or function map: Ghidra exports standalone code blocks (static initializers, thunks, code the analyzer did not attach to a function) as entry_<addr>, and they are not inside any other function. Those were skipped with nothing to cover them, so a thread switched out inside a call made from such a block (JAL return address, loop head, ...) had no registered resume point and could never be resumed at it. Skip an entry_* function only when it lies inside the range of a non-entry function; standalone ones now collect their own resume targets like any other function. The nested check uses a sorted interval lookup, so it stays cheap for maps with tens of thousands of entry_* blocks. Found in a game whose map names ~65k standalone blocks entry_*; a static constructor block (entry_004186f0) switched out inside a call never came back. The new recompiler test generates a tiny ELF with a standalone entry_* block containing a JAL and checks that the return address is registered; it fails without the change. Made by drakolord and assisted with Claude Code.
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.
discoverAdditionalEntryPoints()skipped everyentry_*function when collecting resume targets, assuming they are synthetic wrappers nested in a real function. Ghidra also exports standalone code blocks (static initializers, thunks) asentry_<addr>. Those got no resume points, so a thread switched out inside a call made from one could never be resumed.Now only
entry_*functions inside a real function's range are skipped (sorted interval lookup, cheap for tens of thousands of blocks). Games with many standaloneentry_*blocks get a few more resume cases in the generated output.The new test builds an ELF with a standalone
entry_*block containing aJALand checks that the return address is registered; it fails without the change.ps2x_tests437/437.Made by drakolord and assisted with Claude Code.