[all-commits] [llvm/llvm-project] bacd87: [lld][MachO] Preserve __eh_frame ordering during B...

Karim Alweheshy via All-commits all-commits at lists.llvm.org
Tue May 26 10:20:36 PDT 2026


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: bacd876134494c69d02b4509e125c47b5e86d3d2
      https://github.com/llvm/llvm-project/commit/bacd876134494c69d02b4509e125c47b5e86d3d2
  Author: Karim Alweheshy <9082720+karim-alweheshy at users.noreply.github.com>
  Date:   2026-05-26 (Tue, 26 May 2026)

  Changed paths:
    M lld/MachO/BPSectionOrderer.cpp
    A lld/test/MachO/eh-frame-ordering.s

  Log Message:
  -----------
  [lld][MachO] Preserve __eh_frame ordering during BP section sorting (#191412)

The Balanced Partitioning section orderer collects all live
`ConcatInputSection`s as candidates for content-similarity reordering.
This includes `__eh_frame` CIE and FDE records, which have internal
ordering constraints: each FDE contains a backward-relative 32-bit
offset to its parent CIE, requiring CIEs to precede their FDEs.

When the BP orderer assigns priorities to `__eh_frame` subsections and
`Writer.cpp` sorts by those priorities, FDEs can end up before their
parent CIEs. The resulting CIE-pointer offsets resolve correctly with
32-bit wrapping arithmetic but underflow with 64-bit pointer arithmetic,
causing DWARF consumers (crash reporters, debuggers) to silently lose
unwind data.

## Fix

Have the BP orderer skip the Mach-O `__TEXT,__eh_frame` section
explicitly before collecting candidate subsections, preserving the
existing CIE/FDE order without adding state to `Section`.

This is the only MachO section with this constraint:
- `__unwind_info` is a `SyntheticSection` (not a `ConcatOutputSection`),
so it never enters the BP pipeline
- `__gcc_except_tab` LSDA entries are referenced by absolute offset, so
reordering is safe
- `-order_file` is unaffected because it assigns priorities through
symbol definitions (which live in `__text`, not `__eh_frame`). Only the
BP orderer enumerates sections directly.

## Production impact

Verified on a large iOS application (~218 MB binary, ~34,000 FDEs)
linked with `lld` + `--bp-compression-sort=both`.

### Static analysis of `__eh_frame`

Simulating 64-bit CIE pointer resolution on the output binary across
multiple builds:

| Build | `__eh_frame` layout | FDEs resolved (64-bit) | FDEs failed |
|---|---|---|---|
| lld + BP sort | FDEs first | 15 / 34,257 | **34,242 (99.96%)** |
| lld + fix | CIEs first | 30,558 / 30,558 | **0** |

### Runtime verification

Proxied crash report uploads from a device running both the affected and
fixed binaries:

|  | Affected build | Fixed build |
|---|---|---|
| Threads captured | 3 | 24 |
| Total frames | 28 | 135 |
| Background threads | 0-2 | 23 |

The affected build lost ~85% of thread data. The crash reporter could
only unwind the crashed thread (via compact unwind). All background
thread unwind data was silently dropped.

## Reproducer

Minimal test case (ARM64). Requires `--bp-compression-sort=both` to
trigger:

```bash
llvm-mc -filetype=obj -emit-compact-unwind-non-canonical=true \
  -triple=arm64-apple-macos11.0 test.s -o test.o
ld64.lld -arch arm64 -platform_version macos 11.0 11.0 \
  -syslibroot $(xcrun --show-sdk-path) -lSystem -lc++ \
  test.o -o test --bp-compression-sort=both
llvm-objdump --dwarf=frames test
# Without fix: "error: parsing FDE data at 0x0 failed due to missing CIE"
# With fix: CIE records correctly precede their FDEs
```

Standalone reproducer with 64-bit CIE simulation script:
https://gist.github.com/karim-alweheshy/ae28196c4fbb295f81cc793cfbe0c1b7

## Test

The lit test creates multiple functions with `cfi_escape` (forcing DWARF
unwind mode) and different personality functions (producing separate
CIEs), then links with `--bp-compression-sort=both`. Verified on both
x86_64 and arm64.

Made with [Cursor](https://cursor.com)

---------

Co-authored-by: Karim Alweheshy <karim.alweheshy at reddit.com>
Co-authored-by: Ellis Hoag <ellis.sparky.hoag at gmail.com>



To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications


More information about the All-commits mailing list