[ELF] EhFrameSection: postpone FDE liveness check to finalizeSections
authorFangrui Song <maskray@google.com>
Mon, 26 Aug 2019 10:32:12 +0000 (10:32 +0000)
committerFangrui Song <maskray@google.com>
Mon, 26 Aug 2019 10:32:12 +0000 (10:32 +0000)
EhFrameSection::addSection checks liveness of FDE early. This makes it
infeasible to move combineEhSections() before ICF.

Postpone the check to EhFrameSection::finalizeContents(). This is what
ARMExidxSyntheticSection does and it will make a subsequent patch D66717
simpler.

Reviewed By: ruiu

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

llvm-svn: 369890

lld/ELF/SyntheticSections.cpp
lld/ELF/SyntheticSections.h
lld/ELF/Writer.cpp
lld/ELF/Writer.h

index 1320a18b823f711d2c04eb6e967e6897b53282b7..3a372f5736c6409e837c3d4b72e3485ae6427c1d 100644 (file)
@@ -402,7 +402,7 @@ bool EhFrameSection::isFdeLive(EhSectionPiece &fde, ArrayRef<RelTy> rels) {
 // a list of FDEs. This function searches an existing CIE or create a new
 // one and associates FDEs to the CIE.
 template <class ELFT, class RelTy>
-void EhFrameSection::addSectionAux(EhInputSection *sec, ArrayRef<RelTy> rels) {
+void EhFrameSection::addRecords(EhInputSection *sec, ArrayRef<RelTy> rels) {
   offsetToCie.clear();
   for (EhSectionPiece &piece : sec->pieces) {
     // The empty record is the end marker.
@@ -428,8 +428,17 @@ void EhFrameSection::addSectionAux(EhInputSection *sec, ArrayRef<RelTy> rels) {
   }
 }
 
-template <class ELFT> void EhFrameSection::addSection(InputSectionBase *c) {
-  auto *sec = cast<EhInputSection>(c);
+template <class ELFT>
+void EhFrameSection::addSectionAux(EhInputSection *sec) {
+  if (!sec->isLive())
+    return;
+  if (sec->areRelocsRela)
+    addRecords<ELFT>(sec, sec->template relas<ELFT>());
+  else
+    addRecords<ELFT>(sec, sec->template rels<ELFT>());
+}
+
+void EhFrameSection::addSection(EhInputSection *sec) {
   sec->parent = this;
 
   alignment = std::max(alignment, sec->alignment);
@@ -437,14 +446,6 @@ template <class ELFT> void EhFrameSection::addSection(InputSectionBase *c) {
 
   for (auto *ds : sec->dependentSections)
     dependentSections.push_back(ds);
-
-  if (sec->pieces.empty())
-    return;
-
-  if (sec->areRelocsRela)
-    addSectionAux<ELFT>(sec, sec->template relas<ELFT>());
-  else
-    addSectionAux<ELFT>(sec, sec->template rels<ELFT>());
 }
 
 static void writeCieFde(uint8_t *buf, ArrayRef<uint8_t> d) {
@@ -461,6 +462,28 @@ static void writeCieFde(uint8_t *buf, ArrayRef<uint8_t> d) {
 
 void EhFrameSection::finalizeContents() {
   assert(!this->size); // Not finalized.
+
+  switch (config->ekind) {
+  case ELFNoneKind:
+    llvm_unreachable("invalid ekind");
+  case ELF32LEKind:
+    for (EhInputSection *sec : sections)
+      addSectionAux<ELF32LE>(sec);
+    break;
+  case ELF32BEKind:
+    for (EhInputSection *sec : sections)
+      addSectionAux<ELF32BE>(sec);
+    break;
+  case ELF64LEKind:
+    for (EhInputSection *sec : sections)
+      addSectionAux<ELF64LE>(sec);
+    break;
+  case ELF64BEKind:
+    for (EhInputSection *sec : sections)
+      addSectionAux<ELF64BE>(sec);
+    break;
+  }
+
   size_t off = 0;
   for (CieRecord *rec : cieRecords) {
     rec->cie->outputOff = off;
@@ -3267,17 +3290,14 @@ static bool isDuplicateArmExidxSec(InputSection *prev, InputSection *cur) {
 // with the highest address and any InputSections that have mergeable
 // .ARM.exidx table entries are removed from it.
 void ARMExidxSyntheticSection::finalizeContents() {
-  if (script->hasSectionsCommand) {
-    // The executableSections and exidxSections that we use to derive the
-    // final contents of this SyntheticSection are populated before the
-    // linker script assigns InputSections to OutputSections. The linker script
-    // SECTIONS command may have a /DISCARD/ entry that removes executable
-    // InputSections and their dependent .ARM.exidx section that we recorded
-    // earlier.
-    auto isDiscarded = [](const InputSection *isec) { return !isec->isLive(); };
-    llvm::erase_if(executableSections, isDiscarded);
-    llvm::erase_if(exidxSections, isDiscarded);
-  }
+  // The executableSections and exidxSections that we use to derive the final
+  // contents of this SyntheticSection are populated before
+  // processSectionCommands() and ICF. A /DISCARD/ entry in SECTIONS command or
+  // ICF may remove executable InputSections and their dependent .ARM.exidx
+  // section that we recorded earlier.
+  auto isDiscarded = [](const InputSection *isec) { return !isec->isLive(); };
+  llvm::erase_if(executableSections, isDiscarded);
+  llvm::erase_if(exidxSections, isDiscarded);
 
   // Sort the executable sections that may or may not have associated
   // .ARM.exidx sections by order of ascending address. This requires the
@@ -3639,11 +3659,6 @@ template void elf::splitSections<ELF32BE>();
 template void elf::splitSections<ELF64LE>();
 template void elf::splitSections<ELF64BE>();
 
-template void EhFrameSection::addSection<ELF32LE>(InputSectionBase *);
-template void EhFrameSection::addSection<ELF32BE>(InputSectionBase *);
-template void EhFrameSection::addSection<ELF64LE>(InputSectionBase *);
-template void EhFrameSection::addSection<ELF64BE>(InputSectionBase *);
-
 template void PltSection::addEntry<ELF32LE>(Symbol &Sym);
 template void PltSection::addEntry<ELF32BE>(Symbol &Sym);
 template void PltSection::addEntry<ELF64LE>(Symbol &Sym);
index 1c4dd06e027768d199bbdc54db6712ed73fb09a7..70ec36c4420d80b4bb403f392858dfad8521b14c 100644 (file)
@@ -76,7 +76,7 @@ public:
     return SyntheticSection::classof(d) && d->name == ".eh_frame";
   }
 
-  template <class ELFT> void addSection(InputSectionBase *s);
+  void addSection(EhInputSection *sec);
 
   std::vector<EhInputSection *> sections;
   size_t numFdes = 0;
@@ -97,7 +97,9 @@ private:
   uint64_t size = 0;
 
   template <class ELFT, class RelTy>
-  void addSectionAux(EhInputSection *s, llvm::ArrayRef<RelTy> rels);
+  void addRecords(EhInputSection *s, llvm::ArrayRef<RelTy> rels);
+  template <class ELFT>
+  void addSectionAux(EhInputSection *s);
 
   template <class ELFT, class RelTy>
   CieRecord *addCie(EhSectionPiece &piece, ArrayRef<RelTy> rels);
index dcf4bbb61bfe1f05776bb0b66376624e538cc68f..5c12787cf1b573750f3c9a2defa36f8ed40e06c0 100644 (file)
@@ -174,7 +174,7 @@ static void copySectionsIntoPartitions() {
                        newSections.end());
 }
 
-template <class ELFT> static void combineEhSections() {
+void elf::combineEhSections() {
   for (InputSectionBase *&s : inputSections) {
     // Ignore dead sections and the partition end marker (.part.end),
     // whose partition number is out of bounds.
@@ -183,7 +183,7 @@ template <class ELFT> static void combineEhSections() {
 
     Partition &part = s->getPartition();
     if (auto *es = dyn_cast<EhInputSection>(s)) {
-      part.ehFrame->addSection<ELFT>(es);
+      part.ehFrame->addSection(es);
       s = nullptr;
     } else if (s->kind() == SectionBase::Regular && part.armExidx &&
                part.armExidx->addSection(cast<InputSection>(s))) {
@@ -552,7 +552,7 @@ template <class ELFT> void Writer<ELFT>::run() {
   // into synthetic sections. Do that now so that they aren't assigned to
   // output sections in the usual way.
   if (!config->relocatable)
-    combineEhSections<ELFT>();
+    combineEhSections();
 
   // We want to process linker script commands. When SECTIONS command
   // is given we let it create sections.
index 784fba9c75a6d774b9695e45ef6e7a523cc1d153..58d8d3116576c09eecf65c40f9630724bcc8fd36 100644 (file)
@@ -19,6 +19,7 @@ namespace elf {
 class InputFile;
 class OutputSection;
 class InputSectionBase;
+void combineEhSections();
 template <class ELFT> void writeResult();
 
 // This describes a program header entry.