[lld] r321154 - [ELF] Fix an assignment command at the end of an .ARM.exidx section.

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 20 00:56:10 PST 2017


Author: ikudrin
Date: Wed Dec 20 00:56:10 2017
New Revision: 321154

URL: http://llvm.org/viewvc/llvm-project?rev=321154&view=rev
Log:
[ELF] Fix an assignment command at the end of an .ARM.exidx section.

The value of the symbol in the assignment should include the sentinel entry.

Differential Revision: https://reviews.llvm.org/D41234

Added:
    lld/trunk/test/ELF/arm-exidx-dedup-and-sentinel.s
Modified:
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/ELF/SyntheticSections.h
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=321154&r1=321153&r2=321154&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Wed Dec 20 00:56:10 2017
@@ -2561,31 +2561,25 @@ ARMExidxSentinelSection::ARMExidxSentine
 // The sentinel must have the PREL31 value of an address higher than any
 // address described by any other table entry.
 void ARMExidxSentinelSection::writeTo(uint8_t *Buf) {
-  // The Sections are sorted in order of ascending PREL31 address with the
-  // sentinel last. We need to find the InputSection that precedes the
-  // sentinel.
-  OutputSection *C = getParent();
-  InputSection *Highest = nullptr;
-  unsigned Skip = 1;
-  for (const BaseCommand *Base : llvm::reverse(C->SectionCommands)) {
-    if (!isa<InputSectionDescription>(Base))
-      continue;
-    auto L = cast<InputSectionDescription>(Base);
-    if (Skip >= L->Sections.size()) {
-      Skip -= L->Sections.size();
-      continue;
-    }
-    Highest = L->Sections[L->Sections.size() - Skip - 1];
-    break;
-  }
   assert(Highest);
-  InputSection *LS = Highest->getLinkOrderDep();
-  uint64_t S = LS->getParent()->Addr + LS->getOffset(LS->getSize());
+  uint64_t S =
+      Highest->getParent()->Addr + Highest->getOffset(Highest->getSize());
   uint64_t P = getVA();
   Target->relocateOne(Buf, R_ARM_PREL31, S - P);
   write32le(Buf + 4, 1);
 }
 
+// The sentinel has to be removed if there are no other .ARM.exidx entries.
+bool ARMExidxSentinelSection::empty() const {
+  OutputSection *OS = getParent();
+  for (auto *B : OS->SectionCommands)
+    if (auto *ISD = dyn_cast<InputSectionDescription>(B))
+      for (auto *S : ISD->Sections)
+        if (!isa<ARMExidxSentinelSection>(S))
+          return false;
+  return true;
+}
+
 ThunkSection::ThunkSection(OutputSection *OS, uint64_t Off)
     : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
                        Config->Wordsize, ".text.thunk") {

Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=321154&r1=321153&r2=321154&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Wed Dec 20 00:56:10 2017
@@ -785,6 +785,9 @@ public:
   ARMExidxSentinelSection();
   size_t getSize() const override { return 8; }
   void writeTo(uint8_t *Buf) override;
+  bool empty() const override;
+
+  InputSection *Highest = 0;
 };
 
 // A container for one or more linker generated thunks. Instances of these

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=321154&r1=321153&r2=321154&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Dec 20 00:56:10 2017
@@ -54,7 +54,6 @@ private:
   void resolveShfLinkOrder();
   void sortInputSections();
   void finalizeSections();
-  void addPredefinedSections();
   void setReservedSymbolSections();
 
   std::vector<PhdrEntry *> createPhdrs();
@@ -390,6 +389,11 @@ template <class ELFT> static void create
   Add(InX::ShStrTab);
   if (InX::StrTab)
     Add(InX::StrTab);
+
+  if (Config->EMachine == EM_ARM && !Config->Relocatable)
+    // Add a sentinel to terminate .ARM.exidx. It helps an unwinder
+    // to find the exact address range of the last entry.
+    Add(make<ARMExidxSentinelSection>());
 }
 
 // The main function of the writer.
@@ -1145,10 +1149,10 @@ template <class ELFT> void Writer<ELFT>:
 }
 
 static bool compareByFilePosition(InputSection *A, InputSection *B) {
-  // Synthetic doesn't have link order dependecy, stable_sort will keep it last
+  // Synthetic, i. e. a sentinel section, should go last.
   if (A->kind() == InputSectionBase::Synthetic ||
       B->kind() == InputSectionBase::Synthetic)
-    return false;
+    return A->kind() != InputSectionBase::Synthetic;
   InputSection *LA = A->getLinkOrderDep();
   InputSection *LB = B->getLinkOrderDep();
   OutputSection *AOut = LA->getParent();
@@ -1231,23 +1235,37 @@ template <class ELFT> void Writer<ELFT>:
     }
     std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition);
 
-    if (Config->MergeArmExidx && !Config->Relocatable &&
-        Config->EMachine == EM_ARM && Sec->Type == SHT_ARM_EXIDX) {
-      // The EHABI for the Arm Architecture permits consecutive identical
-      // table entries to be merged. We use a simple implementation that
-      // removes a .ARM.exidx Input Section if it can be merged into the
-      // previous one. This does not require any rewriting of InputSection
-      // contents but misses opportunities for fine grained deduplication where
-      // only a subset of the InputSection contents can be merged.
-      int Cur = 1;
-      int Prev = 0;
-      int N = Sections.size();
-      while (Cur < N) {
-        if (isDuplicateArmExidxSec(Sections[Prev], Sections[Cur]))
-          Sections[Cur] = nullptr;
-        else
-          Prev = Cur;
-        ++Cur;
+    if (!Config->Relocatable && Config->EMachine == EM_ARM &&
+        Sec->Type == SHT_ARM_EXIDX) {
+
+      if (!Sections.empty() && isa<ARMExidxSentinelSection>(Sections.back())) {
+        assert(Sections.size() >= 2 &&
+               "We should create a sentinel section only if there are "
+               "alive regular exidx sections.");
+        // The last executable section is required to fill the sentinel.
+        // Remember it here so that we don't have to find it again.
+        auto *Sentinel = cast<ARMExidxSentinelSection>(Sections.back());
+        Sentinel->Highest = Sections[Sections.size() - 2]->getLinkOrderDep();
+      }
+
+      if (Config->MergeArmExidx) {
+        // The EHABI for the Arm Architecture permits consecutive identical
+        // table entries to be merged. We use a simple implementation that
+        // removes a .ARM.exidx Input Section if it can be merged into the
+        // previous one. This does not require any rewriting of InputSection
+        // contents but misses opportunities for fine grained deduplication
+        // where only a subset of the InputSection contents can be merged.
+        int Cur = 1;
+        int Prev = 0;
+        // The last one is a sentinel entry which should not be removed.
+        int N = Sections.size() - 1;
+        while (Cur < N) {
+          if (isDuplicateArmExidxSec(Sections[Prev], Sections[Cur]))
+            Sections[Cur] = nullptr;
+          else
+            Prev = Cur;
+          ++Cur;
+        }
       }
     }
 
@@ -1413,7 +1431,6 @@ template <class ELFT> void Writer<ELFT>:
   if (errorCount())
     return;
 
-  addPredefinedSections();
   removeUnusedSyntheticSections();
 
   sortSections();
@@ -1510,17 +1527,6 @@ template <class ELFT> void Writer<ELFT>:
                  [](SyntheticSection *SS) { SS->postThunkContents(); });
 }
 
-template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
-  // ARM ABI requires .ARM.exidx to be terminated by some piece of data.
-  // We have the terminater synthetic section class. Add that at the end.
-  OutputSection *Cmd = findSection(".ARM.exidx");
-  if (!Cmd || !Cmd->Live || Config->Relocatable)
-    return;
-
-  auto *Sentinel = make<ARMExidxSentinelSection>();
-  Cmd->addSection(Sentinel);
-}
-
 // The linker is expected to define SECNAME_start and SECNAME_end
 // symbols for a few sections. This function defines them.
 template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {

Added: lld/trunk/test/ELF/arm-exidx-dedup-and-sentinel.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-exidx-dedup-and-sentinel.s?rev=321154&view=auto
==============================================================================
--- lld/trunk/test/ELF/arm-exidx-dedup-and-sentinel.s (added)
+++ lld/trunk/test/ELF/arm-exidx-dedup-and-sentinel.s Wed Dec 20 00:56:10 2017
@@ -0,0 +1,29 @@
+// REQUIRES: arm
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
+// RUN: ld.lld %t.o -shared -o %t.so --section-start .text=0x2000 --section-start .ARM.exidx=0x1000
+// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t.so | FileCheck %s
+
+ .syntax unified
+
+ .section .text.foo, "ax", %progbits
+ .globl foo
+foo:
+ .fnstart
+ bx lr
+ .cantunwind
+ .fnend
+
+ .section .text.bar, "ax", %progbits
+ .globl bar
+bar:
+ .fnstart
+ bx lr
+ .cantunwind
+ .fnend
+
+// CHECK: Contents of section .ARM.exidx:
+// 1000 + 1000 = 0x2000 = foo
+// The entry for bar is the same as previous and is eliminated.
+// The sentinel entry should be preserved.
+// 1008 + 1000 = 0x2008 = bar + sizeof(bar)
+// CHECK-NEXT: 1000 00100000 01000000 00100000 01000000

Modified: lld/trunk/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s?rev=321154&r1=321153&r2=321154&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s (original)
+++ lld/trunk/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s Wed Dec 20 00:56:10 2017
@@ -8,6 +8,7 @@
 ## was anything but an input section description.
 # RUN: ld.lld --no-merge-exidx-entries -T %t.script %t.o -shared -o %t.so
 # RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t.so | FileCheck %s
+# RUN: llvm-readobj -s -t %t.so | FileCheck %s --check-prefix=SYMBOL
 
  .syntax unified
  .text
@@ -22,3 +23,19 @@ _start:
 # 1000 + 1000 = 0x2000 = _start
 # 1008 + 0ffc = 0x2004 = _start + sizeof(_start)
 # CHECK-NEXT: 1000 00100000 01000000 fc0f0000 01000000
+
+# SYMBOL:       Section {
+# SYMBOL:         Name: .ARM.exidx
+# SYMBOL-NEXT:    Type: SHT_ARM_EXIDX
+# SYMBOL-NEXT:    Flags [
+# SYMBOL-NEXT:      SHF_ALLOC
+# SYMBOL-NEXT:      SHF_LINK_ORDER
+# SYMBOL-NEXT:    ]
+# SYMBOL-NEXT:    Address: 0x1000
+# SYMBOL-NEXT:    Offset:
+# SYMBOL-NEXT:    Size: 16
+
+# Symbol 'foo' is expected to point at the end of the section.
+# SYMBOL:       Symbol {
+# SYMBOL:         Name: foo
+# SYMBOL-NEXT:    Value: 0x1010




More information about the llvm-commits mailing list