diff options
author | Fangrui Song <maskray@google.com> | 2019-09-24 11:48:31 +0000 |
---|---|---|
committer | Fangrui Song <maskray@google.com> | 2019-09-24 11:48:31 +0000 |
commit | e47bbd28f8e9dfea4e019e27e9d371c144c3302e (patch) | |
tree | 799459668b1b23aa9f3691564487958ff364ac0c /lld/ELF/LinkerScript.cpp | |
parent | 06cdcb5f68b923c7e6e632edd91f49e4f9dd653e (diff) | |
download | bcm5719-llvm-e47bbd28f8e9dfea4e019e27e9d371c144c3302e.tar.gz bcm5719-llvm-e47bbd28f8e9dfea4e019e27e9d371c144c3302e.zip |
[ELF] Make MergeInputSection merging aware of output sections
Fixes PR38748
mergeSections() calls getOutputSectionName() to get output section
names. Two MergeInputSections may be merged even if they are made
different by SECTIONS commands.
This patch moves mergeSections() after processSectionCommands() and
addOrphanSections() to fix the issue. The new pass is renamed to
OutputSection::finalizeInputSections().
processSectionCommands() and addorphanSections() are changed to add
sections to InputSectionDescription::sectionBases.
finalizeInputSections() merges MergeInputSections and migrates
`sectionBases` to `sections`.
For the -r case, we drop an optimization that tries keeping sh_entsize
non-zero. This is for the simplicity of addOrphanSections(). The
updated merge-entsize2.s reflects the change.
Reviewed By: grimar
Differential Revision: https://reviews.llvm.org/D67504
llvm-svn: 372734
Diffstat (limited to 'lld/ELF/LinkerScript.cpp')
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 95 |
1 files changed, 41 insertions, 54 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index cd02e779e7a..48f6c38cce6 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -341,19 +341,19 @@ bool LinkerScript::shouldKeep(InputSectionBase *s) { } // A helper function for the SORT() command. -static bool matchConstraints(ArrayRef<InputSection *> sections, +static bool matchConstraints(ArrayRef<InputSectionBase *> sections, ConstraintKind kind) { if (kind == ConstraintKind::NoConstraint) return true; bool isRW = llvm::any_of( - sections, [](InputSection *sec) { return sec->flags & SHF_WRITE; }); + sections, [](InputSectionBase *sec) { return sec->flags & SHF_WRITE; }); return (isRW && kind == ConstraintKind::ReadWrite) || (!isRW && kind == ConstraintKind::ReadOnly); } -static void sortSections(MutableArrayRef<InputSection *> vec, +static void sortSections(MutableArrayRef<InputSectionBase *> vec, SortSectionPolicy k) { auto alignmentComparator = [](InputSectionBase *a, InputSectionBase *b) { // ">" is not a mistake. Sections with larger alignments are placed @@ -392,7 +392,7 @@ static void sortSections(MutableArrayRef<InputSection *> vec, // --sort-section is handled as an inner SORT command. // 3. If one SORT command is given, and if it is SORT_NONE, don't sort. // 4. If no SORT command is given, sort according to --sort-section. -static void sortInputSections(MutableArrayRef<InputSection *> vec, +static void sortInputSections(MutableArrayRef<InputSectionBase *> vec, const SectionPattern &pat) { if (pat.sortOuter == SortSectionPolicy::None) return; @@ -405,9 +405,9 @@ static void sortInputSections(MutableArrayRef<InputSection *> vec, } // Compute and remember which sections the InputSectionDescription matches. -std::vector<InputSection *> +std::vector<InputSectionBase *> LinkerScript::computeInputSections(const InputSectionDescription *cmd) { - std::vector<InputSection *> ret; + std::vector<InputSectionBase *> ret; // Collects all sections that satisfy constraints of Cmd. for (const SectionPattern &pat : cmd->sectionPatterns) { @@ -422,10 +422,8 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd) { // which are common because they are in the default bfd script. // We do not ignore SHT_REL[A] linker-synthesized sections here because // want to support scripts that do custom layout for them. - // - // It is safe to assume that Sec is an InputSection because mergeable or - // EH input sections have already been handled and eliminated. - if (cast<InputSection>(sec)->getRelocatedSection()) + if (isa<InputSection>(sec) && + cast<InputSection>(sec)->getRelocatedSection()) continue; std::string filename = getFilename(sec->file); @@ -434,42 +432,41 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd) { !pat.sectionPat.match(sec->name)) continue; - ret.push_back(cast<InputSection>(sec)); + ret.push_back(sec); sec->assigned = true; } - sortInputSections(MutableArrayRef<InputSection *>(ret).slice(sizeBefore), - pat); + sortInputSections( + MutableArrayRef<InputSectionBase *>(ret).slice(sizeBefore), pat); } return ret; } -void LinkerScript::discard(ArrayRef<InputSection *> v) { - for (InputSection *s : v) { - if (s == in.shStrTab || s == mainPart->relaDyn || s == mainPart->relrDyn) - error("discarding " + s->name + " section is not allowed"); - - // You can discard .hash and .gnu.hash sections by linker scripts. Since - // they are synthesized sections, we need to handle them differently than - // other regular sections. - if (s == mainPart->gnuHashTab) - mainPart->gnuHashTab = nullptr; - if (s == mainPart->hashTab) - mainPart->hashTab = nullptr; - - s->markDead(); - discard(s->dependentSections); - } +void LinkerScript::discard(InputSectionBase *s) { + if (s == in.shStrTab || s == mainPart->relaDyn || s == mainPart->relrDyn) + error("discarding " + s->name + " section is not allowed"); + + // You can discard .hash and .gnu.hash sections by linker scripts. Since + // they are synthesized sections, we need to handle them differently than + // other regular sections. + if (s == mainPart->gnuHashTab) + mainPart->gnuHashTab = nullptr; + if (s == mainPart->hashTab) + mainPart->hashTab = nullptr; + + s->markDead(); + for (InputSection *ds : s->dependentSections) + discard(ds); } -std::vector<InputSection *> +std::vector<InputSectionBase *> LinkerScript::createInputSectionList(OutputSection &outCmd) { - std::vector<InputSection *> ret; + std::vector<InputSectionBase *> ret; for (BaseCommand *base : outCmd.sectionCommands) { if (auto *cmd = dyn_cast<InputSectionDescription>(base)) { - cmd->sections = computeInputSections(cmd); - ret.insert(ret.end(), cmd->sections.begin(), cmd->sections.end()); + cmd->sectionBases = computeInputSections(cmd); + ret.insert(ret.end(), cmd->sectionBases.begin(), cmd->sectionBases.end()); } } return ret; @@ -480,12 +477,13 @@ void LinkerScript::processSectionCommands() { size_t i = 0; for (BaseCommand *base : sectionCommands) { if (auto *sec = dyn_cast<OutputSection>(base)) { - std::vector<InputSection *> v = createInputSectionList(*sec); + std::vector<InputSectionBase *> v = createInputSectionList(*sec); // The output section name `/DISCARD/' is special. // Any input section assigned to it is discarded. if (sec->name == "/DISCARD/") { - discard(v); + for (InputSectionBase *s : v) + discard(s); sec->sectionCommands.clear(); continue; } @@ -513,15 +511,9 @@ void LinkerScript::processSectionCommands() { s->alignment = subalign; } - // Some input sections may be removed from the list after ICF. - for (InputSection *s : v) - sec->addSection(s); - sec->sectionIndex = i++; - if (sec->noload) - sec->type = SHT_NOBITS; - if (sec->nonAlloc) - sec->flags &= ~(uint64_t)SHF_ALLOC; + for (InputSectionBase *s : v) + s->parent = sec; } } } @@ -565,7 +557,7 @@ static OutputSection *findByName(ArrayRef<BaseCommand *> vec, static OutputSection *createSection(InputSectionBase *isec, StringRef outsecName) { OutputSection *sec = script->createOutputSection(outsecName, "<internal>"); - sec->addSection(cast<InputSection>(isec)); + sec->recordSection(isec); return sec; } @@ -594,7 +586,7 @@ addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map, OutputSection *out = sec->getRelocatedSection()->getOutputSection(); if (out->relocationSection) { - out->relocationSection->addSection(sec); + out->relocationSection->recordSection(sec); return nullptr; } @@ -602,12 +594,6 @@ addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map, return out->relocationSection; } - // When control reaches here, mergeable sections have already been merged into - // synthetic sections. For relocatable case we want to create one output - // section per syntetic section so that they have a valid sh_entsize. - if (config->relocatable && (isec->flags & SHF_MERGE)) - return createSection(isec, outsecName); - // The ELF spec just says // ---------------------------------------------------------------- // In the first phase, input sections that match in name, type and @@ -654,7 +640,7 @@ addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map, for (OutputSection *sec : v) { if (sec->partition != isec->partition) continue; - sec->addSection(cast<InputSection>(isec)); + sec->recordSection(isec); return nullptr; } @@ -680,13 +666,14 @@ void LinkerScript::addOrphanSections() { warn(toString(s) + " is being placed in '" + name + "'"); if (OutputSection *sec = findByName(sectionCommands, name)) { - sec->addSection(cast<InputSection>(s)); + sec->recordSection(s); return; } if (OutputSection *os = addInputSec(map, s, name)) v.push_back(os); - assert(s->getOutputSection()->sectionIndex == UINT32_MAX); + assert(isa<MergeInputSection>(s) || + s->getOutputSection()->sectionIndex == UINT32_MAX); }; // For futher --emit-reloc handling code we need target output section |