[lld][ELF] lld drops live FDEs from .eh_frame_hdr with zero-sized functions at same address
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
https://godbolt.org/z/547Gbej7f
```C++
__attribute__((cold))
void empty() {
__builtin_unreachable();
}
__attribute__((cold))
int main() {
try {
throw 42;
} catch (int x) {
return x;
}
}
```
The above should return 42, however it instead doesn't find the unwind table for `main` and terminates with
```
terminate called after throwing an instance of 'int'
Program terminated with signal: SIGSEGV
```
This happens because `empty` compiles to a zero-byte function and lands on the same address as `main` in the final binary, where the `.eh_frame_hdr` then only points to the FDE of `empty`.
(The `__attribute__((cold))` is just so that both functions land in the same section.)
`readelf -wf` output on above code compiled with `clang -O2 -fuse-ld=lld`
```
Contents of the .eh_frame_hdr section:
Version: 1
Pointer Encoding Format: 0x1b (sdata4, pcrel)
Count Encoding Format: 0x3 (udata4, absolute)
Table Encoding Format: 0x3b (sdata4, datarel)
Start of frame section: 0x20 (offset: 0x788)
Entries in search table: 0x2
0x10cc (offset: 0x1830) -> 0x3c fde=[ 18]
0x11b8 (offset: 0x191c) -> 0x68 fde=[ 44]
Contents of the .eh_frame section:
00000000 0000000000000014 00000000 CIE
Version: 1
Augmentation: "zR"
Code alignment factor: 1
Data alignment factor: -8
Return address column: 16
Augmentation data: 1b
DW_CFA_def_cfa: r7 (rsp) ofs 8
DW_CFA_offset: r16 (rip) at cfa-8
DW_CFA_undefined: r16 (rip)
00000018 0000000000000010 0000001c FDE cie=00000000 pc=0000000000001830..0000000000001852
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
0000002c 0000000000000014 00000000 CIE
Version: 1
Augmentation: "zR"
Code alignment factor: 1
Data alignment factor: -8
Return address column: 16
Augmentation data: 1b
DW_CFA_def_cfa: r7 (rsp) ofs 8
DW_CFA_offset: r16 (rip) at cfa-8
DW_CFA_nop
DW_CFA_nop
00000044 0000000000000010 0000001c FDE cie=0000002c pc=000000000000191c..000000000000191c
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
00000058 000000000000001c 00000000 CIE
Version: 1
Augmentation: "zPLR"
Code alignment factor: 1
Data alignment factor: -8
Return address column: 16
Augmentation data: 9b 15 34 00 00 1b 1b
DW_CFA_def_cfa: r7 (rsp) ofs 8
DW_CFA_offset: r16 (rip) at cfa-8
DW_CFA_nop
DW_CFA_nop
00000078 0000000000000020 00000024 FDE cie=00000058 pc=000000000000191c..0000000000001951
Augmentation data: 3b ff ff ff
DW_CFA_advance_loc: 1 to 000000000000191d
DW_CFA_def_cfa_offset: 16
DW_CFA_offset: r3 (rbx) at cfa-16
DW_CFA_advance_loc: 51 to 0000000000001950
DW_CFA_def_cfa_offset: 8
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
0000009c ZERO terminator
```
Contributor guide
Research direction
Start with the Godbolt reproducer and inspect lld's ELF .eh_frame_hdr generation, using the supplied readelf -wf output to trace why the zero-sized function's entry replaces main's FDE. Done means the compiled program finds main's unwind table, returns 42, and preserves the relevant live FDE entries in .eh_frame_hdr.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100