Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -13,6 +13,7 @@ #include "Config.h" #include "lld/Core/LLVM.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/MC/StringTableBuilder.h" #include "llvm/Object/ELF.h" @@ -613,6 +614,38 @@ static OutputSectionBase *ProgramHeaders; }; +// This class knows how to create an output section for a given +// input section. Output section type is determined by various +// factors, including input section's sh_flags, sh_type and +// linker scripts. +template struct SectionKey { + typedef typename std::conditional::type uintX_t; + StringRef Name; + uint32_t Type; + uintX_t Flags; + uintX_t Alignment; +}; + +template class OutputSectionFactory { + typedef typename ELFT::Shdr Elf_Shdr; + typedef typename ELFT::uint uintX_t; + typedef typename SectionKey Key; + +public: + std::pair *, bool> create(InputSectionBase *C, + StringRef OutsecName); + + OutputSectionBase *lookup(StringRef Name, uint32_t Type, + uintX_t Flags) { + return Map.lookup({Name, Type, Flags, 0}); + } + +private: + Key createKey(InputSectionBase *C, StringRef OutsecName); + + llvm::SmallDenseMap *> Map; +}; + template BuildIdSection *Out::BuildId; template DynamicSection *Out::Dynamic; template EhFrameHeader *Out::EhFrameHdr; @@ -642,4 +675,25 @@ } // namespace elf } // namespace lld +namespace llvm { +template struct DenseMapInfo> { + typedef typename lld::elf::SectionKey Key; + + static Key getEmptyKey() { + return Key{DenseMapInfo::getEmptyKey(), 0, 0, 0}; + } + static Key getTombstoneKey() { + return Key{DenseMapInfo::getTombstoneKey(), 0, 0, 0}; + } + static unsigned getHashValue(const Key &Val) { + return hash_combine(Val.Name, Val.Type, Val.Flags, Val.Alignment); + } + static bool isEqual(const Key &LHS, const Key &RHS) { + return DenseMapInfo::isEqual(LHS.Name, RHS.Name) && + LHS.Type == RHS.Type && LHS.Flags == RHS.Flags && + LHS.Alignment == RHS.Alignment; + } +}; +} // namespace llvm + #endif // LLD_ELF_OUTPUT_SECTIONS_H Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -1692,6 +1692,61 @@ } 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) { + case InputSectionBase::Regular: + Sec = new OutputSection(Key.Name, Key.Type, Key.Flags); + break; + case InputSectionBase::EHFrame: + Sec = new EHOutputSection(Key.Name, Key.Type, Key.Flags); + break; + case InputSectionBase::Merge: + Sec = new MergeOutputSection(Key.Name, Key.Type, Key.Flags, + Key.Alignment); + break; + case InputSectionBase::MipsReginfo: + Sec = new MipsReginfoOutputSection(); + break; + case InputSectionBase::MipsOptions: + Sec = new MipsOptionsOutputSection(); + break; + } + return {Sec, true}; +} + +template +SectionKey +OutputSectionFactory::createKey(InputSectionBase *C, + StringRef OutsecName) { + const Elf_Shdr *H = C->getSectionHdr(); + uintX_t Flags = H->sh_flags & ~SHF_GROUP; + + // For SHF_MERGE we create different output sections for each alignment. + // This makes each output section simple and keeps a single level mapping from + // input to output. + uintX_t Alignment = 0; + if (isa>(C)) + Alignment = std::max(H->sh_addralign, H->sh_entsize); + + // GNU as can give .eh_frame section type SHT_PROGBITS or SHT_X86_64_UNWIND + // depending on the construct. We want to canonicalize it so that + // there is only one .eh_frame in the end. + uint32_t Type = H->sh_type; + if (Type == SHT_PROGBITS && Config->EMachine == EM_X86_64 && + isa>(C)) + Type = SHT_X86_64_UNWIND; + + return SectionKey{OutsecName, Type, Flags, Alignment}; +} + +template MipsOptionsOutputSection::MipsOptionsOutputSection() : OutputSectionBase(".MIPS.options", SHT_MIPS_OPTIONS, SHF_ALLOC | SHF_MIPS_NOSTRIP) { @@ -1835,5 +1890,10 @@ template class BuildIdSha1; template class BuildIdSha1; template class BuildIdSha1; + +template class OutputSectionFactory; +template class OutputSectionFactory; +template class OutputSectionFactory; +template class OutputSectionFactory; } } Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -10,6 +10,7 @@ #include "Writer.h" #include "Config.h" #include "LinkerScript.h" +#include "InputSection.h" #include "OutputSections.h" #include "SymbolTable.h" #include "Target.h" @@ -247,37 +248,6 @@ check(Buffer->commit()); } -namespace { -template struct SectionKey { - typedef typename std::conditional::type uintX_t; - StringRef Name; - uint32_t Type; - uintX_t Flags; - uintX_t Alignment; -}; -} -namespace llvm { -template struct DenseMapInfo> { - static SectionKey getEmptyKey() { - return SectionKey{DenseMapInfo::getEmptyKey(), 0, 0, - 0}; - } - static SectionKey getTombstoneKey() { - return SectionKey{DenseMapInfo::getTombstoneKey(), 0, - 0, 0}; - } - static unsigned getHashValue(const SectionKey &Val) { - return hash_combine(Val.Name, Val.Type, Val.Flags, Val.Alignment); - } - static bool isEqual(const SectionKey &LHS, - const SectionKey &RHS) { - return DenseMapInfo::isEqual(LHS.Name, RHS.Name) && - LHS.Type == RHS.Type && LHS.Flags == RHS.Flags && - LHS.Alignment == RHS.Alignment; - } -}; -} - // Returns the number of relocations processed. template static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body, @@ -1132,87 +1102,6 @@ return true; } -// This class knows how to create an output section for a given -// input section. Output section type is determined by various -// factors, including input section's sh_flags, sh_type and -// linker scripts. -namespace { -template class OutputSectionFactory { - typedef typename ELFT::Shdr Elf_Shdr; - typedef typename ELFT::uint uintX_t; - -public: - std::pair *, bool> create(InputSectionBase *C, - StringRef OutsecName); - - OutputSectionBase *lookup(StringRef Name, uint32_t Type, - uintX_t Flags) { - return Map.lookup({Name, Type, Flags, 0}); - } - -private: - SectionKey createKey(InputSectionBase *C, - StringRef OutsecName); - - SmallDenseMap, OutputSectionBase *> Map; -}; -} - -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) { - case InputSectionBase::Regular: - Sec = new OutputSection(Key.Name, Key.Type, Key.Flags); - break; - case InputSectionBase::EHFrame: - Sec = new EHOutputSection(Key.Name, Key.Type, Key.Flags); - break; - case InputSectionBase::Merge: - Sec = new MergeOutputSection(Key.Name, Key.Type, Key.Flags, - Key.Alignment); - break; - case InputSectionBase::MipsReginfo: - Sec = new MipsReginfoOutputSection(); - break; - case InputSectionBase::MipsOptions: - Sec = new MipsOptionsOutputSection(); - break; - } - return {Sec, true}; -} - -template -SectionKey -OutputSectionFactory::createKey(InputSectionBase *C, - StringRef OutsecName) { - const Elf_Shdr *H = C->getSectionHdr(); - uintX_t Flags = H->sh_flags & ~SHF_GROUP; - - // For SHF_MERGE we create different output sections for each alignment. - // This makes each output section simple and keeps a single level mapping from - // input to output. - uintX_t Alignment = 0; - if (isa>(C)) - Alignment = std::max(H->sh_addralign, H->sh_entsize); - - // GNU as can give .eh_frame section type SHT_PROGBITS or SHT_X86_64_UNWIND - // depending on the construct. We want to canonicalize it so that - // there is only one .eh_frame in the end. - uint32_t Type = H->sh_type; - if (Type == SHT_PROGBITS && Config->EMachine == EM_X86_64 && - isa>(C)) - Type = SHT_X86_64_UNWIND; - - return SectionKey{OutsecName, Type, Flags, Alignment}; -} - // The linker is expected to define some symbols depending on // the linking result. This function defines such symbols. template void Writer::addReservedSymbols() {