Detemplate the got.

This is a bit hackish, but allows for a lot of followup cleanups.

llvm-svn: 302845
This commit is contained in:
Rafael Espindola 2017-05-11 23:26:03 +00:00
parent 2a6b7991d4
commit 88ab9fb163
7 changed files with 63 additions and 63 deletions

View File

@ -402,16 +402,16 @@ getRelocTargetVA(uint32_t Type, int64_t A, typename ELFT::uint P,
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:
@ -520,19 +520,18 @@ getRelocTargetVA(uint32_t Type, int64_t A, typename ELFT::uint P,
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");
}

View File

@ -156,17 +156,17 @@ static unsigned handleARMTlsRelocation(uint32_t Type, SymbolBody &Body,
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;
@ -176,8 +176,8 @@ static unsigned handleARMTlsRelocation(uint32_t Type, SymbolBody &Body,
// 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);
@ -207,10 +207,10 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C,
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});
@ -224,10 +224,10 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C,
{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;
}
@ -242,19 +242,19 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C,
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});
@ -268,8 +268,8 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C,
{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 {
@ -774,7 +774,7 @@ static void addPltEntry(PltSection *Plt, GotPltSection *GotPlt,
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;
@ -792,10 +792,10 @@ static void addGotEntry(SymbolBody &Sym, bool Preemptible) {
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
@ -856,7 +856,7 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) {
// 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());

View File

@ -164,7 +164,7 @@ uint64_t SymbolBody::getVA(int64_t Addend) const {
}
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 {

View File

@ -618,17 +618,16 @@ template <class ELFT> void EhFrameSection<ELFT>::writeTo(uint8_t *Buf) {
}
}
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;
@ -639,7 +638,7 @@ template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) {
// 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;
@ -647,21 +646,19 @@ template <class ELFT> bool GotSection<ELFT>::addTlsIndex() {
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;
@ -2249,6 +2246,7 @@ SyntheticSection *InX::Dynamic;
StringTableSection *InX::DynStrTab;
InputSection *InX::Interp;
GdbIndexSection *InX::GdbIndex;
GotBaseSection *InX::Got;
GotPltSection *InX::GotPlt;
IgotPltSection *InX::IgotPlt;
MipsGotSection *InX::MipsGot;

View File

@ -104,10 +104,9 @@ private:
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;
@ -125,12 +124,17 @@ public:
// 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.
@ -754,6 +758,7 @@ struct InX {
static StringTableSection *DynStrTab;
static InputSection *Interp;
static GdbIndexSection *GdbIndex;
static GotBaseSection *Got;
static GotPltSection *GotPlt;
static IgotPltSection *IgotPlt;
static MipsGotSection *MipsGot;
@ -768,7 +773,6 @@ template <class ELFT> struct In : public InX {
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;
@ -783,7 +787,6 @@ template <class ELFT> struct In : public InX {
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;

View File

@ -460,7 +460,7 @@ void X86TargetInfo::writePltHeader(uint8_t *Buf) const {
};
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);
@ -490,7 +490,7 @@ void X86TargetInfo::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
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 {
@ -1140,7 +1140,7 @@ uint64_t getPPC64TocBase() {
// 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

View File

@ -404,8 +404,8 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
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>();
@ -613,7 +613,7 @@ template <class ELFT> bool elf::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 (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
@ -1184,7 +1184,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
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,