[lld] r356666 - [ELF][ARM] Redesign of .ARM.exidx handling to use a SyntheticSection

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 21 07:06:41 PDT 2019


Author: psmith
Date: Thu Mar 21 07:06:40 2019
New Revision: 356666

URL: http://llvm.org/viewvc/llvm-project?rev=356666&view=rev
Log:
[ELF][ARM] Redesign of .ARM.exidx handling to use a SyntheticSection

Instead of creating extra Synthetic .ARM.exidx sections to account for
gaps in the table, create a single .ARM.exidx SyntheticSection that can
derive the contents of the gaps from a sorted list of the executable
InputSections. This has the benefit of moving the ARM specific code for
SyntheticSections in SHF_LINK_ORDER processing and the table merging code
into the ARM specific SyntheticSection. This also makes it easier to create
EXIDX_CANTUNWIND table entries for executable InputSections that don't
have an associated .ARM.exidx section.

Fixes pr40277

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


Added:
    lld/trunk/test/ELF/arm-exidx-add-missing.s
    lld/trunk/test/ELF/arm-exidx-no-add-missing.s
Modified:
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/ELF/SyntheticSections.h
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/ELF/arm-data-prel.s
    lld/trunk/test/ELF/arm-exidx-canunwind.s
    lld/trunk/test/ELF/arm-exidx-dedup.s
    lld/trunk/test/ELF/arm-exidx-gc.s
    lld/trunk/test/ELF/arm-exidx-shared.s

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=356666&r1=356665&r2=356666&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Thu Mar 21 07:06:40 2019
@@ -289,7 +289,9 @@ void OutputSection::finalize() {
     // SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We
     // need to translate the InputSection sh_link to the OutputSection sh_link,
     // all InputSections in the OutputSection have the same dependency.
-    if (auto *D = First->getLinkOrderDep())
+    if (auto *EX = dyn_cast<ARMExidxSyntheticSection>(First))
+      Link = EX->getLinkOrderDep()->getParent()->SectionIndex;
+    else if (auto *D = First->getLinkOrderDep())
       Link = D->getParent()->SectionIndex;
   }
 

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=356666&r1=356665&r2=356666&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Thu Mar 21 07:06:40 2019
@@ -3052,33 +3052,183 @@ MipsRldMapSection::MipsRldMapSection()
     : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, Config->Wordsize,
                        ".rld_map") {}
 
-ARMExidxSentinelSection::ARMExidxSentinelSection()
+ARMExidxSyntheticSection::ARMExidxSyntheticSection()
     : SyntheticSection(SHF_ALLOC | SHF_LINK_ORDER, SHT_ARM_EXIDX,
-                       Config->Wordsize, ".ARM.exidx") {}
+                       Config->Wordsize, ".ARM.exidx") {
+  for (InputSectionBase *&IS : InputSections) {
+    if (isa<InputSection>(IS) && IS->Type == SHT_ARM_EXIDX) {
+      ExidxSections.push_back(cast<InputSection>(IS));
+      IS = nullptr;
+    } else if (IS->Live && isa<InputSection>(IS) &&
+               IS->kind() != SectionBase::Synthetic &&
+               (IS->Flags & SHF_ALLOC) && (IS->Flags & SHF_EXECINSTR) &&
+               IS->getSize() > 0) {
+      ExecutableSections.push_back(cast<InputSection>(IS));
+    }
+  }
+  setSizeAndOffsets();
 
-// Write a terminating sentinel entry to the end of the .ARM.exidx table.
-// This section will have been sorted last in the .ARM.exidx table.
-// This table entry will have the form:
-// | PREL31 upper bound of code that has exception tables | EXIDX_CANTUNWIND |
-// 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) {
-  assert(Highest);
-  uint64_t S = Highest->getVA(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 {
-  for (InputSection *IS : getInputSections(getParent()))
-    if (!isa<ARMExidxSentinelSection>(IS))
+  std::vector<InputSectionBase *> &V = InputSections;
+  V.erase(std::remove(V.begin(), V.end(), nullptr), V.end());
+}
+
+static InputSection *findExidxSection(InputSection *IS) {
+  for (InputSection *D : IS->DependentSections)
+    if (D->Type == SHT_ARM_EXIDX)
+      return D;
+  return nullptr;
+}
+
+void ARMExidxSyntheticSection::setSizeAndOffsets() {
+  size_t Offset = 0;
+  Size = 0;
+  for (InputSection *IS : ExecutableSections) {
+    if (InputSection *D = findExidxSection(IS)) {
+      D->OutSecOff = Offset;
+      D->Parent = getParent();
+      Offset += D->getSize();
+      Empty = false;
+    } else {
+      Offset += 8;
+    }
+  }
+  // Size includes Sentinel.
+  Size = Offset + 8;
+}
+
+// References to .ARM.Extab Sections have bit 31 clear and are not the
+// special EXIDX_CANTUNWIND bit-pattern.
+static bool isExtabRef(uint32_t Unwind) {
+  return (Unwind & 0x80000000) == 0 && Unwind != 0x1;
+}
+
+// Return true if the .ARM.exidx section Cur can be merged into the .ARM.exidx
+// section Prev, where Cur follows Prev in the table. This can be done if the
+// unwinding instructions in Cur are identical to Prev. Linker generated
+// EXIDX_CANTUNWIND entries are represented by nullptr as they do not have an
+// InputSection.
+static bool isDuplicateArmExidxSec(InputSection *Prev, InputSection *Cur) {
+
+  struct ExidxEntry {
+    ulittle32_t Fn;
+    ulittle32_t Unwind;
+  };
+  // Get the last table Entry from the previous .ARM.exidx section. If Prev is
+  // nullptr then it will be a synthesized EXIDX_CANTUNWIND entry.
+  ExidxEntry PrevEntry = {ulittle32_t(0), ulittle32_t(1)};
+  if (Prev)
+    PrevEntry = Prev->getDataAs<ExidxEntry>().back();
+  if (isExtabRef(PrevEntry.Unwind))
+    return false;
+
+  // We consider the unwind instructions of an .ARM.exidx table entry
+  // a duplicate if the previous unwind instructions if:
+  // - Both are the special EXIDX_CANTUNWIND.
+  // - Both are the same inline unwind instructions.
+  // We do not attempt to follow and check links into .ARM.extab tables as
+  // consecutive identical entries are rare and the effort to check that they
+  // are identical is high.
+
+  // If Cur is nullptr then this is synthesized EXIDX_CANTUNWIND entry.
+  if (Cur == nullptr)
+    return PrevEntry.Unwind == 1;
+
+  for (const ExidxEntry Entry : Cur->getDataAs<ExidxEntry>())
+    if (isExtabRef(Entry.Unwind) || Entry.Unwind != PrevEntry.Unwind)
       return false;
+
+  // All table entries in this .ARM.exidx Section can be merged into the
+  // previous Section.
   return true;
 }
 
-bool ARMExidxSentinelSection::classof(const SectionBase *D) {
+// The .ARM.exidx table must be sorted in ascending order of the address of the
+// functions the table describes. Optionally duplicate adjacent table entries
+// can be removed. At the end of the function the ExecutableSections must be
+// sorted in ascending order of address, Sentinel is set to the InputSection
+// with the highest address and any InputSections that have mergeable
+// .ARM.exidx table entries are removed from it.
+void ARMExidxSyntheticSection::finalizeContents() {
+  // Sort the executable sections that may or may not have associated
+  // .ARM.exidx sections by order of ascending address. This requires the
+  // relative positions of InputSections to be known.
+  auto CompareByFilePosition = [](const InputSection *A,
+                                  const InputSection *B) {
+    OutputSection *AOut = A->getParent();
+    OutputSection *BOut = B->getParent();
+
+    if (AOut != BOut)
+      return AOut->SectionIndex < BOut->SectionIndex;
+    return A->OutSecOff < B->OutSecOff;
+  };
+  std::stable_sort(ExecutableSections.begin(), ExecutableSections.end(),
+                   CompareByFilePosition);
+  Sentinel = ExecutableSections.back();
+  // Optionally merge adjacent duplicate entries.
+  if (Config->MergeArmExidx) {
+    std::vector<InputSection *> SelectedSections;
+    SelectedSections.reserve(ExecutableSections.size());
+    SelectedSections.push_back(ExecutableSections[0]);
+    size_t Prev = 0;
+    for (size_t I = 1; I < ExecutableSections.size(); ++I) {
+      InputSection *EX1 = findExidxSection(ExecutableSections[Prev]);
+      InputSection *EX2 = findExidxSection(ExecutableSections[I]);
+      if (!isDuplicateArmExidxSec(EX1, EX2)) {
+        SelectedSections.push_back(ExecutableSections[I]);
+        Prev = I;
+      }
+    }
+    ExecutableSections = std::move(SelectedSections);
+  }
+  setSizeAndOffsets();
+}
+
+InputSection *ARMExidxSyntheticSection::getLinkOrderDep() const {
+  for (InputSection *IS : ExecutableSections)
+    if (findExidxSection(IS))
+      return IS;
+  return nullptr;
+}
+
+// To write the .ARM.exidx table from the ExecutableSections we have three cases
+// 1.) The InputSection has a .ARM.exidx InputSection in its dependent sections.
+//     We write the .ARM.exidx section contents and apply its relocations.
+// 2.) The InputSection does not have a dependent .ARM.exidx InputSection. We
+//     must write the contents of an EXIDX_CANTUNWIND directly. We use the
+//     start of the InputSection as the purpose of the linker generated
+//     section is to terminate the address range of the previous entry.
+// 3.) A trailing EXIDX_CANTUNWIND sentinel section is required at the end of
+//     the table to terminate the address range of the final entry.
+void ARMExidxSyntheticSection::writeTo(uint8_t *Buf) {
+
+  const uint8_t CantUnwindData[8] = {0, 0, 0, 0,  // PREL31 to target
+                                     1, 0, 0, 0}; // EXIDX_CANTUNWIND
+
+  uint64_t Offset = 0;
+  for (InputSection *IS : ExecutableSections) {
+    assert(IS->getParent() != nullptr);
+    if (InputSection *D = findExidxSection(IS)) {
+      memcpy(Buf + Offset, D->data().data(), D->data().size());
+      D->relocateAlloc(Buf, Buf + D->getSize());
+      Offset += D->getSize();
+    } else {
+      // A Linker generated CANTUNWIND section.
+      memcpy(Buf + Offset, CantUnwindData, sizeof(CantUnwindData));
+      uint64_t S = IS->getVA();
+      uint64_t P = getVA() + Offset;
+      Target->relocateOne(Buf + Offset, R_ARM_PREL31, S - P);
+      Offset += 8;
+    }
+  }
+  // Write Sentinel.
+  memcpy(Buf + Offset, CantUnwindData, sizeof(CantUnwindData));
+  uint64_t S = Sentinel->getVA(Sentinel->getSize());
+  uint64_t P = getVA() + Offset;
+  Target->relocateOne(Buf + Offset, R_ARM_PREL31, S - P);
+  assert(Size == Offset + 8);
+}
+
+bool ARMExidxSyntheticSection::classof(const SectionBase *D) {
   return D->kind() == InputSectionBase::Synthetic && D->Type == SHT_ARM_EXIDX;
 }
 

Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=356666&r1=356665&r2=356666&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Thu Mar 21 07:06:40 2019
@@ -936,19 +936,76 @@ public:
   void writeTo(uint8_t *Buf) override {}
 };
 
-class ARMExidxSentinelSection : public SyntheticSection {
+// Representation of the combined .ARM.Exidx input sections. We process these
+// as a SyntheticSection like .eh_frame as we need to merge duplicate entries
+// and add terminating sentinel entries.
+//
+// The .ARM.exidx input sections after SHF_LINK_ORDER processing is done form
+// a table that the unwinder can derive (Addresses are encoded as offsets from
+// table):
+// | Address of function | Unwind instructions for function |
+// where the unwind instructions are either a small number of unwind or the
+// special EXIDX_CANTUNWIND entry representing no unwinding information.
+// When an exception is thrown from an address A, the unwinder searches the
+// table for the closest table entry with Address of function <= A. This means
+// that for two consecutive table entries:
+// | A1 | U1 |
+// | A2 | U2 |
+// The range of addresses described by U1 is [A1, A2)
+//
+// There are two cases where we need a linker generated table entry to fixup
+// the address ranges in the table
+// Case 1:
+// - A sentinel entry added with an address higher than all
+// executable sections. This was needed to work around libunwind bug pr31091.
+// - After address assignment we need to find the highest addressed executable
+// section and use the limit of that section so that the unwinder never
+// matches it.
+// Case 2:
+// - InputSections without a .ARM.exidx section (usually from Assembly)
+// need a table entry so that they terminate the range of the previously
+// function. This is pr40277.
+//
+// Instead of storing pointers to the .ARM.exidx InputSections from
+// InputObjects, we store pointers to the executable sections that need
+// .ARM.exidx sections. We can then use the dependentSections of these to
+// either find the .ARM.exidx section or know that we need to generate one.
+class ARMExidxSyntheticSection : public SyntheticSection {
 public:
-  ARMExidxSentinelSection();
-  size_t getSize() const override { return 8; }
+  ARMExidxSyntheticSection();
+  size_t getSize() const override { return Size; }
   void writeTo(uint8_t *Buf) override;
-  bool empty() const override;
+  bool empty() const override { return Empty; }
+  // Sort and remove duplicate entries.
+  void finalizeContents() override;
+  InputSection *getLinkOrderDep() const;
 
   static bool classof(const SectionBase *D);
 
-  // The last section referenced by a regular .ARM.exidx section.
-  // It is found and filled in Writer<ELFT>::resolveShfLinkOrder().
-  // The sentinel points at the end of that section.
-  InputSection *Highest = nullptr;
+  // Links to the ARMExidxSections so we can transfer the relocations once the
+  // layout is known.
+  std::vector<InputSection *> ExidxSections;
+
+private:
+  // Derive Size from contents of ExecutableSections, including any linker
+  // generated sentinels. Also set the OutSecOff of the ExidxSections.
+  void setSizeAndOffsets();
+  size_t Size;
+
+  // Empty if ExecutableSections contains no dependent .ARM.exidx sections.
+  bool Empty = true;
+
+  // Instead of storing pointers to the .ARM.exidx InputSections from
+  // InputObjects, we store pointers to the executable sections that need
+  // .ARM.exidx sections. We can then use the dependentSections of these to
+  // either find the .ARM.exidx section or know that we need to generate one.
+  std::vector<InputSection *> ExecutableSections;
+
+  // The executable InputSection with the highest address to use for the
+  // sentinel. We store separately from ExecutableSections as merging of
+  // duplicate entries may mean this InputSection is removed from
+  // ExecutableSections.
+  InputSection *Sentinel = nullptr;
 };
 
 // A container for one or more linker generated thunks. Instances of these
@@ -1003,6 +1060,7 @@ Defined *addSyntheticLocal(StringRef Nam
 // Linker generated sections which can be used as inputs.
 struct InStruct {
   InputSection *ARMAttributes;
+  ARMExidxSyntheticSection *ARMExidx;
   BssSection *Bss;
   BssSection *BssRelRo;
   BuildIdSection *BuildId;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=356666&r1=356665&r2=356666&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Mar 21 07:06:40 2019
@@ -435,10 +435,12 @@ template <class ELFT> static void create
   if (In.StrTab)
     Add(In.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>());
+  if (Config->EMachine == EM_ARM && !Config->Relocatable) {
+    // The ARMExidxsyntheticsection replaces all the individual .ARM.exidx
+    // InputSections.
+    In.ARMExidx = make<ARMExidxSyntheticSection>();
+    Add(In.ARMExidx);
+  }
 }
 
 // The main function of the writer.
@@ -921,6 +923,9 @@ void Writer<ELFT>::forEachRelSec(
       Fn(*IS);
   for (EhInputSection *ES : In.EhFrame->Sections)
     Fn(*ES);
+  if (In.ARMExidx)
+    for (InputSection *Ex : In.ARMExidx->ExidxSections)
+      Fn(*Ex);
 }
 
 // This function generates assignments for predefined symbols (e.g. _end or
@@ -1383,11 +1388,6 @@ template <class ELFT> void Writer<ELFT>:
 }
 
 static bool compareByFilePosition(InputSection *A, InputSection *B) {
-  // Synthetic, i. e. a sentinel section, should go last.
-  if (A->kind() == InputSectionBase::Synthetic ||
-      B->kind() == InputSectionBase::Synthetic)
-    return A->kind() != InputSectionBase::Synthetic;
-
   InputSection *LA = A->getLinkOrderDep();
   InputSection *LB = B->getLinkOrderDep();
   OutputSection *AOut = LA->getParent();
@@ -1398,53 +1398,6 @@ static bool compareByFilePosition(InputS
   return LA->OutSecOff < LB->OutSecOff;
 }
 
-// This function is used by the --merge-exidx-entries to detect duplicate
-// .ARM.exidx sections. It is Arm only.
-//
-// The .ARM.exidx section is of the form:
-// | PREL31 offset to function | Unwind instructions for function |
-// where the unwind instructions are either a small number of unwind
-// instructions inlined into the table entry, the special CANT_UNWIND value of
-// 0x1 or a PREL31 offset into a .ARM.extab Section that contains unwind
-// instructions.
-//
-// We return true if all the unwind instructions in the .ARM.exidx entries of
-// Cur can be merged into the last entry of Prev.
-static bool isDuplicateArmExidxSec(InputSection *Prev, InputSection *Cur) {
-
-  // References to .ARM.Extab Sections have bit 31 clear and are not the
-  // special EXIDX_CANTUNWIND bit-pattern.
-  auto IsExtabRef = [](uint32_t Unwind) {
-    return (Unwind & 0x80000000) == 0 && Unwind != 0x1;
-  };
-
-  struct ExidxEntry {
-    ulittle32_t Fn;
-    ulittle32_t Unwind;
-  };
-
-  // Get the last table Entry from the previous .ARM.exidx section.
-  const ExidxEntry &PrevEntry = Prev->getDataAs<ExidxEntry>().back();
-  if (IsExtabRef(PrevEntry.Unwind))
-    return false;
-
-  // We consider the unwind instructions of an .ARM.exidx table entry
-  // a duplicate if the previous unwind instructions if:
-  // - Both are the special EXIDX_CANTUNWIND.
-  // - Both are the same inline unwind instructions.
-  // We do not attempt to follow and check links into .ARM.extab tables as
-  // consecutive identical entries are rare and the effort to check that they
-  // are identical is high.
-
-  for (const ExidxEntry Entry : Cur->getDataAs<ExidxEntry>())
-    if (IsExtabRef(Entry.Unwind) || Entry.Unwind != PrevEntry.Unwind)
-      return false;
-
-  // All table entries in this .ARM.exidx Section can be merged into the
-  // previous Section.
-  return true;
-}
-
 template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
   for (OutputSection *Sec : OutputSections) {
     if (!(Sec->Flags & SHF_LINK_ORDER))
@@ -1462,46 +1415,17 @@ template <class ELFT> void Writer<ELFT>:
         }
       }
     }
-    std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition);
 
+    // The ARM.exidx section use SHF_LINK_ORDER, but we have consolidated
+    // this processing inside the ARMExidxsyntheticsection::finalizeContents().
     if (!Config->Relocatable && Config->EMachine == EM_ARM &&
-        Sec->Type == SHT_ARM_EXIDX) {
-
-      if (auto *Sentinel = dyn_cast<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.
-        Sentinel->Highest = Sections[Sections.size() - 2]->getLinkOrderDep();
-      }
+        Sec->Type == SHT_ARM_EXIDX)
+      continue;
 
-      // 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.
-      if (Config->MergeArmExidx) {
-        size_t Prev = 0;
-        // The last one is a sentinel entry which should not be removed.
-        for (size_t I = 1; I < Sections.size() - 1; ++I) {
-          if (isDuplicateArmExidxSec(Sections[Prev], Sections[I]))
-            Sections[I] = nullptr;
-          else
-            Prev = I;
-        }
-      }
-    }
+    std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition);
 
     for (int I = 0, N = Sections.size(); I < N; ++I)
       *ScriptSections[I] = Sections[I];
-
-    // Remove the Sections we marked as duplicate earlier.
-    for (BaseCommand *Base : Sec->SectionCommands)
-      if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
-        llvm::erase_if(ISD->Sections, [](InputSection *IS) { return !IS; });
   }
 }
 
@@ -1771,6 +1695,7 @@ template <class ELFT> void Writer<ELFT>:
   // Dynamic section must be the last one in this list and dynamic
   // symbol table section (DynSymTab) must be the first one.
   finalizeSynthetic(In.DynSymTab);
+  finalizeSynthetic(In.ARMExidx);
   finalizeSynthetic(In.Bss);
   finalizeSynthetic(In.BssRelRo);
   finalizeSynthetic(In.GnuHashTab);
@@ -1797,8 +1722,8 @@ template <class ELFT> void Writer<ELFT>:
   if (!Script->HasSectionsCommand && !Config->Relocatable)
     fixSectionAlignments();
 
-  // After link order processing .ARM.exidx sections can be deduplicated, which
-  // needs to be resolved before any other address dependent operation.
+  // SHFLinkOrder processing must be processed after relative section placements are
+  // known but before addresses are allocated.
   resolveShfLinkOrder();
 
   // Jump instructions in many ISAs have small displacements, and therefore they

Modified: lld/trunk/test/ELF/arm-data-prel.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-data-prel.s?rev=356666&r1=356665&r2=356666&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-data-prel.s (original)
+++ lld/trunk/test/ELF/arm-data-prel.s Thu Mar 21 07:06:40 2019
@@ -1,9 +1,8 @@
 // REQUIRES: arm
-// RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o %t.o
+// RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj --arm-add-build-attributes -o %t.o
 // RUN: echo "SECTIONS { \
 // RUN:          .text : { *(.text) } \
 // RUN:          .prel.test : { *(.ARM.exidx) } \
-// RUN:          .prel.test.TEST1 : { *(.ARM.exidx.TEST1) } \
 // RUN:          .TEST1 : { *(.TEST1) } } " > %t.script
 // RUN: ld.lld --script %t.script %t.o -o %t
 // RUN: llvm-readobj -s -sd %t | FileCheck --check-prefix=CHECK %s
@@ -47,17 +46,14 @@ __aeabi_unwind_cpp_pr0:
 // The expected value of the exception table is
 // Word0 0 in bit 31, -4 encoded in 31-bit signed offset
 // Word1 Inline table entry EHT Inline Personality Routine #0
-// CHECK:  Name: .prel.test
-// CHECK:  SectionData (
-// CHECK:     0000: FCFFFF7F B0B0B080
-// CHECK:  )
-
-// The expected value of the exception table is
-// Word0 0 in bit 31, +8 encoded in 31-bit signed offset
-// Word1 Inline table entry EHT Inline Personality Routine #0
+// Word3 0 in bit 31, +10 encoded in 31-bit signed offset
+// Word4 Inline table entry EHT Inline Personality Routine #0
 // set vsp = r11
 // pop r11, r14
-// CHECK:  Name: .prel.test.TEST1
+// Word5 Sentinel +18 EXIDX_CANTUNWIND
+
+// CHECK:  Name: .prel.test
 // CHECK:  SectionData (
-// CHECK:     0000: 08000000 80849B80
+// CHECK:     0000: FCFFFF7F B0B0B080 10000000 80849B80
+// CHECK:     0010: 18000000 01000000
 // CHECK:  )

Added: lld/trunk/test/ELF/arm-exidx-add-missing.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-exidx-add-missing.s?rev=356666&view=auto
==============================================================================
--- lld/trunk/test/ELF/arm-exidx-add-missing.s (added)
+++ lld/trunk/test/ELF/arm-exidx-add-missing.s Thu Mar 21 07:06:40 2019
@@ -0,0 +1,66 @@
+// REQUIRES: arm
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi --arm-add-build-attributes %s -o %t
+// RUN: ld-lld %t --no-merge-exidx-entries -o %t2
+// RUN: llvm-objdump -s %t2 | FileCheck %s
+// RUN: ld-lld %t -o %t3
+// RUN: llvm-objdump -s %t3 | FileCheck %s -check-prefix=CHECK-MERGE
+
+// The ARM.exidx section is a table of 8-byte entries of the form:
+// | PREL31 Relocation to start of function | Unwinding information |
+// The range of addresses covered by the table entry is terminated by the
+// next table entry. This means that an executable section without a .ARM.exidx
+// section does not terminate the range of addresses. To fix this the linker
+// synthesises an EXIDX_CANTUNWIND entry for each section wihout a .ARM.exidx
+// section.
+
+        .syntax unified
+
+        // Expect inline unwind instructions
+        .section .text.01, "ax", %progbits
+        .global f1
+f1:
+        .fnstart
+        bx lr
+        .save {r7, lr}
+        .setfp r7, sp, #0
+        .fnend
+
+        // Expect no unwind information from assembler. The linker must
+        // synthesise an EXIDX_CANTUNWIND entry to prevent an exception
+        // thrown through f2 from matching against the unwind instructions
+        // for f1.
+        .section .text.02, "ax", %progbits
+        .global f2
+f2:
+        bx lr
+
+
+        // Expect 1 EXIDX_CANTUNWIND entry that can be merged into the linker
+        // generated EXIDX_CANTUNWIND as if the assembler had generated it.
+        .section .text.03, "ax",%progbits
+        .global f3
+f3:
+        .fnstart
+        bx lr
+        .cantunwind
+        .fnend
+
+        // Dummy implementation of personality routines to satisfy reference
+        // from exception tables, linker will generate EXIDX_CANTUNWIND.
+        .section .text.__aeabi_unwind_cpp_pr0, "ax", %progbits
+        .global __aeabi_unwind_cpp_pr0
+__aeabi_unwind_cpp_pr0:
+        bx lr
+
+// f1, f2
+// CHECK:      100d4 2c0f0000 08849780 280f0000 01000000
+// f3, __aeabi_unwind_cpp_pr0
+// CHECK-NEXT: 100e4 240f0000 01000000 200f0000 01000000
+// sentinel
+// CHECK-NEXT: 100f4 1c0f0000 01000000
+
+// f1, (f2, f3, __aeabi_unwind_cpp_pr0)
+// CHECK-MERGE:      100d4 2c0f0000 08849780 280f0000 01000000
+// sentinel
+// CHECK-MERGE-NEXT: 100e4 2c0f0000 01000000
+

Modified: lld/trunk/test/ELF/arm-exidx-canunwind.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-exidx-canunwind.s?rev=356666&r1=356665&r2=356666&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-exidx-canunwind.s (original)
+++ lld/trunk/test/ELF/arm-exidx-canunwind.s Thu Mar 21 07:06:40 2019
@@ -1,6 +1,6 @@
 // REQUIRES: arm
-// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
-// RUN: ld.lld %t -o %t2 2>&1
+// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: ld.lld %t -o %t2
 // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s
 // RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXIDX %s
 // RUN: llvm-readobj --program-headers --sections %t2 | FileCheck -check-prefix=CHECK-PT %s
@@ -66,15 +66,14 @@ _start:
 // CHECK:      __aeabi_unwind_cpp_pr0:
 // CHECK-NEXT:    11018:       1e ff 2f e1     bx      lr
 
-// CHECK-EXIDX: Contents of section .ARM.exidx:
-// 100d4 + f38 = 1100c = func1 (inline unwinding data)
-// 100dc + f34 = 11010 = func2 (100e0 + c = 100ec = .ARM.extab entry)
-// CHECK-EXIDX-NEXT: 100d4 380f0000 08849780 340f0000 0c000000
-// 100e4 + f30 = 11014 = terminate = func2 + sizeof(func2)
-// CHECK-EXIDX-NEXT: 100e4 300f0000 01000000
-// CHECK-EXIDX-NEXT: Contents of section .ARM.extab:
-// 100ec + f28 = 11014 = __gxx_personality_v0
-// CHECK-EXIDX-NEXT: 100ec 280f0000 b0b0b000 00000000
+// 100d4 + f2c = 11000 = main (linker generated cantunwind)
+// 100dc + f30 = 1100c = func1 (inline unwinding data)
+// CHECK-EXIDX:      100d4 2c0f0000 01000000 300f0000 08849780
+// 100e4 + f2c = 11010 = func2 (100e8 + 14 = 100fc = .ARM.extab entry)
+// 100ec + f28 = 11014 = __gcc_personality_v0 (linker generated cantunwind)
+// CHECK-EXIDX-NEXT: 100e4 2c0f0000 14000000 280f0000 01000000
+// 100f4 + f28 = 1101c = sentinel
+// CHECK-EXIDX-NEXT: 100f4 280f0000 01000000
 
 // CHECK-PT:          Name: .ARM.exidx
 // CHECK-PT-NEXT:     Type: SHT_ARM_EXIDX (0x70000001)
@@ -84,14 +83,14 @@ _start:
 // CHECK-PT-NEXT:     ]
 // CHECK-PT-NEXT:     Address: 0x100D4
 // CHECK-PT-NEXT:     Offset: 0xD4
-// CHECK-PT-NEXT:     Size: 24
+// CHECK-PT-NEXT:     Size: 40
 
 // CHECK-PT:          Type: PT_ARM_EXIDX (0x70000001)
 // CHECK-PT-NEXT:     Offset: 0xD4
 // CHECK-PT-NEXT:     VirtualAddress: 0x100D4
 // CHECK-PT-NEXT:     PhysicalAddress: 0x100D4
-// CHECK-PT-NEXT:     FileSize: 24
-// CHECK-PT-NEXT:     MemSize: 24
+// CHECK-PT-NEXT:     FileSize: 40
+// CHECK-PT-NEXT:     MemSize: 40
 // CHECK-PT-NEXT:     Flags [ (0x4)
 // CHECK-PT-NEXT:       PF_R (0x4)
 // CHECK-PT-NEXT:     ]

Modified: lld/trunk/test/ELF/arm-exidx-dedup.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-exidx-dedup.s?rev=356666&r1=356665&r2=356666&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-exidx-dedup.s (original)
+++ lld/trunk/test/ELF/arm-exidx-dedup.s Thu Mar 21 07:06:40 2019
@@ -1,27 +1,29 @@
 // REQUIRES: arm
-// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t
 // RUN: ld.lld %t --no-merge-exidx-entries -o %t2
 // RUN: llvm-objdump -s %t2 | FileCheck --check-prefix CHECK-DUPS %s
 // RUN: ld.lld %t -o %t3
 // RUN: llvm-objdump -s %t3 | FileCheck %s
+
 // Test that lld can at least remove duplicate .ARM.exidx sections. A more
 // fine grained implementation will be able to remove duplicate entries within
 // a .ARM.exidx section.
 
 // With duplicate entries
 // CHECK-DUPS: Contents of section .ARM.exidx:
-// CHECK-DUPS-NEXT:  100d4 2c0f0000 01000000 280f0000 01000000
-// CHECK-DUPS-NEXT:  100e4 240f0000 01000000 200f0000 01000000
-// CHECK-DUPS-NEXT:  100f4 1c0f0000 08849780 180f0000 08849780
-// CHECK-DUPS-NEXT:  10104 140f0000 08849780 100f0000 14000000
-// CHECK-DUPS-NEXT:  10114 0c0f0000 18000000 080f0000 01000000
+// CHECK-DUPS-NEXT: 100d4 2c0f0000 01000000 280f0000 01000000
+// CHECK-DUPS-NEXT: 100e4 240f0000 01000000 200f0000 01000000
+// CHECK-DUPS-NEXT: 100f4 1c0f0000 08849780 180f0000 08849780
+// CHECK-DUPS-NEXT: 10104 140f0000 08849780 100f0000 24000000
+// CHECK-DUPS-NEXT: 10114 0c0f0000 28000000 080f0000 01000000
+// CHECK-DUPS-NEXT: 10124 040f0000 01000000 000f0000 01000000
 // CHECK-DUPS-NEXT: Contents of section .ARM.extab:
 
 // After duplicate entry removal
 // CHECK: Contents of section .ARM.exidx:
-// CHECK-NEXT:  100d4 2c0f0000 01000000 340f0000 08849780
-// CHECK-NEXT:  100e4 380f0000 14000000 340f0000 18000000
-// CHECK-NEXT:  100f4 300f0000 01000000
+// CHECK-NEXT: 100d4 2c0f0000 01000000 340f0000 08849780
+// CHECK-NEXT: 100e4 380f0000 1c000000 340f0000 20000000
+// CHECK-NEXT: 100f4 300f0000 01000000 300f0000 01000000
 // CHECK-NEXT: Contents of section .ARM.extab:
         .syntax unified
 
@@ -113,8 +115,9 @@ f8:
         .long 0
         .fnend
 
- // Dummy implementation of personality routines to satisfy reference from
- // exception tables
+// Dummy implementation of personality routines to satisfy reference from
+// exception tables
+// Expect Linker generated EXIDX_CANTUNWIND tables
         .section .text.__gcc_personality_v0, "ax", %progbits
         .global __gxx_personality_v0
 __gxx_personality_v0:

Modified: lld/trunk/test/ELF/arm-exidx-gc.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-exidx-gc.s?rev=356666&r1=356665&r2=356666&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-exidx-gc.s (original)
+++ lld/trunk/test/ELF/arm-exidx-gc.s Thu Mar 21 07:06:40 2019
@@ -1,5 +1,5 @@
 // REQUIRES: arm
-// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t
 // RUN: ld.lld %t --no-merge-exidx-entries -o %t2 --gc-sections 2>&1
 // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s
 // RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXIDX %s
@@ -111,14 +111,15 @@ _start:
 // CHECK-NOT: __gxx_personality_v1
 
 // CHECK-EXIDX: Contents of section .ARM.exidx:
-// 100d4 + f38 = 1100c = func1
-// 100dc + f34 = 11010 = func2 (100e0 + 1c = 100fc = .ARM.extab)
-// CHECK-EXIDX-NEXT: 100d4 380f0000 08849780 340f0000 1c000000
-// 100e4 + f30 = 11014 = __gxx_personality_v0
-// 100ec + f2c = 11018 = __aeabi_unwind_cpp_pr0
-// CHECK-EXIDX-NEXT: 100e4 300f0000 01000000 2c0f0000 01000000
-// 100f4 + f28 = 1101c = __aeabi_unwind_cpp_pr0 + sizeof(__aeabi_unwind_cpp_pr0)
-// CHECK-EXIDX-NEXT: 100f4 280f0000 01000000
+// 100d4 + f2c = 11000
+// 100dc + f30 = 1100c = func1
+// CHECK-EXIDX-NEXT: 100d4 2c0f0000 01000000 300f0000 08849780
+// 100e4 + f2c = 11010 = func2 (100e8 + 1c = 10104 = .ARM.extab)
+// 100ec + f28 = 11014 = __gxx_personality_v0
+// CHECK-EXIDX-NEXT: 100e4 2c0f0000 1c000000 280f0000 01000000
+// 100f4 + f24 = 11018 = __aeabi_unwind_cpp_pr0
+// 100fc + f20 = 1101c = __aeabi_unwind_cpp_pr0 + sizeof(__aeabi_unwind_cpp_pr0)
+// CHECK-EXIDX-NEXT: 100f4 240f0000 01000000 200f0000 01000000
 // CHECK-EXIDX-NEXT: Contents of section .ARM.extab:
-// 100fc + f18 = 11014 = __gxx_personality_v0
-// CHECK-EXIDX-NEXT: 100fc 180f0000 b0b0b000
+// 10104 + f10 = 11014 = __gxx_personality_v0
+// CHECK-EXIDX-NEXT: 10104 100f0000 b0b0b000

Added: lld/trunk/test/ELF/arm-exidx-no-add-missing.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-exidx-no-add-missing.s?rev=356666&view=auto
==============================================================================
--- lld/trunk/test/ELF/arm-exidx-no-add-missing.s (added)
+++ lld/trunk/test/ELF/arm-exidx-no-add-missing.s Thu Mar 21 07:06:40 2019
@@ -0,0 +1,16 @@
+// REQUIRES: arm
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi --arm-add-build-attributes %s -o %t
+// RUN: ld-lld %t -o %t2
+// RUN: llvm-objdump -s %t2 | FileCheck %s
+
+// We do not want to generate missing EXIDX_CANTUNWIND entries if there are no
+// input .ARM.exidx sections.
+
+// CHECK-NOT: .ARM.exidx
+        .syntax unified
+        .text
+	.globl _start
+	.type _start, %function
+_start:
+	bx lr
+

Modified: lld/trunk/test/ELF/arm-exidx-shared.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-exidx-shared.s?rev=356666&r1=356665&r2=356666&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-exidx-shared.s (original)
+++ lld/trunk/test/ELF/arm-exidx-shared.s Thu Mar 21 07:06:40 2019
@@ -1,8 +1,8 @@
 // REQUIRES: arm
-// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t
 // RUN: ld.lld --hash-style=sysv %t --shared -o %t2 2>&1
 // RUN: llvm-readobj --relocations %t2 | FileCheck %s
-// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXTAB %s
+// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck --check-prefix=CHECK-EXTAB-NEXT %s
 
 // Check that the relative R_ARM_PREL31 relocation can access a PLT entry
 // for when the personality routine is referenced from a shared library.
@@ -41,5 +41,5 @@ __aeabi_unwind_cpp_pr0:
 // CHECK-NEXT:     0x300C R_ARM_JUMP_SLOT __gxx_personality_v0
 
 // CHECK-EXTAB: Contents of section .ARM.extab:
-// 0x0210 + 0x0e20 = 0x1030 = __gxx_personality_v0(PLT)
-// CHECK-EXTAB-NEXT:  0230 000e0000 b0b0b000 00000000
+// 0x0238 + 0xdf8 = 0x1030 = __gxx_personality_v0(PLT)      
+// CHECK-EXTAB-NEXT: 0238 f80d0000 b0b0b000 00000000 




More information about the llvm-commits mailing list