Make OutputSectionBase a class instead of class template.
The disadvantage is that we use uint64_t instad of uint32_t for some
value in 32 bit files. The advantage is a substantially simpler code,
faster builds and less code duplication.
llvm-svn: 286414
diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h
index 7ca4399..bc4f81a 100644
--- a/lld/ELF/OutputSections.h
+++ b/lld/ELF/OutputSections.h
@@ -42,10 +42,8 @@
// input sections, others are created by the linker.
// The writer creates multiple OutputSections and assign them unique,
// non-overlapping file offsets and VAs.
-template <class ELFT> class OutputSectionBase {
+class OutputSectionBase {
public:
- typedef typename ELFT::uint uintX_t;
- typedef typename ELFT::Shdr Elf_Shdr;
enum Kind {
Base,
Dynamic,
@@ -66,15 +64,15 @@
VersTable
};
- OutputSectionBase(StringRef Name, uint32_t Type, uintX_t Flags);
- void setLMAOffset(uintX_t LMAOff) { LMAOffset = LMAOff; }
- uintX_t getLMA() const { return Addr + LMAOffset; }
- void writeHeaderTo(Elf_Shdr *SHdr);
+ OutputSectionBase(StringRef Name, uint32_t Type, uint64_t Flags);
+ void setLMAOffset(uint64_t LMAOff) { LMAOffset = LMAOff; }
+ uint64_t getLMA() const { return Addr + LMAOffset; }
+ template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *SHdr);
StringRef getName() const { return Name; }
- virtual void addSection(InputSectionBase<ELFT> *C) {}
+ virtual void addSection(InputSectionData *C) {}
virtual Kind getKind() const { return Base; }
- static bool classof(const OutputSectionBase<ELFT> *B) {
+ static bool classof(const OutputSectionBase *B) {
return B->getKind() == Base;
}
@@ -82,7 +80,7 @@
uint32_t getPhdrFlags() const;
- void updateAlignment(uintX_t Alignment) {
+ void updateAlignment(uint64_t Alignment) {
if (Alignment > Addralign)
Addralign = Alignment;
}
@@ -97,7 +95,7 @@
// between their file offsets should be equal to difference between their
// virtual addresses. To compute some section offset we use the following
// formula: Off = Off_first + VA - VA_first.
- OutputSectionBase<ELFT> *FirstInPtLoad = nullptr;
+ OutputSectionBase *FirstInPtLoad = nullptr;
virtual void finalize() {}
virtual void finalizePieces() {}
@@ -108,21 +106,20 @@
StringRef Name;
// The following fields correspond to Elf_Shdr members.
- uintX_t Size = 0;
- uintX_t Entsize = 0;
- uintX_t Addralign = 0;
- uintX_t Offset = 0;
- uintX_t Flags = 0;
- uintX_t LMAOffset = 0;
- uintX_t Addr = 0;
+ uint64_t Size = 0;
+ uint64_t Entsize = 0;
+ uint64_t Addralign = 0;
+ uint64_t Offset = 0;
+ uint64_t Flags = 0;
+ uint64_t LMAOffset = 0;
+ uint64_t Addr = 0;
uint32_t ShName = 0;
uint32_t Type = 0;
uint32_t Info = 0;
uint32_t Link = 0;
};
-template <class ELFT>
-class GdbIndexSection final : public OutputSectionBase<ELFT> {
+template <class ELFT> class GdbIndexSection final : public OutputSectionBase {
typedef typename ELFT::uint uintX_t;
const unsigned OffsetTypeSize = 4;
@@ -146,8 +143,7 @@
uint32_t CuTypesOffset;
};
-template <class ELFT> class GotSection final : public OutputSectionBase<ELFT> {
- typedef OutputSectionBase<ELFT> Base;
+template <class ELFT> class GotSection final : public OutputSectionBase {
typedef typename ELFT::uint uintX_t;
public:
@@ -163,8 +159,10 @@
uintX_t getMipsGotOffset(const SymbolBody &B, uintX_t Addend) const;
uintX_t getGlobalDynAddr(const SymbolBody &B) const;
uintX_t getGlobalDynOffset(const SymbolBody &B) const;
- typename Base::Kind getKind() const override { return Base::Got; }
- static bool classof(const Base *B) { return B->getKind() == Base::Got; }
+ Kind getKind() const override { return Got; }
+ static bool classof(const OutputSectionBase *B) {
+ return B->getKind() == Got;
+ }
// Returns the symbol which corresponds to the first entry of the global part
// of GOT on MIPS platform. It is required to fill up MIPS-specific dynamic
@@ -192,7 +190,7 @@
uint32_t TlsIndexOff = -1;
uint32_t MipsPageEntries = 0;
// Output sections referenced by MIPS GOT relocations.
- llvm::SmallPtrSet<const OutputSectionBase<ELFT> *, 10> MipsOutSections;
+ llvm::SmallPtrSet<const OutputSectionBase *, 10> MipsOutSections;
llvm::DenseMap<uintX_t, size_t> MipsLocalGotPos;
// MIPS ABI requires to create unique GOT entry for each Symbol/Addend
@@ -213,10 +211,8 @@
void writeMipsGot(uint8_t *Buf);
};
-template <class ELFT>
-class GotPltSection final : public OutputSectionBase<ELFT> {
+template <class ELFT> class GotPltSection final : public OutputSectionBase {
typedef typename ELFT::uint uintX_t;
- typedef OutputSectionBase<ELFT> Base;
public:
GotPltSection();
@@ -224,15 +220,16 @@
void writeTo(uint8_t *Buf) override;
void addEntry(SymbolBody &Sym);
bool empty() const;
- typename Base::Kind getKind() const override { return Base::GotPlt; }
- static bool classof(const Base *B) { return B->getKind() == Base::GotPlt; }
+ Kind getKind() const override { return GotPlt; }
+ static bool classof(const OutputSectionBase *B) {
+ return B->getKind() == GotPlt;
+ }
private:
std::vector<const SymbolBody *> Entries;
};
-template <class ELFT> class PltSection final : public OutputSectionBase<ELFT> {
- typedef OutputSectionBase<ELFT> Base;
+template <class ELFT> class PltSection final : public OutputSectionBase {
typedef typename ELFT::uint uintX_t;
public:
@@ -241,8 +238,10 @@
void writeTo(uint8_t *Buf) override;
void addEntry(SymbolBody &Sym);
bool empty() const { return Entries.empty(); }
- typename Base::Kind getKind() const override { return Base::Plt; }
- static bool classof(const Base *B) { return B->getKind() == Base::Plt; }
+ Kind getKind() const override { return Plt; }
+ static bool classof(const OutputSectionBase *B) {
+ return B->getKind() == Plt;
+ }
private:
std::vector<std::pair<const SymbolBody *, unsigned>> Entries;
@@ -258,7 +257,7 @@
: Type(Type), Sym(Sym), InputSec(InputSec), OffsetInSec(OffsetInSec),
UseSymVA(UseSymVA), Addend(Addend) {}
- DynamicReloc(uint32_t Type, const OutputSectionBase<ELFT> *OutputSec,
+ DynamicReloc(uint32_t Type, const OutputSectionBase *OutputSec,
uintX_t OffsetInSec, bool UseSymVA, SymbolBody *Sym,
uintX_t Addend)
: Type(Type), Sym(Sym), OutputSec(OutputSec), OffsetInSec(OffsetInSec),
@@ -267,14 +266,14 @@
uintX_t getOffset() const;
uintX_t getAddend() const;
uint32_t getSymIndex() const;
- const OutputSectionBase<ELFT> *getOutputSec() const { return OutputSec; }
+ const OutputSectionBase *getOutputSec() const { return OutputSec; }
uint32_t Type;
private:
SymbolBody *Sym;
const InputSectionBase<ELFT> *InputSec = nullptr;
- const OutputSectionBase<ELFT> *OutputSec = nullptr;
+ const OutputSectionBase *OutputSec = nullptr;
uintX_t OffsetInSec;
bool UseSymVA;
uintX_t Addend;
@@ -286,8 +285,8 @@
};
template <class ELFT>
-class SymbolTableSection final : public OutputSectionBase<ELFT> {
- typedef OutputSectionBase<ELFT> Base;
+class SymbolTableSection final : public OutputSectionBase {
+ typedef OutputSectionBase Base;
public:
typedef typename ELFT::Shdr Elf_Shdr;
@@ -313,7 +312,7 @@
void writeLocalSymbols(uint8_t *&Buf);
void writeGlobalSymbols(uint8_t *Buf);
- const OutputSectionBase<ELFT> *getOutputSection(SymbolBody *Sym);
+ const OutputSectionBase *getOutputSection(SymbolBody *Sym);
// A vector of symbols and their string table offsets.
std::vector<SymbolTableEntry> Symbols;
@@ -328,17 +327,18 @@
// The section shall contain an array of Elf_Verdef structures, optionally
// followed by an array of Elf_Verdaux structures.
template <class ELFT>
-class VersionDefinitionSection final : public OutputSectionBase<ELFT> {
+class VersionDefinitionSection final : public OutputSectionBase {
typedef typename ELFT::Verdef Elf_Verdef;
typedef typename ELFT::Verdaux Elf_Verdaux;
- typedef OutputSectionBase<ELFT> Base;
public:
VersionDefinitionSection();
void finalize() override;
void writeTo(uint8_t *Buf) override;
- typename Base::Kind getKind() const override { return Base::VersDef; }
- static bool classof(const Base *B) { return B->getKind() == Base::VersDef; }
+ Kind getKind() const override { return VersDef; }
+ static bool classof(const OutputSectionBase *B) {
+ return B->getKind() == VersDef;
+ }
private:
void writeOne(uint8_t *Buf, uint32_t Index, StringRef Name, size_t NameOff);
@@ -353,16 +353,17 @@
// The values 0 and 1 are reserved. All other values are used for versions in
// the own object or in any of the dependencies.
template <class ELFT>
-class VersionTableSection final : public OutputSectionBase<ELFT> {
- typedef OutputSectionBase<ELFT> Base;
+class VersionTableSection final : public OutputSectionBase {
typedef typename ELFT::Versym Elf_Versym;
public:
VersionTableSection();
void finalize() override;
void writeTo(uint8_t *Buf) override;
- typename Base::Kind getKind() const override { return Base::VersTable; }
- static bool classof(const Base *B) { return B->getKind() == Base::VersTable; }
+ Kind getKind() const override { return VersTable; }
+ static bool classof(const OutputSectionBase *B) {
+ return B->getKind() == VersTable;
+ }
};
// The .gnu.version_r section defines the version identifiers used by
@@ -371,8 +372,7 @@
// a reference to a linked list of Elf_Vernaux data structures which define the
// mapping from version identifiers to version names.
template <class ELFT>
-class VersionNeedSection final : public OutputSectionBase<ELFT> {
- typedef OutputSectionBase<ELFT> Base;
+class VersionNeedSection final : public OutputSectionBase {
typedef typename ELFT::Verneed Elf_Verneed;
typedef typename ELFT::Vernaux Elf_Vernaux;
@@ -389,16 +389,16 @@
void finalize() override;
void writeTo(uint8_t *Buf) override;
size_t getNeedNum() const { return Needed.size(); }
- typename Base::Kind getKind() const override { return Base::VersNeed; }
- static bool classof(const Base *B) { return B->getKind() == Base::VersNeed; }
+ Kind getKind() const override { return VersNeed; }
+ static bool classof(const OutputSectionBase *B) {
+ return B->getKind() == VersNeed;
+ }
};
-template <class ELFT>
-class RelocationSection final : public OutputSectionBase<ELFT> {
+template <class ELFT> class RelocationSection final : public OutputSectionBase {
typedef typename ELFT::Rel Elf_Rel;
typedef typename ELFT::Rela Elf_Rela;
typedef typename ELFT::uint uintX_t;
- typedef OutputSectionBase<ELFT> Base;
public:
RelocationSection(StringRef Name, bool Sort);
@@ -407,9 +407,11 @@
void finalize() override;
void writeTo(uint8_t *Buf) override;
bool hasRelocs() const { return !Relocs.empty(); }
- typename Base::Kind getKind() const override { return Base::Reloc; }
+ Kind getKind() const override { return Reloc; }
size_t getRelativeRelocCount() const { return NumRelativeRelocs; }
- static bool classof(const Base *B) { return B->getKind() == Base::Reloc; }
+ static bool classof(const OutputSectionBase *B) {
+ return B->getKind() == Reloc;
+ }
private:
bool Sort;
@@ -417,9 +419,7 @@
std::vector<DynamicReloc<ELFT>> Relocs;
};
-template <class ELFT>
-class OutputSection final : public OutputSectionBase<ELFT> {
- typedef OutputSectionBase<ELFT> Base;
+template <class ELFT> class OutputSection final : public OutputSectionBase {
public:
typedef typename ELFT::Shdr Elf_Shdr;
@@ -428,33 +428,36 @@
typedef typename ELFT::Rela Elf_Rela;
typedef typename ELFT::uint uintX_t;
OutputSection(StringRef Name, uint32_t Type, uintX_t Flags);
- void addSection(InputSectionBase<ELFT> *C) override;
+ void addSection(InputSectionData *C) override;
void sortInitFini();
void sortCtorsDtors();
void writeTo(uint8_t *Buf) override;
void finalize() override;
void assignOffsets() override;
- typename Base::Kind getKind() const override { return Base::Regular; }
- static bool classof(const Base *B) { return B->getKind() == Base::Regular; }
+ Kind getKind() const override { return Regular; }
+ static bool classof(const OutputSectionBase *B) {
+ return B->getKind() == Regular;
+ }
std::vector<InputSection<ELFT> *> Sections;
};
template <class ELFT>
-class MergeOutputSection final : public OutputSectionBase<ELFT> {
+class MergeOutputSection final : public OutputSectionBase {
typedef typename ELFT::uint uintX_t;
- typedef OutputSectionBase<ELFT> Base;
public:
MergeOutputSection(StringRef Name, uint32_t Type, uintX_t Flags,
uintX_t Alignment);
- void addSection(InputSectionBase<ELFT> *S) override;
+ void addSection(InputSectionData *S) override;
void writeTo(uint8_t *Buf) override;
unsigned getOffset(llvm::CachedHashStringRef Val);
void finalize() override;
void finalizePieces() override;
bool shouldTailMerge() const;
- typename Base::Kind getKind() const override { return Base::Merge; }
- static bool classof(const Base *B) { return B->getKind() == Base::Merge; }
+ Kind getKind() const override { return Merge; }
+ static bool classof(const OutputSectionBase *B) {
+ return B->getKind() == Merge;
+ }
private:
llvm::StringTableBuilder Builder;
@@ -467,13 +470,11 @@
};
// Output section for .eh_frame.
-template <class ELFT>
-class EhOutputSection final : public OutputSectionBase<ELFT> {
+template <class ELFT> class EhOutputSection final : public OutputSectionBase {
typedef typename ELFT::uint uintX_t;
typedef typename ELFT::Shdr Elf_Shdr;
typedef typename ELFT::Rel Elf_Rel;
typedef typename ELFT::Rela Elf_Rela;
- typedef OutputSectionBase<ELFT> Base;
public:
EhOutputSection();
@@ -481,9 +482,11 @@
void finalize() override;
bool empty() const { return Sections.empty(); }
- void addSection(InputSectionBase<ELFT> *S) override;
- typename Base::Kind getKind() const override { return Base::EHFrame; }
- static bool classof(const Base *B) { return B->getKind() == Base::EHFrame; }
+ void addSection(InputSectionData *S) override;
+ Kind getKind() const override { return EHFrame; }
+ static bool classof(const OutputSectionBase *B) {
+ return B->getKind() == EHFrame;
+ }
size_t NumFdes = 0;
@@ -509,8 +512,7 @@
};
template <class ELFT>
-class StringTableSection final : public OutputSectionBase<ELFT> {
- typedef OutputSectionBase<ELFT> Base;
+class StringTableSection final : public OutputSectionBase {
public:
typedef typename ELFT::uint uintX_t;
@@ -518,8 +520,10 @@
unsigned addString(StringRef S, bool HashIt = true);
void writeTo(uint8_t *Buf) override;
bool isDynamic() const { return Dynamic; }
- typename Base::Kind getKind() const override { return Base::StrTable; }
- static bool classof(const Base *B) { return B->getKind() == Base::StrTable; }
+ Kind getKind() const override { return StrTable; }
+ static bool classof(const OutputSectionBase *B) {
+ return B->getKind() == StrTable;
+ }
private:
const bool Dynamic;
@@ -527,27 +531,26 @@
std::vector<StringRef> Strings;
};
-template <class ELFT>
-class HashTableSection final : public OutputSectionBase<ELFT> {
+template <class ELFT> class HashTableSection final : public OutputSectionBase {
typedef typename ELFT::Word Elf_Word;
- typedef OutputSectionBase<ELFT> Base;
public:
HashTableSection();
void finalize() override;
void writeTo(uint8_t *Buf) override;
- typename Base::Kind getKind() const override { return Base::HashTable; }
- static bool classof(const Base *B) { return B->getKind() == Base::HashTable; }
+ Kind getKind() const override { return HashTable; }
+ static bool classof(const OutputSectionBase *B) {
+ return B->getKind() == HashTable;
+ }
};
// Outputs GNU Hash section. For detailed explanation see:
// https://blogs.oracle.com/ali/entry/gnu_hash_elf_sections
template <class ELFT>
-class GnuHashTableSection final : public OutputSectionBase<ELFT> {
+class GnuHashTableSection final : public OutputSectionBase {
typedef typename ELFT::Off Elf_Off;
typedef typename ELFT::Word Elf_Word;
typedef typename ELFT::uint uintX_t;
- typedef OutputSectionBase<ELFT> Base;
public:
GnuHashTableSection();
@@ -557,9 +560,9 @@
// Adds symbols to the hash table.
// Sorts the input to satisfy GNU hash section requirements.
void addSymbols(std::vector<SymbolTableEntry> &Symbols);
- typename Base::Kind getKind() const override { return Base::GnuHashTable; }
- static bool classof(const Base *B) {
- return B->getKind() == Base::GnuHashTable;
+ Kind getKind() const override { return GnuHashTable; }
+ static bool classof(const OutputSectionBase *B) {
+ return B->getKind() == GnuHashTable;
}
private:
@@ -583,9 +586,7 @@
unsigned Shift2;
};
-template <class ELFT>
-class DynamicSection final : public OutputSectionBase<ELFT> {
- typedef OutputSectionBase<ELFT> Base;
+template <class ELFT> class DynamicSection final : public OutputSectionBase {
typedef typename ELFT::Dyn Elf_Dyn;
typedef typename ELFT::Rel Elf_Rel;
typedef typename ELFT::Rela Elf_Rela;
@@ -600,12 +601,12 @@
struct Entry {
int32_t Tag;
union {
- OutputSectionBase<ELFT> *OutSec;
+ OutputSectionBase *OutSec;
uint64_t Val;
const SymbolBody *Sym;
};
enum KindT { SecAddr, SecSize, SymAddr, PlainInt } Kind;
- Entry(int32_t Tag, OutputSectionBase<ELFT> *OutSec, KindT Kind = SecAddr)
+ Entry(int32_t Tag, OutputSectionBase *OutSec, KindT Kind = SecAddr)
: Tag(Tag), OutSec(OutSec), Kind(Kind) {}
Entry(int32_t Tag, uint64_t Val) : Tag(Tag), Val(Val), Kind(PlainInt) {}
Entry(int32_t Tag, const SymbolBody *Sym)
@@ -621,8 +622,10 @@
DynamicSection();
void finalize() override;
void writeTo(uint8_t *Buf) override;
- typename Base::Kind getKind() const override { return Base::Dynamic; }
- static bool classof(const Base *B) { return B->getKind() == Base::Dynamic; }
+ Kind getKind() const override { return Dynamic; }
+ static bool classof(const OutputSectionBase *B) {
+ return B->getKind() == Dynamic;
+ }
private:
void addEntries();
@@ -638,19 +641,17 @@
// Detailed info about internals can be found in Ian Lance Taylor's blog:
// http://www.airs.com/blog/archives/460 (".eh_frame")
// http://www.airs.com/blog/archives/462 (".eh_frame_hdr")
-template <class ELFT>
-class EhFrameHeader final : public OutputSectionBase<ELFT> {
+template <class ELFT> class EhFrameHeader final : public OutputSectionBase {
typedef typename ELFT::uint uintX_t;
- typedef OutputSectionBase<ELFT> Base;
public:
EhFrameHeader();
void finalize() override;
void writeTo(uint8_t *Buf) override;
void addFde(uint32_t Pc, uint32_t FdeVA);
- typename Base::Kind getKind() const override { return Base::EHFrameHdr; }
- static bool classof(const Base *B) {
- return B->getKind() == Base::EHFrameHdr;
+ Kind getKind() const override { return EHFrameHdr; }
+ static bool classof(const OutputSectionBase *B) {
+ return B->getKind() == EHFrameHdr;
}
private:
@@ -680,7 +681,7 @@
static HashTableSection<ELFT> *HashTab;
static OutputSection<ELFT> *Bss;
static OutputSection<ELFT> *MipsRldMap;
- static OutputSectionBase<ELFT> *Opd;
+ static OutputSectionBase *Opd;
static uint8_t *OpdBuf;
static PltSection<ELFT> *Plt;
static RelocationSection<ELFT> *RelaDyn;
@@ -694,12 +695,12 @@
static VersionTableSection<ELFT> *VerSym;
static VersionNeedSection<ELFT> *VerNeed;
static Elf_Phdr *TlsPhdr;
- static OutputSectionBase<ELFT> *DebugInfo;
- static OutputSectionBase<ELFT> *ElfHeader;
- static OutputSectionBase<ELFT> *ProgramHeaders;
- static OutputSectionBase<ELFT> *PreinitArray;
- static OutputSectionBase<ELFT> *InitArray;
- static OutputSectionBase<ELFT> *FiniArray;
+ static OutputSectionBase *DebugInfo;
+ static OutputSectionBase *ElfHeader;
+ static OutputSectionBase *ProgramHeaders;
+ static OutputSectionBase *PreinitArray;
+ static OutputSectionBase *InitArray;
+ static OutputSectionBase *FiniArray;
};
template <bool Is64Bits> struct SectionKey {
@@ -720,13 +721,13 @@
typedef typename elf::SectionKey<ELFT::Is64Bits> Key;
public:
- std::pair<OutputSectionBase<ELFT> *, bool> create(InputSectionBase<ELFT> *C,
- StringRef OutsecName);
- std::pair<OutputSectionBase<ELFT> *, bool>
+ std::pair<OutputSectionBase *, bool> create(InputSectionBase<ELFT> *C,
+ StringRef OutsecName);
+ std::pair<OutputSectionBase *, bool>
create(const SectionKey<ELFT::Is64Bits> &Key, InputSectionBase<ELFT> *C);
private:
- llvm::SmallDenseMap<Key, OutputSectionBase<ELFT> *> Map;
+ llvm::SmallDenseMap<Key, OutputSectionBase *> Map;
};
template <class ELFT> uint64_t getHeaderSize() {
@@ -746,7 +747,7 @@
template <class ELFT> HashTableSection<ELFT> *Out<ELFT>::HashTab;
template <class ELFT> OutputSection<ELFT> *Out<ELFT>::Bss;
template <class ELFT> OutputSection<ELFT> *Out<ELFT>::MipsRldMap;
-template <class ELFT> OutputSectionBase<ELFT> *Out<ELFT>::Opd;
+template <class ELFT> OutputSectionBase *Out<ELFT>::Opd;
template <class ELFT> uint8_t *Out<ELFT>::OpdBuf;
template <class ELFT> PltSection<ELFT> *Out<ELFT>::Plt;
template <class ELFT> RelocationSection<ELFT> *Out<ELFT>::RelaDyn;
@@ -760,12 +761,12 @@
template <class ELFT> VersionTableSection<ELFT> *Out<ELFT>::VerSym;
template <class ELFT> VersionNeedSection<ELFT> *Out<ELFT>::VerNeed;
template <class ELFT> typename ELFT::Phdr *Out<ELFT>::TlsPhdr;
-template <class ELFT> OutputSectionBase<ELFT> *Out<ELFT>::DebugInfo;
-template <class ELFT> OutputSectionBase<ELFT> *Out<ELFT>::ElfHeader;
-template <class ELFT> OutputSectionBase<ELFT> *Out<ELFT>::ProgramHeaders;
-template <class ELFT> OutputSectionBase<ELFT> *Out<ELFT>::PreinitArray;
-template <class ELFT> OutputSectionBase<ELFT> *Out<ELFT>::InitArray;
-template <class ELFT> OutputSectionBase<ELFT> *Out<ELFT>::FiniArray;
+template <class ELFT> OutputSectionBase *Out<ELFT>::DebugInfo;
+template <class ELFT> OutputSectionBase *Out<ELFT>::ElfHeader;
+template <class ELFT> OutputSectionBase *Out<ELFT>::ProgramHeaders;
+template <class ELFT> OutputSectionBase *Out<ELFT>::PreinitArray;
+template <class ELFT> OutputSectionBase *Out<ELFT>::InitArray;
+template <class ELFT> OutputSectionBase *Out<ELFT>::FiniArray;
} // namespace elf
} // namespace lld