[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
This commit is contained in:
Fangrui Song 2019-08-26 10:32:12 +00:00
parent debcac9fef
commit 1681ceb2c4
4 changed files with 50 additions and 32 deletions

View 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);

View 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);

View 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.

View 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.