Skip to content

Commit 38b632c

Browse files
committed
[ELF] --gdb-index: support --icf={safe,all}
The combination has not been tested before. In the case of ICF, `e.section->getVA(0)` equals the start address of the output section. This can cause incorrect overlapping with the actual function at the start of the output section and potentially trigger a GDB internal error in `dw2_find_pc_sect_compunit_symtab` (presumably because: if a short address range incorrectly starts at the start address of the output section, GDB may pick it instead of the correct longer address range. When mapping an address within the long address range but out of the scope of the short address range, the routine may find nothing - while the code asserts that it can find something). Note that in the case of ICF there may be duplicate address range entries, but GDB appears to be fine with them. Reviewed By: grimar Differential Revision: https://reviews.llvm.org/D89751
1 parent cc07fbe commit 38b632c

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed

lld/ELF/SyntheticSections.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2914,7 +2914,8 @@ void GdbIndexSection::writeTo(uint8_t *buf) {
29142914
uint32_t cuOff = 0;
29152915
for (GdbChunk &chunk : chunks) {
29162916
for (AddressEntry &e : chunk.addressAreas) {
2917-
uint64_t baseAddr = e.section->getVA(0);
2917+
// In the case of ICF there may be duplicate address range entries.
2918+
const uint64_t baseAddr = e.section->repl->getVA(0);
29182919
write64le(buf, baseAddr + e.lowAddress);
29192920
write64le(buf + 8, baseAddr + e.highAddress);
29202921
write32le(buf + 16, e.cuIndex + cuOff);

lld/test/ELF/gdb-index-icf.s

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# REQUIRES: x86
2+
## Test that the address range contributed by an ICF folded function is identical
3+
## to that of the folded-in function. Not considering ICF may lead to an address
4+
## range whose low address equals the start address of the output section.
5+
6+
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
7+
# RUN: ld.lld --gdb-index --icf=all -Ttext=0x1000 %t.o -o %t
8+
# RUN: llvm-dwarfdump --gdb-index %t | FileCheck %s
9+
10+
# CHECK: Address area offset = 0x38, has 2 entries:
11+
# CHECK-NEXT: Low/High address = [0x1001, 0x1002) (Size: 0x1), CU id = 0
12+
# CHECK-NEXT: Low/High address = [0x1001, 0x1002) (Size: 0x1), CU id = 1
13+
14+
.text
15+
nop
16+
17+
.section .text.0,"ax"
18+
.Lfunc_begin0:
19+
ret
20+
.Lfunc_end0:
21+
22+
.section .text.1,"ax"
23+
.Lfunc_begin1:
24+
ret
25+
.Lfunc_end1:
26+
27+
.section .debug_abbrev,"",@progbits
28+
.byte 1 # Abbreviation Code
29+
.byte 65 # DW_TAG_type_unit
30+
.byte 0 # DW_CHILDREN_no
31+
.byte 0 # EOM(1)
32+
.byte 0 # EOM(2)
33+
34+
.byte 2 # Abbreviation Code
35+
.byte 17 # DW_TAG_compile_unit
36+
.byte 0 # DW_CHILDREN_no
37+
.byte 17 # DW_AT_low_pc
38+
.byte 1 # DW_FORM_addr
39+
.byte 18 # DW_AT_high_pc
40+
.byte 6 # DW_FORM_data4
41+
.byte 0 # EOM(1)
42+
.byte 0 # EOM(2)
43+
44+
.byte 0 # EOM(3)
45+
46+
.section .debug_info,"",@progbits
47+
.Lcu_begin0:
48+
.long .Lcu_end0-.Lcu_begin0-4 # Length of Unit
49+
.short 5 # DWARF version number
50+
.byte 1 # DWARF Unit Type
51+
.byte 8 # Address Size
52+
.long .debug_abbrev # Offset Into Abbrev. Section
53+
.byte 2 # Abbrev [2] DW_TAG_compile_unit
54+
.quad .Lfunc_begin0 # DW_AT_low_pc
55+
.long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
56+
.Lcu_end0:
57+
58+
.Lcu_begin1:
59+
.long .Lcu_end1-.Lcu_begin1-4 # Length of Unit
60+
.short 5 # DWARF version number
61+
.byte 1 # DWARF Unit Type
62+
.byte 8 # Address Size
63+
.long .debug_abbrev # Offset Into Abbrev. Section
64+
.byte 2 # Abbrev [2] DW_TAG_compile_unit
65+
.quad .Lfunc_begin1 # DW_AT_low_pc
66+
.long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc
67+
.Lcu_end1:

0 commit comments

Comments
 (0)