summaryrefslogtreecommitdiff
path: root/ELF/SyntheticSections.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ELF/SyntheticSections.cpp')
-rw-r--r--ELF/SyntheticSections.cpp506
1 files changed, 291 insertions, 215 deletions
diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp
index ae02434572c2a..f459c1b6b4792 100644
--- a/ELF/SyntheticSections.cpp
+++ b/ELF/SyntheticSections.cpp
@@ -30,10 +30,11 @@
#include "lld/Common/Threads.h"
#include "lld/Common/Version.h"
#include "llvm/ADT/SetOperations.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
-#include "llvm/Object/Decompressor.h"
#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Support/Compression.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MD5.h"
@@ -104,7 +105,7 @@ MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() {
Create = true;
std::string Filename = toString(Sec->File);
- const size_t Size = Sec->Data.size();
+ const size_t Size = Sec->data().size();
// Older version of BFD (such as the default FreeBSD linker) concatenate
// .MIPS.abiflags instead of merging. To allow for this case (or potential
// zero padding) we ignore everything after the first Elf_Mips_ABIFlags
@@ -113,7 +114,7 @@ MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() {
Twine(Size) + " instead of " + Twine(sizeof(Elf_Mips_ABIFlags)));
return nullptr;
}
- auto *S = reinterpret_cast<const Elf_Mips_ABIFlags *>(Sec->Data.data());
+ auto *S = reinterpret_cast<const Elf_Mips_ABIFlags *>(Sec->data().data());
if (S->version != 0) {
error(Filename + ": unexpected .MIPS.abiflags version " +
Twine(S->version));
@@ -153,7 +154,7 @@ template <class ELFT> void MipsOptionsSection<ELFT>::writeTo(uint8_t *Buf) {
Options->size = getSize();
if (!Config->Relocatable)
- Reginfo.ri_gp_value = InX::MipsGot->getGp();
+ Reginfo.ri_gp_value = In.MipsGot->getGp();
memcpy(Buf + sizeof(Elf_Mips_Options), &Reginfo, sizeof(Reginfo));
}
@@ -176,7 +177,7 @@ MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() {
Sec->Live = false;
std::string Filename = toString(Sec->File);
- ArrayRef<uint8_t> D = Sec->Data;
+ ArrayRef<uint8_t> D = Sec->data();
while (!D.empty()) {
if (D.size() < sizeof(Elf_Mips_Options)) {
@@ -210,7 +211,7 @@ MipsReginfoSection<ELFT>::MipsReginfoSection(Elf_Mips_RegInfo Reginfo)
template <class ELFT> void MipsReginfoSection<ELFT>::writeTo(uint8_t *Buf) {
if (!Config->Relocatable)
- Reginfo.ri_gp_value = InX::MipsGot->getGp();
+ Reginfo.ri_gp_value = In.MipsGot->getGp();
memcpy(Buf, &Reginfo, sizeof(Reginfo));
}
@@ -232,12 +233,12 @@ MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() {
for (InputSectionBase *Sec : Sections) {
Sec->Live = false;
- if (Sec->Data.size() != sizeof(Elf_Mips_RegInfo)) {
+ if (Sec->data().size() != sizeof(Elf_Mips_RegInfo)) {
error(toString(Sec->File) + ": invalid size of .reginfo section");
return nullptr;
}
- auto *R = reinterpret_cast<const Elf_Mips_RegInfo *>(Sec->Data.data());
+ auto *R = reinterpret_cast<const Elf_Mips_RegInfo *>(Sec->data().data());
Reginfo.ri_gprmask |= R->ri_gprmask;
Sec->getFile<ELFT>()->MipsGp0 = R->ri_gp_value;
};
@@ -260,8 +261,8 @@ Defined *elf::addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
uint64_t Size, InputSectionBase &Section) {
auto *S = make<Defined>(Section.File, Name, STB_LOCAL, STV_DEFAULT, Type,
Value, Size, &Section);
- if (InX::SymTab)
- InX::SymTab->addSymbol(S);
+ if (In.SymTab)
+ In.SymTab->addSymbol(S);
return S;
}
@@ -502,7 +503,7 @@ std::vector<EhFrameSection::FdeData> EhFrameSection::getFdeData() const {
uint8_t *Buf = getParent()->Loc + OutSecOff;
std::vector<FdeData> Ret;
- uint64_t VA = InX::EhFrameHdr->getVA();
+ uint64_t VA = In.EhFrameHdr->getVA();
for (CieRecord *Rec : CieRecords) {
uint8_t Enc = getFdeEncoding(Rec->Cie);
for (EhSectionPiece *Fde : Rec->Fdes) {
@@ -937,7 +938,7 @@ template <class ELFT> void MipsGotSection::build() {
Symbol *S = P.first;
uint64_t Offset = P.second * Config->Wordsize;
if (S->IsPreemptible)
- InX::RelaDyn->addReloc(Target->TlsGotRel, this, Offset, S);
+ In.RelaDyn->addReloc(Target->TlsGotRel, this, Offset, S);
}
for (std::pair<Symbol *, size_t> &P : Got.DynTlsSymbols) {
Symbol *S = P.first;
@@ -945,7 +946,7 @@ template <class ELFT> void MipsGotSection::build() {
if (S == nullptr) {
if (!Config->Pic)
continue;
- InX::RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S);
+ In.RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S);
} else {
// When building a shared library we still need a dynamic relocation
// for the module index. Therefore only checking for
@@ -953,13 +954,13 @@ template <class ELFT> void MipsGotSection::build() {
// thread-locals that have been marked as local through a linker script)
if (!S->IsPreemptible && !Config->Pic)
continue;
- InX::RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S);
+ In.RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S);
// However, we can skip writing the TLS offset reloc for non-preemptible
// symbols since it is known even in shared libraries
if (!S->IsPreemptible)
continue;
Offset += Config->Wordsize;
- InX::RelaDyn->addReloc(Target->TlsOffsetRel, this, Offset, S);
+ In.RelaDyn->addReloc(Target->TlsOffsetRel, this, Offset, S);
}
}
@@ -971,7 +972,7 @@ template <class ELFT> void MipsGotSection::build() {
// Dynamic relocations for "global" entries.
for (const std::pair<Symbol *, size_t> &P : Got.Global) {
uint64_t Offset = P.second * Config->Wordsize;
- InX::RelaDyn->addReloc(Target->RelativeRel, this, Offset, P.first);
+ In.RelaDyn->addReloc(Target->RelativeRel, this, Offset, P.first);
}
if (!Config->Pic)
continue;
@@ -981,14 +982,14 @@ template <class ELFT> void MipsGotSection::build() {
size_t PageCount = L.second.Count;
for (size_t PI = 0; PI < PageCount; ++PI) {
uint64_t Offset = (L.second.FirstIndex + PI) * Config->Wordsize;
- InX::RelaDyn->addReloc({Target->RelativeRel, this, Offset, L.first,
- int64_t(PI * 0x10000)});
+ In.RelaDyn->addReloc({Target->RelativeRel, this, Offset, L.first,
+ int64_t(PI * 0x10000)});
}
}
for (const std::pair<GotEntry, size_t> &P : Got.Local16) {
uint64_t Offset = P.second * Config->Wordsize;
- InX::RelaDyn->addReloc({Target->RelativeRel, this, Offset, true,
- P.first.first, P.first.second});
+ In.RelaDyn->addReloc({Target->RelativeRel, this, Offset, true,
+ P.first.first, P.first.second});
}
}
}
@@ -1200,21 +1201,21 @@ DynamicSection<ELFT>::DynamicSection()
// Add strings to .dynstr early so that .dynstr's size will be
// fixed early.
for (StringRef S : Config->FilterList)
- addInt(DT_FILTER, InX::DynStrTab->addString(S));
+ addInt(DT_FILTER, In.DynStrTab->addString(S));
for (StringRef S : Config->AuxiliaryList)
- addInt(DT_AUXILIARY, InX::DynStrTab->addString(S));
+ addInt(DT_AUXILIARY, In.DynStrTab->addString(S));
if (!Config->Rpath.empty())
addInt(Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH,
- InX::DynStrTab->addString(Config->Rpath));
+ In.DynStrTab->addString(Config->Rpath));
for (InputFile *File : SharedFiles) {
SharedFile<ELFT> *F = cast<SharedFile<ELFT>>(File);
if (F->IsNeeded)
- addInt(DT_NEEDED, InX::DynStrTab->addString(F->SoName));
+ addInt(DT_NEEDED, In.DynStrTab->addString(F->SoName));
}
if (!Config->SoName.empty())
- addInt(DT_SONAME, InX::DynStrTab->addString(Config->SoName));
+ addInt(DT_SONAME, In.DynStrTab->addString(Config->SoName));
}
template <class ELFT>
@@ -1254,18 +1255,33 @@ void DynamicSection<ELFT>::addSym(int32_t Tag, Symbol *Sym) {
Entries.push_back({Tag, [=] { return Sym->getVA(); }});
}
+// A Linker script may assign the RELA relocation sections to the same
+// output section. When this occurs we cannot just use the OutputSection
+// Size. Moreover the [DT_JMPREL, DT_JMPREL + DT_PLTRELSZ) is permitted to
+// overlap with the [DT_RELA, DT_RELA + DT_RELASZ).
+static uint64_t addPltRelSz() {
+ size_t Size = In.RelaPlt->getSize();
+ if (In.RelaIplt->getParent() == In.RelaPlt->getParent() &&
+ In.RelaIplt->Name == In.RelaPlt->Name)
+ Size += In.RelaIplt->getSize();
+ return Size;
+}
+
// Add remaining entries to complete .dynamic contents.
template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
- if (this->Size)
- return; // Already finalized.
-
// Set DT_FLAGS and DT_FLAGS_1.
uint32_t DtFlags = 0;
uint32_t DtFlags1 = 0;
if (Config->Bsymbolic)
DtFlags |= DF_SYMBOLIC;
+ if (Config->ZGlobal)
+ DtFlags1 |= DF_1_GLOBAL;
if (Config->ZInitfirst)
DtFlags1 |= DF_1_INITFIRST;
+ if (Config->ZInterpose)
+ DtFlags1 |= DF_1_INTERPOSE;
+ if (Config->ZNodefaultlib)
+ DtFlags1 |= DF_1_NODEFLIB;
if (Config->ZNodelete)
DtFlags1 |= DF_1_NODELETE;
if (Config->ZNodlopen)
@@ -1297,10 +1313,12 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
if (!Config->Shared && !Config->Relocatable && !Config->ZRodynamic)
addInt(DT_DEBUG, 0);
- this->Link = InX::DynStrTab->getParent()->SectionIndex;
- if (!InX::RelaDyn->empty()) {
- addInSec(InX::RelaDyn->DynamicTag, InX::RelaDyn);
- addSize(InX::RelaDyn->SizeDynamicTag, InX::RelaDyn->getParent());
+ if (OutputSection *Sec = In.DynStrTab->getParent())
+ this->Link = Sec->SectionIndex;
+
+ if (!In.RelaDyn->empty()) {
+ addInSec(In.RelaDyn->DynamicTag, In.RelaDyn);
+ addSize(In.RelaDyn->SizeDynamicTag, In.RelaDyn->getParent());
bool IsRela = Config->IsRela;
addInt(IsRela ? DT_RELAENT : DT_RELENT,
@@ -1310,16 +1328,16 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
// The problem is in the tight relation between dynamic
// relocations and GOT. So do not emit this tag on MIPS.
if (Config->EMachine != EM_MIPS) {
- size_t NumRelativeRels = InX::RelaDyn->getRelativeRelocCount();
+ size_t NumRelativeRels = In.RelaDyn->getRelativeRelocCount();
if (Config->ZCombreloc && NumRelativeRels)
addInt(IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels);
}
}
- if (InX::RelrDyn && !InX::RelrDyn->Relocs.empty()) {
+ if (In.RelrDyn && !In.RelrDyn->Relocs.empty()) {
addInSec(Config->UseAndroidRelrTags ? DT_ANDROID_RELR : DT_RELR,
- InX::RelrDyn);
+ In.RelrDyn);
addSize(Config->UseAndroidRelrTags ? DT_ANDROID_RELRSZ : DT_RELRSZ,
- InX::RelrDyn->getParent());
+ In.RelrDyn->getParent());
addInt(Config->UseAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT,
sizeof(Elf_Relr));
}
@@ -1329,33 +1347,33 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
// as RelaIplt have. And we still want to emit proper dynamic tags for that
// case, so here we always use RelaPlt as marker for the begining of
// .rel[a].plt section.
- if (InX::RelaPlt->getParent()->Live) {
- addInSec(DT_JMPREL, InX::RelaPlt);
- addSize(DT_PLTRELSZ, InX::RelaPlt->getParent());
+ if (In.RelaPlt->getParent()->Live) {
+ addInSec(DT_JMPREL, In.RelaPlt);
+ Entries.push_back({DT_PLTRELSZ, addPltRelSz});
switch (Config->EMachine) {
case EM_MIPS:
- addInSec(DT_MIPS_PLTGOT, InX::GotPlt);
+ addInSec(DT_MIPS_PLTGOT, In.GotPlt);
break;
case EM_SPARCV9:
- addInSec(DT_PLTGOT, InX::Plt);
+ addInSec(DT_PLTGOT, In.Plt);
break;
default:
- addInSec(DT_PLTGOT, InX::GotPlt);
+ addInSec(DT_PLTGOT, In.GotPlt);
break;
}
addInt(DT_PLTREL, Config->IsRela ? DT_RELA : DT_REL);
}
- addInSec(DT_SYMTAB, InX::DynSymTab);
+ addInSec(DT_SYMTAB, In.DynSymTab);
addInt(DT_SYMENT, sizeof(Elf_Sym));
- addInSec(DT_STRTAB, InX::DynStrTab);
- addInt(DT_STRSZ, InX::DynStrTab->getSize());
+ addInSec(DT_STRTAB, In.DynStrTab);
+ addInt(DT_STRSZ, In.DynStrTab->getSize());
if (!Config->ZText)
addInt(DT_TEXTREL, 0);
- if (InX::GnuHashTab)
- addInSec(DT_GNU_HASH, InX::GnuHashTab);
- if (InX::HashTab)
- addInSec(DT_HASH, InX::HashTab);
+ if (In.GnuHashTab)
+ addInSec(DT_GNU_HASH, In.GnuHashTab);
+ if (In.HashTab)
+ addInSec(DT_HASH, In.HashTab);
if (Out::PreinitArray) {
addOutSec(DT_PREINIT_ARRAY, Out::PreinitArray);
@@ -1377,47 +1395,47 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
if (B->isDefined())
addSym(DT_FINI, B);
- bool HasVerNeed = In<ELFT>::VerNeed->getNeedNum() != 0;
- if (HasVerNeed || In<ELFT>::VerDef)
- addInSec(DT_VERSYM, In<ELFT>::VerSym);
- if (In<ELFT>::VerDef) {
- addInSec(DT_VERDEF, In<ELFT>::VerDef);
+ bool HasVerNeed = InX<ELFT>::VerNeed->getNeedNum() != 0;
+ if (HasVerNeed || In.VerDef)
+ addInSec(DT_VERSYM, InX<ELFT>::VerSym);
+ if (In.VerDef) {
+ addInSec(DT_VERDEF, In.VerDef);
addInt(DT_VERDEFNUM, getVerDefNum());
}
if (HasVerNeed) {
- addInSec(DT_VERNEED, In<ELFT>::VerNeed);
- addInt(DT_VERNEEDNUM, In<ELFT>::VerNeed->getNeedNum());
+ addInSec(DT_VERNEED, InX<ELFT>::VerNeed);
+ addInt(DT_VERNEEDNUM, InX<ELFT>::VerNeed->getNeedNum());
}
if (Config->EMachine == EM_MIPS) {
addInt(DT_MIPS_RLD_VERSION, 1);
addInt(DT_MIPS_FLAGS, RHF_NOTPOT);
addInt(DT_MIPS_BASE_ADDRESS, Target->getImageBase());
- addInt(DT_MIPS_SYMTABNO, InX::DynSymTab->getNumSymbols());
+ addInt(DT_MIPS_SYMTABNO, In.DynSymTab->getNumSymbols());
- add(DT_MIPS_LOCAL_GOTNO, [] { return InX::MipsGot->getLocalEntriesNum(); });
+ add(DT_MIPS_LOCAL_GOTNO, [] { return In.MipsGot->getLocalEntriesNum(); });
- if (const Symbol *B = InX::MipsGot->getFirstGlobalEntry())
+ if (const Symbol *B = In.MipsGot->getFirstGlobalEntry())
addInt(DT_MIPS_GOTSYM, B->DynsymIndex);
else
- addInt(DT_MIPS_GOTSYM, InX::DynSymTab->getNumSymbols());
- addInSec(DT_PLTGOT, InX::MipsGot);
- if (InX::MipsRldMap) {
+ addInt(DT_MIPS_GOTSYM, In.DynSymTab->getNumSymbols());
+ addInSec(DT_PLTGOT, In.MipsGot);
+ if (In.MipsRldMap) {
if (!Config->Pie)
- addInSec(DT_MIPS_RLD_MAP, InX::MipsRldMap);
+ addInSec(DT_MIPS_RLD_MAP, In.MipsRldMap);
// Store the offset to the .rld_map section
// relative to the address of the tag.
- addInSecRelative(DT_MIPS_RLD_MAP_REL, InX::MipsRldMap);
+ addInSecRelative(DT_MIPS_RLD_MAP_REL, In.MipsRldMap);
}
}
// Glink dynamic tag is required by the V2 abi if the plt section isn't empty.
- if (Config->EMachine == EM_PPC64 && !InX::Plt->empty()) {
+ if (Config->EMachine == EM_PPC64 && !In.Plt->empty()) {
// The Glink tag points to 32 bytes before the first lazy symbol resolution
// stub, which starts directly after the header.
Entries.push_back({DT_PPC64_GLINK, [=] {
unsigned Offset = Target->PltHeaderSize - 32;
- return InX::Plt->getVA(0) + Offset;
+ return In.Plt->getVA(0) + Offset;
}});
}
@@ -1486,13 +1504,17 @@ void RelocationBaseSection::addReloc(const DynamicReloc &Reloc) {
}
void RelocationBaseSection::finalizeContents() {
- // If all relocations are R_*_RELATIVE they don't refer to any
- // dynamic symbol and we don't need a dynamic symbol table. If that
- // is the case, just use 0 as the link.
- Link = InX::DynSymTab ? InX::DynSymTab->getParent()->SectionIndex : 0;
+ // When linking glibc statically, .rel{,a}.plt contains R_*_IRELATIVE
+ // relocations due to IFUNC (e.g. strcpy). sh_link will be set to 0 in that
+ // case.
+ InputSection *SymTab = Config->Relocatable ? In.SymTab : In.DynSymTab;
+ if (SymTab && SymTab->getParent())
+ getParent()->Link = SymTab->getParent()->SectionIndex;
+ else
+ getParent()->Link = 0;
- // Set required output section properties.
- getParent()->Link = Link;
+ if (In.RelaIplt == this || In.RelaPlt == this)
+ getParent()->Info = In.GotPlt->getParent()->SectionIndex;
}
RelrBaseSection::RelrBaseSection()
@@ -1621,10 +1643,9 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
NonRelatives.push_back(R);
}
- llvm::sort(Relatives.begin(), Relatives.end(),
- [](const Elf_Rel &A, const Elf_Rel &B) {
- return A.r_offset < B.r_offset;
- });
+ llvm::sort(Relatives, [](const Elf_Rel &A, const Elf_Rel &B) {
+ return A.r_offset < B.r_offset;
+ });
// Try to find groups of relative relocations which are spaced one word
// apart from one another. These generally correspond to vtable entries. The
@@ -1702,10 +1723,9 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
}
// Finally the non-relative relocations.
- llvm::sort(NonRelatives.begin(), NonRelatives.end(),
- [](const Elf_Rela &A, const Elf_Rela &B) {
- return A.r_offset < B.r_offset;
- });
+ llvm::sort(NonRelatives, [](const Elf_Rela &A, const Elf_Rela &B) {
+ return A.r_offset < B.r_offset;
+ });
if (!NonRelatives.empty()) {
Add(NonRelatives.size());
Add(HasAddendIfRela);
@@ -1720,6 +1740,11 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
}
}
+ // Don't allow the section to shrink; otherwise the size of the section can
+ // oscillate infinitely.
+ if (RelocData.size() < OldSize)
+ RelocData.append(OldSize - RelocData.size(), 0);
+
// Returns whether the section size changed. We need to keep recomputing both
// section layout and the contents of this section until the size converges
// because changing this section's size can affect section layout, which in
@@ -1843,10 +1868,13 @@ static bool sortMipsSymbols(const SymbolTableEntry &L,
}
void SymbolTableBaseSection::finalizeContents() {
- getParent()->Link = StrTabSec.getParent()->SectionIndex;
+ if (OutputSection *Sec = StrTabSec.getParent())
+ getParent()->Link = Sec->SectionIndex;
- if (this->Type != SHT_DYNSYM)
+ if (this->Type != SHT_DYNSYM) {
+ sortSymTabSymbols();
return;
+ }
// If it is a .dynsym, there should be no local symbols, but we need
// to do a few things for the dynamic linker.
@@ -1855,9 +1883,9 @@ void SymbolTableBaseSection::finalizeContents() {
// Because the first symbol entry is a null entry, 1 is the first.
getParent()->Info = 1;
- if (InX::GnuHashTab) {
+ if (In.GnuHashTab) {
// NB: It also sorts Symbols to meet the GNU hash table requirements.
- InX::GnuHashTab->addSymbols(Symbols);
+ In.GnuHashTab->addSymbols(Symbols);
} else if (Config->EMachine == EM_MIPS) {
std::stable_sort(Symbols.begin(), Symbols.end(), sortMipsSymbols);
}
@@ -1874,9 +1902,7 @@ void SymbolTableBaseSection::finalizeContents() {
// Aside from above, we put local symbols in groups starting with the STT_FILE
// symbol. That is convenient for purpose of identifying where are local symbols
// coming from.
-void SymbolTableBaseSection::postThunkContents() {
- assert(this->Type == SHT_SYMTAB);
-
+void SymbolTableBaseSection::sortSymTabSymbols() {
// Move all local symbols before global symbols.
auto E = std::stable_partition(
Symbols.begin(), Symbols.end(), [](const SymbolTableEntry &S) {
@@ -1948,7 +1974,8 @@ static uint32_t getSymSectionIndex(Symbol *Sym) {
if (!isa<Defined>(Sym) || Sym->NeedsPltAddr)
return SHN_UNDEF;
if (const OutputSection *OS = Sym->getOutputSection())
- return OS->SectionIndex >= SHN_LORESERVE ? SHN_XINDEX : OS->SectionIndex;
+ return OS->SectionIndex >= SHN_LORESERVE ? (uint32_t)SHN_XINDEX
+ : OS->SectionIndex;
return SHN_ABS;
}
@@ -2038,7 +2065,7 @@ void SymtabShndxSection::writeTo(uint8_t *Buf) {
// with an entry in .symtab. If the corresponding entry contains SHN_XINDEX,
// we need to write actual index, otherwise, we must write SHN_UNDEF(0).
Buf += 4; // Ignore .symtab[0] entry.
- for (const SymbolTableEntry &Entry : InX::SymTab->getSymbols()) {
+ for (const SymbolTableEntry &Entry : In.SymTab->getSymbols()) {
if (getSymSectionIndex(Entry.Sym) == SHN_XINDEX)
write32(Buf, Entry.Sym->getOutputSection()->SectionIndex);
Buf += 4;
@@ -2059,11 +2086,11 @@ bool SymtabShndxSection::empty() const {
}
void SymtabShndxSection::finalizeContents() {
- getParent()->Link = InX::SymTab->getParent()->SectionIndex;
+ getParent()->Link = In.SymTab->getParent()->SectionIndex;
}
size_t SymtabShndxSection::getSize() const {
- return InX::SymTab->getNumSymbols() * 4;
+ return In.SymTab->getNumSymbols() * 4;
}
// .hash and .gnu.hash sections contain on-disk hash tables that map
@@ -2102,7 +2129,8 @@ GnuHashTableSection::GnuHashTableSection()
}
void GnuHashTableSection::finalizeContents() {
- getParent()->Link = InX::DynSymTab->getParent()->SectionIndex;
+ if (OutputSection *Sec = In.DynSymTab->getParent())
+ getParent()->Link = Sec->SectionIndex;
// Computes bloom filter size in word size. We want to allocate 12
// bits for each symbol. It must be a power of two.
@@ -2127,7 +2155,7 @@ void GnuHashTableSection::writeTo(uint8_t *Buf) {
// Write a header.
write32(Buf, NBuckets);
- write32(Buf + 4, InX::DynSymTab->getNumSymbols() - Symbols.size());
+ write32(Buf + 4, In.DynSymTab->getNumSymbols() - Symbols.size());
write32(Buf + 8, MaskWords);
write32(Buf + 12, Shift2);
Buf += 16;
@@ -2148,6 +2176,8 @@ void GnuHashTableSection::writeTo(uint8_t *Buf) {
void GnuHashTableSection::writeBloomFilter(uint8_t *Buf) {
unsigned C = Config->Is64 ? 64 : 32;
for (const Entry &Sym : Symbols) {
+ // When C = 64, we choose a word with bits [6:...] and set 1 to two bits in
+ // the word using bits [0:5] and [26:31].
size_t I = (Sym.Hash / C) & (MaskWords - 1);
uint64_t Val = readUint(Buf + I * Config->Wordsize);
Val |= uint64_t(1) << (Sym.Hash % C);
@@ -2232,13 +2262,14 @@ HashTableSection::HashTableSection()
}
void HashTableSection::finalizeContents() {
- getParent()->Link = InX::DynSymTab->getParent()->SectionIndex;
+ if (OutputSection *Sec = In.DynSymTab->getParent())
+ getParent()->Link = Sec->SectionIndex;
unsigned NumEntries = 2; // nbucket and nchain.
- NumEntries += InX::DynSymTab->getNumSymbols(); // The chain entries.
+ NumEntries += In.DynSymTab->getNumSymbols(); // The chain entries.
// Create as many buckets as there are symbols.
- NumEntries += InX::DynSymTab->getNumSymbols();
+ NumEntries += In.DynSymTab->getNumSymbols();
this->Size = NumEntries * 4;
}
@@ -2246,7 +2277,7 @@ void HashTableSection::writeTo(uint8_t *Buf) {
// See comment in GnuHashTableSection::writeTo.
memset(Buf, 0, Size);
- unsigned NumSymbols = InX::DynSymTab->getNumSymbols();
+ unsigned NumSymbols = In.DynSymTab->getNumSymbols();
uint32_t *P = reinterpret_cast<uint32_t *>(Buf);
write32(P++, NumSymbols); // nbucket
@@ -2255,7 +2286,7 @@ void HashTableSection::writeTo(uint8_t *Buf) {
uint32_t *Buckets = P;
uint32_t *Chains = P + NumSymbols;
- for (const SymbolTableEntry &S : InX::DynSymTab->getSymbols()) {
+ for (const SymbolTableEntry &S : In.DynSymTab->getSymbols()) {
Symbol *Sym = S.Sym;
StringRef Name = Sym->getName();
unsigned I = Sym->DynsymIndex;
@@ -2270,7 +2301,8 @@ void HashTableSection::writeTo(uint8_t *Buf) {
PltSection::PltSection(bool IsIplt)
: SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16,
Config->EMachine == EM_PPC64 ? ".glink" : ".plt"),
- HeaderSize(IsIplt ? 0 : Target->PltHeaderSize), IsIplt(IsIplt) {
+ HeaderSize(!IsIplt || Config->ZRetpolineplt ? Target->PltHeaderSize : 0),
+ IsIplt(IsIplt) {
// The PLT needs to be writable on SPARC as the dynamic linker will
// modify the instructions in the PLT entries.
if (Config->EMachine == EM_SPARCV9)
@@ -2278,9 +2310,9 @@ PltSection::PltSection(bool IsIplt)
}
void PltSection::writeTo(uint8_t *Buf) {
- // At beginning of PLT but not the IPLT, we have code to call the dynamic
+ // At beginning of PLT or retpoline IPLT, we have code to call the dynamic
// linker to resolve dynsyms at runtime. Write such code.
- if (!IsIplt)
+ if (HeaderSize > 0)
Target->writePltHeader(Buf);
size_t Off = HeaderSize;
// The IPlt is immediately after the Plt, account for this in RelOff
@@ -2298,9 +2330,9 @@ void PltSection::writeTo(uint8_t *Buf) {
template <class ELFT> void PltSection::addEntry(Symbol &Sym) {
Sym.PltIndex = Entries.size();
- RelocationBaseSection *PltRelocSection = InX::RelaPlt;
+ RelocationBaseSection *PltRelocSection = In.RelaPlt;
if (IsIplt) {
- PltRelocSection = InX::RelaIplt;
+ PltRelocSection = In.RelaIplt;
Sym.IsInIplt = true;
}
unsigned RelOff =
@@ -2326,14 +2358,14 @@ void PltSection::addSymbols() {
}
unsigned PltSection::getPltRelocOff() const {
- return IsIplt ? InX::Plt->getSize() : 0;
+ return IsIplt ? In.Plt->getSize() : 0;
}
// The string hash function for .gdb_index.
static uint32_t computeGdbHash(StringRef S) {
uint32_t H = 0;
for (uint8_t C : S)
- H = H * 67 + tolower(C) - 113;
+ H = H * 67 + toLower(C) - 113;
return H;
}
@@ -2371,7 +2403,7 @@ static std::vector<InputSection *> getDebugInfoSections() {
static std::vector<GdbIndexSection::CuEntry> readCuList(DWARFContext &Dwarf) {
std::vector<GdbIndexSection::CuEntry> Ret;
- for (std::unique_ptr<DWARFCompileUnit> &Cu : Dwarf.compile_units())
+ for (std::unique_ptr<DWARFUnit> &Cu : Dwarf.compile_units())
Ret.push_back({Cu->getOffset(), Cu->getLength() + 4});
return Ret;
}
@@ -2381,12 +2413,15 @@ readAddressAreas(DWARFContext &Dwarf, InputSection *Sec) {
std::vector<GdbIndexSection::AddressEntry> Ret;
uint32_t CuIdx = 0;
- for (std::unique_ptr<DWARFCompileUnit> &Cu : Dwarf.compile_units()) {
- DWARFAddressRangesVector Ranges;
- Cu->collectAddressRanges(Ranges);
+ for (std::unique_ptr<DWARFUnit> &Cu : Dwarf.compile_units()) {
+ Expected<DWARFAddressRangesVector> Ranges = Cu->collectAddressRanges();
+ if (!Ranges) {
+ error(toString(Sec) + ": " + toString(Ranges.takeError()));
+ return {};
+ }
ArrayRef<InputSectionBase *> Sections = Sec->File->getSections();
- for (DWARFAddressRange &R : Ranges) {
+ for (DWARFAddressRange &R : *Ranges) {
InputSectionBase *S = Sections[R.SectionIndex];
if (!S || S == &InputSection::Discarded || !S->Live)
continue;
@@ -2399,21 +2434,35 @@ readAddressAreas(DWARFContext &Dwarf, InputSection *Sec) {
}
++CuIdx;
}
+
return Ret;
}
-static std::vector<GdbIndexSection::NameTypeEntry>
-readPubNamesAndTypes(DWARFContext &Dwarf, uint32_t Idx) {
- StringRef Sec1 = Dwarf.getDWARFObj().getGnuPubNamesSection();
- StringRef Sec2 = Dwarf.getDWARFObj().getGnuPubTypesSection();
-
- std::vector<GdbIndexSection::NameTypeEntry> Ret;
- for (StringRef Sec : {Sec1, Sec2}) {
- DWARFDebugPubTable Table(Sec, Config->IsLE, true);
- for (const DWARFDebugPubTable::Set &Set : Table.getData())
+template <class ELFT>
+static std::vector<GdbIndexSection::NameAttrEntry>
+readPubNamesAndTypes(const LLDDwarfObj<ELFT> &Obj,
+ const std::vector<GdbIndexSection::CuEntry> &CUs) {
+ const DWARFSection &PubNames = Obj.getGnuPubNamesSection();
+ const DWARFSection &PubTypes = Obj.getGnuPubTypesSection();
+
+ std::vector<GdbIndexSection::NameAttrEntry> Ret;
+ for (const DWARFSection *Pub : {&PubNames, &PubTypes}) {
+ DWARFDebugPubTable Table(Obj, *Pub, Config->IsLE, true);
+ for (const DWARFDebugPubTable::Set &Set : Table.getData()) {
+ // The value written into the constant pool is Kind << 24 | CuIndex. As we
+ // don't know how many compilation units precede this object to compute
+ // CuIndex, we compute (Kind << 24 | CuIndexInThisObject) instead, and add
+ // the number of preceding compilation units later.
+ uint32_t I =
+ lower_bound(CUs, Set.Offset,
+ [](GdbIndexSection::CuEntry CU, uint32_t Offset) {
+ return CU.CuOffset < Offset;
+ }) -
+ CUs.begin();
for (const DWARFDebugPubTable::Entry &Ent : Set.Entries)
Ret.push_back({{Ent.Name, computeGdbHash(Ent.Name)},
- (Ent.Descriptor.toBits() << 24) | Idx});
+ (Ent.Descriptor.toBits() << 24) | I});
+ }
}
return Ret;
}
@@ -2421,9 +2470,18 @@ readPubNamesAndTypes(DWARFContext &Dwarf, uint32_t Idx) {
// Create a list of symbols from a given list of symbol names and types
// by uniquifying them by name.
static std::vector<GdbIndexSection::GdbSymbol>
-createSymbols(ArrayRef<std::vector<GdbIndexSection::NameTypeEntry>> NameTypes) {
+createSymbols(ArrayRef<std::vector<GdbIndexSection::NameAttrEntry>> NameAttrs,
+ const std::vector<GdbIndexSection::GdbChunk> &Chunks) {
typedef GdbIndexSection::GdbSymbol GdbSymbol;
- typedef GdbIndexSection::NameTypeEntry NameTypeEntry;
+ typedef GdbIndexSection::NameAttrEntry NameAttrEntry;
+
+ // For each chunk, compute the number of compilation units preceding it.
+ uint32_t CuIdx = 0;
+ std::vector<uint32_t> CuIdxs(Chunks.size());
+ for (uint32_t I = 0, E = Chunks.size(); I != E; ++I) {
+ CuIdxs[I] = CuIdx;
+ CuIdx += Chunks[I].CompilationUnits.size();
+ }
// The number of symbols we will handle in this function is of the order
// of millions for very large executables, so we use multi-threading to
@@ -2441,21 +2499,24 @@ createSymbols(ArrayRef<std::vector<GdbIndexSection::NameTypeEntry>> NameTypes) {
// Instantiate GdbSymbols while uniqufying them by name.
std::vector<std::vector<GdbSymbol>> Symbols(NumShards);
parallelForEachN(0, Concurrency, [&](size_t ThreadId) {
- for (ArrayRef<NameTypeEntry> Entries : NameTypes) {
- for (const NameTypeEntry &Ent : Entries) {
+ uint32_t I = 0;
+ for (ArrayRef<NameAttrEntry> Entries : NameAttrs) {
+ for (const NameAttrEntry &Ent : Entries) {
size_t ShardId = Ent.Name.hash() >> Shift;
if ((ShardId & (Concurrency - 1)) != ThreadId)
continue;
+ uint32_t V = Ent.CuIndexAndAttrs + CuIdxs[I];
size_t &Idx = Map[ShardId][Ent.Name];
if (Idx) {
- Symbols[ShardId][Idx - 1].CuVector.push_back(Ent.Type);
+ Symbols[ShardId][Idx - 1].CuVector.push_back(V);
continue;
}
Idx = Symbols[ShardId].size() + 1;
- Symbols[ShardId].push_back({Ent.Name, {Ent.Type}, 0, 0});
+ Symbols[ShardId].push_back({Ent.Name, {V}, 0, 0});
}
+ ++I;
}
});
@@ -2498,7 +2559,7 @@ template <class ELFT> GdbIndexSection *GdbIndexSection::create() {
S->Live = false;
std::vector<GdbChunk> Chunks(Sections.size());
- std::vector<std::vector<NameTypeEntry>> NameTypes(Sections.size());
+ std::vector<std::vector<NameAttrEntry>> NameAttrs(Sections.size());
parallelForEachN(0, Sections.size(), [&](size_t I) {
ObjFile<ELFT> *File = Sections[I]->getFile<ELFT>();
@@ -2507,12 +2568,14 @@ template <class ELFT> GdbIndexSection *GdbIndexSection::create() {
Chunks[I].Sec = Sections[I];
Chunks[I].CompilationUnits = readCuList(Dwarf);
Chunks[I].AddressAreas = readAddressAreas(Dwarf, Sections[I]);
- NameTypes[I] = readPubNamesAndTypes(Dwarf, I);
+ NameAttrs[I] = readPubNamesAndTypes<ELFT>(
+ static_cast<const LLDDwarfObj<ELFT> &>(Dwarf.getDWARFObj()),
+ Chunks[I].CompilationUnits);
});
auto *Ret = make<GdbIndexSection>();
Ret->Chunks = std::move(Chunks);
- Ret->Symbols = createSymbols(NameTypes);
+ Ret->Symbols = createSymbols(NameAttrs, Ret->Chunks);
Ret->initOutputSize();
return Ret;
}
@@ -2570,8 +2633,9 @@ void GdbIndexSection::writeTo(uint8_t *Buf) {
// Write the string pool.
Hdr->ConstantPoolOff = Buf - Start;
- for (GdbSymbol &Sym : Symbols)
+ parallelForEach(Symbols, [&](GdbSymbol &Sym) {
memcpy(Buf + Sym.NameOff, Sym.Name.data(), Sym.Name.size());
+ });
// Write the CU vectors.
for (GdbSymbol &Sym : Symbols) {
@@ -2584,7 +2648,7 @@ void GdbIndexSection::writeTo(uint8_t *Buf) {
}
}
-bool GdbIndexSection::empty() const { return !Out::DebugInfo; }
+bool GdbIndexSection::empty() const { return Chunks.empty(); }
EhFrameHeader::EhFrameHeader()
: SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 4, ".eh_frame_hdr") {}
@@ -2596,13 +2660,13 @@ EhFrameHeader::EhFrameHeader()
void EhFrameHeader::writeTo(uint8_t *Buf) {
typedef EhFrameSection::FdeData FdeData;
- std::vector<FdeData> Fdes = InX::EhFrame->getFdeData();
+ std::vector<FdeData> Fdes = In.EhFrame->getFdeData();
Buf[0] = 1;
Buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4;
Buf[2] = DW_EH_PE_udata4;
Buf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4;
- write32(Buf + 4, InX::EhFrame->getParent()->Addr - this->getVA() - 4);
+ write32(Buf + 4, In.EhFrame->getParent()->Addr - this->getVA() - 4);
write32(Buf + 8, Fdes.size());
Buf += 12;
@@ -2615,13 +2679,12 @@ void EhFrameHeader::writeTo(uint8_t *Buf) {
size_t EhFrameHeader::getSize() const {
// .eh_frame_hdr has a 12 bytes header followed by an array of FDEs.
- return 12 + InX::EhFrame->NumFdes * 8;
+ return 12 + In.EhFrame->NumFdes * 8;
}
-bool EhFrameHeader::empty() const { return InX::EhFrame->empty(); }
+bool EhFrameHeader::empty() const { return In.EhFrame->empty(); }
-template <class ELFT>
-VersionDefinitionSection<ELFT>::VersionDefinitionSection()
+VersionDefinitionSection::VersionDefinitionSection()
: SyntheticSection(SHF_ALLOC, SHT_GNU_verdef, sizeof(uint32_t),
".gnu.version_d") {}
@@ -2631,12 +2694,13 @@ static StringRef getFileDefName() {
return Config->OutputFile;
}
-template <class ELFT> void VersionDefinitionSection<ELFT>::finalizeContents() {
- FileDefNameOff = InX::DynStrTab->addString(getFileDefName());
+void VersionDefinitionSection::finalizeContents() {
+ FileDefNameOff = In.DynStrTab->addString(getFileDefName());
for (VersionDefinition &V : Config->VersionDefinitions)
- V.NameOff = InX::DynStrTab->addString(V.Name);
+ V.NameOff = In.DynStrTab->addString(V.Name);
- getParent()->Link = InX::DynStrTab->getParent()->SectionIndex;
+ if (OutputSection *Sec = In.DynStrTab->getParent())
+ getParent()->Link = Sec->SectionIndex;
// sh_info should be set to the number of definitions. This fact is missed in
// documentation, but confirmed by binutils community:
@@ -2644,68 +2708,68 @@ template <class ELFT> void VersionDefinitionSection<ELFT>::finalizeContents() {
getParent()->Info = getVerDefNum();
}
-template <class ELFT>
-void VersionDefinitionSection<ELFT>::writeOne(uint8_t *Buf, uint32_t Index,
- StringRef Name, size_t NameOff) {
- auto *Verdef = reinterpret_cast<Elf_Verdef *>(Buf);
- Verdef->vd_version = 1;
- Verdef->vd_cnt = 1;
- Verdef->vd_aux = sizeof(Elf_Verdef);
- Verdef->vd_next = sizeof(Elf_Verdef) + sizeof(Elf_Verdaux);
- Verdef->vd_flags = (Index == 1 ? VER_FLG_BASE : 0);
- Verdef->vd_ndx = Index;
- Verdef->vd_hash = hashSysV(Name);
-
- auto *Verdaux = reinterpret_cast<Elf_Verdaux *>(Buf + sizeof(Elf_Verdef));
- Verdaux->vda_name = NameOff;
- Verdaux->vda_next = 0;
+void VersionDefinitionSection::writeOne(uint8_t *Buf, uint32_t Index,
+ StringRef Name, size_t NameOff) {
+ uint16_t Flags = Index == 1 ? VER_FLG_BASE : 0;
+
+ // Write a verdef.
+ write16(Buf, 1); // vd_version
+ write16(Buf + 2, Flags); // vd_flags
+ write16(Buf + 4, Index); // vd_ndx
+ write16(Buf + 6, 1); // vd_cnt
+ write32(Buf + 8, hashSysV(Name)); // vd_hash
+ write32(Buf + 12, 20); // vd_aux
+ write32(Buf + 16, 28); // vd_next
+
+ // Write a veraux.
+ write32(Buf + 20, NameOff); // vda_name
+ write32(Buf + 24, 0); // vda_next
}
-template <class ELFT>
-void VersionDefinitionSection<ELFT>::writeTo(uint8_t *Buf) {
+void VersionDefinitionSection::writeTo(uint8_t *Buf) {
writeOne(Buf, 1, getFileDefName(), FileDefNameOff);
for (VersionDefinition &V : Config->VersionDefinitions) {
- Buf += sizeof(Elf_Verdef) + sizeof(Elf_Verdaux);
+ Buf += EntrySize;
writeOne(Buf, V.Id, V.Name, V.NameOff);
}
// Need to terminate the last version definition.
- Elf_Verdef *Verdef = reinterpret_cast<Elf_Verdef *>(Buf);
- Verdef->vd_next = 0;
+ write32(Buf + 16, 0); // vd_next
}
-template <class ELFT> size_t VersionDefinitionSection<ELFT>::getSize() const {
- return (sizeof(Elf_Verdef) + sizeof(Elf_Verdaux)) * getVerDefNum();
+size_t VersionDefinitionSection::getSize() const {
+ return EntrySize * getVerDefNum();
}
+// .gnu.version is a table where each entry is 2 byte long.
template <class ELFT>
VersionTableSection<ELFT>::VersionTableSection()
: SyntheticSection(SHF_ALLOC, SHT_GNU_versym, sizeof(uint16_t),
".gnu.version") {
- this->Entsize = sizeof(Elf_Versym);
+ this->Entsize = 2;
}
template <class ELFT> void VersionTableSection<ELFT>::finalizeContents() {
// At the moment of june 2016 GNU docs does not mention that sh_link field
// should be set, but Sun docs do. Also readelf relies on this field.
- getParent()->Link = InX::DynSymTab->getParent()->SectionIndex;
+ getParent()->Link = In.DynSymTab->getParent()->SectionIndex;
}
template <class ELFT> size_t VersionTableSection<ELFT>::getSize() const {
- return sizeof(Elf_Versym) * (InX::DynSymTab->getSymbols().size() + 1);
+ return (In.DynSymTab->getSymbols().size() + 1) * 2;
}
template <class ELFT> void VersionTableSection<ELFT>::writeTo(uint8_t *Buf) {
- auto *OutVersym = reinterpret_cast<Elf_Versym *>(Buf) + 1;
- for (const SymbolTableEntry &S : InX::DynSymTab->getSymbols()) {
- OutVersym->vs_index = S.Sym->VersionId;
- ++OutVersym;
+ Buf += 2;
+ for (const SymbolTableEntry &S : In.DynSymTab->getSymbols()) {
+ write16(Buf, S.Sym->VersionId);
+ Buf += 2;
}
}
template <class ELFT> bool VersionTableSection<ELFT>::empty() const {
- return !In<ELFT>::VerDef && In<ELFT>::VerNeed->empty();
+ return !In.VerDef && InX<ELFT>::VerNeed->empty();
}
template <class ELFT>
@@ -2729,7 +2793,7 @@ template <class ELFT> void VersionNeedSection<ELFT>::addSymbol(Symbol *SS) {
// to create one by adding it to our needed list and creating a dynstr entry
// for the soname.
if (File.VerdefMap.empty())
- Needed.push_back({&File, InX::DynStrTab->addString(File.SoName)});
+ Needed.push_back({&File, In.DynStrTab->addString(File.SoName)});
const typename ELFT::Verdef *Ver = File.Verdefs[SS->VerdefIndex];
typename SharedFile<ELFT>::NeededVer &NV = File.VerdefMap[Ver];
@@ -2737,8 +2801,8 @@ template <class ELFT> void VersionNeedSection<ELFT>::addSymbol(Symbol *SS) {
// prepare to create one by allocating a version identifier and creating a
// dynstr entry for the version name.
if (NV.Index == 0) {
- NV.StrTab = InX::DynStrTab->addString(File.getStringTable().data() +
- Ver->getAux()->vda_name);
+ NV.StrTab = In.DynStrTab->addString(File.getStringTable().data() +
+ Ver->getAux()->vda_name);
NV.Index = NextIndex++;
}
SS->VersionId = NV.Index;
@@ -2780,7 +2844,8 @@ template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *Buf) {
}
template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() {
- getParent()->Link = InX::DynStrTab->getParent()->SectionIndex;
+ if (OutputSection *Sec = In.DynStrTab->getParent())
+ getParent()->Link = Sec->SectionIndex;
getParent()->Info = Needed.size();
}
@@ -2896,12 +2961,6 @@ static MergeSyntheticSection *createMergeSynthetic(StringRef Name,
return make<MergeNoTailSection>(Name, Type, Flags, Alignment);
}
-// Debug sections may be compressed by zlib. Decompress if exists.
-void elf::decompressSections() {
- parallelForEach(InputSections,
- [](InputSectionBase *Sec) { Sec->maybeDecompress(); });
-}
-
template <class ELFT> void elf::splitSections() {
// splitIntoPieces needs to be called on each MergeInputSection
// before calling finalizeContents().
@@ -2929,8 +2988,10 @@ void elf::mergeSections() {
// We do not want to handle sections that are not alive, so just remove
// them instead of trying to merge.
- if (!MS->Live)
+ if (!MS->Live) {
+ S = nullptr;
continue;
+ }
StringRef OutsecName = getOutputSectionName(MS);
uint32_t Alignment = std::max<uint32_t>(MS->Alignment, MS->Entsize);
@@ -3038,34 +3099,54 @@ bool ThunkSection::assignOffsets() {
return Changed;
}
-InputSection *InX::ARMAttributes;
-BssSection *InX::Bss;
-BssSection *InX::BssRelRo;
-BuildIdSection *InX::BuildId;
-EhFrameHeader *InX::EhFrameHdr;
-EhFrameSection *InX::EhFrame;
-SyntheticSection *InX::Dynamic;
-StringTableSection *InX::DynStrTab;
-SymbolTableBaseSection *InX::DynSymTab;
-InputSection *InX::Interp;
-GdbIndexSection *InX::GdbIndex;
-GotSection *InX::Got;
-GotPltSection *InX::GotPlt;
-GnuHashTableSection *InX::GnuHashTab;
-HashTableSection *InX::HashTab;
-IgotPltSection *InX::IgotPlt;
-MipsGotSection *InX::MipsGot;
-MipsRldMapSection *InX::MipsRldMap;
-PltSection *InX::Plt;
-PltSection *InX::Iplt;
-RelocationBaseSection *InX::RelaDyn;
-RelrBaseSection *InX::RelrDyn;
-RelocationBaseSection *InX::RelaPlt;
-RelocationBaseSection *InX::RelaIplt;
-StringTableSection *InX::ShStrTab;
-StringTableSection *InX::StrTab;
-SymbolTableBaseSection *InX::SymTab;
-SymtabShndxSection *InX::SymTabShndx;
+// If linking position-dependent code then the table will store the addresses
+// directly in the binary so the section has type SHT_PROGBITS. If linking
+// position-independent code the section has type SHT_NOBITS since it will be
+// allocated and filled in by the dynamic linker.
+PPC64LongBranchTargetSection::PPC64LongBranchTargetSection()
+ : SyntheticSection(SHF_ALLOC | SHF_WRITE,
+ Config->Pic ? SHT_NOBITS : SHT_PROGBITS, 8,
+ ".branch_lt") {}
+
+void PPC64LongBranchTargetSection::addEntry(Symbol &Sym) {
+ assert(Sym.PPC64BranchltIndex == 0xffff);
+ Sym.PPC64BranchltIndex = Entries.size();
+ Entries.push_back(&Sym);
+}
+
+size_t PPC64LongBranchTargetSection::getSize() const {
+ return Entries.size() * 8;
+}
+
+void PPC64LongBranchTargetSection::writeTo(uint8_t *Buf) {
+ assert(Target->GotPltEntrySize == 8);
+ // If linking non-pic we have the final addresses of the targets and they get
+ // written to the table directly. For pic the dynamic linker will allocate
+ // the section and fill it it.
+ if (Config->Pic)
+ return;
+
+ for (const Symbol *Sym : Entries) {
+ assert(Sym->getVA());
+ // Need calls to branch to the local entry-point since a long-branch
+ // must be a local-call.
+ write64(Buf,
+ Sym->getVA() + getPPC64GlobalEntryToLocalEntryOffset(Sym->StOther));
+ Buf += Target->GotPltEntrySize;
+ }
+}
+
+bool PPC64LongBranchTargetSection::empty() const {
+ // `removeUnusedSyntheticSections()` is called before thunk allocation which
+ // is too early to determine if this section will be empty or not. We need
+ // Finalized to keep the section alive until after thunk creation. Finalized
+ // only gets set to true once `finalizeSections()` is called after thunk
+ // creation. Becuase of this, if we don't create any long-branch thunks we end
+ // up with an empty .branch_lt section in the binary.
+ return Finalized && Entries.empty();
+}
+
+InStruct elf::In;
template GdbIndexSection *GdbIndexSection::create<ELF32LE>();
template GdbIndexSection *GdbIndexSection::create<ELF32BE>();
@@ -3141,8 +3222,3 @@ template class elf::VersionNeedSection<ELF32LE>;
template class elf::VersionNeedSection<ELF32BE>;
template class elf::VersionNeedSection<ELF64LE>;
template class elf::VersionNeedSection<ELF64BE>;
-
-template class elf::VersionDefinitionSection<ELF32LE>;
-template class elf::VersionDefinitionSection<ELF32BE>;
-template class elf::VersionDefinitionSection<ELF64LE>;
-template class elf::VersionDefinitionSection<ELF64BE>;