Skip to content

Commit dc30b0d

Browse files
MaskRaytstellar
authored andcommitted
[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 (cherry picked from commit 7370a48)
1 parent 324127d commit dc30b0d

File tree

2 files changed

+78
-17
lines changed

2 files changed

+78
-17
lines changed

lld/ELF/Writer.cpp

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -722,23 +722,30 @@ template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
722722
auto *sec = dyn_cast<OutputSection>(cmd);
723723
if (!sec)
724724
continue;
725-
auto i = llvm::find_if(sec->commands, [](SectionCommand *cmd) {
726-
if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
727-
return !isd->sections.empty();
728-
return false;
729-
});
730-
if (i == sec->commands.end())
731-
continue;
732-
InputSectionBase *isec = cast<InputSectionDescription>(*i)->sections[0];
733-
734-
// Relocations are not using REL[A] section symbols.
735-
if (isec->type == SHT_REL || isec->type == SHT_RELA)
736-
continue;
737-
738-
// Unlike other synthetic sections, mergeable output sections contain data
739-
// copied from input sections, and there may be a relocation pointing to its
740-
// contents if -r or --emit-reloc is given.
741-
if (isa<SyntheticSection>(isec) && !(isec->flags & SHF_MERGE))
725+
OutputSection &osec = *sec;
726+
InputSectionBase *isec = nullptr;
727+
// Iterate over all input sections and add a STT_SECTION symbol if any input
728+
// section may be a relocation target.
729+
for (SectionCommand *cmd : osec.commands) {
730+
auto *isd = dyn_cast<InputSectionDescription>(cmd);
731+
if (!isd)
732+
continue;
733+
for (InputSectionBase *s : isd->sections) {
734+
// Relocations are not using REL[A] section symbols.
735+
if (s->type == SHT_REL || s->type == SHT_RELA)
736+
continue;
737+
738+
// Unlike other synthetic sections, mergeable output sections contain
739+
// data copied from input sections, and there may be a relocation
740+
// pointing to its contents if -r or --emit-reloc is given.
741+
if (isa<SyntheticSection>(s) && !(s->flags & SHF_MERGE))
742+
continue;
743+
744+
isec = s;
745+
break;
746+
}
747+
}
748+
if (!isec)
742749
continue;
743750

744751
// 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)