From 97403d15eeceedb6ce48ac9bdf09d1e2a73283eb Mon Sep 17 00:00:00 2001 From: Eugene Leviant Date: Thu, 1 Sep 2016 09:55:57 +0000 Subject: [PATCH] Eliminate LayoutInputSection class Previously we used LayoutInputSection class to correctly assign symbols defined in linker script. This patch removes it and uses pointer to preceding input section in SymbolAssignment class instead. Differential revision: https://reviews.llvm.org/D23661 llvm-svn: 280348 --- lld/ELF/InputSection.cpp | 15 +++---- lld/ELF/InputSection.h | 49 +++++++++++--------- lld/ELF/LinkerScript.cpp | 110 +++++++++++++++++---------------------------- lld/ELF/LinkerScript.h | 5 +-- lld/ELF/OutputSections.cpp | 2 - 5 files changed, 76 insertions(+), 105 deletions(-) diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index aad9bc7..321c880 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -30,14 +30,10 @@ using namespace lld::elf; template InputSectionBase::InputSectionBase(elf::ObjectFile *File, - const Elf_Shdr *Header, - Kind SectionKind) - : Header(Header), File(File), SectionKind(SectionKind), Repl(this), - Compressed(Header->sh_flags & SHF_COMPRESSED) { - // The garbage collector sets sections' Live bits. - // If GC is disabled, all sections are considered live by default. - Live = !Config->GcSections; - + const Elf_Shdr *Hdr, Kind SectionKind) + : InputSectionData(SectionKind, Hdr->sh_flags & SHF_COMPRESSED, + !Config->GcSections), + Header(Hdr), File(File), Repl(this) { // The ELF spec states that a value of 0 means the section has // no alignment constraits. Alignment = std::max(Header->sh_addralign, 1); @@ -71,7 +67,6 @@ template typename ELFT::uint InputSectionBase::getOffset(uintX_t Offset) const { switch (SectionKind) { case Regular: - case Layout: return cast>(this)->OutSecOff + Offset; case EHFrame: // The file crtbeginT.o has relocations pointing to the start of an empty @@ -131,7 +126,7 @@ InputSection::InputSection(elf::ObjectFile *F, template bool InputSection::classof(const InputSectionBase *S) { - return S->SectionKind == Base::Regular || S->SectionKind == Base::Layout; + return S->SectionKind == Base::Regular; } template diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index a12b591..3b7c201 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -30,8 +30,33 @@ template class ObjectFile; template class OutputSection; template class OutputSectionBase; +// We need non-template input section class to store symbol layout +// in linker script parser structures, where we do not have ELFT +// template parameter. For each scripted output section symbol we +// store pointer to preceding InputSectionData object or nullptr, +// if symbol should be placed at the very beginning of the output +// section +class InputSectionData { +public: + enum Kind { Regular, EHFrame, Merge, MipsReginfo, MipsOptions, MipsAbiFlags }; + + // The garbage collector sets sections' Live bits. + // If GC is disabled, all sections are considered live by default. + InputSectionData(Kind SectionKind, bool Compressed, bool Live) + : SectionKind(SectionKind), Live(Live), Compressed(Compressed) {} + + Kind SectionKind; + uint32_t Alignment; + // Used for garbage collection. + bool Live; + + bool Compressed; + // If a section is compressed, this vector has uncompressed section data. + SmallVector Uncompressed; +}; + // This corresponds to a section of an input file. -template class InputSectionBase { +template class InputSectionBase : public InputSectionData { protected: typedef typename ELFT::Chdr Elf_Chdr; typedef typename ELFT::Rel Elf_Rel; @@ -44,30 +69,12 @@ protected: // The file this section is from. ObjectFile *File; - // If a section is compressed, this vector has uncompressed section data. - SmallVector Uncompressed; - public: - enum Kind { - Regular, - EHFrame, - Merge, - MipsReginfo, - MipsOptions, - MipsAbiFlags, - Layout - }; - Kind SectionKind; - - InputSectionBase() : Repl(this) {} + InputSectionBase() : InputSectionData(Regular, false, false), Repl(this) {} InputSectionBase(ObjectFile *File, const Elf_Shdr *Header, Kind SectionKind); OutputSectionBase *OutSec = nullptr; - uint32_t Alignment; - - // Used for garbage collection. - bool Live; // This pointer points to the "real" instance of this instance. // Usually Repl == this. However, if ICF merges two sections, @@ -96,8 +103,6 @@ public: void relocate(uint8_t *Buf, uint8_t *BufEnd); std::vector> Relocations; - - bool Compressed; }; template InputSectionBase InputSectionBase::Discarded; diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index b3a1c45..9afd5ba 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -133,54 +133,6 @@ LinkerScript::getInputSections(const InputSectionDescription *I) { return Ret; } -// You can define new symbols using linker scripts. For example, -// ".text { abc.o(.text); foo = .; def.o(.text); }" defines symbol -// foo just after abc.o's text section contents. This class is to -// handle such symbol definitions. -// -// In order to handle scripts like the above one, we want to -// keep symbol definitions in output sections. Because output sections -// can contain only input sections, we wrap symbol definitions -// with dummy input sections. This class serves that purpose. -template -class elf::LayoutInputSection : public InputSectionBase { -public: - explicit LayoutInputSection(SymbolAssignment *Cmd); - static bool classof(const InputSectionBase *S); - SymbolAssignment *Cmd; - -private: - typename ELFT::Shdr Hdr; -}; - -template -static InputSectionBase * -getNonLayoutSection(std::vector *> &Vec) { - for (InputSectionBase *S : Vec) - if (!isa>(S)) - return S; - return nullptr; -} - -template static T *zero(T *Val) { - memset(Val, 0, sizeof(*Val)); - return Val; -} - -template -LayoutInputSection::LayoutInputSection(SymbolAssignment *Cmd) - : InputSectionBase(nullptr, zero(&Hdr), - InputSectionBase::Layout), - Cmd(Cmd) { - this->Live = true; - Hdr.sh_type = SHT_NOBITS; -} - -template -bool LayoutInputSection::classof(const InputSectionBase *S) { - return S->SectionKind == InputSectionBase::Layout; -} - template static bool compareName(InputSectionBase *A, InputSectionBase *B) { return A->getSectionName() < B->getSectionName(); @@ -236,12 +188,13 @@ template std::vector *> LinkerScript::createInputSectionList(OutputSectionCommand &OutCmd) { std::vector *> Ret; + DenseSet *> SectionIndex; for (const std::unique_ptr &Base : OutCmd.Commands) { if (auto *OutCmd = dyn_cast(Base.get())) { if (shouldDefine(OutCmd)) addSynthetic(OutCmd); - Ret.push_back(new (LAlloc.Allocate()) LayoutInputSection(OutCmd)); + OutCmd->GoesAfter = Ret.empty() ? nullptr : Ret.back(); continue; } @@ -253,7 +206,12 @@ LinkerScript::createInputSectionList(OutputSectionCommand &OutCmd) { std::stable_sort(V.begin(), V.end(), getComparator(Cmd->SortInner)); if (Cmd->SortOuter) std::stable_sort(V.begin(), V.end(), getComparator(Cmd->SortOuter)); - Ret.insert(Ret.end(), V.begin(), V.end()); + + // Add all input sections corresponding to rule 'Cmd' to + // resulting vector. We do not add duplicate input sections. + for (InputSectionBase *S : V) + if (SectionIndex.insert(S).second) + Ret.push_back(S); } return Ret; } @@ -284,13 +242,12 @@ void LinkerScript::createSections(OutputSectionFactory &Factory) { } std::vector *> V = createInputSectionList(*Cmd); - InputSectionBase *Head = getNonLayoutSection(V); - if (!Head) + if (V.empty()) continue; OutputSectionBase *OutSec; bool IsNew; - std::tie(OutSec, IsNew) = Factory.create(Head, Cmd->Name); + std::tie(OutSec, IsNew) = Factory.create(V.front(), Cmd->Name); if (IsNew) OutputSections->push_back(OutSec); @@ -298,8 +255,7 @@ void LinkerScript::createSections(OutputSectionFactory &Factory) { for (InputSectionBase *Sec : V) { if (Subalign) Sec->Alignment = Subalign; - if (!Sec->OutSec) - OutSec->addSection(Sec); + OutSec->addSection(Sec); } } } @@ -359,31 +315,49 @@ void assignOffsets(OutputSectionCommand *Cmd, OutputSectionBase *Sec) { addStartEndSymbols(Cmd, Sec); return; } - typedef typename ELFT::uint uintX_t; uintX_t Off = 0; + auto ItCmd = Cmd->Commands.begin(); + + // Assigns values to all symbols following the given + // input section 'D' in output section 'Sec'. When symbols + // are in the beginning of output section the value of 'D' + // is nullptr. + auto AssignSuccessors = [&](InputSectionData *D) { + for (; ItCmd != Cmd->Commands.end(); ++ItCmd) { + auto *AssignCmd = dyn_cast(ItCmd->get()); + if (!AssignCmd) + continue; + if (D != AssignCmd->GoesAfter) + break; - for (InputSection *I : OutSec->Sections) { - if (auto *L = dyn_cast>(I)) { - uintX_t Value = L->Cmd->Expression(Sec->getVA() + Off) - Sec->getVA(); - if (L->Cmd->Name == ".") { + uintX_t Value = AssignCmd->Expression(Sec->getVA() + Off) - Sec->getVA(); + if (AssignCmd->Name == ".") { + // Update to location counter means update to section size. Off = Value; - } else if (auto *Sym = - cast_or_null>(L->Cmd->Sym)) { - // shouldDefine could have returned false, so we need to check Sym, - // for non-null value. + Sec->setSize(Off); + continue; + } + + if (DefinedSynthetic *Sym = + cast_or_null>(AssignCmd->Sym)) { Sym->Section = OutSec; Sym->Value = Value; } - } else { - Off = alignTo(Off, I->Alignment); - I->OutSecOff = Off; - Off += I->getSize(); } + }; + + AssignSuccessors(nullptr); + for (InputSection *I : OutSec->Sections) { + Off = alignTo(Off, I->Alignment); + I->OutSecOff = Off; + Off += I->getSize(); // Update section size inside for-loop, so that SIZEOF // works correctly in the case below: // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) } Sec->setSize(Off); + // Add symbols following current input section. + AssignSuccessors(I); } } diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index a866470..a5e3d9e 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -26,7 +26,7 @@ class SymbolBody; template class InputSectionBase; template class OutputSectionBase; template class OutputSectionFactory; -template class LayoutInputSection; +class InputSectionData; typedef std::function Expr; @@ -66,6 +66,7 @@ struct SymbolAssignment : BaseCommand { // Command attributes for PROVIDE, HIDDEN and PROVIDE_HIDDEN. bool Provide = false; bool Hidden = false; + InputSectionData *GoesAfter = nullptr; }; // Linker scripts allow additional constraints to be put on ouput sections. @@ -178,8 +179,6 @@ private: std::vector getPhdrIndices(StringRef SectionName); size_t getPhdrIndex(StringRef PhdrName); - llvm::SpecificBumpPtrAllocator> LAlloc; - uintX_t Dot; }; diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 0ec12d0..9874708 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -1825,8 +1825,6 @@ OutputSectionFactory::create(InputSectionBase *C, case InputSectionBase::MipsAbiFlags: Sec = new MipsAbiFlagsOutputSection(); break; - case InputSectionBase::Layout: - llvm_unreachable("Invalid section type"); } Out::Pool.emplace_back(Sec); return {Sec, true}; -- 2.7.4