Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -30,8 +30,26 @@ template class OutputSection; template class OutputSectionBase; +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 +62,12 @@ // 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 +96,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 @@ -30,14 +30,10 @@ 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 @@ 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 @@ 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,12 @@ 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 *>(-1ULL); + } } return Ret; } @@ -274,13 +231,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 +244,7 @@ for (InputSectionBase *Sec : V) { if (Subalign) Sec->Alignment = Subalign; - if (!Sec->OutSec) - OutSec->addSection(Sec); + OutSec->addSection(Sec); } } } @@ -310,37 +265,56 @@ } } -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 == ".") { + // 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; + + 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); } } @@ -404,19 +378,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 @@ -1816,8 +1816,6 @@ case InputSectionBase::MipsAbiFlags: Sec = new MipsAbiFlagsOutputSection(); break; - case InputSectionBase::Layout: - llvm_unreachable("Invalid section type"); } Out::Pool.emplace_back(Sec); return {Sec, true};