[PATCH] D32485: [LLD][ELF] Make SHF_LINK_ORDER sections orphans

Peter Smith via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 25 06:44:39 PDT 2017


peter.smith created this revision.
Herald added subscribers: rengolin, aemerson.

I've separated this out from https://reviews.llvm.org/D32233 as it takes a different approach. Overall I think it is an improvement.

The reordering code for SHF_LINK_ORDER works on OutputSection::Sections if any of the InputSections are covered by an InputSectionDescription from a script then the Script->assignAddresses will take precedence and will likely produce an incorrect order.

      

To make Script->assignAddresses() pick up the order from the OutputSection we make clear all the InputSectionDescriptions::Sections() to make the InputSections orphans.

      

A theoretical drawback of this approach is that it will ruin any symbols defined by the linker script for the OutputSection. However I think this won't be a problem in practice. The default linker script in ld.bfd is

  PROVIDE_HIDDEN (__exidx_start = .);
  .ARM.exidx   : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) }
  PROVIDE_HIDDEN (__exidx_end = .);

Which won't be troubled by making the InputSections Orphans.


https://reviews.llvm.org/D32485

Files:
  ELF/LinkerScript.cpp
  ELF/LinkerScript.h
  ELF/OutputSections.cpp
  test/ELF/arm-exidx-script.s


Index: test/ELF/arm-exidx-script.s
===================================================================
--- /dev/null
+++ test/ELF/arm-exidx-script.s
@@ -0,0 +1,30 @@
+// REQUIRES: arm
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-exidx-cantunwind.s -o %tcantunwind
+// RUN: echo "SECTIONS { \
+// RUN:          .ARM.exidx 0x11000 : { *(.ARM.exidx*) } \
+// RUN:          .func : { *(.func*) } \
+// RUN:          .text : { *(.text*) } } " > %t.script
+// RUN: ld.lld --script %t.script %t %tcantunwind -o %t2 2>&1
+// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s
+// Check that a linker script that describes .ARM.exidx sections orders the
+// .ARM.exidx sections in ascending order of their link order dependencies.
+ .syntax unified
+ .text
+ .global _start
+_start:
+ .fnstart
+ bx lr
+ .cantunwind
+.fnend
+// Check ascending order of first word of each 2 word entry
+// [PREL31 to target, unwind info]
+// 11000 + 38 = 11038, 11008 + 34 = 1103c ... 11030 + 20 = 11050
+// CHECK:       11000 38000000 01000000 34000000 01000000
+// CHECK-NEXT:  11010 30000000 01000000 2c000000 01000000
+// CHECK-NEXT:  11020 28000000 01000000 24000000 01000000
+// CHECK-NEXT:  11030 20000000 01000000
+// CHECK-NEXT: Contents of section .func:
+// CHECK-NEXT:  11038 1eff2fe1 1eff2fe1 1eff2fe1
+// CHECK-NEXT: Contents of section .text:
+// CHECK-NEXT:  11044 1eff2fe1 1eff2fe1 1eff2fe1
Index: ELF/OutputSections.cpp
===================================================================
--- ELF/OutputSections.cpp
+++ ELF/OutputSections.cpp
@@ -113,6 +113,12 @@
 
 template <class ELFT> void OutputSection::finalize() {
   if ((this->Flags & SHF_LINK_ORDER) && !this->Sections.empty()) {
+    std::vector<std::vector<InputSectionBase *> *> InputRanges =
+          Script->inputSectionRanges(Name);
+    // Make the sections with link order dependencies orphans to prevent
+    // the script address assignment taking precedent.
+    for (std::vector<InputSectionBase *> *Range : InputRanges)
+      Range->clear();
     std::sort(Sections.begin(), Sections.end(), compareByFilePosition);
     assignOffsets();
 
Index: ELF/LinkerScript.h
===================================================================
--- ELF/LinkerScript.h
+++ ELF/LinkerScript.h
@@ -257,6 +257,8 @@
 
   std::vector<OutputSection *> *OutputSections;
   void fabricateDefaultCommands(bool AllocateHeader);
+  std::vector<std::vector<InputSectionBase *> *>
+  inputSectionRanges(StringRef S);
   void addOrphanSections(OutputSectionFactory &Factory);
   void removeEmptyCommands();
   void adjustSectionsBeforeSorting();
Index: ELF/LinkerScript.cpp
===================================================================
--- ELF/LinkerScript.cpp
+++ ELF/LinkerScript.cpp
@@ -463,6 +463,28 @@
   Opt.Commands = std::move(Commands);
 }
 
+// For an OutputSection S, return the InputSectionDescriptions that are
+// associated with S. The intention is that callers can iterate over
+// InputSectionDescription::Sections and insert sections such as Thunks.
+std::vector<std::vector<InputSectionBase *> *>
+LinkerScript::inputSectionRanges(StringRef S) {
+  std::vector<std::vector<InputSectionBase *> *> Ranges;
+  auto OutCmdPos = std::find_if(
+      Opt.Commands.begin(), Opt.Commands.end(), [=](BaseCommand *Cmd) {
+        if (auto *OSCmd = dyn_cast<OutputSectionCommand>(Cmd))
+          return (OSCmd->Name == S);
+        return false;
+      });
+  if (OutCmdPos == Opt.Commands.end())
+    return Ranges;
+  auto *OutCmd = cast<OutputSectionCommand>(*OutCmdPos);
+  for (auto *BaseCmd : OutCmd->Commands) {
+    if (auto *ISD = dyn_cast<InputSectionDescription>(BaseCmd))
+      Ranges.push_back(&ISD->Sections);
+  }
+  return Ranges;
+}
+
 // Add sections that didn't match any sections command.
 void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) {
   std::map<OutputSection *, std::vector<InputSectionBase *>> Orphanage;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D32485.96543.patch
Type: text/x-patch
Size: 4040 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170425/a55c2efc/attachment.bin>


More information about the llvm-commits mailing list