Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -30,8 +30,26 @@ template class OutputSection; template class OutputSectionBase; +class InputSectionData { +protected: + // If a section is compressed, this vector has uncompressed section data. + SmallVector Uncompressed; + +public: + enum Kind { Regular, EHFrame, Merge, MipsReginfo, MipsOptions, MipsAbiFlags }; + + InputSectionData(Kind SectionKind) : SectionKind(SectionKind) {} + InputSectionData() {} + + Kind SectionKind; + uint32_t Alignment; + // Used for garbage collection. + bool Live; + bool Compressed; +}; + // 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 +62,13 @@ // 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(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 +97,6 @@ void relocate(uint8_t *Buf, uint8_t *BufEnd); std::vector> Relocations; - - bool Compressed; }; template InputSectionBase InputSectionBase::Discarded; Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -32,11 +32,11 @@ 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) { + : InputSectionData(SectionKind), Header(Header), File(File), Repl(this) { // The garbage collector sets sections' Live bits. // If GC is disabled, all sections are considered live by default. Live = !Config->GcSections; + Compressed = Header->sh_flags & SHF_COMPRESSED; // The ELF spec states that a value of 0 means the section has // no alignment constraits. @@ -71,7 +71,6 @@ 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 +130,7 @@ template bool InputSection::classof(const InputSectionBase *S) { - return S->SectionKind == Base::Regular || S->SectionKind == Base::Layout; + return S->SectionKind == Base::Regular; } template Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -26,7 +26,7 @@ template class OutputSectionBase; template class OutputSectionFactory; template class DefinedCommon; -template class LayoutInputSection; +class InputSectionData; typedef std::function Expr; @@ -64,6 +64,7 @@ // 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. @@ -172,8 +173,6 @@ std::vector getPhdrIndices(StringRef SectionName); size_t getPhdrIndex(StringRef PhdrName); - llvm::SpecificBumpPtrAllocator> LAlloc; - uintX_t Dot; }; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -133,54 +133,6 @@ 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(); @@ -241,7 +193,7 @@ 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 +205,13 @@ 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()); + + for (InputSectionBase *S : V) + if (S->OutSec == nullptr) { + Ret.push_back(S); + S->OutSec = reinterpret_cast *>( + std::numeric_limits::max()); + } } return Ret; } @@ -274,13 +232,12 @@ } 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); @@ -288,8 +245,7 @@ for (InputSectionBase *Sec : V) { if (Subalign) Sec->Alignment = Subalign; - if (!Sec->OutSec) - OutSec->addSection(Sec); + OutSec->addSection(Sec); } } } @@ -310,37 +266,51 @@ } } -template void assignOffsets(OutputSectionBase *Sec) { +template +void assignOffsets(OutputSectionCommand *Cmd, OutputSectionBase *Sec) { auto *OutSec = dyn_cast>(Sec); if (!OutSec) { Sec->assignOffsets(); return; } - typedef typename ELFT::uint uintX_t; uintX_t Off = 0; + auto ItCmd = Cmd->Commands.begin(); - 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 == ".") { - 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. - Sym->Section = OutSec; - Sym->Value = Value; + auto AddSuccessors = [&](InputSectionData *D) { + while (ItCmd != Cmd->Commands.end()) { + auto *AssignCmd = dyn_cast(ItCmd->get()); + if (!AssignCmd) { + ++ItCmd; + } else if (D == AssignCmd->GoesAfter) { + uintX_t Value = + AssignCmd->Expression(Sec->getVA() + Off) - Sec->getVA(); + if (AssignCmd->Name == ".") { + // Update to location counter means update to section size. + Sec->setSize(Off = Value); + } else if (DefinedSynthetic *Sym = + cast_or_null>(AssignCmd->Sym)) { + Sym->Section = OutSec; + Sym->Value = Value; + } + ++ItCmd; + } else { + break; } - } else { - Off = alignTo(Off, I->Alignment); - I->OutSecOff = Off; - Off += I->getSize(); } + }; + + AddSuccessors(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. + AddSuccessors(I); } } @@ -404,19 +374,19 @@ uintX_t TVA = Dot + ThreadBssOffset; TVA = alignTo(TVA, Sec->getAlignment()); Sec->setVA(TVA); - assignOffsets(Sec); + assignOffsets(Cmd, Sec); ThreadBssOffset = TVA - Dot + Sec->getSize(); continue; } if (!(Sec->getFlags() & SHF_ALLOC)) { - Sec->assignOffsets(); + assignOffsets(Cmd, Sec); continue; } Dot = alignTo(Dot, Sec->getAlignment()); Sec->setVA(Dot); - assignOffsets(Sec); + assignOffsets(Cmd, Sec); MinVA = std::min(MinVA, Dot); Dot += Sec->getSize(); } Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -1810,8 +1810,6 @@ case InputSectionBase::MipsAbiFlags: Sec = new MipsAbiFlagsOutputSection(); break; - case InputSectionBase::Layout: - llvm_unreachable("Invalid section type"); } Out::Pool.emplace_back(Sec); return {Sec, true};