diff options
-rw-r--r-- | lld/ELF/InputSection.cpp | 15 | ||||
-rw-r--r-- | lld/ELF/InputSection.h | 49 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 110 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.h | 5 | ||||
-rw-r--r-- | 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 aad9bc763c7..321c880c92c 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -30,14 +30,10 @@ using namespace lld::elf; template <class ELFT> InputSectionBase<ELFT>::InputSectionBase(elf::ObjectFile<ELFT> *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<uintX_t>(Header->sh_addralign, 1); @@ -71,7 +67,6 @@ template <class ELFT> typename ELFT::uint InputSectionBase<ELFT>::getOffset(uintX_t Offset) const { switch (SectionKind) { case Regular: - case Layout: return cast<InputSection<ELFT>>(this)->OutSecOff + Offset; case EHFrame: // The file crtbeginT.o has relocations pointing to the start of an empty @@ -131,7 +126,7 @@ InputSection<ELFT>::InputSection(elf::ObjectFile<ELFT> *F, template <class ELFT> bool InputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) { - return S->SectionKind == Base::Regular || S->SectionKind == Base::Layout; + return S->SectionKind == Base::Regular; } template <class ELFT> diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index a12b5919b6e..3b7c201446e 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -30,8 +30,33 @@ template <class ELFT> class ObjectFile; template <class ELFT> class OutputSection; template <class ELFT> 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<char, 0> Uncompressed; +}; + // This corresponds to a section of an input file. -template <class ELFT> class InputSectionBase { +template <class ELFT> 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<ELFT> *File; - // If a section is compressed, this vector has uncompressed section data. - SmallVector<char, 0> 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<ELFT> *File, const Elf_Shdr *Header, Kind SectionKind); OutputSectionBase<ELFT> *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<Relocation<ELFT>> Relocations; - - bool Compressed; }; template <class ELFT> InputSectionBase<ELFT> InputSectionBase<ELFT>::Discarded; diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index b3a1c45ea2c..9afd5badc2b 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -133,54 +133,6 @@ LinkerScript<ELFT>::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 ELFT> -class elf::LayoutInputSection : public InputSectionBase<ELFT> { -public: - explicit LayoutInputSection(SymbolAssignment *Cmd); - static bool classof(const InputSectionBase<ELFT> *S); - SymbolAssignment *Cmd; - -private: - typename ELFT::Shdr Hdr; -}; - -template <class ELFT> -static InputSectionBase<ELFT> * -getNonLayoutSection(std::vector<InputSectionBase<ELFT> *> &Vec) { - for (InputSectionBase<ELFT> *S : Vec) - if (!isa<LayoutInputSection<ELFT>>(S)) - return S; - return nullptr; -} - -template <class T> static T *zero(T *Val) { - memset(Val, 0, sizeof(*Val)); - return Val; -} - -template <class ELFT> -LayoutInputSection<ELFT>::LayoutInputSection(SymbolAssignment *Cmd) - : InputSectionBase<ELFT>(nullptr, zero(&Hdr), - InputSectionBase<ELFT>::Layout), - Cmd(Cmd) { - this->Live = true; - Hdr.sh_type = SHT_NOBITS; -} - -template <class ELFT> -bool LayoutInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) { - return S->SectionKind == InputSectionBase<ELFT>::Layout; -} - template <class ELFT> static bool compareName(InputSectionBase<ELFT> *A, InputSectionBase<ELFT> *B) { return A->getSectionName() < B->getSectionName(); @@ -236,12 +188,13 @@ template <class ELFT> std::vector<InputSectionBase<ELFT> *> LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &OutCmd) { std::vector<InputSectionBase<ELFT> *> Ret; + DenseSet<InputSectionBase<ELFT> *> SectionIndex; for (const std::unique_ptr<BaseCommand> &Base : OutCmd.Commands) { if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base.get())) { if (shouldDefine<ELFT>(OutCmd)) addSynthetic<ELFT>(OutCmd); - Ret.push_back(new (LAlloc.Allocate()) LayoutInputSection<ELFT>(OutCmd)); + OutCmd->GoesAfter = Ret.empty() ? nullptr : Ret.back(); continue; } @@ -253,7 +206,12 @@ LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &OutCmd) { std::stable_sort(V.begin(), V.end(), getComparator<ELFT>(Cmd->SortInner)); if (Cmd->SortOuter) std::stable_sort(V.begin(), V.end(), getComparator<ELFT>(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<ELFT> *S : V) + if (SectionIndex.insert(S).second) + Ret.push_back(S); } return Ret; } @@ -284,13 +242,12 @@ void LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) { } std::vector<InputSectionBase<ELFT> *> V = createInputSectionList(*Cmd); - InputSectionBase<ELFT> *Head = getNonLayoutSection<ELFT>(V); - if (!Head) + if (V.empty()) continue; OutputSectionBase<ELFT> *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<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) { for (InputSectionBase<ELFT> *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<ELFT> *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<SymbolAssignment>(ItCmd->get()); + if (!AssignCmd) + continue; + if (D != AssignCmd->GoesAfter) + break; - for (InputSection<ELFT> *I : OutSec->Sections) { - if (auto *L = dyn_cast<LayoutInputSection<ELFT>>(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<DefinedSynthetic<ELFT>>(L->Cmd->Sym)) { - // shouldDefine could have returned false, so we need to check Sym, - // for non-null value. + Sec->setSize(Off); + continue; + } + + if (DefinedSynthetic<ELFT> *Sym = + cast_or_null<DefinedSynthetic<ELFT>>(AssignCmd->Sym)) { Sym->Section = OutSec; Sym->Value = Value; } - } else { - Off = alignTo(Off, I->Alignment); - I->OutSecOff = Off; - Off += I->getSize(); } + }; + + AssignSuccessors(nullptr); + for (InputSection<ELFT> *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 a866470fa03..a5e3d9ec52b 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -26,7 +26,7 @@ class SymbolBody; template <class ELFT> class InputSectionBase; template <class ELFT> class OutputSectionBase; template <class ELFT> class OutputSectionFactory; -template <class ELFT> class LayoutInputSection; +class InputSectionData; typedef std::function<uint64_t(uint64_t)> 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<size_t> getPhdrIndices(StringRef SectionName); size_t getPhdrIndex(StringRef PhdrName); - llvm::SpecificBumpPtrAllocator<LayoutInputSection<ELFT>> LAlloc; - uintX_t Dot; }; diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 0ec12d00b9e..98747084c6e 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -1825,8 +1825,6 @@ OutputSectionFactory<ELFT>::create(InputSectionBase<ELFT> *C, case InputSectionBase<ELFT>::MipsAbiFlags: Sec = new MipsAbiFlagsOutputSection<ELFT>(); break; - case InputSectionBase<ELFT>::Layout: - llvm_unreachable("Invalid section type"); } Out<ELFT>::Pool.emplace_back(Sec); return {Sec, true}; |