Issue 165097
Summary LLD: CIEs do not get garbage-collected
Labels lld
Assignees
Reporter Noratrieb
    I originally found this via Rust, where a Rust shared library (cdylib) contained the personality function (`rust_eh_personality`), despite the one single exported function not unwinding anywhere. Digging deeper, I saw that the personality function was still referenced by a CIE in `.eh_frame`, a CIE that did not have any associated FDEs but was still not removed. binutils ld removes the CIE and therefore also the personality function.

This is an assembly reproducer of this problem (adapted from #28949).

```asm
.section .text.dead,"ax"
dead:
    .cfi_startproc
 .cfi_personality 3, mypersonality
    ret
    .cfi_endproc

.section .text.mypersonality,"ax"
mypersonality:
    ret

.section .text
.globl main
main:
    ret
```

Running `clang main.s -no-pie -Wl,--gc-sections -fuse-ld=lld` (`no-pie` seems to be necessary due to the way the assembler generates relocations) will have a CIE referencing `mypersonality` in the final binary. Removing the `-fuse-ld=lld`, so linking with binutils ld, will cause the CIE and personality function to not be present in the binary.

The CIE from `llvm-dwarfdump`:

```
00000044 00000018 00000000 CIE
  Format:                DWARF32
  Version:               1
 Augmentation:          "zPR"
  Code alignment factor: 1
  Data alignment factor: -8
  Return address column: 16
  Personality Address: 00000000002016e9
  Augmentation data:     03 E9 16 20 00 1B

 DW_CFA_def_cfa: RSP +8
  DW_CFA_offset: RIP -8

  CFA=RSP+8: RIP=[CFA-8]
```

`readelf -s` lists `mypersonality` as a present symbol when linked with LLD.
```
    11: 00000000002016e9     0 NOTYPE  LOCAL DEFAULT   11 mypersonality
```

I found https://maskray.me/blog/2021-02-28-linker-garbage-collection which mentions
> Personality routines or language-specific data area referenced by `.eh_frame`. ld.lld handles `--gc-sections` before `.eh_frame` deduplication, so this may retain sections than needed.

So I am not fully sure if this is deliberate behavior, since I would expect the CIE to still be removed (with the personality function present) if "`.eh_frame` deduplication" removed unused CIEs.

In the original case, due to unfortunate circumstances around Rusts personality function (https://github.com/rust-lang/rust/pull/148105), the difference in binary size here between binutils ld and LLD was actually several hundred kilobytes because of this.

mold also appears to not remove the CIE.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to