summaryrefslogtreecommitdiff
path: root/ELF/Writer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ELF/Writer.cpp')
-rw-r--r--ELF/Writer.cpp697
1 files changed, 410 insertions, 287 deletions
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index 73a97380b54b1..17f4c7961d30e 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -53,8 +53,10 @@ private:
void forEachRelSec(llvm::function_ref<void(InputSectionBase &)> Fn);
void sortSections();
void resolveShfLinkOrder();
+ void maybeAddThunks();
void sortInputSections();
void finalizeSections();
+ void checkExecuteOnly();
void setReservedSymbolSections();
std::vector<PhdrEntry *> createPhdrs();
@@ -77,7 +79,6 @@ private:
void addRelIpltSymbols();
void addStartEndSymbols();
void addStartStopSymbols(OutputSection *Sec);
- uint64_t getEntryAddr();
std::vector<PhdrEntry *> Phdrs;
@@ -114,18 +115,16 @@ StringRef elf::getOutputSectionName(const InputSectionBase *S) {
// for instance.
if (Config->ZKeepTextSectionPrefix)
for (StringRef V :
- {".text.hot.", ".text.unlikely.", ".text.startup.", ".text.exit."}) {
+ {".text.hot.", ".text.unlikely.", ".text.startup.", ".text.exit."})
if (isSectionPrefix(V, S->Name))
return V.drop_back();
- }
for (StringRef V :
{".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.",
".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.",
- ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab."}) {
+ ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab."})
if (isSectionPrefix(V, S->Name))
return V.drop_back();
- }
// CommonSection is identified as "COMMON" in linker scripts.
// By default, it should go to .bss section.
@@ -159,7 +158,7 @@ template <class ELFT> static void combineEhFrameSections() {
if (!ES || !ES->Live)
continue;
- InX::EhFrame->addSection<ELFT>(ES);
+ In.EhFrame->addSection<ELFT>(ES);
S = nullptr;
}
@@ -173,10 +172,14 @@ static Defined *addOptionalRegular(StringRef Name, SectionBase *Sec,
Symbol *S = Symtab->find(Name);
if (!S || S->isDefined())
return nullptr;
- Symbol *Sym = Symtab->addRegular(Name, StOther, STT_NOTYPE, Val,
- /*Size=*/0, Binding, Sec,
- /*File=*/nullptr);
- return cast<Defined>(Sym);
+ return Symtab->addDefined(Name, StOther, STT_NOTYPE, Val,
+ /*Size=*/0, Binding, Sec,
+ /*File=*/nullptr);
+}
+
+static Defined *addAbsolute(StringRef Name) {
+ return Symtab->addDefined(Name, STV_HIDDEN, STT_NOTYPE, 0, 0, STB_GLOBAL,
+ nullptr, nullptr);
}
// The linker is expected to define some symbols depending on
@@ -188,21 +191,19 @@ void elf::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::MipsGp = Symtab->addAbsolute("_gp", STV_HIDDEN, STB_GLOBAL);
+ ElfSym::MipsGp = addAbsolute("_gp");
// On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
// start of function and 'gp' pointer into GOT.
if (Symtab->find("_gp_disp"))
- ElfSym::MipsGpDisp =
- Symtab->addAbsolute("_gp_disp", STV_HIDDEN, STB_GLOBAL);
+ ElfSym::MipsGpDisp = addAbsolute("_gp_disp");
// The __gnu_local_gp is a magic symbol equal to the current value of 'gp'
// 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
if (Symtab->find("__gnu_local_gp"))
- ElfSym::MipsLocalGp =
- Symtab->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_GLOBAL);
+ ElfSym::MipsLocalGp = addAbsolute("__gnu_local_gp");
}
// The Power Architecture 64-bit v2 ABI defines a TableOfContents (TOC) which
@@ -211,9 +212,20 @@ void elf::addReservedSymbols() {
// _GLOBAL_OFFSET_TABLE_ and _SDA_BASE_ from the 32-bit ABI. It is used to
// represent the TOC base which is offset by 0x8000 bytes from the start of
// the .got section.
- ElfSym::GlobalOffsetTable = addOptionalRegular(
- (Config->EMachine == EM_PPC64) ? ".TOC." : "_GLOBAL_OFFSET_TABLE_",
- Out::ElfHeader, Target->GotBaseSymOff);
+ // We do not allow _GLOBAL_OFFSET_TABLE_ to be defined by input objects as the
+ // correctness of some relocations depends on its value.
+ StringRef GotTableSymName =
+ (Config->EMachine == EM_PPC64) ? ".TOC." : "_GLOBAL_OFFSET_TABLE_";
+ if (Symbol *S = Symtab->find(GotTableSymName)) {
+ if (S->isDefined())
+ error(toString(S->File) + " cannot redefine linker defined symbol '" +
+ GotTableSymName + "'");
+ else
+ ElfSym::GlobalOffsetTable = Symtab->addDefined(
+ GotTableSymName, STV_HIDDEN, STT_NOTYPE, Target->GotBaseSymOff,
+ /*Size=*/0, STB_GLOBAL, Out::ElfHeader,
+ /*File=*/nullptr);
+ }
// __ehdr_start is the location of ELF file headers. Note that we define
// this symbol unconditionally even when using a linker script, which
@@ -263,54 +275,52 @@ template <class ELFT> static void createSyntheticSections() {
auto Add = [](InputSectionBase *Sec) { InputSections.push_back(Sec); };
- InX::DynStrTab = make<StringTableSection>(".dynstr", true);
- InX::Dynamic = make<DynamicSection<ELFT>>();
+ In.DynStrTab = make<StringTableSection>(".dynstr", true);
+ In.Dynamic = make<DynamicSection<ELFT>>();
if (Config->AndroidPackDynRelocs) {
- InX::RelaDyn = make<AndroidPackedRelocationSection<ELFT>>(
+ In.RelaDyn = make<AndroidPackedRelocationSection<ELFT>>(
Config->IsRela ? ".rela.dyn" : ".rel.dyn");
} else {
- InX::RelaDyn = make<RelocationSection<ELFT>>(
+ In.RelaDyn = make<RelocationSection<ELFT>>(
Config->IsRela ? ".rela.dyn" : ".rel.dyn", Config->ZCombreloc);
}
- InX::ShStrTab = make<StringTableSection>(".shstrtab", false);
+ In.ShStrTab = make<StringTableSection>(".shstrtab", false);
Out::ProgramHeaders = make<OutputSection>("", 0, SHF_ALLOC);
Out::ProgramHeaders->Alignment = Config->Wordsize;
if (needsInterpSection()) {
- InX::Interp = createInterpSection();
- Add(InX::Interp);
- } else {
- InX::Interp = nullptr;
+ In.Interp = createInterpSection();
+ Add(In.Interp);
}
if (Config->Strip != StripPolicy::All) {
- InX::StrTab = make<StringTableSection>(".strtab", false);
- InX::SymTab = make<SymbolTableSection<ELFT>>(*InX::StrTab);
- InX::SymTabShndx = make<SymtabShndxSection>();
+ In.StrTab = make<StringTableSection>(".strtab", false);
+ In.SymTab = make<SymbolTableSection<ELFT>>(*In.StrTab);
+ In.SymTabShndx = make<SymtabShndxSection>();
}
if (Config->BuildId != BuildIdKind::None) {
- InX::BuildId = make<BuildIdSection>();
- Add(InX::BuildId);
+ In.BuildId = make<BuildIdSection>();
+ Add(In.BuildId);
}
- InX::Bss = make<BssSection>(".bss", 0, 1);
- Add(InX::Bss);
+ In.Bss = make<BssSection>(".bss", 0, 1);
+ Add(In.Bss);
// If there is a SECTIONS command and a .data.rel.ro section name use name
// .data.rel.ro.bss so that we match in the .data.rel.ro output section.
// This makes sure our relro is contiguous.
bool HasDataRelRo = Script->HasSectionsCommand && findSection(".data.rel.ro");
- InX::BssRelRo =
+ In.BssRelRo =
make<BssSection>(HasDataRelRo ? ".data.rel.ro.bss" : ".bss.rel.ro", 0, 1);
- Add(InX::BssRelRo);
+ Add(In.BssRelRo);
// Add MIPS-specific sections.
if (Config->EMachine == EM_MIPS) {
if (!Config->Shared && Config->HasDynSymTab) {
- InX::MipsRldMap = make<MipsRldMapSection>();
- Add(InX::MipsRldMap);
+ In.MipsRldMap = make<MipsRldMapSection>();
+ Add(In.MipsRldMap);
}
if (auto *Sec = MipsAbiFlagsSection<ELFT>::create())
Add(Sec);
@@ -321,65 +331,70 @@ template <class ELFT> static void createSyntheticSections() {
}
if (Config->HasDynSymTab) {
- InX::DynSymTab = make<SymbolTableSection<ELFT>>(*InX::DynStrTab);
- Add(InX::DynSymTab);
+ In.DynSymTab = make<SymbolTableSection<ELFT>>(*In.DynStrTab);
+ Add(In.DynSymTab);
- In<ELFT>::VerSym = make<VersionTableSection<ELFT>>();
- Add(In<ELFT>::VerSym);
+ InX<ELFT>::VerSym = make<VersionTableSection<ELFT>>();
+ Add(InX<ELFT>::VerSym);
if (!Config->VersionDefinitions.empty()) {
- In<ELFT>::VerDef = make<VersionDefinitionSection<ELFT>>();
- Add(In<ELFT>::VerDef);
+ In.VerDef = make<VersionDefinitionSection>();
+ Add(In.VerDef);
}
- In<ELFT>::VerNeed = make<VersionNeedSection<ELFT>>();
- Add(In<ELFT>::VerNeed);
+ InX<ELFT>::VerNeed = make<VersionNeedSection<ELFT>>();
+ Add(InX<ELFT>::VerNeed);
if (Config->GnuHash) {
- InX::GnuHashTab = make<GnuHashTableSection>();
- Add(InX::GnuHashTab);
+ In.GnuHashTab = make<GnuHashTableSection>();
+ Add(In.GnuHashTab);
}
if (Config->SysvHash) {
- InX::HashTab = make<HashTableSection>();
- Add(InX::HashTab);
+ In.HashTab = make<HashTableSection>();
+ Add(In.HashTab);
}
- Add(InX::Dynamic);
- Add(InX::DynStrTab);
- Add(InX::RelaDyn);
+ Add(In.Dynamic);
+ Add(In.DynStrTab);
+ Add(In.RelaDyn);
}
if (Config->RelrPackDynRelocs) {
- InX::RelrDyn = make<RelrSection<ELFT>>();
- Add(InX::RelrDyn);
+ In.RelrDyn = make<RelrSection<ELFT>>();
+ Add(In.RelrDyn);
}
// Add .got. MIPS' .got is so different from the other archs,
// it has its own class.
if (Config->EMachine == EM_MIPS) {
- InX::MipsGot = make<MipsGotSection>();
- Add(InX::MipsGot);
+ In.MipsGot = make<MipsGotSection>();
+ Add(In.MipsGot);
} else {
- InX::Got = make<GotSection>();
- Add(InX::Got);
+ In.Got = make<GotSection>();
+ Add(In.Got);
}
- InX::GotPlt = make<GotPltSection>();
- Add(InX::GotPlt);
- InX::IgotPlt = make<IgotPltSection>();
- Add(InX::IgotPlt);
+ if (Config->EMachine == EM_PPC64) {
+ In.PPC64LongBranchTarget = make<PPC64LongBranchTargetSection>();
+ Add(In.PPC64LongBranchTarget);
+ }
+
+ In.GotPlt = make<GotPltSection>();
+ Add(In.GotPlt);
+ In.IgotPlt = make<IgotPltSection>();
+ Add(In.IgotPlt);
if (Config->GdbIndex) {
- InX::GdbIndex = GdbIndexSection::create<ELFT>();
- Add(InX::GdbIndex);
+ In.GdbIndex = GdbIndexSection::create<ELFT>();
+ Add(In.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.
- InX::RelaPlt = make<RelocationSection<ELFT>>(
+ In.RelaPlt = make<RelocationSection<ELFT>>(
Config->IsRela ? ".rela.plt" : ".rel.plt", false /*Sort*/);
- Add(InX::RelaPlt);
+ Add(In.RelaPlt);
// The RelaIplt immediately follows .rel.plt (.rel.dyn for ARM) to ensure
// that the IRelative relocations are processed last by the dynamic loader.
@@ -387,34 +402,42 @@ template <class ELFT> static void createSyntheticSections() {
// packing is enabled because that would cause a section type mismatch.
// However, because the Android dynamic loader reads .rel.plt after .rel.dyn,
// we can get the desired behaviour by placing the iplt section in .rel.plt.
- InX::RelaIplt = make<RelocationSection<ELFT>>(
+ In.RelaIplt = make<RelocationSection<ELFT>>(
(Config->EMachine == EM_ARM && !Config->AndroidPackDynRelocs)
? ".rel.dyn"
- : InX::RelaPlt->Name,
+ : In.RelaPlt->Name,
false /*Sort*/);
- Add(InX::RelaIplt);
-
- InX::Plt = make<PltSection>(false);
- Add(InX::Plt);
- InX::Iplt = make<PltSection>(true);
- Add(InX::Iplt);
+ Add(In.RelaIplt);
+
+ In.Plt = make<PltSection>(false);
+ Add(In.Plt);
+ In.Iplt = make<PltSection>(true);
+ Add(In.Iplt);
+
+ // .note.GNU-stack is always added when we are creating a re-linkable
+ // object file. Other linkers are using the presence of this marker
+ // section to control the executable-ness of the stack area, but that
+ // is irrelevant these days. Stack area should always be non-executable
+ // by default. So we emit this section unconditionally.
+ if (Config->Relocatable)
+ Add(make<GnuStackSection>());
if (!Config->Relocatable) {
if (Config->EhFrameHdr) {
- InX::EhFrameHdr = make<EhFrameHeader>();
- Add(InX::EhFrameHdr);
+ In.EhFrameHdr = make<EhFrameHeader>();
+ Add(In.EhFrameHdr);
}
- InX::EhFrame = make<EhFrameSection>();
- Add(InX::EhFrame);
+ In.EhFrame = make<EhFrameSection>();
+ Add(In.EhFrame);
}
- if (InX::SymTab)
- Add(InX::SymTab);
- if (InX::SymTabShndx)
- Add(InX::SymTabShndx);
- Add(InX::ShStrTab);
- if (InX::StrTab)
- Add(InX::StrTab);
+ if (In.SymTab)
+ Add(In.SymTab);
+ if (In.SymTabShndx)
+ Add(In.SymTabShndx);
+ Add(In.ShStrTab);
+ if (In.StrTab)
+ Add(In.StrTab);
if (Config->EMachine == EM_ARM && !Config->Relocatable)
// Add a sentinel to terminate .ARM.exidx. It helps an unwinder
@@ -451,6 +474,7 @@ template <class ELFT> void Writer<ELFT>::run() {
// to the string table, and add entries to .got and .plt.
// finalizeSections does that.
finalizeSections();
+ checkExecuteOnly();
if (errorCount())
return;
@@ -476,10 +500,9 @@ template <class ELFT> void Writer<ELFT>::run() {
setPhdrs();
- if (Config->Relocatable) {
+ if (Config->Relocatable)
for (OutputSection *Sec : OutputSections)
Sec->Addr = 0;
- }
if (Config->CheckSections)
checkSections();
@@ -548,9 +571,11 @@ static bool includeInSymtab(const Symbol &B) {
if (!Sec)
return true;
Sec = Sec->Repl;
+
// Exclude symbols pointing to garbage-collected sections.
if (isa<InputSectionBase>(Sec) && !Sec->Live)
return false;
+
if (auto *S = dyn_cast<MergeInputSection>(Sec))
if (!S->getSectionPiece(D->Value)->Live)
return false;
@@ -562,7 +587,7 @@ static bool includeInSymtab(const Symbol &B) {
// Local symbols are not in the linker's symbol table. This function scans
// each object file's symbol table to copy local symbols to the output.
template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
- if (!InX::SymTab)
+ if (!In.SymTab)
return;
for (InputFile *File : ObjectFiles) {
ObjFile<ELFT> *F = cast<ObjFile<ELFT>>(File);
@@ -581,16 +606,16 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
SectionBase *Sec = DR->Section;
if (!shouldKeepInSymtab(Sec, B->getName(), *B))
continue;
- InX::SymTab->addSymbol(B);
+ In.SymTab->addSymbol(B);
}
}
}
+// Create a section symbol for each output section so that we can represent
+// relocations that point to the section. If we know that no relocation is
+// referring to a section (that happens if the section is a synthetic one), we
+// don't create a section symbol for that section.
template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
- // Create a section symbol for each output section so that we can represent
- // relocations that point to the section. If we know that no relocation is
- // referring to a section (that happens if the section is a synthetic one), we
- // don't create a section symbol for that section.
for (BaseCommand *Base : Script->SectionCommands) {
auto *Sec = dyn_cast<OutputSection>(Base);
if (!Sec)
@@ -617,7 +642,7 @@ template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
auto *Sym =
make<Defined>(IS->File, "", STB_LOCAL, /*StOther=*/0, STT_SECTION,
/*Value=*/0, /*Size=*/0, IS);
- InX::SymTab->addSymbol(Sym);
+ In.SymTab->addSymbol(Sym);
}
}
@@ -662,9 +687,14 @@ static bool isRelroSection(const OutputSection *Sec) {
// .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 (InX::Got && Sec == InX::Got->getParent())
+ if (In.Got && Sec == In.Got->getParent())
return true;
+ // .toc is a GOT-ish section for PowerPC64. Their contents are accessed
+ // through r2 register, which is reserved for that purpose. Since r2 is used
+ // for accessing .got as well, .got and .toc need to be close enough in the
+ // virtual address space. Usually, .toc comes just after .got. Since we place
+ // .got into RELRO, .toc needs to be placed into RELRO too.
if (Sec->Name.equals(".toc"))
return true;
@@ -672,13 +702,13 @@ static bool isRelroSection(const OutputSection *Sec) {
// 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 == InX::GotPlt->getParent())
+ if (Sec == In.GotPlt->getParent())
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 == InX::Dynamic->getParent())
+ if (Sec == In.Dynamic->getParent())
return true;
// Sections with some special names are put into RELRO. This is a
@@ -700,17 +730,17 @@ static bool isRelroSection(const OutputSection *Sec) {
// * It is easy two see how similar two ranks are (see getRankProximity).
enum RankFlags {
RF_NOT_ADDR_SET = 1 << 18,
- RF_NOT_INTERP = 1 << 17,
- RF_NOT_ALLOC = 1 << 16,
- RF_WRITE = 1 << 15,
- RF_EXEC_WRITE = 1 << 14,
- RF_EXEC = 1 << 13,
- RF_RODATA = 1 << 12,
- RF_NON_TLS_BSS = 1 << 11,
- RF_NON_TLS_BSS_RO = 1 << 10,
- RF_NOT_TLS = 1 << 9,
- RF_BSS = 1 << 8,
- RF_NOTE = 1 << 7,
+ RF_NOT_ALLOC = 1 << 17,
+ RF_NOT_INTERP = 1 << 16,
+ RF_NOT_NOTE = 1 << 15,
+ RF_WRITE = 1 << 14,
+ RF_EXEC_WRITE = 1 << 13,
+ RF_EXEC = 1 << 12,
+ RF_RODATA = 1 << 11,
+ RF_NON_TLS_BSS = 1 << 10,
+ RF_NON_TLS_BSS_RO = 1 << 9,
+ RF_NOT_TLS = 1 << 8,
+ RF_BSS = 1 << 7,
RF_PPC_NOT_TOCBSS = 1 << 6,
RF_PPC_TOCL = 1 << 5,
RF_PPC_TOC = 1 << 4,
@@ -729,16 +759,24 @@ static unsigned getSectionRank(const OutputSection *Sec) {
return Rank;
Rank |= RF_NOT_ADDR_SET;
+ // Allocatable sections go first to reduce the total PT_LOAD size and
+ // so debug info doesn't change addresses in actual code.
+ if (!(Sec->Flags & SHF_ALLOC))
+ return Rank | RF_NOT_ALLOC;
+
// Put .interp first because some loaders want to see that section
// on the first page of the executable file when loaded into memory.
if (Sec->Name == ".interp")
return Rank;
Rank |= RF_NOT_INTERP;
- // Allocatable sections go first to reduce the total PT_LOAD size and
- // so debug info doesn't change addresses in actual code.
- if (!(Sec->Flags & SHF_ALLOC))
- return Rank | RF_NOT_ALLOC;
+ // Put .note sections (which make up one PT_NOTE) at the beginning so that
+ // they are likely to be included in a core file even if core file size is
+ // limited. In particular, we want a .note.gnu.build-id and a .note.tag to be
+ // included in a core to match core files with executables.
+ if (Sec->Type == SHT_NOTE)
+ return Rank;
+ Rank |= RF_NOT_NOTE;
// Sort sections based on their access permission in the following
// order: R, RX, RWX, RW. This order is based on the following
@@ -802,12 +840,6 @@ static unsigned getSectionRank(const OutputSection *Sec) {
if (IsNoBits)
Rank |= RF_BSS;
- // We create a NOTE segment for contiguous .note sections, so make
- // them contigous if there are more than one .note section with the
- // same attributes.
- if (Sec->Type == SHT_NOTE)
- Rank |= RF_NOTE;
-
// Some architectures have additional ordering restrictions for sections
// within the same PT_LOAD.
if (Config->EMachine == EM_PPC64) {
@@ -850,8 +882,10 @@ static unsigned getSectionRank(const OutputSection *Sec) {
static bool compareSections(const BaseCommand *ACmd, const BaseCommand *BCmd) {
const OutputSection *A = cast<OutputSection>(ACmd);
const OutputSection *B = cast<OutputSection>(BCmd);
+
if (A->SortRank != B->SortRank)
return A->SortRank < B->SortRank;
+
if (!(A->SortRank & RF_NOT_ADDR_SET))
return Config->SectionStartMap.lookup(A->Name) <
Config->SectionStartMap.lookup(B->Name);
@@ -874,14 +908,20 @@ void PhdrEntry::add(OutputSection *Sec) {
// need these symbols, since IRELATIVE relocs are resolved through GOT
// and PLT. For details, see http://www.airs.com/blog/archives/403.
template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
- if (needsInterpSection())
+ if (Config->Relocatable || needsInterpSection())
return;
- StringRef S = Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start";
- addOptionalRegular(S, InX::RelaIplt, 0, STV_HIDDEN, STB_WEAK);
- S = Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end";
- ElfSym::RelaIpltEnd =
- addOptionalRegular(S, InX::RelaIplt, 0, STV_HIDDEN, STB_WEAK);
+ // By default, __rela_iplt_{start,end} belong to a dummy section 0
+ // because .rela.plt might be empty and thus removed from output.
+ // We'll override Out::ElfHeader with In.RelaIplt later when we are
+ // sure that .rela.plt exists in output.
+ ElfSym::RelaIpltStart = addOptionalRegular(
+ Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start",
+ Out::ElfHeader, 0, STV_HIDDEN, STB_WEAK);
+
+ ElfSym::RelaIpltEnd = addOptionalRegular(
+ Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end",
+ Out::ElfHeader, 0, STV_HIDDEN, STB_WEAK);
}
template <class ELFT>
@@ -895,7 +935,7 @@ void Writer<ELFT>::forEachRelSec(
for (InputSectionBase *IS : InputSections)
if (IS->Live && isa<InputSection>(IS) && (IS->Flags & SHF_ALLOC))
Fn(*IS);
- for (EhInputSection *ES : InX::EhFrame->Sections)
+ for (EhInputSection *ES : In.EhFrame->Sections)
Fn(*ES);
}
@@ -908,15 +948,19 @@ template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() {
if (ElfSym::GlobalOffsetTable) {
// The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention usually
// to the start of the .got or .got.plt section.
- InputSection *GotSection = InX::GotPlt;
+ InputSection *GotSection = In.GotPlt;
if (!Target->GotBaseSymInGotPlt)
- GotSection = InX::MipsGot ? cast<InputSection>(InX::MipsGot)
- : cast<InputSection>(InX::Got);
+ GotSection = In.MipsGot ? cast<InputSection>(In.MipsGot)
+ : cast<InputSection>(In.Got);
ElfSym::GlobalOffsetTable->Section = GotSection;
}
- if (ElfSym::RelaIpltEnd)
- ElfSym::RelaIpltEnd->Value = InX::RelaIplt->getSize();
+ // .rela_iplt_{start,end} mark the start and the end of .rela.plt section.
+ if (ElfSym::RelaIpltStart && !In.RelaIplt->empty()) {
+ ElfSym::RelaIpltStart->Section = In.RelaIplt;
+ ElfSym::RelaIpltEnd->Section = In.RelaIplt;
+ ElfSym::RelaIpltEnd->Value = In.RelaIplt->getSize();
+ }
PhdrEntry *Last = nullptr;
PhdrEntry *LastRO = nullptr;
@@ -1088,7 +1132,7 @@ static DenseMap<const InputSectionBase *, int> buildSectionOrder() {
SymbolOrderEntry &Ent = It->second;
Ent.Present = true;
- warnUnorderableSymbol(&Sym);
+ maybeWarnUnorderableSymbol(&Sym);
if (auto *D = dyn_cast<Defined>(&Sym)) {
if (auto *Sec = dyn_cast_or_null<InputSectionBase>(D->Section)) {
@@ -1097,6 +1141,7 @@ static DenseMap<const InputSectionBase *, int> buildSectionOrder() {
}
}
};
+
// We want both global and local symbols. We get the global ones from the
// symbol table and iterate the object files for the local ones.
for (Symbol *Sym : Symtab->getSymbols())
@@ -1132,11 +1177,10 @@ sortISDBySectionOrder(InputSectionDescription *ISD,
}
OrderedSections.push_back({IS, I->second});
}
- llvm::sort(
- OrderedSections.begin(), OrderedSections.end(),
- [&](std::pair<InputSection *, int> A, std::pair<InputSection *, int> B) {
- return A.second < B.second;
- });
+ llvm::sort(OrderedSections, [&](std::pair<InputSection *, int> A,
+ std::pair<InputSection *, int> B) {
+ return A.second < B.second;
+ });
// Find an insertion point for the ordered section list in the unordered
// section list. On targets with limited-range branches, this is the mid-point
@@ -1166,7 +1210,7 @@ sortISDBySectionOrder(InputSectionDescription *ISD,
// we effectively double the amount of code that could potentially call into
// the hot code without a thunk.
size_t InsPt = 0;
- if (Target->ThunkSectionSpacing && !OrderedSections.empty()) {
+ if (Target->getThunkSectionSpacing() && !OrderedSections.empty()) {
uint64_t UnorderedPos = 0;
for (; InsPt != UnorderedSections.size(); ++InsPt) {
UnorderedPos += UnorderedSections[InsPt]->getSize();
@@ -1342,10 +1386,12 @@ static bool compareByFilePosition(InputSection *A, InputSection *B) {
if (A->kind() == InputSectionBase::Synthetic ||
B->kind() == InputSectionBase::Synthetic)
return A->kind() != InputSectionBase::Synthetic;
+
InputSection *LA = A->getLinkOrderDep();
InputSection *LB = B->getLinkOrderDep();
OutputSection *AOut = LA->getParent();
OutputSection *BOut = LB->getParent();
+
if (AOut != BOut)
return AOut->SectionIndex < BOut->SectionIndex;
return LA->OutSecOff < LB->OutSecOff;
@@ -1392,6 +1438,7 @@ static bool isDuplicateArmExidxSec(InputSection *Prev, InputSection *Cur) {
for (const ExidxEntry Entry : Cur->getDataAs<ExidxEntry>())
if (IsExtabRef(Entry.Unwind) || Entry.Unwind != PrevEntry.Unwind)
return false;
+
// All table entries in this .ARM.exidx Section can be merged into the
// previous Section.
return true;
@@ -1423,18 +1470,19 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
assert(Sections.size() >= 2 &&
"We should create a sentinel section only if there are "
"alive regular exidx sections.");
+
// The last executable section is required to fill the sentinel.
// Remember it here so that we don't have to find it again.
Sentinel->Highest = Sections[Sections.size() - 2]->getLinkOrderDep();
}
+ // The EHABI for the Arm Architecture permits consecutive identical
+ // table entries to be merged. We use a simple implementation that
+ // removes a .ARM.exidx Input Section if it can be merged into the
+ // previous one. This does not require any rewriting of InputSection
+ // contents but misses opportunities for fine grained deduplication
+ // where only a subset of the InputSection contents can be merged.
if (Config->MergeArmExidx) {
- // The EHABI for the Arm Architecture permits consecutive identical
- // table entries to be merged. We use a simple implementation that
- // removes a .ARM.exidx Input Section if it can be merged into the
- // previous one. This does not require any rewriting of InputSection
- // contents but misses opportunities for fine grained deduplication
- // where only a subset of the InputSection contents can be merged.
size_t Prev = 0;
// The last one is a sentinel entry which should not be removed.
for (size_t I = 1; I < Sections.size() - 1; ++I) {
@@ -1456,11 +1504,49 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
}
}
-static void applySynthetic(const std::vector<SyntheticSection *> &Sections,
- llvm::function_ref<void(SyntheticSection *)> Fn) {
- for (SyntheticSection *SS : Sections)
- if (SS && SS->getParent() && !SS->empty())
- Fn(SS);
+// For most RISC ISAs, we need to generate content that depends on the address
+// of InputSections. For example some architectures such as AArch64 use small
+// displacements for jump instructions that is the linker's responsibility for
+// creating range extension thunks for. As the generation of the content may
+// also alter InputSection addresses we must converge to a fixed point.
+template <class ELFT> void Writer<ELFT>::maybeAddThunks() {
+ if (!Target->NeedsThunks && !Config->AndroidPackDynRelocs &&
+ !Config->RelrPackDynRelocs)
+ return;
+
+ ThunkCreator TC;
+ AArch64Err843419Patcher A64P;
+
+ for (;;) {
+ bool Changed = false;
+
+ Script->assignAddresses();
+
+ if (Target->NeedsThunks)
+ Changed |= TC.createThunks(OutputSections);
+
+ if (Config->FixCortexA53Errata843419) {
+ if (Changed)
+ Script->assignAddresses();
+ Changed |= A64P.createFixes();
+ }
+
+ if (In.MipsGot)
+ In.MipsGot->updateAllocSize();
+
+ Changed |= In.RelaDyn->updateAllocSize();
+
+ if (In.RelrDyn)
+ Changed |= In.RelrDyn->updateAllocSize();
+
+ if (!Changed)
+ return;
+ }
+}
+
+static void finalizeSynthetic(SyntheticSection *Sec) {
+ if (Sec && !Sec->empty() && Sec->getParent())
+ Sec->finalizeContents();
}
// In order to allow users to manipulate linker-synthesized sections,
@@ -1500,6 +1586,7 @@ static void removeUnusedSyntheticSections() {
// with the same name defined in other ELF executable or DSO.
static bool computeIsPreemptible(const Symbol &B) {
assert(!B.isLocal());
+
// Only symbols that appear in dynsym can be preempted.
if (!B.includeInDynsym())
return false;
@@ -1528,7 +1615,6 @@ static bool computeIsPreemptible(const Symbol &B) {
// Create output section objects and add them to OutputSections.
template <class ELFT> void Writer<ELFT>::finalizeSections() {
- Out::DebugInfo = findSection(".debug_info");
Out::PreinitArray = findSection(".preinit_array");
Out::InitArray = findSection(".init_array");
Out::FiniArray = findSection(".fini_array");
@@ -1547,46 +1633,51 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// It should be okay as no one seems to care about the type.
// Even the author of gold doesn't remember why gold behaves that way.
// https://sourceware.org/ml/binutils/2002-03/msg00360.html
- if (InX::DynSymTab)
- Symtab->addRegular("_DYNAMIC", STV_HIDDEN, STT_NOTYPE, 0 /*Value*/,
- /*Size=*/0, STB_WEAK, InX::Dynamic,
+ if (In.Dynamic->Parent)
+ Symtab->addDefined("_DYNAMIC", STV_HIDDEN, STT_NOTYPE, 0 /*Value*/,
+ /*Size=*/0, STB_WEAK, In.Dynamic,
/*File=*/nullptr);
// Define __rel[a]_iplt_{start,end} symbols if needed.
addRelIpltSymbols();
+ // RISC-V's gp can address +/- 2 KiB, set it to .sdata + 0x800 if not defined.
+ if (Config->EMachine == EM_RISCV)
+ if (!dyn_cast_or_null<Defined>(Symtab->find("__global_pointer$")))
+ addOptionalRegular("__global_pointer$", findSection(".sdata"), 0x800);
+
// This responsible for splitting up .eh_frame section into
// pieces. The relocation scan uses those pieces, so this has to be
// earlier.
- applySynthetic({InX::EhFrame},
- [](SyntheticSection *SS) { SS->finalizeContents(); });
+ finalizeSynthetic(In.EhFrame);
for (Symbol *S : Symtab->getSymbols())
- S->IsPreemptible |= computeIsPreemptible(*S);
+ if (!S->IsPreemptible)
+ S->IsPreemptible = computeIsPreemptible(*S);
// Scan relocations. This must be done after every symbol is declared so that
// we can correctly decide if a dynamic relocation is needed.
if (!Config->Relocatable)
forEachRelSec(scanRelocations<ELFT>);
- if (InX::Plt && !InX::Plt->empty())
- InX::Plt->addSymbols();
- if (InX::Iplt && !InX::Iplt->empty())
- InX::Iplt->addSymbols();
+ if (In.Plt && !In.Plt->empty())
+ In.Plt->addSymbols();
+ if (In.Iplt && !In.Iplt->empty())
+ In.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 *Sym : Symtab->getSymbols()) {
if (!includeInSymtab(*Sym))
continue;
- if (InX::SymTab)
- InX::SymTab->addSymbol(Sym);
+ if (In.SymTab)
+ In.SymTab->addSymbol(Sym);
- if (InX::DynSymTab && Sym->includeInDynsym()) {
- InX::DynSymTab->addSymbol(Sym);
+ if (Sym->includeInDynsym()) {
+ In.DynSymTab->addSymbol(Sym);
if (auto *File = dyn_cast_or_null<SharedFile<ELFT>>(Sym->File))
if (File->IsNeeded && !Sym->isUndefined())
- In<ELFT>::VerNeed->addSymbol(Sym);
+ InX<ELFT>::VerNeed->addSymbol(Sym);
}
}
@@ -1594,8 +1685,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (errorCount())
return;
- if (InX::MipsGot)
- InX::MipsGot->build<ELFT>();
+ if (In.MipsGot)
+ In.MipsGot->build<ELFT>();
removeUnusedSyntheticSections();
@@ -1607,15 +1698,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (auto *Sec = dyn_cast<OutputSection>(Base))
OutputSections.push_back(Sec);
- // Ensure data sections are not mixed with executable sections when
- // -execute-only is used.
- if (Config->ExecuteOnly)
- for (OutputSection *OS : OutputSections)
- if (OS->Flags & SHF_EXECINSTR)
- for (InputSection *IS : getInputSections(OS))
- if (!(IS->Flags & SHF_EXECINSTR))
- error("-execute-only does not support intermingling data and code");
-
// Prefer command line supplied address over other constraints.
for (OutputSection *Sec : OutputSections) {
auto I = Config->SectionStartMap.find(Sec->Name);
@@ -1628,10 +1710,10 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// particularly relevant.
Out::ElfHeader->SectionIndex = 1;
- unsigned I = 1;
- for (OutputSection *Sec : OutputSections) {
- Sec->SectionIndex = I++;
- Sec->ShName = InX::ShStrTab->addString(Sec->Name);
+ for (size_t I = 0, E = OutputSections.size(); I != E; ++I) {
+ OutputSection *Sec = OutputSections[I];
+ Sec->SectionIndex = I + 1;
+ Sec->ShName = In.ShStrTab->addString(Sec->Name);
}
// Binary and relocatable output does not have PHDRS.
@@ -1641,6 +1723,12 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
Phdrs = Script->hasPhdrsCommands() ? Script->createPhdrs() : createPhdrs();
addPtArmExid(Phdrs);
Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size();
+
+ // Find the TLS segment. This happens before the section layout loop so that
+ // Android relocation packing can look up TLS symbol addresses.
+ for (PhdrEntry *P : Phdrs)
+ if (P->p_type == PT_TLS)
+ Out::TlsPhdr = P;
}
// Some symbols are defined in term of program headers. Now that we
@@ -1649,15 +1737,30 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// Dynamic section must be the last one in this list and dynamic
// symbol table section (DynSymTab) must be the first one.
- applySynthetic(
- {InX::DynSymTab, InX::Bss, InX::BssRelRo, InX::GnuHashTab,
- InX::HashTab, InX::SymTab, InX::SymTabShndx, InX::ShStrTab,
- InX::StrTab, In<ELFT>::VerDef, InX::DynStrTab, InX::Got,
- InX::MipsGot, InX::IgotPlt, InX::GotPlt, InX::RelaDyn,
- InX::RelrDyn, InX::RelaIplt, InX::RelaPlt, InX::Plt,
- InX::Iplt, InX::EhFrameHdr, In<ELFT>::VerSym, In<ELFT>::VerNeed,
- InX::Dynamic},
- [](SyntheticSection *SS) { SS->finalizeContents(); });
+ finalizeSynthetic(In.DynSymTab);
+ finalizeSynthetic(In.Bss);
+ finalizeSynthetic(In.BssRelRo);
+ finalizeSynthetic(In.GnuHashTab);
+ finalizeSynthetic(In.HashTab);
+ finalizeSynthetic(In.SymTabShndx);
+ finalizeSynthetic(In.ShStrTab);
+ finalizeSynthetic(In.StrTab);
+ finalizeSynthetic(In.VerDef);
+ finalizeSynthetic(In.DynStrTab);
+ finalizeSynthetic(In.Got);
+ finalizeSynthetic(In.MipsGot);
+ finalizeSynthetic(In.IgotPlt);
+ finalizeSynthetic(In.GotPlt);
+ finalizeSynthetic(In.RelaDyn);
+ finalizeSynthetic(In.RelrDyn);
+ finalizeSynthetic(In.RelaIplt);
+ finalizeSynthetic(In.RelaPlt);
+ finalizeSynthetic(In.Plt);
+ finalizeSynthetic(In.Iplt);
+ finalizeSynthetic(In.EhFrameHdr);
+ finalizeSynthetic(InX<ELFT>::VerSym);
+ finalizeSynthetic(InX<ELFT>::VerNeed);
+ finalizeSynthetic(In.Dynamic);
if (!Script->HasSectionsCommand && !Config->Relocatable)
fixSectionAlignments();
@@ -1666,37 +1769,21 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// needs to be resolved before any other address dependent operation.
resolveShfLinkOrder();
- // Some architectures need to generate content that depends on the address
- // of InputSections. For example some architectures use small displacements
- // for jump instructions that is the linker's responsibility for creating
- // range extension thunks for. As the generation of the content may also
- // alter InputSection addresses we must converge to a fixed point.
- if (Target->NeedsThunks || Config->AndroidPackDynRelocs ||
- Config->RelrPackDynRelocs) {
- ThunkCreator TC;
- AArch64Err843419Patcher A64P;
- bool Changed;
- do {
- Script->assignAddresses();
- Changed = false;
- if (Target->NeedsThunks)
- Changed |= TC.createThunks(OutputSections);
- if (Config->FixCortexA53Errata843419) {
- if (Changed)
- Script->assignAddresses();
- Changed |= A64P.createFixes();
- }
- if (InX::MipsGot)
- InX::MipsGot->updateAllocSize();
- Changed |= InX::RelaDyn->updateAllocSize();
- if (InX::RelrDyn)
- Changed |= InX::RelrDyn->updateAllocSize();
- } while (Changed);
- }
+ // Jump instructions in many ISAs have small displacements, and therefore they
+ // cannot jump to arbitrary addresses in memory. For example, RISC-V JAL
+ // instruction can target only +-1 MiB from PC. It is a linker's
+ // responsibility to create and insert small pieces of code between sections
+ // to extend the ranges if jump targets are out of range. Such code pieces are
+ // called "thunks".
+ //
+ // We add thunks at this stage. We couldn't do this before this point because
+ // this is the earliest point where we know sizes of sections and their
+ // layouts (that are needed to determine if jump targets are in range).
+ maybeAddThunks();
- // createThunks may have added local symbols to the static symbol table
- applySynthetic({InX::SymTab},
- [](SyntheticSection *SS) { SS->postThunkContents(); });
+ // maybeAddThunks may have added local symbols to the static symbol table.
+ finalizeSynthetic(In.SymTab);
+ finalizeSynthetic(In.PPC64LongBranchTarget);
// Fill other section headers. The dynamic table is finalized
// at the end because some tags like RELSZ depend on result
@@ -1705,6 +1792,21 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
Sec->finalize<ELFT>();
}
+// Ensure data sections are not mixed with executable sections when
+// -execute-only is used. -execute-only is a feature to make pages executable
+// but not readable, and the feature is currently supported only on AArch64.
+template <class ELFT> void Writer<ELFT>::checkExecuteOnly() {
+ if (!Config->ExecuteOnly)
+ return;
+
+ for (OutputSection *OS : OutputSections)
+ if (OS->Flags & SHF_EXECINSTR)
+ for (InputSection *IS : getInputSections(OS))
+ if (!(IS->Flags & SHF_EXECINSTR))
+ error("cannot place " + toString(IS) + " into " + toString(OS->Name) +
+ ": -execute-only does not support intermingling data and code");
+}
+
// 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() {
@@ -1721,9 +1823,13 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
// program to fail to link due to relocation overflow, if their
// program text is above 2 GiB. We use the address of the .text
// section instead to prevent that failure.
+ //
+ // In a rare sitaution, .text section may not exist. If that's the
+ // case, use the image base address as a last resort.
OutputSection *Default = findSection(".text");
if (!Default)
Default = Out::ElfHeader;
+
auto Define = [=](StringRef Start, StringRef End, OutputSection *OS) {
if (OS) {
addOptionalRegular(Start, OS, 0);
@@ -1763,7 +1869,7 @@ static bool needsPtLoad(OutputSection *Sec) {
// Don't allocate VA space for TLS NOBITS sections. The PT_TLS PHDR is
// responsible for allocating space for them, not the PT_LOAD that
// contains the TLS initialization image.
- if (Sec->Flags & SHF_TLS && Sec->Type == SHT_NOBITS)
+ if ((Sec->Flags & SHF_TLS) && Sec->Type == SHT_NOBITS)
return false;
return true;
}
@@ -1815,12 +1921,14 @@ template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() {
// Segments are contiguous memory regions that has the same attributes
// (e.g. executable or writable). There is one phdr for each segment.
// 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. At the same time, we don't want to create a separate
- // load segment for the headers, even if the first output section has
- // an AT attribute.
+ // different flags or is loaded at a discontiguous address or memory
+ // region using AT or AT> linker script command, respectively. At the same
+ // time, we don't want to create a separate load segment for the headers,
+ // even if the first output section has an AT or AT> attribute.
uint64_t NewFlags = computeFlags(Sec->getPhdrFlags());
- if ((Sec->LMAExpr && Load->LastSec != Out::ProgramHeaders) ||
+ if (((Sec->LMAExpr ||
+ (Sec->LMARegion && (Sec->LMARegion != Load->FirstSec->LMARegion))) &&
+ Load->LastSec != Out::ProgramHeaders) ||
Sec->MemRegion != Load->FirstSec->MemRegion || Flags != NewFlags) {
Load = AddHdr(PT_LOAD, NewFlags);
@@ -1839,9 +1947,8 @@ template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() {
Ret.push_back(TlsHdr);
// Add an entry for .dynamic.
- if (InX::DynSymTab)
- AddHdr(PT_DYNAMIC, InX::Dynamic->getParent()->getPhdrFlags())
- ->add(InX::Dynamic->getParent());
+ if (OutputSection *Sec = In.Dynamic->getParent())
+ AddHdr(PT_DYNAMIC, Sec->getPhdrFlags())->add(Sec);
// PT_GNU_RELRO includes all sections that should be marked as
// read-only by dynamic linker after proccessing relocations.
@@ -1869,10 +1976,10 @@ template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() {
Ret.push_back(RelRo);
// PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr.
- if (!InX::EhFrame->empty() && InX::EhFrameHdr && InX::EhFrame->getParent() &&
- InX::EhFrameHdr->getParent())
- AddHdr(PT_GNU_EH_FRAME, InX::EhFrameHdr->getParent()->getPhdrFlags())
- ->add(InX::EhFrameHdr->getParent());
+ if (!In.EhFrame->empty() && In.EhFrameHdr && In.EhFrame->getParent() &&
+ In.EhFrameHdr->getParent())
+ AddHdr(PT_GNU_EH_FRAME, In.EhFrameHdr->getParent()->getPhdrFlags())
+ ->add(In.EhFrameHdr->getParent());
// PT_OPENBSD_RANDOMIZE is an OpenBSD-specific feature. That makes
// the dynamic linker fill the segment with random data.
@@ -1943,77 +2050,77 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
for (const PhdrEntry *P : Phdrs) {
if (P->p_type != PT_GNU_RELRO)
continue;
+
if (P->FirstSec)
PageAlign(P->FirstSec);
+
// Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we
// have to align it to a page.
auto End = OutputSections.end();
auto I = std::find(OutputSections.begin(), End, P->LastSec);
if (I == End || (I + 1) == End)
continue;
+
OutputSection *Cmd = (*(I + 1));
if (needsPtLoad(Cmd))
PageAlign(Cmd);
}
}
-// Adjusts the file alignment for a given output section and returns
-// 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.
-static uint64_t getFileAlignment(uint64_t Off, OutputSection *Cmd) {
- OutputSection *First = Cmd->PtLoad ? Cmd->PtLoad->FirstSec : nullptr;
- // The first section in a PT_LOAD has to have congruent offset and address
- // module the page size.
- if (Cmd == First)
- return alignTo(Off, std::max<uint64_t>(Cmd->Alignment, Config->MaxPageSize),
- Cmd->Addr);
-
- // For SHT_NOBITS we don't want the alignment of the section to impact the
- // offset of the sections that follow. Since nothing seems to care about the
- // sh_offset of the SHT_NOBITS section itself, just ignore it.
- if (Cmd->Type == SHT_NOBITS)
+// Compute an in-file position for a given section. 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.
+static uint64_t computeFileOffset(OutputSection *OS, uint64_t Off) {
+ // File offsets are not significant for .bss sections. By convention, we keep
+ // section offsets monotonically increasing rather than setting to zero.
+ if (OS->Type == SHT_NOBITS)
return Off;
// If the section is not in a PT_LOAD, we just have to align it.
- if (!Cmd->PtLoad)
- return alignTo(Off, Cmd->Alignment);
+ if (!OS->PtLoad)
+ return alignTo(Off, OS->Alignment);
+
+ // The first section in a PT_LOAD has to have congruent offset and address
+ // module the page size.
+ OutputSection *First = OS->PtLoad->FirstSec;
+ if (OS == First) {
+ uint64_t Alignment = std::max<uint64_t>(OS->Alignment, Config->MaxPageSize);
+ return alignTo(Off, Alignment, OS->Addr);
+ }
// If two sections share the same PT_LOAD the file offset is calculated
// using this formula: Off2 = Off1 + (VA2 - VA1).
- return First->Offset + Cmd->Addr - First->Addr;
+ return First->Offset + OS->Addr - First->Addr;
}
-static uint64_t setOffset(OutputSection *Cmd, uint64_t Off) {
- Off = getFileAlignment(Off, Cmd);
- Cmd->Offset = Off;
+// Set an in-file position to a given section and returns the end position of
+// the section.
+static uint64_t setFileOffset(OutputSection *OS, uint64_t Off) {
+ Off = computeFileOffset(OS, Off);
+ OS->Offset = Off;
- // For SHT_NOBITS we should not count the size.
- if (Cmd->Type == SHT_NOBITS)
+ if (OS->Type == SHT_NOBITS)
return Off;
-
- return Off + Cmd->Size;
+ return Off + OS->Size;
}
template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() {
uint64_t Off = 0;
for (OutputSection *Sec : OutputSections)
if (Sec->Flags & SHF_ALLOC)
- Off = setOffset(Sec, Off);
+ Off = setFileOffset(Sec, Off);
FileSize = alignTo(Off, Config->Wordsize);
}
static std::string rangeToString(uint64_t Addr, uint64_t Len) {
- if (Len == 0)
- return "<empty range at 0x" + utohexstr(Addr) + ">";
return "[0x" + utohexstr(Addr) + ", 0x" + utohexstr(Addr + Len - 1) + "]";
}
// Assign file offsets to output sections.
template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
uint64_t Off = 0;
- Off = setOffset(Out::ElfHeader, Off);
- Off = setOffset(Out::ProgramHeaders, Off);
+ Off = setFileOffset(Out::ElfHeader, Off);
+ Off = setFileOffset(Out::ProgramHeaders, Off);
PhdrEntry *LastRX = nullptr;
for (PhdrEntry *P : Phdrs)
@@ -2021,9 +2128,10 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
LastRX = P;
for (OutputSection *Sec : OutputSections) {
- Off = setOffset(Sec, Off);
+ Off = setFileOffset(Sec, Off);
if (Script->HasSectionsCommand)
continue;
+
// If this is a last section of the last executable segment and that
// segment is the last loadable segment, align the offset of the
// following section to avoid loading non-segments parts of the file.
@@ -2048,7 +2156,7 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
continue;
if ((Sec->Offset > FileSize) || (Sec->Offset + Sec->Size > FileSize))
error("unable to place section " + Sec->Name + " at file offset " +
- rangeToString(Sec->Offset, Sec->Offset + Sec->Size) +
+ rangeToString(Sec->Offset, Sec->Size) +
"; check your linker script for overflows");
}
}
@@ -2059,19 +2167,23 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() {
for (PhdrEntry *P : Phdrs) {
OutputSection *First = P->FirstSec;
OutputSection *Last = P->LastSec;
+
if (First) {
P->p_filesz = Last->Offset - First->Offset;
if (Last->Type != SHT_NOBITS)
P->p_filesz += Last->Size;
+
P->p_memsz = Last->Addr + Last->Size - First->Addr;
P->p_offset = First->Offset;
P->p_vaddr = First->Addr;
+
if (!P->HasLMA)
P->p_paddr = First->getLMA();
}
- if (P->p_type == PT_LOAD)
+
+ if (P->p_type == PT_LOAD) {
P->p_align = std::max<uint64_t>(P->p_align, Config->MaxPageSize);
- else if (P->p_type == PT_GNU_RELRO) {
+ } else if (P->p_type == PT_GNU_RELRO) {
P->p_align = 1;
// The glibc dynamic loader rounds the size down, so we need to round up
// to protect the last page. This is a no-op on FreeBSD which always
@@ -2079,12 +2191,22 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() {
P->p_memsz = alignTo(P->p_memsz, Target->PageSize);
}
- // 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::TlsPhdr = P;
- if (P->p_memsz)
- P->p_memsz = alignTo(P->p_memsz, P->p_align);
+ if (P->p_type == PT_TLS && P->p_memsz) {
+ if (!Config->Shared &&
+ (Config->EMachine == EM_ARM || Config->EMachine == EM_AARCH64)) {
+ // On ARM/AArch64, reserve extra space (8 words) between the thread
+ // pointer and an executable's TLS segment by overaligning the segment.
+ // This reservation is needed for backwards compatibility with Android's
+ // TCB, which allocates several slots after the thread pointer (e.g.
+ // TLS_SLOT_STACK_GUARD==5). For simplicity, this overalignment is also
+ // done on other operating systems.
+ P->p_align = std::max<uint64_t>(P->p_align, Config->Wordsize * 8);
+ }
+
+ // The TLS pointer goes after PT_TLS for variant 2 targets. At least glibc
+ // will align it, so round up the size to make sure the offsets are
+ // correct.
+ P->p_memsz = alignTo(P->p_memsz, P->p_align);
}
}
}
@@ -2101,10 +2223,9 @@ struct SectionOffset {
// load and virtual adresses).
static void checkOverlap(StringRef Name, std::vector<SectionOffset> &Sections,
bool IsVirtualAddr) {
- llvm::sort(Sections.begin(), Sections.end(),
- [=](const SectionOffset &A, const SectionOffset &B) {
- return A.Offset < B.Offset;
- });
+ llvm::sort(Sections, [=](const SectionOffset &A, const SectionOffset &B) {
+ return A.Offset < B.Offset;
+ });
// Finding overlap is easy given a vector is sorted by start position.
// If an element starts before the end of the previous element, they overlap.
@@ -2148,7 +2269,7 @@ template <class ELFT> void Writer<ELFT>::checkSections() {
// file so we skip any non-allocated sections in that case.
std::vector<SectionOffset> FileOffs;
for (OutputSection *Sec : OutputSections)
- if (0 < Sec->Size && Sec->Type != SHT_NOBITS &&
+ if (Sec->Size > 0 && Sec->Type != SHT_NOBITS &&
(!Config->OFormatBinary || (Sec->Flags & SHF_ALLOC)))
FileOffs.push_back({Sec, Sec->Offset});
checkOverlap("file", FileOffs, false);
@@ -2166,7 +2287,7 @@ template <class ELFT> void Writer<ELFT>::checkSections() {
// ranges in the file.
std::vector<SectionOffset> VMAs;
for (OutputSection *Sec : OutputSections)
- if (0 < Sec->Size && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS))
+ if (Sec->Size > 0 && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS))
VMAs.push_back({Sec, Sec->Addr});
checkOverlap("virtual address", VMAs, true);
@@ -2175,7 +2296,7 @@ template <class ELFT> void Writer<ELFT>::checkSections() {
// script with AT().
std::vector<SectionOffset> LMAs;
for (OutputSection *Sec : OutputSections)
- if (0 < Sec->Size && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS))
+ if (Sec->Size > 0 && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS))
LMAs.push_back({Sec, Sec->getLMA()});
checkOverlap("load address", LMAs, false);
}
@@ -2188,7 +2309,7 @@ template <class ELFT> void Writer<ELFT>::checkSections() {
// 4. the number represented by the entry symbol, if it is a number;
// 5. the address of the first byte of the .text section, if present;
// 6. the address 0.
-template <class ELFT> uint64_t Writer<ELFT>::getEntryAddr() {
+static uint64_t getEntryAddr() {
// Case 1, 2 or 3
if (Symbol *B = Symtab->find(Config->Entry))
return B->getVA();
@@ -2231,6 +2352,7 @@ static uint8_t getAbiVersion() {
template <class ELFT> void Writer<ELFT>::writeHeader() {
uint8_t *Buf = Buffer->getBufferStart();
+
// For executable segments, the trap instructions are written before writing
// the header. Setting Elf header bytes to zero ensures that any unused bytes
// in header are zero-cleared, instead of having trap instructions.
@@ -2289,7 +2411,7 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
else
EHdr->e_shnum = Num;
- uint32_t StrTabIndex = InX::ShStrTab->getParent()->SectionIndex;
+ uint32_t StrTabIndex = In.ShStrTab->getParent()->SectionIndex;
if (StrTabIndex >= SHN_LORESERVE) {
SHdrs->sh_link = StrTabIndex;
EHdr->e_shstrndx = SHN_XINDEX;
@@ -2303,7 +2425,8 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
// Open a result file.
template <class ELFT> void Writer<ELFT>::openFile() {
- if (!Config->Is64 && FileSize > UINT32_MAX) {
+ uint64_t MaxSize = Config->Is64 ? INT64_MAX : UINT32_MAX;
+ if (MaxSize < FileSize) {
error("output file too large: " + Twine(FileSize) + " bytes");
return;
}
@@ -2368,8 +2491,8 @@ template <class ELFT> void Writer<ELFT>::writeSections() {
uint8_t *Buf = Buffer->getBufferStart();
OutputSection *EhFrameHdr = nullptr;
- if (InX::EhFrameHdr && !InX::EhFrameHdr->empty())
- EhFrameHdr = InX::EhFrameHdr->getParent();
+ if (In.EhFrameHdr && !In.EhFrameHdr->empty())
+ EhFrameHdr = In.EhFrameHdr->getParent();
// 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
@@ -2389,13 +2512,13 @@ template <class ELFT> void Writer<ELFT>::writeSections() {
}
template <class ELFT> void Writer<ELFT>::writeBuildId() {
- if (!InX::BuildId || !InX::BuildId->getParent())
+ if (!In.BuildId || !In.BuildId->getParent())
return;
// Compute a hash of all sections of the output file.
uint8_t *Start = Buffer->getBufferStart();
uint8_t *End = Start + FileSize;
- InX::BuildId->writeBuildId({Start, End});
+ In.BuildId->writeBuildId({Start, End});
}
template void elf::writeResult<ELF32LE>();