[PATCH] D33780: [ELF] - Linkerscript - do not emit multiple relocation sections when using --emit-relocs.

George Rimar via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 1 07:56:30 PDT 2017


grimar created this revision.
Herald added a subscriber: emaste.

I tried to link head linux kernel and faced with fact that objcopy
refuses to proccess one of LLD linked binaries:

  RELOCS  arch/x86/realmode/rm/realmode.relocs
  OBJCOPY arch/x86/realmode/rm/realmode.bin

objcopy:arch/x86/realmode/rm/realmode.elf: Bad value

That happens because using script LLD produces 2 relocation sections
that point to the same output section. For example without this patch
output for testcase would be:

  [ 1] .foo              PROGBITS         0000000000000000  00001000
       000000000000000a  0000000000000000  AX       0     0     1
  [ 3] .rela.foo         RELA             0000000000000000  00001010
       0000000000000018  0000000000000018   I       6     1     8
  [ 4] .rela.bar         RELA             0000000000000000  00001028
       0000000000000018  0000000000000018   I       6     1     8

(both .rela.foo and .rela.bar points to .foo).

And implementation of objcopy does not like that. AFAIK it 
generally tools does not support that. We already workaround this
for non-script case, so looks reasonable to do the same for script too,
since at least kernel uses it.


https://reviews.llvm.org/D33780

Files:
  ELF/LinkerScript.cpp
  test/ELF/linkerscript/emit-relocs-multiple.s


Index: test/ELF/linkerscript/emit-relocs-multiple.s
===================================================================
--- test/ELF/linkerscript/emit-relocs-multiple.s
+++ test/ELF/linkerscript/emit-relocs-multiple.s
@@ -0,0 +1,21 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: echo "SECTIONS { .foo : { *(.foo) *(.bar) } }" > %t.script
+# RUN: ld.lld --emit-relocs --script %t.script %t.o -o %t1
+# RUN: llvm-readobj -s -r %t1 | FileCheck %s
+
+# CHECK-NOT:  .rela.bar
+# CHECK:      Relocations [
+# CHECK-NEXT:   Section {{.*}} .rela.foo {
+# CHECK-NEXT:     0x1 R_X86_64_32 .foo 0x0
+# CHECK-NEXT:     0x6 R_X86_64_32 .foo 0x5
+# CHECK-NEXT:   }
+# CHECK-NEXT: ]
+
+.section .foo,"ax", at progbits
+aaa:
+  movl $aaa, %edx
+
+.section .bar,"ax", at progbits
+bbb:
+  movl $bbb, %edx
Index: ELF/LinkerScript.cpp
===================================================================
--- ELF/LinkerScript.cpp
+++ ELF/LinkerScript.cpp
@@ -484,11 +484,35 @@
   Opt.Commands = std::move(Commands);
 }
 
+// Imagine .boo : { *(.foo) *(.bar) } script. Both foo and bar may have
+// relocation sections .rela.foo and .rela.bar for example. Most tools does not
+// allow to have multiple REL[A] sections for output section. Hence we should
+// combine these relocation sections into single output.
+static void addRelocationSections(ArrayRef<InputSection *> Arr,
+                                  OutputSectionFactory &Factory) {
+  // Each regular output section may have single relocation section referenced
+  // by. This mapping allows to find relocation section by output section.
+  DenseMap<OutputSection *, OutputSection *> RelocationSections;
+  for (InputSection *Sec : Arr) {
+    OutputSection *Out = Sec->getRelocatedSection()->getOutputSection();
+    OutputSection *&RelocationSec = RelocationSections[Out];
+    StringRef Name = getOutputSectionName(Sec->Name);
+    Factory.addInputSec(Sec, Name, RelocationSec);
+  }
+}
+
 // Add sections that didn't match any sections command.
 void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) {
+  std::vector<InputSection *> RelocSections;
   for (InputSectionBase *S : InputSections) {
     if (!S->Live || S->Parent)
       continue;
+    if (!isa<SyntheticSection>(S) &&
+        (S->Type == SHT_REL || S->Type == SHT_RELA)) {
+      RelocSections.push_back(cast<InputSection>(S));
+      continue;
+    }
+
     StringRef Name = getOutputSectionName(S->Name);
     auto I = std::find_if(
         Opt.Commands.begin(), Opt.Commands.end(), [&](BaseCommand *Base) {
@@ -512,6 +536,8 @@
       Cmd->Commands.push_back(ISD);
     }
   }
+
+  addRelocationSections(RelocSections, Factory);
 }
 
 uint64_t LinkerScript::advance(uint64_t Size, unsigned Align) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D33780.101026.patch
Type: text/x-patch
Size: 2772 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170601/304e00b0/attachment.bin>


More information about the llvm-commits mailing list