[lld] 7370a48 - [ELF] --emit-relocs: fix missing STT_SECTION when the first input section is synthetic
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 29 08:56:27 PDT 2022
Author: Fangrui Song
Date: 2022-03-29T08:56:21-07:00
New Revision: 7370a489b1005e424b23bd0009af2365aef4db53
URL: https://github.com/llvm/llvm-project/commit/7370a489b1005e424b23bd0009af2365aef4db53
DIFF: https://github.com/llvm/llvm-project/commit/7370a489b1005e424b23bd0009af2365aef4db53.diff
LOG: [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) }`
(abc388ed3cf0ef7e617ebe243d3b0b32d29e69a5 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
Added:
lld/test/ELF/emit-relocs-synthetic.s
Modified:
lld/ELF/Writer.cpp
Removed:
################################################################################
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 8ca72b3455927..6d763119d0bfc 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -711,23 +711,29 @@ template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
if (!osd)
continue;
OutputSection &osec = osd->osec;
- auto i = llvm::find_if(osec.commands, [](SectionCommand *cmd) {
- if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
- return !isd->sections.empty();
- return false;
- });
- if (i == osec.commands.end())
- continue;
- InputSectionBase *isec = cast<InputSectionDescription>(*i)->sections[0];
-
- // Relocations are not using REL[A] section symbols.
- if (isec->type == SHT_REL || isec->type == SHT_RELA)
- continue;
-
- // Unlike other synthetic sections, mergeable output sections contain data
- // copied from input sections, and there may be a relocation pointing to its
- // contents if -r or --emit-reloc is given.
- if (isa<SyntheticSection>(isec) && !(isec->flags & SHF_MERGE))
+ InputSectionBase *isec = nullptr;
+ // Iterate over all input sections and add a STT_SECTION symbol if any input
+ // section may be a relocation target.
+ for (SectionCommand *cmd : osec.commands) {
+ auto *isd = dyn_cast<InputSectionDescription>(cmd);
+ if (!isd)
+ continue;
+ for (InputSectionBase *s : isd->sections) {
+ // Relocations are not using REL[A] section symbols.
+ if (s->type == SHT_REL || s->type == SHT_RELA)
+ continue;
+
+ // Unlike other synthetic sections, mergeable output sections contain
+ // data copied from input sections, and there may be a relocation
+ // pointing to its contents if -r or --emit-reloc is given.
+ if (isa<SyntheticSection>(s) && !(s->flags & SHF_MERGE))
+ continue;
+
+ isec = s;
+ break;
+ }
+ }
+ if (!isec)
continue;
// Set the symbol to be relative to the output section so that its st_value
diff --git a/lld/test/ELF/emit-relocs-synthetic.s b/lld/test/ELF/emit-relocs-synthetic.s
new file mode 100644
index 0000000000000..737f96e5e191c
--- /dev/null
+++ b/lld/test/ELF/emit-relocs-synthetic.s
@@ -0,0 +1,54 @@
+# REQUIRES: x86
+## Regression test: add STT_SECTION even if synthetic sections are interleaved
+## with regular input sections.
+
+# RUN: rm -rf %t && split-file %s %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/a.s -o %t/a.o
+# RUN: ld.lld --emit-relocs --no-relax -T %t/1.t %t/a.o -o %t/a1
+# RUN: llvm-objdump -dr %t/a1 | FileCheck %s --check-prefixes=CHECK,CHECK1
+# RUN: ld.lld --emit-relocs --no-relax -T %t/2.t %t/a.o -o %t/a2
+# RUN: llvm-objdump -dr %t/a2 | FileCheck %s --check-prefixes=CHECK,CHECK2
+
+# CHECK: <_start>:
+## %t/a1: bss is at offset 17. bss-4 = .bss + 0xd
+## %t/a2: bss is at offset 16. bss-4 = .bss + 0xc
+# CHECK-NEXT: movl [[#]](%rip), %eax
+# CHECK1-NEXT: R_X86_64_PC32 .bss+0xd
+# CHECK2-NEXT: R_X86_64_PC32 .bss+0xc
+# CHECK-NEXT: movl [[#]](%rip), %eax
+# CHECK-NEXT: R_X86_64_PC32 common-0x4
+# CHECK-NEXT: movl [[#]](%rip), %eax
+## %t/a1: input .data is at offset 8. 8-4 = 0x4
+## %t/a2: input .data is at offset 0. 0-4 = -0x4
+# CHECK1-NEXT: R_X86_64_GOTPCRELX .data+0x4
+# CHECK2-NEXT: R_X86_64_GOTPCRELX .data-0x4
+
+#--- a.s
+.globl _start
+_start:
+ movl bss(%rip), %eax
+ movl common(%rip), %eax
+## Compilers don't produce this. We just check the behavior.
+ movl .data at gotpcrel(%rip), %eax
+
+.section .data,"aw", at progbits
+.quad 0
+
+.section .bss,"aw", at nobits
+.space 16
+bss:
+.byte 0
+
+.comm common,1,1
+
+#--- 1.t
+SECTIONS {
+ .data : { *(.got) *(.data) }
+ .bss : { *(COMMON) *(.bss) }
+}
+
+#--- 2.t
+SECTIONS {
+ .data : { *(.data) *(.got) }
+ .bss : { *(.bss) *(COMMON) }
+}
More information about the llvm-commits
mailing list