forked from OSchip/llvm-project
Detemplate the got.
This is a bit hackish, but allows for a lot of followup cleanups. llvm-svn: 302845
This commit is contained in:
parent
2a6b7991d4
commit
88ab9fb163
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue