[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