From 1681ceb2c422ad0f19769090303f2cfc4bbb2243 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 26 Aug 2019 10:32:12 +0000 Subject: [PATCH] [ELF] EhFrameSection: postpone FDE liveness check to finalizeSections 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 | 69 +++++++++++++++++++++-------------- lld/ELF/SyntheticSections.h | 6 ++- lld/ELF/Writer.cpp | 6 +-- lld/ELF/Writer.h | 1 + 4 files changed, 50 insertions(+), 32 deletions(-) diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 1320a18b823f..3a372f5736c6 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -402,7 +402,7 @@ bool EhFrameSection::isFdeLive(EhSectionPiece &fde, ArrayRef rels) { // a list of FDEs. This function searches an existing CIE or create a new // one and associates FDEs to the CIE. template -void EhFrameSection::addSectionAux(EhInputSection *sec, ArrayRef rels) { +void EhFrameSection::addRecords(EhInputSection *sec, ArrayRef 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 rels) { } } -template void EhFrameSection::addSection(InputSectionBase *c) { - auto *sec = cast(c); +template +void EhFrameSection::addSectionAux(EhInputSection *sec) { + if (!sec->isLive()) + return; + if (sec->areRelocsRela) + addRecords(sec, sec->template relas()); + else + addRecords(sec, sec->template rels()); +} + +void EhFrameSection::addSection(EhInputSection *sec) { sec->parent = this; alignment = std::max(alignment, sec->alignment); @@ -437,14 +446,6 @@ template void EhFrameSection::addSection(InputSectionBase *c) { for (auto *ds : sec->dependentSections) dependentSections.push_back(ds); - - if (sec->pieces.empty()) - return; - - if (sec->areRelocsRela) - addSectionAux(sec, sec->template relas()); - else - addSectionAux(sec, sec->template rels()); } static void writeCieFde(uint8_t *buf, ArrayRef d) { @@ -461,6 +462,28 @@ static void writeCieFde(uint8_t *buf, ArrayRef 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(sec); + break; + case ELF32BEKind: + for (EhInputSection *sec : sections) + addSectionAux(sec); + break; + case ELF64LEKind: + for (EhInputSection *sec : sections) + addSectionAux(sec); + break; + case ELF64BEKind: + for (EhInputSection *sec : sections) + addSectionAux(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(); template void elf::splitSections(); template void elf::splitSections(); -template void EhFrameSection::addSection(InputSectionBase *); -template void EhFrameSection::addSection(InputSectionBase *); -template void EhFrameSection::addSection(InputSectionBase *); -template void EhFrameSection::addSection(InputSectionBase *); - template void PltSection::addEntry(Symbol &Sym); template void PltSection::addEntry(Symbol &Sym); template void PltSection::addEntry(Symbol &Sym); diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 1c4dd06e0277..70ec36c4420d 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -76,7 +76,7 @@ public: return SyntheticSection::classof(d) && d->name == ".eh_frame"; } - template void addSection(InputSectionBase *s); + void addSection(EhInputSection *sec); std::vector sections; size_t numFdes = 0; @@ -97,7 +97,9 @@ private: uint64_t size = 0; template - void addSectionAux(EhInputSection *s, llvm::ArrayRef rels); + void addRecords(EhInputSection *s, llvm::ArrayRef rels); + template + void addSectionAux(EhInputSection *s); template CieRecord *addCie(EhSectionPiece &piece, ArrayRef rels); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index dcf4bbb61bfe..5c12787cf1b5 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -174,7 +174,7 @@ static void copySectionsIntoPartitions() { newSections.end()); } -template 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 static void combineEhSections() { Partition &part = s->getPartition(); if (auto *es = dyn_cast(s)) { - part.ehFrame->addSection(es); + part.ehFrame->addSection(es); s = nullptr; } else if (s->kind() == SectionBase::Regular && part.armExidx && part.armExidx->addSection(cast(s))) { @@ -552,7 +552,7 @@ template void Writer::run() { // into synthetic sections. Do that now so that they aren't assigned to // output sections in the usual way. if (!config->relocatable) - combineEhSections(); + combineEhSections(); // We want to process linker script commands. When SECTIONS command // is given we let it create sections. diff --git a/lld/ELF/Writer.h b/lld/ELF/Writer.h index 784fba9c75a6..58d8d3116576 100644 --- a/lld/ELF/Writer.h +++ b/lld/ELF/Writer.h @@ -19,6 +19,7 @@ namespace elf { class InputFile; class OutputSection; class InputSectionBase; +void combineEhSections(); template void writeResult(); // This describes a program header entry.