Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -140,7 +140,7 @@ public: LinkerScript(); ~LinkerScript(); - void createSections(OutputSectionFactory &Factory); + void createSections(); std::vector> createPhdrs(); bool ignoreInterpSection(); @@ -165,6 +165,9 @@ std::vector *> createInputSectionList(OutputSectionCommand &Cmd); + std::pair *, bool> + createOutputSection(InputSectionBase *C, StringRef Name); + // "ScriptConfig" is a bit too long, so define a short name for it. ScriptConfiguration &Opt = *ScriptConfig; @@ -174,6 +177,8 @@ llvm::SpecificBumpPtrAllocator> LAlloc; + std::vector>> OwningSections; + uintX_t Dot; }; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -259,7 +259,40 @@ } template -void LinkerScript::createSections(OutputSectionFactory &Factory) { +std::pair *, bool> +LinkerScript::createOutputSection(InputSectionBase *C, + StringRef Name) { + typedef typename ELFT::Shdr Elf_Shdr; + + bool IsNew = true; + OutputSectionBase *Sec = nullptr; + for (std::unique_ptr> &S : OwningSections) + if (S->getName() == Name) { + Sec = S.get(); + IsNew = false; + break; + } + + const Elf_Shdr *H = C->getSectionHdr(); + uintX_t Flags = H->sh_flags & ~SHF_GROUP & ~SHF_COMPRESSED; + uintX_t Alignment = 0; + if (isa>(C)) + Alignment = std::max(H->sh_addralign, H->sh_entsize); + uint32_t Type = H->sh_type; + + if (!Sec) { + std::tie(Sec, IsNew) = + allocSection(C->SectionKind, Name, Flags, Alignment, Type); + if (IsNew) + OwningSections.emplace_back(Sec); + return {Sec, IsNew}; + } + + return{ Sec, IsNew }; +} + +template +void LinkerScript::createSections() { for (const std::unique_ptr &Base1 : Opt.Commands) { if (auto *Cmd = dyn_cast(Base1.get())) { if (shouldDefine(Cmd)) @@ -280,7 +313,7 @@ OutputSectionBase *OutSec; bool IsNew; - std::tie(OutSec, IsNew) = Factory.create(Head, Cmd->Name); + std::tie(OutSec, IsNew) = createOutputSection(Head, Cmd->Name); if (IsNew) OutputSections->push_back(OutSec); @@ -302,7 +335,7 @@ continue; OutputSectionBase *OutSec; bool IsNew; - std::tie(OutSec, IsNew) = Factory.create(S, getOutputSectionName(S)); + std::tie(OutSec, IsNew) = createOutputSection(S, getOutputSectionName(S)); if (IsNew) OutputSections->push_back(OutSec); OutSec->addSection(S); Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -34,11 +34,17 @@ template class MergeInputSection; template class MipsReginfoInputSection; template class OutputSection; +template class OutputSectionBase; template class ObjectFile; template class SharedFile; template class SharedSymbol; template class DefinedRegular; +template +std::pair *, bool> +allocSection(unsigned Kind, StringRef Name, typename ELFT::uint Flags, + typename ELFT::uint Alignment, uint32_t Type); + // This represents a section in an output file. // Different sub classes represent different types of sections. Some contain // input sections, others are created by the linker. @@ -93,6 +99,7 @@ uintX_t getSize() const { return Header.sh_size; } void setSize(uintX_t Val) { Header.sh_size = Val; } uintX_t getFlags() const { return Header.sh_flags; } + void setFlags(uintX_t Val) { Header.sh_flags = Val; } uint32_t getPhdrFlags() const; uintX_t getFileOff() const { return Header.sh_offset; } uintX_t getAlignment() const { return Header.sh_addralign; } Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -1784,22 +1784,17 @@ template std::pair *, bool> -OutputSectionFactory::create(InputSectionBase *C, - StringRef OutsecName) { - SectionKey Key = createKey(C, OutsecName); - OutputSectionBase *&Sec = Map[Key]; - if (Sec) - return {Sec, false}; - - switch (C->SectionKind) { +elf::allocSection(unsigned Kind, StringRef Name, typename ELFT::uint Flags, + typename ELFT::uint Alignment, uint32_t Type) { + OutputSectionBase *Sec; + switch (Kind) { case InputSectionBase::Regular: - Sec = new OutputSection(Key.Name, Key.Type, Key.Flags); + Sec = new OutputSection(Name, Type, Flags); break; case InputSectionBase::EHFrame: return {Out::EhFrame, false}; case InputSectionBase::Merge: - Sec = new MergeOutputSection(Key.Name, Key.Type, Key.Flags, - Key.Alignment); + Sec = new MergeOutputSection(Name, Type, Flags, Alignment); break; case InputSectionBase::MipsReginfo: Sec = new MipsReginfoOutputSection(); @@ -1810,9 +1805,26 @@ case InputSectionBase::MipsAbiFlags: Sec = new MipsAbiFlagsOutputSection(); break; - case InputSectionBase::Layout: + default: llvm_unreachable("Invalid section type"); } + return {Sec, true}; +} + +template +std::pair *, bool> +OutputSectionFactory::create(InputSectionBase *C, + StringRef OutsecName) { + SectionKey Key = createKey(C, OutsecName); + OutputSectionBase *&Sec = Map[Key]; + if (Sec) + return {Sec, false}; + + bool Allocated; + std::tie(Sec, Allocated) = allocSection( + C->SectionKind, Key.Name, Key.Flags, Key.Alignment, Key.Type); + if (!Allocated) + return {Sec, false}; Out::Pool.emplace_back(Sec); return {Sec, true}; } @@ -2005,3 +2017,16 @@ template class OutputSectionFactory; } } + +template std::pair *, bool> +elf::allocSection(unsigned Kind, StringRef Name, ELF32LE::uint Flags, + ELF32LE::uint Alignment, uint32_t Type); +template std::pair *, bool> +elf::allocSection(unsigned Kind, StringRef Name, ELF32BE::uint Flags, + ELF32BE::uint Alignment, uint32_t Type); +template std::pair *, bool> +elf::allocSection(unsigned Kind, StringRef Name, ELF64LE::uint Flags, + ELF64LE::uint Alignment, uint32_t Type); +template std::pair *, bool> +elf::allocSection(unsigned Kind, StringRef Name, ELF64BE::uint Flags, + ELF64BE::uint Alignment, uint32_t Type); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -248,7 +248,7 @@ Script::X->OutputSections = &OutputSections; if (ScriptConfig->HasContents) - Script::X->createSections(Factory); + Script::X->createSections(); else createSections();