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/Writer.cpp b/lld/ELF/Writer.cpp
index 7e37064..662baf4 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -77,13 +77,13 @@
std::unique_ptr<FileOutputBuffer> Buffer;
- std::vector<OutputSectionBase<ELFT> *> OutputSections;
+ std::vector<OutputSectionBase *> OutputSections;
OutputSectionFactory<ELFT> Factory;
void addRelIpltSymbols();
void addStartEndSymbols();
- void addStartStopSymbols(OutputSectionBase<ELFT> *Sec);
- OutputSectionBase<ELFT> *findSection(StringRef Name);
+ void addStartStopSymbols(OutputSectionBase *Sec);
+ OutputSectionBase *findSection(StringRef Name);
std::vector<Phdr> Phdrs;
@@ -221,9 +221,9 @@
Out<ELFT>::VerSym = make<VersionTableSection<ELFT>>();
Out<ELFT>::VerNeed = make<VersionNeedSection<ELFT>>();
- Out<ELFT>::ElfHeader = make<OutputSectionBase<ELFT>>("", 0, SHF_ALLOC);
+ Out<ELFT>::ElfHeader = make<OutputSectionBase>("", 0, SHF_ALLOC);
Out<ELFT>::ElfHeader->Size = sizeof(Elf_Ehdr);
- Out<ELFT>::ProgramHeaders = make<OutputSectionBase<ELFT>>("", 0, SHF_ALLOC);
+ Out<ELFT>::ProgramHeaders = make<OutputSectionBase>("", 0, SHF_ALLOC);
Out<ELFT>::ProgramHeaders->updateAlignment(sizeof(uintX_t));
if (needsInterpSection<ELFT>()) {
@@ -411,11 +411,10 @@
.Default(1);
}
-template <class ELFT>
-bool elf::isRelroSection(const OutputSectionBase<ELFT> *Sec) {
+template <class ELFT> bool elf::isRelroSection(const OutputSectionBase *Sec) {
if (!Config->ZRelro)
return false;
- typename ELFT::uint Flags = Sec->Flags;
+ uint64_t Flags = Sec->Flags;
if (!(Flags & SHF_ALLOC) || !(Flags & SHF_WRITE))
return false;
if (Flags & SHF_TLS)
@@ -434,8 +433,8 @@
}
template <class ELFT>
-static bool compareSectionsNonScript(const OutputSectionBase<ELFT> *A,
- const OutputSectionBase<ELFT> *B) {
+static bool compareSectionsNonScript(const OutputSectionBase *A,
+ const OutputSectionBase *B) {
// Put .interp first because some loaders want to see that section
// on the first page of the executable file when loaded into memory.
bool AIsInterp = A->getName() == ".interp";
@@ -496,8 +495,8 @@
return BIsNoBits;
// We place RelRo section before plain r/w ones.
- bool AIsRelRo = isRelroSection(A);
- bool BIsRelRo = isRelroSection(B);
+ bool AIsRelRo = isRelroSection<ELFT>(A);
+ bool BIsRelRo = isRelroSection<ELFT>(B);
if (AIsRelRo != BIsRelRo)
return AIsRelRo;
@@ -512,8 +511,8 @@
// Output section ordering is determined by this function.
template <class ELFT>
-static bool compareSections(const OutputSectionBase<ELFT> *A,
- const OutputSectionBase<ELFT> *B) {
+static bool compareSections(const OutputSectionBase *A,
+ const OutputSectionBase *B) {
// For now, put sections mentioned in a linker script first.
int AIndex = Script<ELFT>::X->getSectionIndex(A->getName());
int BIndex = Script<ELFT>::X->getSectionIndex(B->getName());
@@ -525,7 +524,7 @@
if (AInScript)
return AIndex < BIndex;
- return compareSectionsNonScript(A, B);
+ return compareSectionsNonScript<ELFT>(A, B);
}
// Program header entry
@@ -535,7 +534,7 @@
H.p_flags = Flags;
}
-template <class ELFT> void PhdrEntry<ELFT>::add(OutputSectionBase<ELFT> *Sec) {
+template <class ELFT> void PhdrEntry<ELFT>::add(OutputSectionBase *Sec) {
Last = Sec;
if (!First)
First = Sec;
@@ -545,9 +544,9 @@
}
template <class ELFT>
-static Symbol *
-addOptionalSynthetic(StringRef Name, OutputSectionBase<ELFT> *Sec,
- typename ELFT::uint Val, uint8_t StOther = STV_HIDDEN) {
+static Symbol *addOptionalSynthetic(StringRef Name, OutputSectionBase *Sec,
+ typename ELFT::uint Val,
+ uint8_t StOther = STV_HIDDEN) {
SymbolBody *S = Symtab<ELFT>::X->find(Name);
if (!S)
return nullptr;
@@ -566,11 +565,11 @@
if (Out<ELFT>::DynSymTab || !Out<ELFT>::RelaPlt)
return;
StringRef S = Config->Rela ? "__rela_iplt_start" : "__rel_iplt_start";
- addOptionalSynthetic(S, Out<ELFT>::RelaPlt, 0);
+ addOptionalSynthetic<ELFT>(S, Out<ELFT>::RelaPlt, 0);
S = Config->Rela ? "__rela_iplt_end" : "__rel_iplt_end";
- addOptionalSynthetic(S, Out<ELFT>::RelaPlt,
- DefinedSynthetic<ELFT>::SectionEnd);
+ addOptionalSynthetic<ELFT>(S, Out<ELFT>::RelaPlt,
+ DefinedSynthetic<ELFT>::SectionEnd);
}
// The linker is expected to define some symbols depending on
@@ -587,7 +586,7 @@
// On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
// start of function and 'gp' pointer into GOT.
Symbol *Sym =
- addOptionalSynthetic("_gp_disp", Out<ELFT>::Got, MipsGPOffset);
+ addOptionalSynthetic<ELFT>("_gp_disp", Out<ELFT>::Got, MipsGPOffset);
if (Sym)
ElfSym<ELFT>::MipsGpDisp = Sym->body();
@@ -595,7 +594,7 @@
// pointer. This symbol is used in the code generated by .cpload pseudo-op
// in case of using -mno-shared option.
// https://sourceware.org/ml/binutils/2004-12/msg00094.html
- addOptionalSynthetic("__gnu_local_gp", Out<ELFT>::Got, MipsGPOffset);
+ addOptionalSynthetic<ELFT>("__gnu_local_gp", Out<ELFT>::Got, MipsGPOffset);
}
// In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol
@@ -649,13 +648,13 @@
// Sort input sections by section name suffixes for
// __attribute__((init_priority(N))).
-template <class ELFT> static void sortInitFini(OutputSectionBase<ELFT> *S) {
+template <class ELFT> static void sortInitFini(OutputSectionBase *S) {
if (S)
reinterpret_cast<OutputSection<ELFT> *>(S)->sortInitFini();
}
// Sort input sections by the special rule for .ctors and .dtors.
-template <class ELFT> static void sortCtorsDtors(OutputSectionBase<ELFT> *S) {
+template <class ELFT> static void sortCtorsDtors(OutputSectionBase *S) {
if (S)
reinterpret_cast<OutputSection<ELFT> *>(S)->sortCtorsDtors();
}
@@ -691,7 +690,7 @@
reportDiscarded(IS);
return;
}
- OutputSectionBase<ELFT> *Sec;
+ OutputSectionBase *Sec;
bool IsNew;
StringRef OutsecName = getOutputSectionName(IS->Name);
std::tie(Sec, IsNew) = Factory.create(IS, OutsecName);
@@ -704,18 +703,18 @@
for (InputSectionBase<ELFT> *IS : Symtab<ELFT>::X->Sections)
addInputSec(IS);
- sortInitFini(findSection(".init_array"));
- sortInitFini(findSection(".fini_array"));
- sortCtorsDtors(findSection(".ctors"));
- sortCtorsDtors(findSection(".dtors"));
+ sortInitFini<ELFT>(findSection(".init_array"));
+ sortInitFini<ELFT>(findSection(".fini_array"));
+ sortCtorsDtors<ELFT>(findSection(".ctors"));
+ sortCtorsDtors<ELFT>(findSection(".dtors"));
- for (OutputSectionBase<ELFT> *Sec : OutputSections)
+ for (OutputSectionBase *Sec : OutputSections)
Sec->assignOffsets();
}
template <class ELFT>
-static bool canSharePtLoad(const OutputSectionBase<ELFT> &S1,
- const OutputSectionBase<ELFT> &S2) {
+static bool canSharePtLoad(const OutputSectionBase &S1,
+ const OutputSectionBase &S2) {
if (!(S1.Flags & SHF_ALLOC) || !(S2.Flags & SHF_ALLOC))
return false;
@@ -767,15 +766,14 @@
auto I = OutputSections.begin();
auto E = OutputSections.end();
auto NonScriptI =
- std::find_if(OutputSections.begin(), E, [](OutputSectionBase<ELFT> *S) {
+ std::find_if(OutputSections.begin(), E, [](OutputSectionBase *S) {
return Script<ELFT>::X->getSectionIndex(S->getName()) == INT_MAX;
});
while (NonScriptI != E) {
- auto BestPos =
- std::max_element(I, NonScriptI, [&](OutputSectionBase<ELFT> *&A,
- OutputSectionBase<ELFT> *&B) {
- bool ACanSharePtLoad = canSharePtLoad(**NonScriptI, *A);
- bool BCanSharePtLoad = canSharePtLoad(**NonScriptI, *B);
+ auto BestPos = std::max_element(
+ I, NonScriptI, [&](OutputSectionBase *&A, OutputSectionBase *&B) {
+ bool ACanSharePtLoad = canSharePtLoad<ELFT>(**NonScriptI, *A);
+ bool BCanSharePtLoad = canSharePtLoad<ELFT>(**NonScriptI, *B);
if (ACanSharePtLoad != BCanSharePtLoad)
return BCanSharePtLoad;
@@ -812,7 +810,7 @@
// addresses of each section by section name. Add such symbols.
if (!Config->Relocatable) {
addStartEndSymbols();
- for (OutputSectionBase<ELFT> *Sec : OutputSections)
+ for (OutputSectionBase *Sec : OutputSections)
addStartStopSymbols(Sec);
}
@@ -865,7 +863,7 @@
sortSections();
unsigned I = 1;
- for (OutputSectionBase<ELFT> *Sec : OutputSections) {
+ for (OutputSectionBase *Sec : OutputSections) {
Sec->SectionIndex = I++;
Sec->ShName = Out<ELFT>::ShStrTab->addString(Sec->getName());
}
@@ -878,7 +876,7 @@
// Fill other section headers. The dynamic table is finalized
// at the end because some tags like RELSZ depend on result
// of finalizing other sections.
- for (OutputSectionBase<ELFT> *Sec : OutputSections)
+ for (OutputSectionBase *Sec : OutputSections)
if (Sec != Out<ELFT>::Dynamic)
Sec->finalize();
@@ -887,7 +885,7 @@
// Now that all output offsets are fixed. Finalize mergeable sections
// to fix their maps from input offsets to output offsets.
- for (OutputSectionBase<ELFT> *Sec : OutputSections)
+ for (OutputSectionBase *Sec : OutputSections)
Sec->finalizePieces();
}
@@ -907,7 +905,7 @@
// This function add Out<ELFT>::* sections to OutputSections.
template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
- auto Add = [&](OutputSectionBase<ELFT> *OS) {
+ auto Add = [&](OutputSectionBase *OS) {
if (OS)
OutputSections.push_back(OS);
};
@@ -958,11 +956,11 @@
// The linker is expected to define SECNAME_start and SECNAME_end
// symbols for a few sections. This function defines them.
template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
- auto Define = [&](StringRef Start, StringRef End,
- OutputSectionBase<ELFT> *OS) {
+ auto Define = [&](StringRef Start, StringRef End, OutputSectionBase *OS) {
// These symbols resolve to the image base if the section does not exist.
- addOptionalSynthetic(Start, OS, 0);
- addOptionalSynthetic(End, OS, OS ? DefinedSynthetic<ELFT>::SectionEnd : 0);
+ addOptionalSynthetic<ELFT>(Start, OS, 0);
+ addOptionalSynthetic<ELFT>(End, OS,
+ OS ? DefinedSynthetic<ELFT>::SectionEnd : 0);
};
Define("__preinit_array_start", "__preinit_array_end",
@@ -970,7 +968,7 @@
Define("__init_array_start", "__init_array_end", Out<ELFT>::InitArray);
Define("__fini_array_start", "__fini_array_end", Out<ELFT>::FiniArray);
- if (OutputSectionBase<ELFT> *Sec = findSection(".ARM.exidx"))
+ if (OutputSectionBase *Sec = findSection(".ARM.exidx"))
Define("__exidx_start", "__exidx_end", Sec);
}
@@ -980,24 +978,24 @@
// respectively. This is not requested by the ELF standard, but GNU ld and
// gold provide the feature, and used by many programs.
template <class ELFT>
-void Writer<ELFT>::addStartStopSymbols(OutputSectionBase<ELFT> *Sec) {
+void Writer<ELFT>::addStartStopSymbols(OutputSectionBase *Sec) {
StringRef S = Sec->getName();
if (!isValidCIdentifier(S))
return;
- addOptionalSynthetic(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT);
- addOptionalSynthetic(Saver.save("__stop_" + S), Sec,
- DefinedSynthetic<ELFT>::SectionEnd, STV_DEFAULT);
+ addOptionalSynthetic<ELFT>(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT);
+ addOptionalSynthetic<ELFT>(Saver.save("__stop_" + S), Sec,
+ DefinedSynthetic<ELFT>::SectionEnd, STV_DEFAULT);
}
template <class ELFT>
-OutputSectionBase<ELFT> *Writer<ELFT>::findSection(StringRef Name) {
- for (OutputSectionBase<ELFT> *Sec : OutputSections)
+OutputSectionBase *Writer<ELFT>::findSection(StringRef Name) {
+ for (OutputSectionBase *Sec : OutputSections)
if (Sec->getName() == Name)
return Sec;
return nullptr;
}
-template <class ELFT> static bool needsPtLoad(OutputSectionBase<ELFT> *Sec) {
+template <class ELFT> static bool needsPtLoad(OutputSectionBase *Sec) {
if (!(Sec->Flags & SHF_ALLOC))
return false;
@@ -1034,7 +1032,7 @@
Hdr.add(Out<ELFT>::ProgramHeaders);
// PT_INTERP must be the second entry if exists.
- if (OutputSectionBase<ELFT> *Sec = findSection(".interp")) {
+ if (OutputSectionBase *Sec = findSection(".interp")) {
Phdr &Hdr = *AddHdr(PT_INTERP, Sec->getPhdrFlags());
Hdr.add(Sec);
}
@@ -1051,7 +1049,7 @@
Phdr RelRo(PT_GNU_RELRO, PF_R);
Phdr Note(PT_NOTE, PF_R);
Phdr ARMExidx(PT_ARM_EXIDX, PF_R);
- for (OutputSectionBase<ELFT> *Sec : OutputSections) {
+ for (OutputSectionBase *Sec : OutputSections) {
if (!(Sec->Flags & SHF_ALLOC))
break;
@@ -1061,7 +1059,7 @@
if (Sec->Flags & SHF_TLS)
TlsHdr.add(Sec);
- if (!needsPtLoad(Sec))
+ if (!needsPtLoad<ELFT>(Sec))
continue;
// Segments are contiguous memory regions that has the same attributes
@@ -1077,7 +1075,7 @@
Load->add(Sec);
- if (isRelroSection(Sec))
+ if (isRelroSection<ELFT>(Sec))
RelRo.add(Sec);
if (Sec->Type == SHT_NOTE)
Note.add(Sec);
@@ -1109,7 +1107,7 @@
// PT_OPENBSD_RANDOMIZE specifies the location and size of a part of the
// memory image of the program that must be filled with random data before any
// code in the object is executed.
- if (OutputSectionBase<ELFT> *Sec = findSection(".openbsd.randomdata")) {
+ if (OutputSectionBase *Sec = findSection(".openbsd.randomdata")) {
Phdr &Hdr = *AddHdr(PT_OPENBSD_RANDOMIZE, Sec->getPhdrFlags());
Hdr.add(Sec);
}
@@ -1154,8 +1152,8 @@
auto I = std::find(OutputSections.begin(), End, P.Last);
if (I == End || (I + 1) == End)
continue;
- OutputSectionBase<ELFT> *Sec = *(I + 1);
- if (needsPtLoad(Sec))
+ OutputSectionBase *Sec = *(I + 1);
+ if (needsPtLoad<ELFT>(Sec))
Sec->PageAlign = true;
}
}
@@ -1175,7 +1173,7 @@
template <class ELFT> void Writer<ELFT>::assignAddresses() {
uintX_t VA = Config->ImageBase + getHeaderSize<ELFT>();
uintX_t ThreadBssOffset = 0;
- for (OutputSectionBase<ELFT> *Sec : OutputSections) {
+ for (OutputSectionBase *Sec : OutputSections) {
uintX_t Alignment = Sec->Addralign;
if (Sec->PageAlign)
Alignment = std::max<uintX_t>(Alignment, Config->MaxPageSize);
@@ -1185,7 +1183,7 @@
VA = I->second;
// We only assign VAs to allocated sections.
- if (needsPtLoad(Sec)) {
+ if (needsPtLoad<ELFT>(Sec)) {
VA = alignTo(VA, Alignment);
Sec->Addr = VA;
VA += Sec->Size;
@@ -1203,13 +1201,13 @@
// virtual address (modulo the page size) so that the loader can load
// executables without any address adjustment.
template <class ELFT, class uintX_t>
-static uintX_t getFileAlignment(uintX_t Off, OutputSectionBase<ELFT> *Sec) {
+static uintX_t getFileAlignment(uintX_t Off, OutputSectionBase *Sec) {
uintX_t Alignment = Sec->Addralign;
if (Sec->PageAlign)
Alignment = std::max<uintX_t>(Alignment, Config->MaxPageSize);
Off = alignTo(Off, Alignment);
- OutputSectionBase<ELFT> *First = Sec->FirstInPtLoad;
+ OutputSectionBase *First = Sec->FirstInPtLoad;
// If the section is not in a PT_LOAD, we have no other constraint.
if (!First)
return Off;
@@ -1222,7 +1220,7 @@
}
template <class ELFT, class uintX_t>
-void setOffset(OutputSectionBase<ELFT> *Sec, uintX_t &Off) {
+void setOffset(OutputSectionBase *Sec, uintX_t &Off) {
if (Sec->Type == SHT_NOBITS) {
Sec->Offset = Off;
return;
@@ -1235,20 +1233,20 @@
template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() {
uintX_t Off = 0;
- for (OutputSectionBase<ELFT> *Sec : OutputSections)
+ for (OutputSectionBase *Sec : OutputSections)
if (Sec->Flags & SHF_ALLOC)
- setOffset(Sec, Off);
+ setOffset<ELFT>(Sec, Off);
FileSize = alignTo(Off, sizeof(uintX_t));
}
// Assign file offsets to output sections.
template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
uintX_t Off = 0;
- setOffset(Out<ELFT>::ElfHeader, Off);
- setOffset(Out<ELFT>::ProgramHeaders, Off);
+ setOffset<ELFT>(Out<ELFT>::ElfHeader, Off);
+ setOffset<ELFT>(Out<ELFT>::ProgramHeaders, Off);
- for (OutputSectionBase<ELFT> *Sec : OutputSections)
- setOffset(Sec, Off);
+ for (OutputSectionBase *Sec : OutputSections)
+ setOffset<ELFT>(Sec, Off);
SectionHeaderOff = alignTo(Off, sizeof(uintX_t));
FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr);
@@ -1259,8 +1257,8 @@
template <class ELFT> void Writer<ELFT>::setPhdrs() {
for (Phdr &P : Phdrs) {
Elf_Phdr &H = P.H;
- OutputSectionBase<ELFT> *First = P.First;
- OutputSectionBase<ELFT> *Last = P.Last;
+ OutputSectionBase *First = P.First;
+ OutputSectionBase *Last = P.Last;
if (First) {
H.p_filesz = Last->Offset - First->Offset;
if (Last->Type != SHT_NOBITS)
@@ -1382,8 +1380,8 @@
// Write the section header table. Note that the first table entry is null.
auto *SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff);
- for (OutputSectionBase<ELFT> *Sec : OutputSections)
- Sec->writeHeaderTo(++SHdrs);
+ for (OutputSectionBase *Sec : OutputSections)
+ Sec->writeHeaderTo<ELFT>(++SHdrs);
}
template <class ELFT> void Writer<ELFT>::openFile() {
@@ -1398,7 +1396,7 @@
template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
uint8_t *Buf = Buffer->getBufferStart();
- for (OutputSectionBase<ELFT> *Sec : OutputSections)
+ for (OutputSectionBase *Sec : OutputSections)
if (Sec->Flags & SHF_ALLOC)
Sec->writeTo(Buf + Sec->Offset);
}
@@ -1477,11 +1475,11 @@
Out<ELFT>::Opd->writeTo(Buf + Out<ELFT>::Opd->Offset);
}
- for (OutputSectionBase<ELFT> *Sec : OutputSections)
+ for (OutputSectionBase *Sec : OutputSections)
if (Sec != Out<ELFT>::Opd && Sec != Out<ELFT>::EhFrameHdr)
Sec->writeTo(Buf + Sec->Offset);
- OutputSectionBase<ELFT> *ARMExidx = findSection(".ARM.exidx");
+ OutputSectionBase *ARMExidx = findSection(".ARM.exidx");
if (!Config->Relocatable)
if (auto *OS = dyn_cast_or_null<OutputSection<ELFT>>(ARMExidx))
sortARMExidx(Buf + OS->Offset, OS->Addr, OS->Size);
@@ -1512,10 +1510,10 @@
template struct elf::PhdrEntry<ELF64LE>;
template struct elf::PhdrEntry<ELF64BE>;
-template bool elf::isRelroSection<ELF32LE>(const OutputSectionBase<ELF32LE> *);
-template bool elf::isRelroSection<ELF32BE>(const OutputSectionBase<ELF32BE> *);
-template bool elf::isRelroSection<ELF64LE>(const OutputSectionBase<ELF64LE> *);
-template bool elf::isRelroSection<ELF64BE>(const OutputSectionBase<ELF64BE> *);
+template bool elf::isRelroSection<ELF32LE>(const OutputSectionBase *);
+template bool elf::isRelroSection<ELF32BE>(const OutputSectionBase *);
+template bool elf::isRelroSection<ELF64LE>(const OutputSectionBase *);
+template bool elf::isRelroSection<ELF64BE>(const OutputSectionBase *);
template void elf::reportDiscarded<ELF32LE>(InputSectionBase<ELF32LE> *);
template void elf::reportDiscarded<ELF32BE>(InputSectionBase<ELF32BE> *);