aboutsummaryrefslogtreecommitdiff
path: root/ELF/Writer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ELF/Writer.cpp')
-rw-r--r--ELF/Writer.cpp1192
1 files changed, 647 insertions, 545 deletions
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index b004a4f0d7f7..3ded0c675b80 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -9,7 +9,9 @@
#include "Writer.h"
#include "Config.h"
+#include "Filesystem.h"
#include "LinkerScript.h"
+#include "MapFile.h"
#include "Memory.h"
#include "OutputSections.h"
#include "Relocations.h"
@@ -20,10 +22,8 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <climits>
-#include <thread>
using namespace llvm;
using namespace llvm::ELF;
@@ -38,22 +38,19 @@ namespace {
// The writer writes a SymbolTable result to a file.
template <class ELFT> class Writer {
public:
- typedef typename ELFT::uint uintX_t;
typedef typename ELFT::Shdr Elf_Shdr;
typedef typename ELFT::Ehdr Elf_Ehdr;
typedef typename ELFT::Phdr Elf_Phdr;
- typedef typename ELFT::Sym Elf_Sym;
- typedef typename ELFT::SymRange Elf_Sym_Range;
- typedef typename ELFT::Rela Elf_Rela;
+
void run();
private:
void createSyntheticSections();
void copyLocalSymbols();
+ void addSectionSymbols();
void addReservedSymbols();
- void addInputSec(InputSectionBase<ELFT> *S);
void createSections();
- void forEachRelSec(std::function<void(InputSectionBase<ELFT> &)> Fn);
+ void forEachRelSec(std::function<void(InputSectionBase &)> Fn);
void sortSections();
void finalizeSections();
void addPredefinedSections();
@@ -67,7 +64,7 @@ private:
void setPhdrs();
void fixHeaders();
void fixSectionAlignments();
- void fixAbsoluteSymbols();
+ void fixPredefinedSymbols();
void openFile();
void writeHeader();
void writeSections();
@@ -76,19 +73,19 @@ private:
std::unique_ptr<FileOutputBuffer> Buffer;
- std::vector<OutputSectionBase *> OutputSections;
- OutputSectionFactory<ELFT> Factory;
+ std::vector<OutputSection *> OutputSections;
+ OutputSectionFactory Factory{OutputSections};
void addRelIpltSymbols();
void addStartEndSymbols();
- void addStartStopSymbols(OutputSectionBase *Sec);
- uintX_t getEntryAddr();
- OutputSectionBase *findSection(StringRef Name);
+ void addStartStopSymbols(OutputSection *Sec);
+ uint64_t getEntryAddr();
+ OutputSection *findSection(StringRef Name);
std::vector<PhdrEntry> Phdrs;
- uintX_t FileSize;
- uintX_t SectionHeaderOff;
+ uint64_t FileSize;
+ uint64_t SectionHeaderOff;
bool AllocateHeader = true;
};
} // anonymous namespace
@@ -97,9 +94,21 @@ StringRef elf::getOutputSectionName(StringRef Name) {
if (Config->Relocatable)
return Name;
+ // If -emit-relocs is given (which is rare), we need to copy
+ // relocation sections to the output. If input section .foo is
+ // output as .bar, we want to rename .rel.foo .rel.bar as well.
+ if (Config->EmitRelocs) {
+ for (StringRef V : {".rel.", ".rela."}) {
+ if (Name.startswith(V)) {
+ StringRef Inner = getOutputSectionName(Name.substr(V.size() - 1));
+ return Saver.save(Twine(V.drop_back()) + Inner);
+ }
+ }
+ }
+
for (StringRef V :
- {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.",
- ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.",
+ {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.",
+ ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.",
".gcc_except_table.", ".tdata.", ".ARM.exidx."}) {
StringRef Prefix = V.drop_back();
if (Name.startswith(V) || Name == Prefix)
@@ -118,17 +127,9 @@ StringRef elf::getOutputSectionName(StringRef Name) {
return Name;
}
-template <class ELFT> void elf::reportDiscarded(InputSectionBase<ELFT> *IS) {
- if (!Config->PrintGcSections)
- return;
- errs() << "removing unused section from '" << IS->Name << "' in file '"
- << IS->getFile()->getName() << "'\n";
-}
-
template <class ELFT> static bool needsInterpSection() {
return !Symtab<ELFT>::X->getSharedFiles().empty() &&
- !Config->DynamicLinker.empty() &&
- !Script<ELFT>::X->ignoreInterpSection();
+ !Config->DynamicLinker.empty() && !Script->ignoreInterpSection();
}
template <class ELFT> void elf::writeResult() { Writer<ELFT>().run(); }
@@ -139,49 +140,105 @@ template <class ELFT> void Writer<ELFT>::removeEmptyPTLoad() {
return false;
if (!P.First)
return true;
- uintX_t Size = P.Last->Addr + P.Last->Size - P.First->Addr;
+ uint64_t Size = P.Last->Addr + P.Last->Size - P.First->Addr;
return Size == 0;
});
Phdrs.erase(I, Phdrs.end());
}
+// This function scans over the input sections and creates mergeable
+// synthetic sections. It removes MergeInputSections from array and
+// adds new synthetic ones. Each synthetic section is added to the
+// location of the first input section it replaces.
+static void combineMergableSections() {
+ std::vector<MergeSyntheticSection *> MergeSections;
+ for (InputSectionBase *&S : InputSections) {
+ MergeInputSection *MS = dyn_cast<MergeInputSection>(S);
+ if (!MS)
+ continue;
+
+ // We do not want to handle sections that are not alive, so just remove
+ // them instead of trying to merge.
+ if (!MS->Live)
+ continue;
+
+ StringRef OutsecName = getOutputSectionName(MS->Name);
+ uint64_t Flags = MS->Flags & ~(uint64_t)(SHF_GROUP | SHF_COMPRESSED);
+ uint32_t Alignment = std::max<uint32_t>(MS->Alignment, MS->Entsize);
+
+ auto I =
+ llvm::find_if(MergeSections, [=](MergeSyntheticSection *Sec) {
+ return Sec->Name == OutsecName && Sec->Flags == Flags &&
+ Sec->Alignment == Alignment;
+ });
+ if (I == MergeSections.end()) {
+ MergeSyntheticSection *Syn =
+ make<MergeSyntheticSection>(OutsecName, MS->Type, Flags, Alignment);
+ MergeSections.push_back(Syn);
+ I = std::prev(MergeSections.end());
+ S = Syn;
+ } else {
+ S = nullptr;
+ }
+ (*I)->addSection(MS);
+ }
+
+ std::vector<InputSectionBase *> &V = InputSections;
+ V.erase(std::remove(V.begin(), V.end(), nullptr), V.end());
+}
+
+template <class ELFT> static void combineEhFrameSections() {
+ for (InputSectionBase *&S : InputSections) {
+ EhInputSection *ES = dyn_cast<EhInputSection>(S);
+ if (!ES || !ES->Live)
+ continue;
+
+ In<ELFT>::EhFrame->addSection(ES);
+ S = nullptr;
+ }
+
+ std::vector<InputSectionBase *> &V = InputSections;
+ V.erase(std::remove(V.begin(), V.end(), nullptr), V.end());
+}
+
// The main function of the writer.
template <class ELFT> void Writer<ELFT>::run() {
// Create linker-synthesized sections such as .got or .plt.
// Such sections are of type input section.
createSyntheticSections();
+ combineMergableSections();
+
+ if (!Config->Relocatable)
+ combineEhFrameSections<ELFT>();
// We need to create some reserved symbols such as _end. Create them.
if (!Config->Relocatable)
addReservedSymbols();
- // Some architectures use small displacements for jump instructions.
- // It is linker's responsibility to create thunks containing long
- // jump instructions if jump targets are too far. Create thunks.
- if (Target->NeedsThunks)
- forEachRelSec(createThunks<ELFT>);
-
// Create output sections.
- Script<ELFT>::X->OutputSections = &OutputSections;
- if (ScriptConfig->HasSections) {
+ Script->OutputSections = &OutputSections;
+ if (Script->Opt.HasSections) {
// If linker script contains SECTIONS commands, let it create sections.
- Script<ELFT>::X->processCommands(Factory);
+ Script->processCommands(Factory);
// Linker scripts may have left some input sections unassigned.
// Assign such sections using the default rule.
- Script<ELFT>::X->addOrphanSections(Factory);
+ Script->addOrphanSections(Factory);
} else {
// If linker script does not contain SECTIONS commands, create
// output sections by default rules. We still need to give the
// linker script a chance to run, because it might contain
// non-SECTIONS commands such as ASSERT.
createSections();
- Script<ELFT>::X->processCommands(Factory);
+ Script->processCommands(Factory);
}
if (Config->Discard != DiscardPolicy::All)
copyLocalSymbols();
+ if (Config->CopyRelocs)
+ addSectionSymbols();
+
// Now that we have a complete set of output sections. This function
// completes section contents. For example, we need to add strings
// to the string table, and add entries to .got and .plt.
@@ -193,11 +250,12 @@ template <class ELFT> void Writer<ELFT>::run() {
if (Config->Relocatable) {
assignFileOffsets();
} else {
- if (ScriptConfig->HasSections) {
- Script<ELFT>::X->assignAddresses(Phdrs);
+ if (Script->Opt.HasSections) {
+ Script->assignAddresses(Phdrs);
} else {
fixSectionAlignments();
assignAddresses();
+ Script->processNonSectionCommands();
}
// Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a
@@ -211,9 +269,12 @@ template <class ELFT> void Writer<ELFT>::run() {
assignFileOffsetsBinary();
setPhdrs();
- fixAbsoluteSymbols();
+ fixPredefinedSymbols();
}
+ // It does not make sense try to open the file if we have error already.
+ if (ErrorCount)
+ return;
// Write the result down to a file.
openFile();
if (ErrorCount)
@@ -231,8 +292,13 @@ template <class ELFT> void Writer<ELFT>::run() {
if (ErrorCount)
return;
+ // Handle -Map option.
+ writeMapFile<ELFT>(OutputSections);
+ if (ErrorCount)
+ return;
+
if (auto EC = Buffer->commit())
- error(EC, "failed to write to the output file");
+ error("failed to write to the output file: " + EC.message());
// Flush the output streams and exit immediately. A full shutdown
// is a good test that we are keeping track of all allocated memory,
@@ -241,156 +307,161 @@ template <class ELFT> void Writer<ELFT>::run() {
exitLld(0);
}
-// Initialize Out<ELFT> members.
+// Initialize Out members.
template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
// Initialize all pointers with NULL. This is needed because
// you can call lld::elf::main more than once as a library.
- memset(&Out<ELFT>::First, 0, sizeof(Out<ELFT>));
+ memset(&Out::First, 0, sizeof(Out));
+
+ auto Add = [](InputSectionBase *Sec) { InputSections.push_back(Sec); };
- // Create singleton output sections.
- Out<ELFT>::Bss =
- make<OutputSection<ELFT>>(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
- Out<ELFT>::BssRelRo = make<OutputSection<ELFT>>(".bss.rel.ro", SHT_NOBITS,
- SHF_ALLOC | SHF_WRITE);
- In<ELFT>::DynStrTab = make<StringTableSection<ELFT>>(".dynstr", true);
+ In<ELFT>::DynStrTab = make<StringTableSection>(".dynstr", true);
In<ELFT>::Dynamic = make<DynamicSection<ELFT>>();
- Out<ELFT>::EhFrame = make<EhOutputSection<ELFT>>();
In<ELFT>::RelaDyn = make<RelocationSection<ELFT>>(
- Config->Rela ? ".rela.dyn" : ".rel.dyn", Config->ZCombreloc);
- In<ELFT>::ShStrTab = make<StringTableSection<ELFT>>(".shstrtab", false);
+ Config->IsRela ? ".rela.dyn" : ".rel.dyn", Config->ZCombreloc);
+ In<ELFT>::ShStrTab = make<StringTableSection>(".shstrtab", false);
- Out<ELFT>::ElfHeader = make<OutputSectionBase>("", 0, SHF_ALLOC);
- Out<ELFT>::ElfHeader->Size = sizeof(Elf_Ehdr);
- Out<ELFT>::ProgramHeaders = make<OutputSectionBase>("", 0, SHF_ALLOC);
- Out<ELFT>::ProgramHeaders->updateAlignment(sizeof(uintX_t));
+ Out::ElfHeader = make<OutputSection>("", 0, SHF_ALLOC);
+ Out::ElfHeader->Size = sizeof(Elf_Ehdr);
+ Out::ProgramHeaders = make<OutputSection>("", 0, SHF_ALLOC);
+ Out::ProgramHeaders->updateAlignment(Config->Wordsize);
if (needsInterpSection<ELFT>()) {
- In<ELFT>::Interp = createInterpSection<ELFT>();
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::Interp);
+ In<ELFT>::Interp = createInterpSection();
+ Add(In<ELFT>::Interp);
} else {
In<ELFT>::Interp = nullptr;
}
if (!Config->Relocatable)
- Symtab<ELFT>::X->Sections.push_back(createCommentSection<ELFT>());
+ Add(createCommentSection<ELFT>());
if (Config->Strip != StripPolicy::All) {
- In<ELFT>::StrTab = make<StringTableSection<ELFT>>(".strtab", false);
+ In<ELFT>::StrTab = make<StringTableSection>(".strtab", false);
In<ELFT>::SymTab = make<SymbolTableSection<ELFT>>(*In<ELFT>::StrTab);
}
if (Config->BuildId != BuildIdKind::None) {
- In<ELFT>::BuildId = make<BuildIdSection<ELFT>>();
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::BuildId);
+ In<ELFT>::BuildId = make<BuildIdSection>();
+ Add(In<ELFT>::BuildId);
}
- InputSection<ELFT> *Common = createCommonSection<ELFT>();
- if (!Common->Data.empty()) {
- In<ELFT>::Common = Common;
- Symtab<ELFT>::X->Sections.push_back(Common);
- }
+ In<ELFT>::Common = createCommonSection<ELFT>();
+ if (In<ELFT>::Common)
+ Add(InX::Common);
+
+ In<ELFT>::Bss = make<BssSection>(".bss");
+ Add(In<ELFT>::Bss);
+ In<ELFT>::BssRelRo = make<BssSection>(".bss.rel.ro");
+ Add(In<ELFT>::BssRelRo);
// Add MIPS-specific sections.
- bool HasDynSymTab = !Symtab<ELFT>::X->getSharedFiles().empty() || Config->Pic;
+ bool HasDynSymTab = !Symtab<ELFT>::X->getSharedFiles().empty() ||
+ Config->Pic || Config->ExportDynamic;
if (Config->EMachine == EM_MIPS) {
if (!Config->Shared && HasDynSymTab) {
- In<ELFT>::MipsRldMap = make<MipsRldMapSection<ELFT>>();
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::MipsRldMap);
+ In<ELFT>::MipsRldMap = make<MipsRldMapSection>();
+ Add(In<ELFT>::MipsRldMap);
}
if (auto *Sec = MipsAbiFlagsSection<ELFT>::create())
- Symtab<ELFT>::X->Sections.push_back(Sec);
+ Add(Sec);
if (auto *Sec = MipsOptionsSection<ELFT>::create())
- Symtab<ELFT>::X->Sections.push_back(Sec);
+ Add(Sec);
if (auto *Sec = MipsReginfoSection<ELFT>::create())
- Symtab<ELFT>::X->Sections.push_back(Sec);
+ Add(Sec);
}
if (HasDynSymTab) {
In<ELFT>::DynSymTab = make<SymbolTableSection<ELFT>>(*In<ELFT>::DynStrTab);
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::DynSymTab);
+ Add(In<ELFT>::DynSymTab);
In<ELFT>::VerSym = make<VersionTableSection<ELFT>>();
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::VerSym);
+ Add(In<ELFT>::VerSym);
if (!Config->VersionDefinitions.empty()) {
In<ELFT>::VerDef = make<VersionDefinitionSection<ELFT>>();
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::VerDef);
+ Add(In<ELFT>::VerDef);
}
In<ELFT>::VerNeed = make<VersionNeedSection<ELFT>>();
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::VerNeed);
+ Add(In<ELFT>::VerNeed);
if (Config->GnuHash) {
In<ELFT>::GnuHashTab = make<GnuHashTableSection<ELFT>>();
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::GnuHashTab);
+ Add(In<ELFT>::GnuHashTab);
}
if (Config->SysvHash) {
In<ELFT>::HashTab = make<HashTableSection<ELFT>>();
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::HashTab);
+ Add(In<ELFT>::HashTab);
}
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::Dynamic);
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::DynStrTab);
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::RelaDyn);
+ Add(In<ELFT>::Dynamic);
+ Add(In<ELFT>::DynStrTab);
+ Add(In<ELFT>::RelaDyn);
}
// Add .got. MIPS' .got is so different from the other archs,
// it has its own class.
if (Config->EMachine == EM_MIPS) {
- In<ELFT>::MipsGot = make<MipsGotSection<ELFT>>();
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::MipsGot);
+ In<ELFT>::MipsGot = make<MipsGotSection>();
+ Add(In<ELFT>::MipsGot);
} else {
In<ELFT>::Got = make<GotSection<ELFT>>();
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::Got);
+ Add(In<ELFT>::Got);
}
- In<ELFT>::GotPlt = make<GotPltSection<ELFT>>();
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::GotPlt);
- In<ELFT>::IgotPlt = make<IgotPltSection<ELFT>>();
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::IgotPlt);
+ In<ELFT>::GotPlt = make<GotPltSection>();
+ Add(In<ELFT>::GotPlt);
+ In<ELFT>::IgotPlt = make<IgotPltSection>();
+ Add(In<ELFT>::IgotPlt);
if (Config->GdbIndex) {
- In<ELFT>::GdbIndex = make<GdbIndexSection<ELFT>>();
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::GdbIndex);
+ In<ELFT>::GdbIndex = make<GdbIndexSection>();
+ Add(In<ELFT>::GdbIndex);
}
// We always need to add rel[a].plt to output if it has entries.
// Even for static linking it can contain R_[*]_IRELATIVE relocations.
In<ELFT>::RelaPlt = make<RelocationSection<ELFT>>(
- Config->Rela ? ".rela.plt" : ".rel.plt", false /*Sort*/);
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::RelaPlt);
+ Config->IsRela ? ".rela.plt" : ".rel.plt", false /*Sort*/);
+ Add(In<ELFT>::RelaPlt);
// The RelaIplt immediately follows .rel.plt (.rel.dyn for ARM) to ensure
// that the IRelative relocations are processed last by the dynamic loader
In<ELFT>::RelaIplt = make<RelocationSection<ELFT>>(
(Config->EMachine == EM_ARM) ? ".rel.dyn" : In<ELFT>::RelaPlt->Name,
false /*Sort*/);
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::RelaIplt);
+ Add(In<ELFT>::RelaIplt);
- In<ELFT>::Plt = make<PltSection<ELFT>>();
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::Plt);
- In<ELFT>::Iplt = make<IpltSection<ELFT>>();
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::Iplt);
+ In<ELFT>::Plt = make<PltSection>(Target->PltHeaderSize);
+ Add(In<ELFT>::Plt);
+ In<ELFT>::Iplt = make<PltSection>(0);
+ Add(In<ELFT>::Iplt);
- if (Config->EhFrameHdr) {
- In<ELFT>::EhFrameHdr = make<EhFrameHeader<ELFT>>();
- Symtab<ELFT>::X->Sections.push_back(In<ELFT>::EhFrameHdr);
+ if (!Config->Relocatable) {
+ if (Config->EhFrameHdr) {
+ In<ELFT>::EhFrameHdr = make<EhFrameHeader<ELFT>>();
+ Add(In<ELFT>::EhFrameHdr);
+ }
+ In<ELFT>::EhFrame = make<EhFrameSection<ELFT>>();
+ Add(In<ELFT>::EhFrame);
}
+
+ if (In<ELFT>::SymTab)
+ Add(In<ELFT>::SymTab);
+ Add(In<ELFT>::ShStrTab);
+ if (In<ELFT>::StrTab)
+ Add(In<ELFT>::StrTab);
}
-template <class ELFT>
-static bool shouldKeepInSymtab(InputSectionBase<ELFT> *Sec, StringRef SymName,
+static bool shouldKeepInSymtab(SectionBase *Sec, StringRef SymName,
const SymbolBody &B) {
- if (B.isFile())
+ if (B.isFile() || B.isSection())
return false;
- // We keep sections in symtab for relocatable output.
- if (B.isSection())
- return Config->Relocatable;
-
// If sym references a section in a discarded group, don't keep it.
- if (Sec == &InputSection<ELFT>::Discarded)
+ if (Sec == &InputSection::Discarded)
return false;
if (Config->Discard == DiscardPolicy::None)
@@ -410,24 +481,23 @@ static bool shouldKeepInSymtab(InputSectionBase<ELFT> *Sec, StringRef SymName,
return !Sec || !(Sec->Flags & SHF_MERGE);
}
-template <class ELFT> static bool includeInSymtab(const SymbolBody &B) {
+static bool includeInSymtab(const SymbolBody &B) {
if (!B.isLocal() && !B.symbol()->IsUsedInRegularObj)
return false;
- // If --retain-symbols-file is given, we'll keep only symbols listed in that
- // file.
- if (Config->Discard == DiscardPolicy::RetainFile &&
- !Config->RetainSymbolsFile.count(B.getName()))
- return false;
-
- if (auto *D = dyn_cast<DefinedRegular<ELFT>>(&B)) {
+ if (auto *D = dyn_cast<DefinedRegular>(&B)) {
// Always include absolute symbols.
- if (!D->Section)
+ SectionBase *Sec = D->Section;
+ if (!Sec)
return true;
- // Exclude symbols pointing to garbage-collected sections.
- if (!D->Section->Live)
- return false;
- if (auto *S = dyn_cast<MergeInputSection<ELFT>>(D->Section))
+ if (auto *IS = dyn_cast<InputSectionBase>(Sec)) {
+ Sec = IS->Repl;
+ IS = cast<InputSectionBase>(Sec);
+ // Exclude symbols pointing to garbage-collected sections.
+ if (!IS->Live)
+ return false;
+ }
+ if (auto *S = dyn_cast<MergeInputSection>(Sec))
if (!S->getSectionPiece(D->Value)->Live)
return false;
}
@@ -444,22 +514,41 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
if (!B->IsLocal)
fatal(toString(F) +
": broken object: getLocalSymbols returns a non-local symbol");
- auto *DR = dyn_cast<DefinedRegular<ELFT>>(B);
+ auto *DR = dyn_cast<DefinedRegular>(B);
// No reason to keep local undefined symbol in symtab.
if (!DR)
continue;
- if (!includeInSymtab<ELFT>(*B))
+ if (!includeInSymtab(*B))
continue;
- InputSectionBase<ELFT> *Sec = DR->Section;
- if (!shouldKeepInSymtab<ELFT>(Sec, B->getName(), *B))
+ SectionBase *Sec = DR->Section;
+ if (!shouldKeepInSymtab(Sec, B->getName(), *B))
continue;
- In<ELFT>::SymTab->addLocal(B);
+ In<ELFT>::SymTab->addSymbol(B);
}
}
}
+template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
+ // Create one STT_SECTION symbol for each output section we might
+ // have a relocation with.
+ for (OutputSection *Sec : OutputSections) {
+ if (Sec->Sections.empty())
+ continue;
+
+ InputSection *IS = Sec->Sections[0];
+ if (isa<SyntheticSection>(IS) || IS->Type == SHT_REL ||
+ IS->Type == SHT_RELA)
+ continue;
+
+ auto *Sym =
+ make<DefinedRegular>("", /*IsLocal=*/true, /*StOther=*/0, STT_SECTION,
+ /*Value=*/0, /*Size=*/0, IS, nullptr);
+ In<ELFT>::SymTab->addSymbol(Sym);
+ }
+}
+
// PPC64 has a number of special SHT_PROGBITS+SHF_ALLOC+SHF_WRITE sections that
// we would like to make sure appear is a specific order to maximize their
// coverage by a single signed 16-bit offset from the TOC base pointer.
@@ -478,46 +567,94 @@ static int getPPC64SectionRank(StringRef SectionName) {
// All sections with SHF_MIPS_GPREL flag should be grouped together
// because data in these sections is addressable with a gp relative address.
-static int getMipsSectionRank(const OutputSectionBase *S) {
+static int getMipsSectionRank(const OutputSection *S) {
if ((S->Flags & SHF_MIPS_GPREL) == 0)
return 0;
- if (S->getName() == ".got")
+ if (S->Name == ".got")
return 1;
return 2;
}
-template <class ELFT> bool elf::isRelroSection(const OutputSectionBase *Sec) {
+// Today's loaders have a feature to make segments read-only after
+// processing dynamic relocations to enhance security. PT_GNU_RELRO
+// is defined for that.
+//
+// This function returns true if a section needs to be put into a
+// PT_GNU_RELRO segment.
+template <class ELFT> bool elf::isRelroSection(const OutputSection *Sec) {
if (!Config->ZRelro)
return false;
+
uint64_t Flags = Sec->Flags;
+
+ // Non-allocatable or non-writable sections don't need RELRO because
+ // they are not writable or not even mapped to memory in the first place.
+ // RELRO is for sections that are essentially read-only but need to
+ // be writable only at process startup to allow dynamic linker to
+ // apply relocations.
if (!(Flags & SHF_ALLOC) || !(Flags & SHF_WRITE))
return false;
+
+ // Once initialized, TLS data segments are used as data templates
+ // for a thread-local storage. For each new thread, runtime
+ // allocates memory for a TLS and copy templates there. No thread
+ // are supposed to use templates directly. Thus, it can be in RELRO.
if (Flags & SHF_TLS)
return true;
+
+ // .init_array, .preinit_array and .fini_array contain pointers to
+ // functions that are executed on process startup or exit. These
+ // pointers are set by the static linker, and they are not expected
+ // to change at runtime. But if you are an attacker, you could do
+ // interesting things by manipulating pointers in .fini_array, for
+ // example. So they are put into RELRO.
uint32_t Type = Sec->Type;
if (Type == SHT_INIT_ARRAY || Type == SHT_FINI_ARRAY ||
Type == SHT_PREINIT_ARRAY)
return true;
+
+ // .got contains pointers to external symbols. They are resolved by
+ // the dynamic linker when a module is loaded into memory, and after
+ // that they are not expected to change. So, it can be in RELRO.
+ if (In<ELFT>::Got && Sec == In<ELFT>::Got->OutSec)
+ return true;
+
+ // .got.plt contains pointers to external function symbols. They are
+ // by default resolved lazily, so we usually cannot put it into RELRO.
+ // However, if "-z now" is given, the lazy symbol resolution is
+ // disabled, which enables us to put it into RELRO.
if (Sec == In<ELFT>::GotPlt->OutSec)
return Config->ZNow;
+
+ // .dynamic section contains data for the dynamic linker, and
+ // there's no need to write to it at runtime, so it's better to put
+ // it into RELRO.
if (Sec == In<ELFT>::Dynamic->OutSec)
return true;
- if (In<ELFT>::Got && Sec == In<ELFT>::Got->OutSec)
- return true;
- if (Sec == Out<ELFT>::BssRelRo)
+
+ // .bss.rel.ro is used for copy relocations for read-only symbols.
+ // Since the dynamic linker needs to process copy relocations, the
+ // section cannot be read-only, but once initialized, they shouldn't
+ // change.
+ if (Sec == In<ELFT>::BssRelRo->OutSec)
return true;
- StringRef S = Sec->getName();
+
+ // Sections with some special names are put into RELRO. This is a
+ // bit unfortunate because section names shouldn't be significant in
+ // ELF in spirit. But in reality many linker features depend on
+ // magic section names.
+ StringRef S = Sec->Name;
return S == ".data.rel.ro" || S == ".ctors" || S == ".dtors" || S == ".jcr" ||
S == ".eh_frame" || S == ".openbsd.randomdata";
}
template <class ELFT>
-static bool compareSectionsNonScript(const OutputSectionBase *A,
- const OutputSectionBase *B) {
+static bool compareSectionsNonScript(const OutputSection *A,
+ const OutputSection *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";
- bool BIsInterp = B->getName() == ".interp";
+ bool AIsInterp = A->Name == ".interp";
+ bool BIsInterp = B->Name == ".interp";
if (AIsInterp != BIsInterp)
return AIsInterp;
@@ -535,8 +672,8 @@ static bool compareSectionsNonScript(const OutputSectionBase *A,
// We want to put section specified by -T option first, so we
// can start assigning VA starting from them later.
- auto AAddrSetI = Config->SectionStartMap.find(A->getName());
- auto BAddrSetI = Config->SectionStartMap.find(B->getName());
+ auto AAddrSetI = Config->SectionStartMap.find(A->Name);
+ auto BAddrSetI = Config->SectionStartMap.find(B->Name);
bool AHasAddrSet = AAddrSetI != Config->SectionStartMap.end();
bool BHasAddrSet = BAddrSetI != Config->SectionStartMap.end();
if (AHasAddrSet != BHasAddrSet)
@@ -601,8 +738,7 @@ static bool compareSectionsNonScript(const OutputSectionBase *A,
// Some architectures have additional ordering restrictions for sections
// within the same PT_LOAD.
if (Config->EMachine == EM_PPC64)
- return getPPC64SectionRank(A->getName()) <
- getPPC64SectionRank(B->getName());
+ return getPPC64SectionRank(A->Name) < getPPC64SectionRank(B->Name);
if (Config->EMachine == EM_MIPS)
return getMipsSectionRank(A) < getMipsSectionRank(B);
@@ -611,11 +747,10 @@ static bool compareSectionsNonScript(const OutputSectionBase *A,
// Output section ordering is determined by this function.
template <class ELFT>
-static bool compareSections(const OutputSectionBase *A,
- const OutputSectionBase *B) {
+static bool compareSections(const OutputSection *A, const OutputSection *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());
+ int AIndex = Script->getSectionIndex(A->Name);
+ int BIndex = Script->getSectionIndex(B->Name);
bool AInScript = AIndex != INT_MAX;
bool BInScript = BIndex != INT_MAX;
if (AInScript != BInScript)
@@ -633,43 +768,37 @@ PhdrEntry::PhdrEntry(unsigned Type, unsigned Flags) {
p_flags = Flags;
}
-void PhdrEntry::add(OutputSectionBase *Sec) {
+void PhdrEntry::add(OutputSection *Sec) {
Last = Sec;
if (!First)
First = Sec;
- p_align = std::max(p_align, Sec->Addralign);
+ p_align = std::max(p_align, Sec->Alignment);
if (p_type == PT_LOAD)
Sec->FirstInPtLoad = First;
}
template <class ELFT>
-static void addOptionalSynthetic(StringRef Name, OutputSectionBase *Sec,
- typename ELFT::uint Val,
- uint8_t StOther = STV_HIDDEN) {
- if (SymbolBody *S = Symtab<ELFT>::X->find(Name))
- if (!S->isInCurrentDSO())
- Symtab<ELFT>::X->addSynthetic(Name, Sec, Val, StOther);
-}
-
-template <class ELFT>
-static Symbol *addRegular(StringRef Name, InputSectionBase<ELFT> *Sec,
- typename ELFT::uint Value) {
+static Symbol *addRegular(StringRef Name, SectionBase *Sec, uint64_t Value,
+ uint8_t StOther = STV_HIDDEN,
+ uint8_t Binding = STB_WEAK) {
// The linker generated symbols are added as STB_WEAK to allow user defined
// ones to override them.
- return Symtab<ELFT>::X->addRegular(Name, STV_HIDDEN, STT_NOTYPE, Value,
- /*Size=*/0, STB_WEAK, Sec,
+ return Symtab<ELFT>::X->addRegular(Name, StOther, STT_NOTYPE, Value,
+ /*Size=*/0, Binding, Sec,
/*File=*/nullptr);
}
template <class ELFT>
-static Symbol *addOptionalRegular(StringRef Name, InputSectionBase<ELFT> *IS,
- typename ELFT::uint Value) {
+static DefinedRegular *
+addOptionalRegular(StringRef Name, SectionBase *Sec, uint64_t Val,
+ uint8_t StOther = STV_HIDDEN, uint8_t Binding = STB_GLOBAL) {
SymbolBody *S = Symtab<ELFT>::X->find(Name);
if (!S)
return nullptr;
if (S->isInCurrentDSO())
- return S->symbol();
- return addRegular(Name, IS, Value);
+ return nullptr;
+ return cast<DefinedRegular>(
+ addRegular<ELFT>(Name, Sec, Val, StOther, Binding)->body());
}
// The beginning and the ending of .rel[a].plt section are marked
@@ -681,11 +810,11 @@ static Symbol *addOptionalRegular(StringRef Name, InputSectionBase<ELFT> *IS,
template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
if (In<ELFT>::DynSymTab)
return;
- StringRef S = Config->Rela ? "__rela_iplt_start" : "__rel_iplt_start";
- addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, 0);
+ StringRef S = Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start";
+ addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, 0, STV_HIDDEN, STB_WEAK);
- S = Config->Rela ? "__rela_iplt_end" : "__rel_iplt_end";
- addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, -1);
+ S = Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end";
+ addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, -1, STV_HIDDEN, STB_WEAK);
}
// The linker is expected to define some symbols depending on
@@ -697,15 +826,12 @@ template <class ELFT> void Writer<ELFT>::addReservedSymbols() {
// to GOT. Default offset is 0x7ff0.
// See "Global Data Symbols" in Chapter 6 in the following document:
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
- ElfSym<ELFT>::MipsGp =
- Symtab<ELFT>::X->addAbsolute("_gp", STV_HIDDEN, STB_LOCAL);
+ ElfSym::MipsGp = Symtab<ELFT>::X->addAbsolute("_gp", STV_HIDDEN, STB_LOCAL);
// On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
- // start of function and 'gp' pointer into GOT. To simplify relocation
- // calculation we assign _gp value to it and calculate corresponding
- // relocations as relative to this value.
+ // start of function and 'gp' pointer into GOT.
if (Symtab<ELFT>::X->find("_gp_disp"))
- ElfSym<ELFT>::MipsGpDisp =
+ ElfSym::MipsGpDisp =
Symtab<ELFT>::X->addAbsolute("_gp_disp", STV_HIDDEN, STB_LOCAL);
// The __gnu_local_gp is a magic symbol equal to the current value of 'gp'
@@ -713,7 +839,7 @@ template <class ELFT> void Writer<ELFT>::addReservedSymbols() {
// in case of using -mno-shared option.
// https://sourceware.org/ml/binutils/2004-12/msg00094.html
if (Symtab<ELFT>::X->find("__gnu_local_gp"))
- ElfSym<ELFT>::MipsLocalGp =
+ ElfSym::MipsLocalGp =
Symtab<ELFT>::X->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_LOCAL);
}
@@ -742,45 +868,41 @@ template <class ELFT> void Writer<ELFT>::addReservedSymbols() {
Symtab<ELFT>::X->addIgnored("__tls_get_addr");
// If linker script do layout we do not need to create any standart symbols.
- if (ScriptConfig->HasSections)
+ if (Script->Opt.HasSections)
return;
- ElfSym<ELFT>::EhdrStart = Symtab<ELFT>::X->addIgnored("__ehdr_start");
+ // __ehdr_start is the location of ELF file headers.
+ addOptionalRegular<ELFT>("__ehdr_start", Out::ElfHeader, 0, STV_HIDDEN);
- auto Define = [this](StringRef S, DefinedRegular<ELFT> *&Sym1,
- DefinedRegular<ELFT> *&Sym2) {
- Sym1 = Symtab<ELFT>::X->addIgnored(S, STV_DEFAULT);
-
- // The name without the underscore is not a reserved name,
- // so it is defined only when there is a reference against it.
- assert(S.startswith("_"));
- S = S.substr(1);
- if (SymbolBody *B = Symtab<ELFT>::X->find(S))
- if (B->isUndefined())
- Sym2 = Symtab<ELFT>::X->addAbsolute(S, STV_DEFAULT);
+ auto Add = [](StringRef S) {
+ return addOptionalRegular<ELFT>(S, Out::ElfHeader, 0, STV_DEFAULT);
};
- Define("_end", ElfSym<ELFT>::End, ElfSym<ELFT>::End2);
- Define("_etext", ElfSym<ELFT>::Etext, ElfSym<ELFT>::Etext2);
- Define("_edata", ElfSym<ELFT>::Edata, ElfSym<ELFT>::Edata2);
+ ElfSym::Bss = Add("__bss_start");
+ ElfSym::End1 = Add("end");
+ ElfSym::End2 = Add("_end");
+ ElfSym::Etext1 = Add("etext");
+ ElfSym::Etext2 = Add("_etext");
+ ElfSym::Edata1 = Add("edata");
+ ElfSym::Edata2 = Add("_edata");
}
// Sort input sections by section name suffixes for
// __attribute__((init_priority(N))).
-template <class ELFT> static void sortInitFini(OutputSectionBase *S) {
+static void sortInitFini(OutputSection *S) {
if (S)
- reinterpret_cast<OutputSection<ELFT> *>(S)->sortInitFini();
+ reinterpret_cast<OutputSection *>(S)->sortInitFini();
}
// Sort input sections by the special rule for .ctors and .dtors.
-template <class ELFT> static void sortCtorsDtors(OutputSectionBase *S) {
+static void sortCtorsDtors(OutputSection *S) {
if (S)
- reinterpret_cast<OutputSection<ELFT> *>(S)->sortCtorsDtors();
+ reinterpret_cast<OutputSection *>(S)->sortCtorsDtors();
}
// Sort input sections using the list provided by --symbol-ordering-file.
template <class ELFT>
-static void sortBySymbolsOrder(ArrayRef<OutputSectionBase *> OutputSections) {
+static void sortBySymbolsOrder(ArrayRef<OutputSection *> OutputSections) {
if (Config->SymbolOrderingFile.empty())
return;
@@ -793,10 +915,10 @@ static void sortBySymbolsOrder(ArrayRef<OutputSectionBase *> OutputSections) {
SymbolOrder.insert({S, Priority++});
// Build a map from sections to their priorities.
- DenseMap<InputSectionBase<ELFT> *, int> SectionOrder;
+ DenseMap<SectionBase *, int> SectionOrder;
for (elf::ObjectFile<ELFT> *File : Symtab<ELFT>::X->getObjectFiles()) {
for (SymbolBody *Body : File->getSymbols()) {
- auto *D = dyn_cast<DefinedRegular<ELFT>>(Body);
+ auto *D = dyn_cast<DefinedRegular>(Body);
if (!D || !D->Section)
continue;
int &Priority = SectionOrder[D->Section];
@@ -805,15 +927,14 @@ static void sortBySymbolsOrder(ArrayRef<OutputSectionBase *> OutputSections) {
}
// Sort sections by priority.
- for (OutputSectionBase *Base : OutputSections)
- if (auto *Sec = dyn_cast<OutputSection<ELFT>>(Base))
- Sec->sort([&](InputSection<ELFT> *S) { return SectionOrder.lookup(S); });
+ for (OutputSection *Base : OutputSections)
+ if (auto *Sec = dyn_cast<OutputSection>(Base))
+ Sec->sort([&](InputSectionBase *S) { return SectionOrder.lookup(S); });
}
template <class ELFT>
-void Writer<ELFT>::forEachRelSec(
- std::function<void(InputSectionBase<ELFT> &)> Fn) {
- for (InputSectionBase<ELFT> *IS : Symtab<ELFT>::X->Sections) {
+void Writer<ELFT>::forEachRelSec(std::function<void(InputSectionBase &)> Fn) {
+ for (InputSectionBase *IS : InputSections) {
if (!IS->Live)
continue;
// Scan all relocations. Each relocation goes through a series
@@ -823,46 +944,32 @@ void Writer<ELFT>::forEachRelSec(
// processed by InputSection::relocateNonAlloc.
if (!(IS->Flags & SHF_ALLOC))
continue;
- if (isa<InputSection<ELFT>>(IS) || isa<EhInputSection<ELFT>>(IS))
+ if (isa<InputSection>(IS) || isa<EhInputSection>(IS))
Fn(*IS);
}
-}
-
-template <class ELFT>
-void Writer<ELFT>::addInputSec(InputSectionBase<ELFT> *IS) {
- if (!IS)
- return;
- if (!IS->Live) {
- reportDiscarded(IS);
- return;
+ if (!Config->Relocatable) {
+ for (EhInputSection *ES : In<ELFT>::EhFrame->Sections)
+ Fn(*ES);
}
- OutputSectionBase *Sec;
- bool IsNew;
- StringRef OutsecName = getOutputSectionName(IS->Name);
- std::tie(Sec, IsNew) = Factory.create(IS, OutsecName);
- if (IsNew)
- OutputSections.push_back(Sec);
- Sec->addSection(IS);
}
template <class ELFT> void Writer<ELFT>::createSections() {
- for (InputSectionBase<ELFT> *IS : Symtab<ELFT>::X->Sections)
- addInputSec(IS);
+ for (InputSectionBase *IS : InputSections)
+ if (IS)
+ Factory.addInputSec(IS, getOutputSectionName(IS->Name));
sortBySymbolsOrder<ELFT>(OutputSections);
- sortInitFini<ELFT>(findSection(".init_array"));
- sortInitFini<ELFT>(findSection(".fini_array"));
- sortCtorsDtors<ELFT>(findSection(".ctors"));
- sortCtorsDtors<ELFT>(findSection(".dtors"));
+ sortInitFini(findSection(".init_array"));
+ sortInitFini(findSection(".fini_array"));
+ sortCtorsDtors(findSection(".ctors"));
+ sortCtorsDtors(findSection(".dtors"));
- for (OutputSectionBase *Sec : OutputSections)
+ for (OutputSection *Sec : OutputSections)
Sec->assignOffsets();
}
-template <class ELFT>
-static bool canSharePtLoad(const OutputSectionBase &S1,
- const OutputSectionBase &S2) {
+static bool canSharePtLoad(const OutputSection &S1, const OutputSection &S2) {
if (!(S1.Flags & SHF_ALLOC) || !(S2.Flags & SHF_ALLOC))
return false;
@@ -881,12 +988,12 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
// relative order for SHF_LINK_ORDER sections.
if (Config->Relocatable)
return;
- if (!ScriptConfig->HasSections) {
+ if (!Script->Opt.HasSections) {
std::stable_sort(OutputSections.begin(), OutputSections.end(),
compareSectionsNonScript<ELFT>);
return;
}
- Script<ELFT>::X->adjustSectionsBeforeSorting();
+ Script->adjustSectionsBeforeSorting();
// The order of the sections in the script is arbitrary and may not agree with
// compareSectionsNonScript. This means that we cannot easily define a
@@ -918,14 +1025,14 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
auto I = OutputSections.begin();
auto E = OutputSections.end();
auto NonScriptI =
- std::find_if(OutputSections.begin(), E, [](OutputSectionBase *S) {
- return Script<ELFT>::X->getSectionIndex(S->getName()) == INT_MAX;
+ std::find_if(OutputSections.begin(), E, [](OutputSection *S) {
+ return Script->getSectionIndex(S->Name) == INT_MAX;
});
while (NonScriptI != E) {
auto BestPos = std::max_element(
- I, NonScriptI, [&](OutputSectionBase *&A, OutputSectionBase *&B) {
- bool ACanSharePtLoad = canSharePtLoad<ELFT>(**NonScriptI, *A);
- bool BCanSharePtLoad = canSharePtLoad<ELFT>(**NonScriptI, *B);
+ I, NonScriptI, [&](OutputSection *&A, OutputSection *&B) {
+ bool ACanSharePtLoad = canSharePtLoad(**NonScriptI, *A);
+ bool BCanSharePtLoad = canSharePtLoad(**NonScriptI, *B);
if (ACanSharePtLoad != BCanSharePtLoad)
return BCanSharePtLoad;
@@ -949,16 +1056,14 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
++NonScriptI;
}
- Script<ELFT>::X->adjustSectionsAfterSorting();
+ Script->adjustSectionsAfterSorting();
}
-template <class ELFT>
-static void
-finalizeSynthetic(const std::vector<SyntheticSection<ELFT> *> &Sections) {
- for (SyntheticSection<ELFT> *SS : Sections)
+static void applySynthetic(const std::vector<SyntheticSection *> &Sections,
+ std::function<void(SyntheticSection *)> Fn) {
+ for (SyntheticSection *SS : Sections)
if (SS && SS->OutSec && !SS->empty()) {
- SS->finalize();
- SS->OutSec->Size = 0;
+ Fn(SS);
SS->OutSec->assignOffsets();
}
}
@@ -966,40 +1071,40 @@ finalizeSynthetic(const std::vector<SyntheticSection<ELFT> *> &Sections) {
// We need to add input synthetic sections early in createSyntheticSections()
// to make them visible from linkescript side. But not all sections are always
// required to be in output. For example we don't need dynamic section content
-// sometimes. This function filters out such unused sections from output.
-template <class ELFT>
-static void removeUnusedSyntheticSections(std::vector<OutputSectionBase *> &V) {
- // Input synthetic sections are placed after all regular ones. We iterate over
- // them all and exit at first non-synthetic.
- for (InputSectionBase<ELFT> *S : llvm::reverse(Symtab<ELFT>::X->Sections)) {
- SyntheticSection<ELFT> *SS = dyn_cast<SyntheticSection<ELFT>>(S);
+// sometimes. This function filters out such unused sections from the output.
+static void removeUnusedSyntheticSections(std::vector<OutputSection *> &V) {
+ // All input synthetic sections that can be empty are placed after
+ // all regular ones. We iterate over them all and exit at first
+ // non-synthetic.
+ for (InputSectionBase *S : llvm::reverse(InputSections)) {
+ SyntheticSection *SS = dyn_cast<SyntheticSection>(S);
if (!SS)
return;
if (!SS->empty() || !SS->OutSec)
continue;
- OutputSection<ELFT> *OutSec = cast<OutputSection<ELFT>>(SS->OutSec);
- OutSec->Sections.erase(
- std::find(OutSec->Sections.begin(), OutSec->Sections.end(), SS));
- // If there is no other sections in output section, remove it from output.
- if (OutSec->Sections.empty())
- V.erase(std::find(V.begin(), V.end(), OutSec));
+ SS->OutSec->Sections.erase(std::find(SS->OutSec->Sections.begin(),
+ SS->OutSec->Sections.end(), SS));
+ // If there are no other sections in the output section, remove it from the
+ // output.
+ if (SS->OutSec->Sections.empty())
+ V.erase(std::find(V.begin(), V.end(), SS->OutSec));
}
}
// Create output section objects and add them to OutputSections.
template <class ELFT> void Writer<ELFT>::finalizeSections() {
- Out<ELFT>::DebugInfo = findSection(".debug_info");
- Out<ELFT>::PreinitArray = findSection(".preinit_array");
- Out<ELFT>::InitArray = findSection(".init_array");
- Out<ELFT>::FiniArray = findSection(".fini_array");
+ Out::DebugInfo = findSection(".debug_info");
+ Out::PreinitArray = findSection(".preinit_array");
+ Out::InitArray = findSection(".init_array");
+ Out::FiniArray = findSection(".fini_array");
// The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop
// symbols for sections, so that the runtime can get the start and end
// addresses of each section by section name. Add such symbols.
if (!Config->Relocatable) {
addStartEndSymbols();
- for (OutputSectionBase *Sec : OutputSections)
+ for (OutputSection *Sec : OutputSections)
addStartStopSymbols(Sec);
}
@@ -1008,34 +1113,40 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// Even the author of gold doesn't remember why gold behaves that way.
// https://sourceware.org/ml/binutils/2002-03/msg00360.html
if (In<ELFT>::DynSymTab)
- addRegular("_DYNAMIC", In<ELFT>::Dynamic, 0);
+ addRegular<ELFT>("_DYNAMIC", In<ELFT>::Dynamic, 0);
// Define __rel[a]_iplt_{start,end} symbols if needed.
addRelIpltSymbols();
- if (!Out<ELFT>::EhFrame->empty()) {
- OutputSections.push_back(Out<ELFT>::EhFrame);
- Out<ELFT>::EhFrame->finalize();
- }
+ // This responsible for splitting up .eh_frame section into
+ // pieces. The relocation scan uses those pieces, so this has to be
+ // earlier.
+ applySynthetic({In<ELFT>::EhFrame},
+ [](SyntheticSection *SS) { SS->finalizeContents(); });
// Scan relocations. This must be done after every symbol is declared so that
// we can correctly decide if a dynamic relocation is needed.
forEachRelSec(scanRelocations<ELFT>);
- // Now that we have defined all possible symbols including linker-
+ if (In<ELFT>::Plt && !In<ELFT>::Plt->empty())
+ In<ELFT>::Plt->addSymbols();
+ if (In<ELFT>::Iplt && !In<ELFT>::Iplt->empty())
+ In<ELFT>::Iplt->addSymbols();
+
+ // Now that we have defined all possible global symbols including linker-
// synthesized ones. Visit all symbols to give the finishing touches.
for (Symbol *S : Symtab<ELFT>::X->getSymbols()) {
SymbolBody *Body = S->body();
- if (!includeInSymtab<ELFT>(*Body))
+ if (!includeInSymtab(*Body))
continue;
if (In<ELFT>::SymTab)
- In<ELFT>::SymTab->addGlobal(Body);
+ In<ELFT>::SymTab->addSymbol(Body);
if (In<ELFT>::DynSymTab && S->includeInDynsym()) {
- In<ELFT>::DynSymTab->addGlobal(Body);
- if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(Body))
- if (SS->file()->isNeeded())
+ In<ELFT>::DynSymTab->addSymbol(Body);
+ if (auto *SS = dyn_cast<SharedSymbol>(Body))
+ if (cast<SharedFile<ELFT>>(SS->File)->isNeeded())
In<ELFT>::VerNeed->addSymbol(SS);
}
}
@@ -1045,78 +1156,101 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
return;
// So far we have added sections from input object files.
- // This function adds linker-created Out<ELFT>::* sections.
+ // This function adds linker-created Out::* sections.
addPredefinedSections();
- removeUnusedSyntheticSections<ELFT>(OutputSections);
+ removeUnusedSyntheticSections(OutputSections);
sortSections();
+ // This is a bit of a hack. A value of 0 means undef, so we set it
+ // to 1 t make __ehdr_start defined. The section number is not
+ // particularly relevant.
+ Out::ElfHeader->SectionIndex = 1;
+
unsigned I = 1;
- for (OutputSectionBase *Sec : OutputSections) {
+ for (OutputSection *Sec : OutputSections) {
Sec->SectionIndex = I++;
- Sec->ShName = In<ELFT>::ShStrTab->addString(Sec->getName());
+ Sec->ShName = In<ELFT>::ShStrTab->addString(Sec->Name);
}
// Binary and relocatable output does not have PHDRS.
// The headers have to be created before finalize as that can influence the
// image base and the dynamic section on mips includes the image base.
if (!Config->Relocatable && !Config->OFormatBinary) {
- Phdrs = Script<ELFT>::X->hasPhdrsCommands() ? Script<ELFT>::X->createPhdrs()
- : createPhdrs();
+ Phdrs = Script->hasPhdrsCommands() ? Script->createPhdrs() : createPhdrs();
addPtArmExid(Phdrs);
fixHeaders();
}
+ // Dynamic section must be the last one in this list and dynamic
+ // symbol table section (DynSymTab) must be the first one.
+ applySynthetic({In<ELFT>::DynSymTab, In<ELFT>::Bss, In<ELFT>::BssRelRo,
+ In<ELFT>::GnuHashTab, In<ELFT>::HashTab, In<ELFT>::SymTab,
+ In<ELFT>::ShStrTab, In<ELFT>::StrTab, In<ELFT>::VerDef,
+ In<ELFT>::DynStrTab, In<ELFT>::GdbIndex, In<ELFT>::Got,
+ In<ELFT>::MipsGot, In<ELFT>::IgotPlt, In<ELFT>::GotPlt,
+ In<ELFT>::RelaDyn, In<ELFT>::RelaIplt, In<ELFT>::RelaPlt,
+ In<ELFT>::Plt, In<ELFT>::Iplt, In<ELFT>::Plt,
+ In<ELFT>::EhFrameHdr, In<ELFT>::VerSym, In<ELFT>::VerNeed,
+ In<ELFT>::Dynamic},
+ [](SyntheticSection *SS) { SS->finalizeContents(); });
+
+ // Some architectures use small displacements for jump instructions.
+ // It is linker's responsibility to create thunks containing long
+ // jump instructions if jump targets are too far. Create thunks.
+ if (Target->NeedsThunks) {
+ // FIXME: only ARM Interworking and Mips LA25 Thunks are implemented,
+ // these
+ // do not require address information. To support range extension Thunks
+ // we need to assign addresses so that we can tell if jump instructions
+ // are out of range. This will need to turn into a loop that converges
+ // when no more Thunks are added
+ ThunkCreator<ELFT> TC;
+ if (TC.createThunks(OutputSections))
+ applySynthetic({In<ELFT>::MipsGot},
+ [](SyntheticSection *SS) { SS->updateAllocSize(); });
+ }
// 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 *Sec : OutputSections)
- Sec->finalize();
+ for (OutputSection *Sec : OutputSections)
+ Sec->finalize<ELFT>();
- // Dynamic section must be the last one in this list and dynamic
- // symbol table section (DynSymTab) must be the first one.
- finalizeSynthetic<ELFT>(
- {In<ELFT>::DynSymTab, In<ELFT>::GnuHashTab, In<ELFT>::HashTab,
- In<ELFT>::SymTab, In<ELFT>::ShStrTab, In<ELFT>::StrTab,
- In<ELFT>::VerDef, In<ELFT>::DynStrTab, In<ELFT>::GdbIndex,
- In<ELFT>::Got, In<ELFT>::MipsGot, In<ELFT>::IgotPlt,
- In<ELFT>::GotPlt, In<ELFT>::RelaDyn, In<ELFT>::RelaIplt,
- In<ELFT>::RelaPlt, In<ELFT>::Plt, In<ELFT>::Iplt,
- In<ELFT>::Plt, In<ELFT>::EhFrameHdr, In<ELFT>::VerSym,
- In<ELFT>::VerNeed, In<ELFT>::Dynamic});
+ // createThunks may have added local symbols to the static symbol table
+ applySynthetic({In<ELFT>::SymTab, In<ELFT>::ShStrTab, In<ELFT>::StrTab},
+ [](SyntheticSection *SS) { SS->postThunkContents(); });
}
template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
- if (Out<ELFT>::Bss->Size > 0)
- OutputSections.push_back(Out<ELFT>::Bss);
- if (Out<ELFT>::BssRelRo->Size > 0)
- OutputSections.push_back(Out<ELFT>::BssRelRo);
-
- auto OS = dyn_cast_or_null<OutputSection<ELFT>>(findSection(".ARM.exidx"));
+ // ARM ABI requires .ARM.exidx to be terminated by some piece of data.
+ // We have the terminater synthetic section class. Add that at the end.
+ auto *OS = dyn_cast_or_null<OutputSection>(findSection(".ARM.exidx"));
if (OS && !OS->Sections.empty() && !Config->Relocatable)
- OS->addSection(make<ARMExidxSentinelSection<ELFT>>());
-
- addInputSec(In<ELFT>::SymTab);
- addInputSec(In<ELFT>::ShStrTab);
- addInputSec(In<ELFT>::StrTab);
+ OS->addSection(make<ARMExidxSentinelSection>());
}
// 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 *OS) {
+ auto Define = [&](StringRef Start, StringRef End, OutputSection *OS) {
// These symbols resolve to the image base if the section does not exist.
// A special value -1 indicates end of the section.
- addOptionalSynthetic<ELFT>(Start, OS, 0);
- addOptionalSynthetic<ELFT>(End, OS, OS ? -1 : 0);
+ if (OS) {
+ addOptionalRegular<ELFT>(Start, OS, 0);
+ addOptionalRegular<ELFT>(End, OS, -1);
+ } else {
+ if (Config->Pic)
+ OS = Out::ElfHeader;
+ addOptionalRegular<ELFT>(Start, OS, 0);
+ addOptionalRegular<ELFT>(End, OS, 0);
+ }
};
- Define("__preinit_array_start", "__preinit_array_end",
- Out<ELFT>::PreinitArray);
- Define("__init_array_start", "__init_array_end", Out<ELFT>::InitArray);
- Define("__fini_array_start", "__fini_array_end", Out<ELFT>::FiniArray);
+ Define("__preinit_array_start", "__preinit_array_end", Out::PreinitArray);
+ Define("__init_array_start", "__init_array_end", Out::InitArray);
+ Define("__fini_array_start", "__fini_array_end", Out::FiniArray);
- if (OutputSectionBase *Sec = findSection(".ARM.exidx"))
+ if (OutputSection *Sec = findSection(".ARM.exidx"))
Define("__exidx_start", "__exidx_end", Sec);
}
@@ -1126,23 +1260,22 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
// 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 *Sec) {
- StringRef S = Sec->getName();
+void Writer<ELFT>::addStartStopSymbols(OutputSection *Sec) {
+ StringRef S = Sec->Name;
if (!isValidCIdentifier(S))
return;
- addOptionalSynthetic<ELFT>(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT);
- addOptionalSynthetic<ELFT>(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT);
+ addOptionalRegular<ELFT>(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT);
+ addOptionalRegular<ELFT>(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT);
}
-template <class ELFT>
-OutputSectionBase *Writer<ELFT>::findSection(StringRef Name) {
- for (OutputSectionBase *Sec : OutputSections)
- if (Sec->getName() == Name)
+template <class ELFT> OutputSection *Writer<ELFT>::findSection(StringRef Name) {
+ for (OutputSection *Sec : OutputSections)
+ if (Sec->Name == Name)
return Sec;
return nullptr;
}
-template <class ELFT> static bool needsPtLoad(OutputSectionBase *Sec) {
+static bool needsPtLoad(OutputSection *Sec) {
if (!(Sec->Flags & SHF_ALLOC))
return false;
@@ -1158,13 +1291,12 @@ template <class ELFT> static bool needsPtLoad(OutputSectionBase *Sec) {
// linker scripts are designed for creating two PT_LOADs only, one RX and one
// RW. This means that there is no alignment in the RO to RX transition and we
// cannot create a PT_LOAD there.
-template <class ELFT>
-static typename ELFT::uint computeFlags(typename ELFT::uint F) {
- if (Config->OMagic)
+static uint64_t computeFlags(uint64_t Flags) {
+ if (Config->Omagic)
return PF_R | PF_W | PF_X;
- if (Config->SingleRoRx && !(F & PF_W))
- return F | PF_X;
- return F;
+ if (Config->SingleRoRx && !(Flags & PF_W))
+ return Flags | PF_X;
+ return Flags;
}
// Decide which program headers to create and which sections to include in each
@@ -1177,33 +1309,19 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() {
};
// The first phdr entry is PT_PHDR which describes the program header itself.
- PhdrEntry &Hdr = *AddHdr(PT_PHDR, PF_R);
- Hdr.add(Out<ELFT>::ProgramHeaders);
+ AddHdr(PT_PHDR, PF_R)->add(Out::ProgramHeaders);
// PT_INTERP must be the second entry if exists.
- if (OutputSectionBase *Sec = findSection(".interp")) {
- PhdrEntry &Hdr = *AddHdr(PT_INTERP, Sec->getPhdrFlags());
- Hdr.add(Sec);
- }
+ if (OutputSection *Sec = findSection(".interp"))
+ AddHdr(PT_INTERP, Sec->getPhdrFlags())->add(Sec);
// Add the first PT_LOAD segment for regular output sections.
- uintX_t Flags = computeFlags<ELFT>(PF_R);
+ uint64_t Flags = computeFlags(PF_R);
PhdrEntry *Load = AddHdr(PT_LOAD, Flags);
-
- PhdrEntry TlsHdr(PT_TLS, PF_R);
- PhdrEntry RelRo(PT_GNU_RELRO, PF_R);
- PhdrEntry Note(PT_NOTE, PF_R);
- for (OutputSectionBase *Sec : OutputSections) {
+ for (OutputSection *Sec : OutputSections) {
if (!(Sec->Flags & SHF_ALLOC))
break;
-
- // If we meet TLS section then we create TLS header
- // and put all TLS sections inside for further use when
- // assign addresses.
- if (Sec->Flags & SHF_TLS)
- TlsHdr.add(Sec);
-
- if (!needsPtLoad<ELFT>(Sec))
+ if (!needsPtLoad(Sec))
continue;
// Segments are contiguous memory regions that has the same attributes
@@ -1211,58 +1329,58 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() {
// Therefore, we need to create a new phdr when the next section has
// different flags or is loaded at a discontiguous address using AT linker
// script command.
- uintX_t NewFlags = computeFlags<ELFT>(Sec->getPhdrFlags());
- if (Script<ELFT>::X->hasLMA(Sec->getName()) || Flags != NewFlags) {
+ uint64_t NewFlags = computeFlags(Sec->getPhdrFlags());
+ if (Script->hasLMA(Sec->Name) || Flags != NewFlags) {
Load = AddHdr(PT_LOAD, NewFlags);
Flags = NewFlags;
}
Load->add(Sec);
-
- if (isRelroSection<ELFT>(Sec))
- RelRo.add(Sec);
- if (Sec->Type == SHT_NOTE)
- Note.add(Sec);
}
- // Add the TLS segment unless it's empty.
+ // Add a TLS segment if any.
+ PhdrEntry TlsHdr(PT_TLS, PF_R);
+ for (OutputSection *Sec : OutputSections)
+ if (Sec->Flags & SHF_TLS)
+ TlsHdr.add(Sec);
if (TlsHdr.First)
Ret.push_back(std::move(TlsHdr));
// Add an entry for .dynamic.
- if (In<ELFT>::DynSymTab) {
- PhdrEntry &H =
- *AddHdr(PT_DYNAMIC, In<ELFT>::Dynamic->OutSec->getPhdrFlags());
- H.add(In<ELFT>::Dynamic->OutSec);
- }
+ if (In<ELFT>::DynSymTab)
+ AddHdr(PT_DYNAMIC, In<ELFT>::Dynamic->OutSec->getPhdrFlags())
+ ->add(In<ELFT>::Dynamic->OutSec);
// PT_GNU_RELRO includes all sections that should be marked as
// read-only by dynamic linker after proccessing relocations.
+ PhdrEntry RelRo(PT_GNU_RELRO, PF_R);
+ for (OutputSection *Sec : OutputSections)
+ if (needsPtLoad(Sec) && isRelroSection<ELFT>(Sec))
+ RelRo.add(Sec);
if (RelRo.First)
Ret.push_back(std::move(RelRo));
// PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr.
- if (!Out<ELFT>::EhFrame->empty() && In<ELFT>::EhFrameHdr) {
- PhdrEntry &Hdr =
- *AddHdr(PT_GNU_EH_FRAME, In<ELFT>::EhFrameHdr->OutSec->getPhdrFlags());
- Hdr.add(In<ELFT>::EhFrameHdr->OutSec);
- }
+ if (!In<ELFT>::EhFrame->empty() && In<ELFT>::EhFrameHdr &&
+ In<ELFT>::EhFrame->OutSec && In<ELFT>::EhFrameHdr->OutSec)
+ AddHdr(PT_GNU_EH_FRAME, In<ELFT>::EhFrameHdr->OutSec->getPhdrFlags())
+ ->add(In<ELFT>::EhFrameHdr->OutSec);
- // 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 *Sec = findSection(".openbsd.randomdata")) {
- PhdrEntry &Hdr = *AddHdr(PT_OPENBSD_RANDOMIZE, Sec->getPhdrFlags());
- Hdr.add(Sec);
- }
+ // PT_OPENBSD_RANDOMIZE is an OpenBSD-specific feature. That makes
+ // the dynamic linker fill the segment with random data.
+ if (OutputSection *Sec = findSection(".openbsd.randomdata"))
+ AddHdr(PT_OPENBSD_RANDOMIZE, Sec->getPhdrFlags())->add(Sec);
// PT_GNU_STACK is a special section to tell the loader to make the
- // pages for the stack non-executable.
- if (!Config->ZExecstack) {
- PhdrEntry &Hdr = *AddHdr(PT_GNU_STACK, PF_R | PF_W);
- if (Config->ZStackSize != uint64_t(-1))
- Hdr.p_memsz = Config->ZStackSize;
- }
+ // pages for the stack non-executable. If you really want an executable
+ // stack, you can pass -z execstack, but that's not recommended for
+ // security reasons.
+ unsigned Perm;
+ if (Config->ZExecstack)
+ Perm = PF_R | PF_W | PF_X;
+ else
+ Perm = PF_R | PF_W;
+ AddHdr(PT_GNU_STACK, Perm)->p_memsz = Config->ZStackSize;
// PT_OPENBSD_WXNEEDED is a OpenBSD-specific header to mark the executable
// is expected to perform W^X violations, such as calling mprotect(2) or
@@ -1271,8 +1389,17 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() {
if (Config->ZWxneeded)
AddHdr(PT_OPENBSD_WXNEEDED, PF_X);
- if (Note.First)
- Ret.push_back(std::move(Note));
+ // Create one PT_NOTE per a group of contiguous .note sections.
+ PhdrEntry *Note = nullptr;
+ for (OutputSection *Sec : OutputSections) {
+ if (Sec->Type == SHT_NOTE) {
+ if (!Note || Script->hasLMA(Sec->Name))
+ Note = AddHdr(PT_NOTE, PF_R);
+ Note->add(Sec);
+ } else {
+ Note = nullptr;
+ }
+ }
return Ret;
}
@@ -1282,7 +1409,7 @@ void Writer<ELFT>::addPtArmExid(std::vector<PhdrEntry> &Phdrs) {
return;
auto I = std::find_if(
OutputSections.begin(), OutputSections.end(),
- [](OutputSectionBase *Sec) { return Sec->Type == SHT_ARM_EXIDX; });
+ [](OutputSection *Sec) { return Sec->Type == SHT_ARM_EXIDX; });
if (I == OutputSections.end())
return;
@@ -1311,83 +1438,94 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
auto I = std::find(OutputSections.begin(), End, P.Last);
if (I == End || (I + 1) == End)
continue;
- OutputSectionBase *Sec = *(I + 1);
- if (needsPtLoad<ELFT>(Sec))
+ OutputSection *Sec = *(I + 1);
+ if (needsPtLoad(Sec))
Sec->PageAlign = true;
}
}
-template <class ELFT>
-void elf::allocateHeaders(MutableArrayRef<PhdrEntry> Phdrs,
- ArrayRef<OutputSectionBase *> OutputSections) {
+bool elf::allocateHeaders(std::vector<PhdrEntry> &Phdrs,
+ ArrayRef<OutputSection *> OutputSections,
+ uint64_t Min) {
auto FirstPTLoad =
std::find_if(Phdrs.begin(), Phdrs.end(),
[](const PhdrEntry &E) { return E.p_type == PT_LOAD; });
if (FirstPTLoad == Phdrs.end())
- return;
+ return false;
+
+ uint64_t HeaderSize = getHeaderSize();
+ if (HeaderSize > Min) {
+ auto PhdrI =
+ std::find_if(Phdrs.begin(), Phdrs.end(),
+ [](const PhdrEntry &E) { return E.p_type == PT_PHDR; });
+ if (PhdrI != Phdrs.end())
+ Phdrs.erase(PhdrI);
+ return false;
+ }
+ Min = alignDown(Min - HeaderSize, Config->MaxPageSize);
+
+ if (!Script->Opt.HasSections)
+ Config->ImageBase = Min = std::min(Min, Config->ImageBase);
+
+ Out::ElfHeader->Addr = Min;
+ Out::ProgramHeaders->Addr = Min + Out::ElfHeader->Size;
+
+ if (Script->hasPhdrsCommands())
+ return true;
+
if (FirstPTLoad->First)
- for (OutputSectionBase *Sec : OutputSections)
+ for (OutputSection *Sec : OutputSections)
if (Sec->FirstInPtLoad == FirstPTLoad->First)
- Sec->FirstInPtLoad = Out<ELFT>::ElfHeader;
- FirstPTLoad->First = Out<ELFT>::ElfHeader;
+ Sec->FirstInPtLoad = Out::ElfHeader;
+ FirstPTLoad->First = Out::ElfHeader;
if (!FirstPTLoad->Last)
- FirstPTLoad->Last = Out<ELFT>::ProgramHeaders;
+ FirstPTLoad->Last = Out::ProgramHeaders;
+ return true;
}
// We should set file offsets and VAs for elf header and program headers
// sections. These are special, we do not include them into output sections
// list, but have them to simplify the code.
template <class ELFT> void Writer<ELFT>::fixHeaders() {
- Out<ELFT>::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size();
+ Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size();
// If the script has SECTIONS, assignAddresses will compute the values.
- if (ScriptConfig->HasSections)
+ if (Script->Opt.HasSections)
return;
- uintX_t HeaderSize = getHeaderSize<ELFT>();
// When -T<section> option is specified, lower the base to make room for those
// sections.
- if (!Config->SectionStartMap.empty()) {
- uint64_t Min = -1;
+ uint64_t Min = -1;
+ if (!Config->SectionStartMap.empty())
for (const auto &P : Config->SectionStartMap)
Min = std::min(Min, P.second);
- if (HeaderSize < Min)
- Min -= HeaderSize;
- else
- AllocateHeader = false;
- if (Min < Config->ImageBase)
- Config->ImageBase = alignDown(Min, Config->MaxPageSize);
- }
-
- if (AllocateHeader)
- allocateHeaders<ELFT>(Phdrs, OutputSections);
- uintX_t BaseVA = Config->ImageBase;
- Out<ELFT>::ElfHeader->Addr = BaseVA;
- Out<ELFT>::ProgramHeaders->Addr = BaseVA + Out<ELFT>::ElfHeader->Size;
+ AllocateHeader = allocateHeaders(Phdrs, OutputSections, Min);
}
// Assign VAs (addresses at run-time) to output sections.
template <class ELFT> void Writer<ELFT>::assignAddresses() {
- uintX_t VA = Config->ImageBase;
+ uint64_t VA = Config->ImageBase;
+ uint64_t ThreadBssOffset = 0;
+
if (AllocateHeader)
- VA += getHeaderSize<ELFT>();
- uintX_t ThreadBssOffset = 0;
- for (OutputSectionBase *Sec : OutputSections) {
- uintX_t Alignment = Sec->Addralign;
+ VA += getHeaderSize();
+
+ for (OutputSection *Sec : OutputSections) {
+ uint32_t Alignment = Sec->Alignment;
if (Sec->PageAlign)
- Alignment = std::max<uintX_t>(Alignment, Config->MaxPageSize);
+ Alignment = std::max<uint32_t>(Alignment, Config->MaxPageSize);
- auto I = Config->SectionStartMap.find(Sec->getName());
+ auto I = Config->SectionStartMap.find(Sec->Name);
if (I != Config->SectionStartMap.end())
VA = I->second;
// We only assign VAs to allocated sections.
- if (needsPtLoad<ELFT>(Sec)) {
+ if (needsPtLoad(Sec)) {
VA = alignTo(VA, Alignment);
Sec->Addr = VA;
VA += Sec->Size;
} else if (Sec->Flags & SHF_TLS && Sec->Type == SHT_NOBITS) {
- uintX_t TVA = VA + ThreadBssOffset;
+ uint64_t TVA = VA + ThreadBssOffset;
TVA = alignTo(TVA, Alignment);
Sec->Addr = TVA;
ThreadBssOffset = TVA - VA + Sec->Size;
@@ -1399,12 +1537,11 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
// its new file offset. The file offset must be the same with its
// 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 *Sec) {
- OutputSectionBase *First = Sec->FirstInPtLoad;
+static uint64_t getFileAlignment(uint64_t Off, OutputSection *Sec) {
+ OutputSection *First = Sec->FirstInPtLoad;
// If the section is not in a PT_LOAD, we just have to align it.
if (!First)
- return alignTo(Off, Sec->Addralign);
+ return alignTo(Off, Sec->Alignment);
// The first section in a PT_LOAD has to have congruent offset and address
// module the page size.
@@ -1416,36 +1553,35 @@ static uintX_t getFileAlignment(uintX_t Off, OutputSectionBase *Sec) {
return First->Offset + Sec->Addr - First->Addr;
}
-template <class ELFT, class uintX_t>
-void setOffset(OutputSectionBase *Sec, uintX_t &Off) {
+static uint64_t setOffset(OutputSection *Sec, uint64_t Off) {
if (Sec->Type == SHT_NOBITS) {
Sec->Offset = Off;
- return;
+ return Off;
}
- Off = getFileAlignment<ELFT>(Off, Sec);
+ Off = getFileAlignment(Off, Sec);
Sec->Offset = Off;
- Off += Sec->Size;
+ return Off + Sec->Size;
}
template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() {
- uintX_t Off = 0;
- for (OutputSectionBase *Sec : OutputSections)
+ uint64_t Off = 0;
+ for (OutputSection *Sec : OutputSections)
if (Sec->Flags & SHF_ALLOC)
- setOffset<ELFT>(Sec, Off);
- FileSize = alignTo(Off, sizeof(uintX_t));
+ Off = setOffset(Sec, Off);
+ FileSize = alignTo(Off, Config->Wordsize);
}
// Assign file offsets to output sections.
template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
- uintX_t Off = 0;
- setOffset<ELFT>(Out<ELFT>::ElfHeader, Off);
- setOffset<ELFT>(Out<ELFT>::ProgramHeaders, Off);
+ uint64_t Off = 0;
+ Off = setOffset(Out::ElfHeader, Off);
+ Off = setOffset(Out::ProgramHeaders, Off);
- for (OutputSectionBase *Sec : OutputSections)
- setOffset<ELFT>(Sec, Off);
+ for (OutputSection *Sec : OutputSections)
+ Off = setOffset(Sec, Off);
- SectionHeaderOff = alignTo(Off, sizeof(uintX_t));
+ SectionHeaderOff = alignTo(Off, Config->Wordsize);
FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr);
}
@@ -1453,8 +1589,8 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
// file offsets and VAs to all sections.
template <class ELFT> void Writer<ELFT>::setPhdrs() {
for (PhdrEntry &P : Phdrs) {
- OutputSectionBase *First = P.First;
- OutputSectionBase *Last = P.Last;
+ OutputSection *First = P.First;
+ OutputSection *Last = P.Last;
if (First) {
P.p_filesz = Last->Offset - First->Offset;
if (Last->Type != SHT_NOBITS)
@@ -1478,7 +1614,7 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() {
// The TLS pointer goes after PT_TLS. At least glibc will align it,
// so round up the size to make sure the offsets are correct.
if (P.p_type == PT_TLS) {
- Out<ELFT>::TlsPhdr = &P;
+ Out::TlsPhdr = &P;
if (P.p_memsz)
P.p_memsz = alignTo(P.p_memsz, P.p_align);
}
@@ -1492,17 +1628,17 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() {
// 3. the value of the symbol start, if present;
// 4. the address of the first byte of the .text section, if present;
// 5. the address 0.
-template <class ELFT> typename ELFT::uint Writer<ELFT>::getEntryAddr() {
+template <class ELFT> uint64_t Writer<ELFT>::getEntryAddr() {
// Case 1, 2 or 3. As a special case, if the symbol is actually
// a number, we'll use that number as an address.
if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Entry))
- return B->getVA<ELFT>();
+ return B->getVA();
uint64_t Addr;
if (!Config->Entry.getAsInteger(0, Addr))
return Addr;
// Case 4
- if (OutputSectionBase *Sec = findSection(".text")) {
+ if (OutputSection *Sec = findSection(".text")) {
if (Config->WarnMissingEntry)
warn("cannot find entry symbol " + Config->Entry + "; defaulting to 0x" +
utohexstr(Sec->Addr));
@@ -1516,12 +1652,6 @@ template <class ELFT> typename ELFT::uint Writer<ELFT>::getEntryAddr() {
return 0;
}
-template <class ELFT> static uint8_t getELFEncoding() {
- if (ELFT::TargetEndianness == llvm::support::little)
- return ELFDATA2LSB;
- return ELFDATA2MSB;
-}
-
static uint16_t getELFType() {
if (Config->Pic)
return ET_DYN;
@@ -1531,52 +1661,59 @@ static uint16_t getELFType() {
}
// This function is called after we have assigned address and size
-// to each section. This function fixes some predefined absolute
+// to each section. This function fixes some predefined
// symbol values that depend on section address and size.
-template <class ELFT> void Writer<ELFT>::fixAbsoluteSymbols() {
- // __ehdr_start is the location of program headers.
- if (ElfSym<ELFT>::EhdrStart)
- ElfSym<ELFT>::EhdrStart->Value = Out<ELFT>::ProgramHeaders->Addr;
-
- auto Set = [](DefinedRegular<ELFT> *S1, DefinedRegular<ELFT> *S2, uintX_t V) {
- if (S1)
- S1->Value = V;
- if (S2)
- S2->Value = V;
+template <class ELFT> void Writer<ELFT>::fixPredefinedSymbols() {
+ auto Set = [](DefinedRegular *S1, DefinedRegular *S2, OutputSection *Sec,
+ uint64_t Value) {
+ if (S1) {
+ S1->Section = Sec;
+ S1->Value = Value;
+ }
+ if (S2) {
+ S2->Section = Sec;
+ S2->Value = Value;
+ }
};
// _etext is the first location after the last read-only loadable segment.
// _edata is the first location after the last read-write loadable segment.
// _end is the first location after the uninitialized data region.
+ PhdrEntry *Last = nullptr;
+ PhdrEntry *LastRO = nullptr;
+ PhdrEntry *LastRW = nullptr;
for (PhdrEntry &P : Phdrs) {
if (P.p_type != PT_LOAD)
continue;
- Set(ElfSym<ELFT>::End, ElfSym<ELFT>::End2, P.p_vaddr + P.p_memsz);
-
- uintX_t Val = P.p_vaddr + P.p_filesz;
+ Last = &P;
if (P.p_flags & PF_W)
- Set(ElfSym<ELFT>::Edata, ElfSym<ELFT>::Edata2, Val);
+ LastRW = &P;
else
- Set(ElfSym<ELFT>::Etext, ElfSym<ELFT>::Etext2, Val);
+ LastRO = &P;
}
+ if (Last)
+ Set(ElfSym::End1, ElfSym::End2, Last->First, Last->p_memsz);
+ if (LastRO)
+ Set(ElfSym::Etext1, ElfSym::Etext2, LastRO->First, LastRO->p_filesz);
+ if (LastRW)
+ Set(ElfSym::Edata1, ElfSym::Edata2, LastRW->First, LastRW->p_filesz);
+
+ if (ElfSym::Bss)
+ ElfSym::Bss->Section = findSection(".bss");
// Setup MIPS _gp_disp/__gnu_local_gp symbols which should
// be equal to the _gp symbol's value.
if (Config->EMachine == EM_MIPS) {
- if (!ElfSym<ELFT>::MipsGp->Value) {
+ if (!ElfSym::MipsGp->Value) {
// Find GP-relative section with the lowest address
// and use this address to calculate default _gp value.
- uintX_t Gp = -1;
- for (const OutputSectionBase * OS : OutputSections)
+ uint64_t Gp = -1;
+ for (const OutputSection *OS : OutputSections)
if ((OS->Flags & SHF_MIPS_GPREL) && OS->Addr < Gp)
Gp = OS->Addr;
- if (Gp != (uintX_t)-1)
- ElfSym<ELFT>::MipsGp->Value = Gp + 0x7ff0;
+ if (Gp != (uint64_t)-1)
+ ElfSym::MipsGp->Value = Gp + 0x7ff0;
}
- if (ElfSym<ELFT>::MipsGpDisp)
- ElfSym<ELFT>::MipsGpDisp->Value = ElfSym<ELFT>::MipsGp->Value;
- if (ElfSym<ELFT>::MipsLocalGp)
- ElfSym<ELFT>::MipsLocalGp->Value = ElfSym<ELFT>::MipsGp->Value;
}
}
@@ -1586,8 +1723,8 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
// Write the ELF header.
auto *EHdr = reinterpret_cast<Elf_Ehdr *>(Buf);
- EHdr->e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
- EHdr->e_ident[EI_DATA] = getELFEncoding<ELFT>();
+ EHdr->e_ident[EI_CLASS] = Config->Is64 ? ELFCLASS64 : ELFCLASS32;
+ EHdr->e_ident[EI_DATA] = Config->IsLE ? ELFDATA2LSB : ELFDATA2MSB;
EHdr->e_ident[EI_VERSION] = EV_CURRENT;
EHdr->e_ident[EI_OSABI] = Config->OSABI;
EHdr->e_type = getELFType();
@@ -1630,63 +1767,33 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
// 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 *Sec : OutputSections)
+ for (OutputSection *Sec : OutputSections)
Sec->writeHeaderTo<ELFT>(++SHdrs);
}
-// Removes a given file asynchronously. This is a performance hack,
-// so remove this when operating systems are improved.
-//
-// On Linux (and probably on other Unix-like systems), unlink(2) is a
-// noticeably slow system call. As of 2016, unlink takes 250
-// milliseconds to remove a 1 GB file on ext4 filesystem on my machine.
-//
-// To create a new result file, we first remove existing file. So, if
-// you repeatedly link a 1 GB program in a regular compile-link-debug
-// cycle, every cycle wastes 250 milliseconds only to remove a file.
-// Since LLD can link a 1 GB binary in about 5 seconds, that waste
-// actually counts.
-//
-// This function spawns a background thread to call unlink.
-// The calling thread returns almost immediately.
-static void unlinkAsync(StringRef Path) {
- if (!Config->Threads || !sys::fs::exists(Config->OutputFile))
- return;
-
- // First, rename Path to avoid race condition. We cannot remove
- // Path from a different thread because we are now going to create
- // Path as a new file. If we do that in a different thread, the new
- // thread can remove the new file.
- SmallString<128> TempPath;
- if (sys::fs::createUniqueFile(Path + "tmp%%%%%%%%", TempPath))
- return;
- if (sys::fs::rename(Path, TempPath)) {
- sys::fs::remove(TempPath);
+// Open a result file.
+template <class ELFT> void Writer<ELFT>::openFile() {
+ if (!Config->Is64 && FileSize > UINT32_MAX) {
+ error("output file too large: " + Twine(FileSize) + " bytes");
return;
}
- // Remove TempPath in background.
- std::thread([=] { ::remove(TempPath.str().str().c_str()); }).detach();
-}
-
-// Open a result file.
-template <class ELFT> void Writer<ELFT>::openFile() {
unlinkAsync(Config->OutputFile);
ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
FileOutputBuffer::create(Config->OutputFile, FileSize,
FileOutputBuffer::F_executable);
if (auto EC = BufferOrErr.getError())
- error(EC, "failed to open " + Config->OutputFile);
+ error("failed to open " + Config->OutputFile + ": " + EC.message());
else
Buffer = std::move(*BufferOrErr);
}
template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
uint8_t *Buf = Buffer->getBufferStart();
- for (OutputSectionBase *Sec : OutputSections)
+ for (OutputSection *Sec : OutputSections)
if (Sec->Flags & SHF_ALLOC)
- Sec->writeTo(Buf + Sec->Offset);
+ Sec->writeTo<ELFT>(Buf + Sec->Offset);
}
// Write section contents to a mmap'ed file.
@@ -1695,22 +1802,31 @@ template <class ELFT> void Writer<ELFT>::writeSections() {
// PPC64 needs to process relocations in the .opd section
// before processing relocations in code-containing sections.
- Out<ELFT>::Opd = findSection(".opd");
- if (Out<ELFT>::Opd) {
- Out<ELFT>::OpdBuf = Buf + Out<ELFT>::Opd->Offset;
- Out<ELFT>::Opd->writeTo(Buf + Out<ELFT>::Opd->Offset);
+ Out::Opd = findSection(".opd");
+ if (Out::Opd) {
+ Out::OpdBuf = Buf + Out::Opd->Offset;
+ Out::Opd->template writeTo<ELFT>(Buf + Out::Opd->Offset);
}
- OutputSectionBase *EhFrameHdr =
+ OutputSection *EhFrameHdr =
In<ELFT>::EhFrameHdr ? In<ELFT>::EhFrameHdr->OutSec : nullptr;
- for (OutputSectionBase *Sec : OutputSections)
- if (Sec != Out<ELFT>::Opd && Sec != EhFrameHdr)
- Sec->writeTo(Buf + Sec->Offset);
+
+ // In -r or -emit-relocs mode, write the relocation sections first as in
+ // ELf_Rel targets we might find out that we need to modify the relocated
+ // section while doing it.
+ for (OutputSection *Sec : OutputSections)
+ if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA)
+ Sec->writeTo<ELFT>(Buf + Sec->Offset);
+
+ for (OutputSection *Sec : OutputSections)
+ if (Sec != Out::Opd && Sec != EhFrameHdr && Sec->Type != SHT_REL &&
+ Sec->Type != SHT_RELA)
+ Sec->writeTo<ELFT>(Buf + Sec->Offset);
// The .eh_frame_hdr depends on .eh_frame section contents, therefore
// it should be written after .eh_frame is written.
- if (!Out<ELFT>::EhFrame->empty() && EhFrameHdr)
- EhFrameHdr->writeTo(Buf + EhFrameHdr->Offset);
+ if (EhFrameHdr && !EhFrameHdr->Sections.empty())
+ EhFrameHdr->writeTo<ELFT>(Buf + EhFrameHdr->Offset);
}
template <class ELFT> void Writer<ELFT>::writeBuildId() {
@@ -1728,21 +1844,7 @@ template void elf::writeResult<ELF32BE>();
template void elf::writeResult<ELF64LE>();
template void elf::writeResult<ELF64BE>();
-template void elf::allocateHeaders<ELF32LE>(MutableArrayRef<PhdrEntry>,
- ArrayRef<OutputSectionBase *>);
-template void elf::allocateHeaders<ELF32BE>(MutableArrayRef<PhdrEntry>,
- ArrayRef<OutputSectionBase *>);
-template void elf::allocateHeaders<ELF64LE>(MutableArrayRef<PhdrEntry>,
- ArrayRef<OutputSectionBase *>);
-template void elf::allocateHeaders<ELF64BE>(MutableArrayRef<PhdrEntry>,
- ArrayRef<OutputSectionBase *>);
-
-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> *);
-template void elf::reportDiscarded<ELF64LE>(InputSectionBase<ELF64LE> *);
-template void elf::reportDiscarded<ELF64BE>(InputSectionBase<ELF64BE> *);
+template bool elf::isRelroSection<ELF32LE>(const OutputSection *);
+template bool elf::isRelroSection<ELF32BE>(const OutputSection *);
+template bool elf::isRelroSection<ELF64LE>(const OutputSection *);
+template bool elf::isRelroSection<ELF64BE>(const OutputSection *);