Skip to content

fix(relinker): ignore unwind records that cover no code - #6619

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
Get-fix:ps4/relinker-zero-length-fde
Oct 19, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
Get-fix:ps4/relinker-zero-length-fde

Conversation

@Get-fix

@Get-fix Get-fix commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

What

An FDE whose address range is 0 describes no instructions, and an unwinder never matches a pc in it. The exception-table reader rejected one, which stopped the conversion of Limbo (CUSA01664) on main 5d9dcc42d:

FAIL: Strict filter: inconsistent FDE function range (offset 0x3f4ffc)

One of Limbo's 17328 FDEs covers 0 bytes at 0x47dd0, where the next record starts. Such a record is now read and validated as before, but left out of the function list. A record whose start differs from the .eh_frame_hdr entry, or whose range overflows, is still rejected. Part of the PS4 work tracked in #3093.

Tested

Windows 11 Pro 26200, WinLibs GCC 15.2.0 r7, Release, on main 5d9dcc42d:

Not tested on Linux or macOS hosts.

Checklist

🤖 Generated with Claude Code

An FDE whose address range is 0 describes no instructions, and an
unwinder never matches a pc in it. The exception-table reader rejected
it with "inconsistent FDE function range", which stopped the
conversion of Limbo (CUSA01664): one of its 17328 FDEs covers 0 bytes
at 0x47dd0, where the next record starts. Such a record is now read
and left out of the function list.
@simonbbby

Copy link
Copy Markdown
Contributor

Independent Linux and native macOS parser coverage for exact head a9fa0e8b088432e6a7ba7182390a41ff31648550, filling the host gap in the description.

  • Ubuntu 24.04 / GCC 13.3 / x86-64, and macOS 27.2 / Apple clang 21 / arm64.
  • Compiled the unchanged UnwindRecordBoundsTests.cpp, EhFrameReader.cpp and BufferUtils.cpp, using the include directories of unwind_record_bounds_tests. The stock test reports 14 cases passed on both hosts. Substituting only EhFrameReader.cpp from HEAD^ fails on both with Strict filter: inconsistent FDE function range.
  • An external probe reuses Fixture() and sets the FDE range at offset 112 to zero while retaining eight existing malformed CIE/FDE/segment cases, plus a mismatched .eh_frame_hdr start. All nine malformed zero-length cases remain rejected on both hosts.
  • Both the stock test and external probe also pass with AddressSanitizer + UndefinedBehaviorSanitizer on both hosts, with no diagnostics.

One small extra regression is worth keeping: a zero-sized FDE whose start disagrees with its header entry. In a scratch production copy, returning an empty region immediately after reading size == 0 still passes all 14 stock cases, but the external probe catches this malformed record on both hosts. Current PR code correctly rejects it. The case is:

auto bytes = Fixture();
Io::WriteU64(bytes, 112, 0);
Io::WriteU64(bytes, 16, 0x2001);
bool rejected = false;
try { Relinker::UnusedNidFilter::ReadExceptionFunctions(bytes, {load, eh}, {}, {}); }
catch (const std::exception&) { rejected = true; }
Require(rejected);

No repository source changed. Scope: the production exception-table reader and synthetic byte fixtures; no full relinker/CTest build, Limbo conversion, guest execution or Rosetta run. The existing Windows title-conversion evidence remains the title evidence.

@savvaniss

Copy link
Copy Markdown
Contributor

Second-title data point: Hasbro Family Fun Pack (CUSA03312, my own dump) needs this PR, on Linux and Windows.

Relinker-only Release build, Windows 11 Pro 26300, WinLibs GCC 15.2.0 r7. Starting from main f3059421f, I merged, in this order: #7660, #6619 (a9fa0e8b0), #5138 (5f5641732), #6381 (6f8d9a09d), 3b158c1 from #6977, #6354 (81561867f), #6357 (32fe3aa8b), #6684 (ab9d21afc) and #6618 (bf06a8e5c). With that stack, the Linux and --windows conversions of the eboot and its 9 bundled modules complete. I then rebuilt the relinker once per member with only that member left out. Without this PR, both targets stop in the eboot:

FAIL: Strict filter: inconsistent FDE function range (offset 0xd42390)

The other members each stop at their own step, so every one of them is needed for this title; the whole table is on #6977.

AI-assisted: yes (Claude Code)

@adriadam10

Copy link
Copy Markdown
Collaborator

Checked: a zero-range FDE is still read and validated (start vs .eh_frame_hdr, overflow) and only dropped from the function list; the new case in unwind_record_bounds pins it and fails without the change. Relinker CI green on Linux, macOS and Windows, plus the independent Linux/macOS and Hasbro runs in the thread. Merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

relinker unblocks title Names a title ID on the Unblocks line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants