Skip to content

Commit 7370a48

Browse files
committed
[ELF] --emit-relocs: fix missing STT_SECTION when the first input section is synthetic
addSectionSymbols suppresses the STT_SECTION symbol if the first input section is non-SHF_MERGE synthetic. This is incorrect when the first input section is synthetic while a non-synthetic input section exists: * `.bss : { *(COMMON) *(.bss) }` (abc388e regressed the case because COMMON symbols precede .bss in the absence of a linker script) * Place a synthetic section in another section: `.data : { *(.got) *(.data) }` For `%t/a1` in the new test emit-relocs-synthetic.s, ld.lld produces incorrect relocations with symbol index 0. ``` 0000000000000000 <_start>: 0: 8b 05 33 00 00 00 movl 51(%rip), %eax # 0x39 <bss> 0000000000000002: R_X86_64_PC32 *ABS*+0xd 6: 8b 05 1c 00 00 00 movl 28(%rip), %eax # 0x28 <common> 0000000000000008: R_X86_64_PC32 common-0x4 c: 8b 05 06 00 00 00 movl 6(%rip), %eax # 0x18 000000000000000e: R_X86_64_GOTPCRELX *ABS*+0x4 ``` Fix the issue by checking every input section. Reviewed By: ikudrin Differential Revision: https://reviews.llvm.org/D122463
1 parent f079946 commit 7370a48

File tree

2 files changed

+77
-17
lines changed

2 files changed

+77
-17
lines changed

lld/ELF/Writer.cpp

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -711,23 +711,29 @@ template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
711711
if (!osd)
712712
continue;
713713
OutputSection &osec = osd->osec;
714-
auto i = llvm::find_if(osec.commands, [](SectionCommand *cmd) {
715-
if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
716-
return !isd->sections.empty();
717-
return false;
718-
});
719-
if (i == osec.commands.end())
720-
continue;
721-
InputSectionBase *isec = cast<InputSectionDescription>(*i)->sections[0];
722-
723-
// Relocations are not using REL[A] section symbols.
724-
if (isec->type == SHT_REL || isec->type == SHT_RELA)
725-
continue;
726-
727-
// Unlike other synthetic sections, mergeable output sections contain data
728-
// copied from input sections, and there may be a relocation pointing to its
729-
// contents if -r or --emit-reloc is given.
730-
if (isa<SyntheticSection>(isec) && !(isec->flags & SHF_MERGE))
714+
InputSectionBase *isec = nullptr;
715+
// Iterate over all input sections and add a STT_SECTION symbol if any input
716+
// section may be a relocation target.
717+
for (SectionCommand *cmd : osec.commands) {
718+
auto *isd = dyn_cast<InputSectionDescription>(cmd);
719+
if (!isd)
720+
continue;
721+
for (InputSectionBase *s : isd->sections) {
722+
// Relocations are not using REL[A] section symbols.
723+
if (s->type == SHT_REL || s->type == SHT_RELA)
724+
continue;
725+
726+
// Unlike other synthetic sections, mergeable output sections contain
727+
// data copied from input sections, and there may be a relocation
728+
// pointing to its contents if -r or --emit-reloc is given.
729+
if (isa<SyntheticSection>(s) && !(s->flags & SHF_MERGE))
730+
continue;
731+
732+
isec = s;
733+
break;
734+
}
735+
}
736+
if (!isec)
731737
continue;
732738

733739
// Set the symbol to be relative to the output section so that its st_value

lld/test/ELF/emit-relocs-synthetic.s

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# REQUIRES: x86
2+
## Regression test: add STT_SECTION even if synthetic sections are interleaved
3+
## with regular input sections.
4+
5+
# RUN: rm -rf %t && split-file %s %t
6+
# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/a.s -o %t/a.o
7+
# RUN: ld.lld --emit-relocs --no-relax -T %t/1.t %t/a.o -o %t/a1
8+
# RUN: llvm-objdump -dr %t/a1 | FileCheck %s --check-prefixes=CHECK,CHECK1
9+
# RUN: ld.lld --emit-relocs --no-relax -T %t/2.t %t/a.o -o %t/a2
10+
# RUN: llvm-objdump -dr %t/a2 | FileCheck %s --check-prefixes=CHECK,CHECK2
11+
12+
# CHECK: <_start>:
13+
## %t/a1: bss is at offset 17. bss-4 = .bss + 0xd
14+
## %t/a2: bss is at offset 16. bss-4 = .bss + 0xc
15+
# CHECK-NEXT: movl [[#]](%rip), %eax
16+
# CHECK1-NEXT: R_X86_64_PC32 .bss+0xd
17+
# CHECK2-NEXT: R_X86_64_PC32 .bss+0xc
18+
# CHECK-NEXT: movl [[#]](%rip), %eax
19+
# CHECK-NEXT: R_X86_64_PC32 common-0x4
20+
# CHECK-NEXT: movl [[#]](%rip), %eax
21+
## %t/a1: input .data is at offset 8. 8-4 = 0x4
22+
## %t/a2: input .data is at offset 0. 0-4 = -0x4
23+
# CHECK1-NEXT: R_X86_64_GOTPCRELX .data+0x4
24+
# CHECK2-NEXT: R_X86_64_GOTPCRELX .data-0x4
25+
26+
#--- a.s
27+
.globl _start
28+
_start:
29+
movl bss(%rip), %eax
30+
movl common(%rip), %eax
31+
## Compilers don't produce this. We just check the behavior.
32+
movl .data@gotpcrel(%rip), %eax
33+
34+
.section .data,"aw",@progbits
35+
.quad 0
36+
37+
.section .bss,"aw",@nobits
38+
.space 16
39+
bss:
40+
.byte 0
41+
42+
.comm common,1,1
43+
44+
#--- 1.t
45+
SECTIONS {
46+
.data : { *(.got) *(.data) }
47+
.bss : { *(COMMON) *(.bss) }
48+
}
49+
50+
#--- 2.t
51+
SECTIONS {
52+
.data : { *(.data) *(.got) }
53+
.bss : { *(.bss) *(COMMON) }
54+
}

0 commit comments

Comments
 (0)