This is a bit hackish, but allows for a lot of followup cleanups.
llvm-svn: 302845
case R_RELAX_TLS_GD_TO_IE_ABS:
return Body.getGotVA<ELFT>() + A;
case R_GOTONLY_PC:
- return In<ELFT>::Got->getVA() + A - P;
+ return InX::Got->getVA() + A - P;
case R_GOTONLY_PC_FROM_END:
- return In<ELFT>::Got->getVA() + A - P + In<ELFT>::Got->getSize();
+ return InX::Got->getVA() + A - P + InX::Got->getSize();
case R_GOTREL:
- return Body.getVA(A) - In<ELFT>::Got->getVA();
+ return Body.getVA(A) - InX::Got->getVA();
case R_GOTREL_FROM_END:
- return Body.getVA(A) - In<ELFT>::Got->getVA() - In<ELFT>::Got->getSize();
+ return Body.getVA(A) - InX::Got->getVA() - InX::Got->getSize();
case R_GOT_FROM_END:
case R_RELAX_TLS_GD_TO_IE_END:
- return Body.getGotOffset() + A - In<ELFT>::Got->getSize();
+ return Body.getGotOffset() + A - InX::Got->getSize();
case R_GOT_OFF:
return Body.getGotOffset() + A;
case R_GOT_PAGE_PC:
case R_SIZE:
return Body.getSize<ELFT>() + A;
case R_TLSDESC:
- return In<ELFT>::Got->getGlobalDynAddr(Body) + A;
+ return InX::Got->getGlobalDynAddr(Body) + A;
case R_TLSDESC_PAGE:
- return getAArch64Page(In<ELFT>::Got->getGlobalDynAddr(Body) + A) -
+ return getAArch64Page(InX::Got->getGlobalDynAddr(Body) + A) -
getAArch64Page(P);
case R_TLSGD:
- return In<ELFT>::Got->getGlobalDynOffset(Body) + A -
- In<ELFT>::Got->getSize();
+ return InX::Got->getGlobalDynOffset(Body) + A - InX::Got->getSize();
case R_TLSGD_PC:
- return In<ELFT>::Got->getGlobalDynAddr(Body) + A - P;
+ return InX::Got->getGlobalDynAddr(Body) + A - P;
case R_TLSLD:
- return In<ELFT>::Got->getTlsIndexOff() + A - In<ELFT>::Got->getSize();
+ return InX::Got->getTlsIndexOff() + A - InX::Got->getSize();
case R_TLSLD_PC:
- return In<ELFT>::Got->getTlsIndexVA() + A - P;
+ return InX::Got->getTlsIndexVA() + A - P;
}
llvm_unreachable("Invalid expression");
}
auto AddTlsReloc = [&](uint64_t Off, uint32_t Type, SymbolBody *Dest,
bool Dyn) {
if (Dyn)
- In<ELFT>::RelaDyn->addReloc({Type, In<ELFT>::Got, Off, false, Dest, 0});
+ In<ELFT>::RelaDyn->addReloc({Type, InX::Got, Off, false, Dest, 0});
else
- In<ELFT>::Got->Relocations.push_back({R_ABS, Type, Off, 0, Dest});
+ InX::Got->Relocations.push_back({R_ABS, Type, Off, 0, Dest});
};
// Local Dynamic is for access to module local TLS variables, while still
// being suitable for being dynamically loaded via dlopen.
// GOT[e0] is the module index, with a special value of 0 for the current
// module. GOT[e1] is unused. There only needs to be one module index entry.
- if (Expr == R_TLSLD_PC && In<ELFT>::Got->addTlsIndex()) {
- AddTlsReloc(In<ELFT>::Got->getTlsIndexOff(), Target->TlsModuleIndexRel,
+ if (Expr == R_TLSLD_PC && InX::Got->addTlsIndex()) {
+ AddTlsReloc(InX::Got->getTlsIndexOff(), Target->TlsModuleIndexRel,
NeedDynId ? nullptr : &Body, NeedDynId);
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
return 1;
// the module index and offset of symbol in TLS block we can fill these in
// using static GOT relocations.
if (Expr == R_TLSGD_PC) {
- if (In<ELFT>::Got->addDynTlsEntry(Body)) {
- uint64_t Off = In<ELFT>::Got->getGlobalDynOffset(Body);
+ if (InX::Got->addDynTlsEntry(Body)) {
+ uint64_t Off = InX::Got->getGlobalDynOffset(Body);
AddTlsReloc(Off, Target->TlsModuleIndexRel, &Body, NeedDynId);
AddTlsReloc(Off + Config->Wordsize, Target->TlsOffsetRel, &Body,
NeedDynOff);
bool IsPreemptible = isPreemptible(Body, Type);
if (isRelExprOneOf<R_TLSDESC, R_TLSDESC_PAGE, R_TLSDESC_CALL>(Expr) &&
Config->Shared) {
- if (In<ELFT>::Got->addDynTlsEntry(Body)) {
- uint64_t Off = In<ELFT>::Got->getGlobalDynOffset(Body);
- In<ELFT>::RelaDyn->addReloc({Target->TlsDescRel, In<ELFT>::Got, Off,
- !IsPreemptible, &Body, 0});
+ if (InX::Got->addDynTlsEntry(Body)) {
+ uint64_t Off = InX::Got->getGlobalDynOffset(Body);
+ In<ELFT>::RelaDyn->addReloc(
+ {Target->TlsDescRel, InX::Got, Off, !IsPreemptible, &Body, 0});
}
if (Expr != R_TLSDESC_CALL)
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
{R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Body});
return 2;
}
- if (In<ELFT>::Got->addTlsIndex())
- In<ELFT>::RelaDyn->addReloc({Target->TlsModuleIndexRel, In<ELFT>::Got,
- In<ELFT>::Got->getTlsIndexOff(), false,
- nullptr, 0});
+ if (InX::Got->addTlsIndex())
+ In<ELFT>::RelaDyn->addReloc({Target->TlsModuleIndexRel, InX::Got,
+ InX::Got->getTlsIndexOff(), false, nullptr,
+ 0});
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
return 1;
}
if (isRelExprOneOf<R_TLSDESC, R_TLSDESC_PAGE, R_TLSDESC_CALL, R_TLSGD,
R_TLSGD_PC>(Expr)) {
if (Config->Shared) {
- if (In<ELFT>::Got->addDynTlsEntry(Body)) {
- uint64_t Off = In<ELFT>::Got->getGlobalDynOffset(Body);
+ if (InX::Got->addDynTlsEntry(Body)) {
+ uint64_t Off = InX::Got->getGlobalDynOffset(Body);
In<ELFT>::RelaDyn->addReloc(
- {Target->TlsModuleIndexRel, In<ELFT>::Got, Off, false, &Body, 0});
+ {Target->TlsModuleIndexRel, InX::Got, Off, false, &Body, 0});
// If the symbol is preemptible we need the dynamic linker to write
// the offset too.
uint64_t OffsetOff = Off + Config->Wordsize;
if (IsPreemptible)
- In<ELFT>::RelaDyn->addReloc({Target->TlsOffsetRel, In<ELFT>::Got,
- OffsetOff, false, &Body, 0});
+ In<ELFT>::RelaDyn->addReloc(
+ {Target->TlsOffsetRel, InX::Got, OffsetOff, false, &Body, 0});
else
- In<ELFT>::Got->Relocations.push_back(
+ InX::Got->Relocations.push_back(
{R_ABS, Target->TlsOffsetRel, OffsetOff, 0, &Body});
}
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
{Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_IE), Type,
Offset, Addend, &Body});
if (!Body.isInGot()) {
- In<ELFT>::Got->addEntry(Body);
- In<ELFT>::RelaDyn->addReloc({Target->TlsGotRel, In<ELFT>::Got,
+ InX::Got->addEntry(Body);
+ In<ELFT>::RelaDyn->addReloc({Target->TlsGotRel, InX::Got,
Body.getGotOffset(), false, &Body, 0});
}
} else {
template <class ELFT>
static void addGotEntry(SymbolBody &Sym, bool Preemptible) {
- In<ELFT>::Got->addEntry(Sym);
+ InX::Got->addEntry(Sym);
uint64_t Off = Sym.getGotOffset();
uint32_t DynType;
bool Constant = !Preemptible && !(Config->Pic && !isAbsolute(Sym));
if (!Constant)
In<ELFT>::RelaDyn->addReloc(
- {DynType, In<ELFT>::Got, Off, !Preemptible, &Sym, 0});
+ {DynType, InX::Got, Off, !Preemptible, &Sym, 0});
if (Constant || (!Config->IsRela && !Preemptible))
- In<ELFT>::Got->Relocations.push_back({Expr, DynType, Off, 0, &Sym});
+ InX::Got->Relocations.push_back({Expr, DynType, Off, 0, &Sym});
}
// The reason we have to do this early scan is as follows
// needs it to be created. Here we request for that.
if (isRelExprOneOf<R_GOTONLY_PC, R_GOTONLY_PC_FROM_END, R_GOTREL,
R_GOTREL_FROM_END, R_PPC_TOC>(Expr))
- In<ELFT>::Got->HasGotOffRel = true;
+ InX::Got->HasGotOffRel = true;
// Read an addend.
int64_t Addend = computeAddend<ELFT>(Rel, Sec.Data.data());
}
template <class ELFT> typename ELFT::uint SymbolBody::getGotVA() const {
- return In<ELFT>::Got->getVA() + getGotOffset();
+ return InX::Got->getVA() + getGotOffset();
}
uint64_t SymbolBody::getGotOffset() const {
}
}
-template <class ELFT>
-GotSection<ELFT>::GotSection()
+GotBaseSection::GotBaseSection()
: SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
Target->GotEntrySize, ".got") {}
-template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody &Sym) {
+void GotBaseSection::addEntry(SymbolBody &Sym) {
Sym.GotIndex = NumEntries;
++NumEntries;
}
-template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) {
+bool GotBaseSection::addDynTlsEntry(SymbolBody &Sym) {
if (Sym.GlobalDynIndex != -1U)
return false;
Sym.GlobalDynIndex = NumEntries;
// Reserves TLS entries for a TLS module ID and a TLS block offset.
// In total it takes two GOT slots.
-template <class ELFT> bool GotSection<ELFT>::addTlsIndex() {
+bool GotBaseSection::addTlsIndex() {
if (TlsIndexOff != uint32_t(-1))
return false;
TlsIndexOff = NumEntries * Config->Wordsize;
return true;
}
-template <class ELFT>
-uint64_t GotSection<ELFT>::getGlobalDynAddr(const SymbolBody &B) const {
+uint64_t GotBaseSection::getGlobalDynAddr(const SymbolBody &B) const {
return this->getVA() + B.GlobalDynIndex * Config->Wordsize;
}
-template <class ELFT>
-uint64_t GotSection<ELFT>::getGlobalDynOffset(const SymbolBody &B) const {
+uint64_t GotBaseSection::getGlobalDynOffset(const SymbolBody &B) const {
return B.GlobalDynIndex * Config->Wordsize;
}
-template <class ELFT> void GotSection<ELFT>::finalizeContents() {
+void GotBaseSection::finalizeContents() {
Size = NumEntries * Config->Wordsize;
}
-template <class ELFT> bool GotSection<ELFT>::empty() const {
+bool GotBaseSection::empty() const {
// If we have a relocation that is relative to GOT (such as GOTOFFREL),
// we need to emit a GOT even if it's empty.
return NumEntries == 0 && !HasGotOffRel;
StringTableSection *InX::DynStrTab;
InputSection *InX::Interp;
GdbIndexSection *InX::GdbIndex;
+GotBaseSection *InX::Got;
GotPltSection *InX::GotPlt;
IgotPltSection *InX::IgotPlt;
MipsGotSection *InX::MipsGot;
llvm::DenseMap<std::pair<ArrayRef<uint8_t>, SymbolBody *>, CieRecord> CieMap;
};
-template <class ELFT> class GotSection final : public SyntheticSection {
+class GotBaseSection : public SyntheticSection {
public:
- GotSection();
- void writeTo(uint8_t *Buf) override;
+ GotBaseSection();
size_t getSize() const override { return Size; }
void finalizeContents() override;
bool empty() const override;
// that relies on its address.
bool HasGotOffRel = false;
-private:
+protected:
size_t NumEntries = 0;
uint32_t TlsIndexOff = -1;
uint64_t Size = 0;
};
+template <class ELFT> class GotSection final : public GotBaseSection {
+public:
+ void writeTo(uint8_t *Buf) override;
+};
+
// .note.gnu.build-id section.
class BuildIdSection : public SyntheticSection {
// First 16 bytes are a header.
static StringTableSection *DynStrTab;
static InputSection *Interp;
static GdbIndexSection *GdbIndex;
+ static GotBaseSection *Got;
static GotPltSection *GotPlt;
static IgotPltSection *IgotPlt;
static MipsGotSection *MipsGot;
static SymbolTableSection<ELFT> *DynSymTab;
static EhFrameHeader<ELFT> *EhFrameHdr;
static GnuHashTableSection<ELFT> *GnuHashTab;
- static GotSection<ELFT> *Got;
static EhFrameSection<ELFT> *EhFrame;
static HashTableSection<ELFT> *HashTab;
static RelocationSection<ELFT> *RelaDyn;
template <class ELFT> SymbolTableSection<ELFT> *In<ELFT>::DynSymTab;
template <class ELFT> EhFrameHeader<ELFT> *In<ELFT>::EhFrameHdr;
template <class ELFT> GnuHashTableSection<ELFT> *In<ELFT>::GnuHashTab;
-template <class ELFT> GotSection<ELFT> *In<ELFT>::Got;
template <class ELFT> EhFrameSection<ELFT> *In<ELFT>::EhFrame;
template <class ELFT> HashTableSection<ELFT> *In<ELFT>::HashTab;
template <class ELFT> RelocationSection<ELFT> *In<ELFT>::RelaDyn;
};
memcpy(Buf, V, sizeof(V));
- uint32_t Ebx = In<ELF32LE>::Got->getVA() + In<ELF32LE>::Got->getSize();
+ uint32_t Ebx = InX::Got->getVA() + InX::Got->getSize();
uint32_t GotPlt = InX::GotPlt->getVA() - Ebx;
write32le(Buf + 2, GotPlt + 4);
write32le(Buf + 8, GotPlt + 8);
if (Config->Pic) {
// jmp *foo@GOT(%ebx)
- uint32_t Ebx = In<ELF32LE>::Got->getVA() + In<ELF32LE>::Got->getSize();
+ uint32_t Ebx = InX::Got->getVA() + InX::Got->getSize();
Buf[1] = 0xa3;
write32le(Buf + 2, GotPltEntryAddr - Ebx);
} else {
// TOC starts where the first of these sections starts. We always create a
// .got when we see a relocation that uses it, so for us the start is always
// the .got.
- uint64_t TocVA = In<ELF64BE>::Got->getVA();
+ uint64_t TocVA = InX::Got->getVA();
// Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000
// thus permitting a full 64 Kbytes segment. Note that the glibc startup
InX::MipsGot = make<MipsGotSection>();
Add(InX::MipsGot);
} else {
- In<ELFT>::Got = make<GotSection<ELFT>>();
- Add(In<ELFT>::Got);
+ InX::Got = make<GotSection<ELFT>>();
+ Add(InX::Got);
}
InX::GotPlt = make<GotPltSection>();
// .got contains pointers to external symbols. They are resolved by
// the dynamic linker when a module is loaded into memory, and after
// that they are not expected to change. So, it can be in RELRO.
- if (In<ELFT>::Got && Sec == In<ELFT>::Got->OutSec)
+ if (InX::Got && Sec == InX::Got->OutSec)
return true;
// .got.plt contains pointers to external function symbols. They are
applySynthetic({In<ELFT>::DynSymTab, InX::Bss, InX::BssRelRo,
In<ELFT>::GnuHashTab, In<ELFT>::HashTab, In<ELFT>::SymTab,
InX::ShStrTab, InX::StrTab, In<ELFT>::VerDef,
- InX::DynStrTab, InX::GdbIndex, In<ELFT>::Got,
+ InX::DynStrTab, InX::GdbIndex, InX::Got,
InX::MipsGot, InX::IgotPlt, InX::GotPlt,
In<ELFT>::RelaDyn, In<ELFT>::RelaIplt, In<ELFT>::RelaPlt,
InX::Plt, InX::Iplt, In<ELFT>::EhFrameHdr,