-
Notifications
You must be signed in to change notification settings - Fork 15k
Description
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).
.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:
retRunning 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-sectionsbefore.eh_framededuplication, 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 (rust-lang/rust#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.