Use relocations to fill statically known got entries.

Right now we just remember a SymbolBody for each got entry and
duplicate a bit of logic to decide what value, if any, should be
written for that SymbolBody.

With ARM there will be more complicated values, and it seems better to
just use the relocation code to fill the got entries. This makes it
clear that each entry is filled by the dynamic linker or by the static
linker.

llvm-svn: 288107
This commit is contained in:
Rafael Espindola 2016-11-29 03:45:36 +00:00
parent d3b32df3de
commit f1e245315b
4 changed files with 32 additions and 34 deletions

View File

@ -188,10 +188,13 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body,
// If the symbol is preemptible we need the dynamic linker to write // If the symbol is preemptible we need the dynamic linker to write
// the offset too. // the offset too.
uintX_t OffsetOff = Off + (uintX_t)sizeof(uintX_t);
if (isPreemptible(Body, Type)) if (isPreemptible(Body, Type))
In<ELFT>::RelaDyn->addReloc({Target->TlsOffsetRel, In<ELFT>::Got, In<ELFT>::RelaDyn->addReloc({Target->TlsOffsetRel, In<ELFT>::Got,
Off + (uintX_t)sizeof(uintX_t), false, OffsetOff, false, &Body, 0});
&Body, 0}); else
In<ELFT>::Got->Relocations.push_back(
{R_ABS, Target->TlsOffsetRel, OffsetOff, 0, &Body});
} }
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
return 1; return 1;
@ -741,17 +744,19 @@ static void scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
continue; continue;
In<ELFT>::Got->addEntry(Body); In<ELFT>::Got->addEntry(Body);
if (Preemptible || (Config->Pic && !isAbsolute<ELFT>(Body))) { uintX_t Off = Body.getGotOffset<ELFT>();
uint32_t DynType; uint32_t DynType;
if (Body.isTls()) if (Body.isTls())
DynType = Target->TlsGotRel; DynType = Target->TlsGotRel;
else if (Preemptible) else if (!Preemptible && Config->Pic && !isAbsolute<ELFT>(Body))
DynType = Target->GotRel; DynType = Target->RelativeRel;
else else
DynType = Target->RelativeRel; DynType = Target->GotRel;
AddDyn({DynType, In<ELFT>::Got, Body.getGotOffset<ELFT>(), !Preemptible,
&Body, 0}); if (Preemptible || (Config->Pic && !isAbsolute<ELFT>(Body)))
} AddDyn({DynType, In<ELFT>::Got, Off, !Preemptible, &Body, 0});
else
In<ELFT>::Got->Relocations.push_back({R_ABS, DynType, Off, 0, &Body});
continue; continue;
} }
} }

View File

@ -383,17 +383,16 @@ GotSection<ELFT>::GotSection()
Target->GotEntrySize, ".got") {} Target->GotEntrySize, ".got") {}
template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody &Sym) { template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody &Sym) {
Sym.GotIndex = Entries.size(); Sym.GotIndex = NumEntries;
Entries.push_back(&Sym); ++NumEntries;
} }
template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) { template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) {
if (Sym.GlobalDynIndex != -1U) if (Sym.GlobalDynIndex != -1U)
return false; return false;
Sym.GlobalDynIndex = Entries.size(); Sym.GlobalDynIndex = NumEntries;
// Global Dynamic TLS entries take two GOT slots. // Global Dynamic TLS entries take two GOT slots.
Entries.push_back(nullptr); NumEntries += 2;
Entries.push_back(&Sym);
return true; return true;
} }
@ -402,9 +401,8 @@ template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) {
template <class ELFT> bool GotSection<ELFT>::addTlsIndex() { template <class ELFT> bool GotSection<ELFT>::addTlsIndex() {
if (TlsIndexOff != uint32_t(-1)) if (TlsIndexOff != uint32_t(-1))
return false; return false;
TlsIndexOff = Entries.size() * sizeof(uintX_t); TlsIndexOff = NumEntries * sizeof(uintX_t);
Entries.push_back(nullptr); NumEntries += 2;
Entries.push_back(nullptr);
return true; return true;
} }
@ -421,26 +419,17 @@ GotSection<ELFT>::getGlobalDynOffset(const SymbolBody &B) const {
} }
template <class ELFT> void GotSection<ELFT>::finalize() { template <class ELFT> void GotSection<ELFT>::finalize() {
Size = Entries.size() * sizeof(uintX_t); Size = NumEntries * sizeof(uintX_t);
} }
template <class ELFT> bool GotSection<ELFT>::empty() const { template <class ELFT> bool GotSection<ELFT>::empty() const {
// If we have a relocation that is relative to GOT (such as GOTOFFREL), // If we have a relocation that is relative to GOT (such as GOTOFFREL),
// we need to emit a GOT even if it's empty. // we need to emit a GOT even if it's empty.
return Entries.empty() && !HasGotOffRel; return NumEntries == 0 && !HasGotOffRel;
} }
template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) { template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) {
for (const SymbolBody *B : Entries) { this->relocate(Buf, Buf + Size);
uint8_t *Entry = Buf;
Buf += sizeof(uintX_t);
if (!B)
continue;
if (B->isPreemptible())
continue; // The dynamic linker will take care of it.
uintX_t VA = B->getVA<ELFT>();
write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, VA);
}
} }
template <class ELFT> template <class ELFT>

View File

@ -67,7 +67,7 @@ public:
bool HasGotOffRel = false; bool HasGotOffRel = false;
private: private:
std::vector<const SymbolBody *> Entries; size_t NumEntries = 0;
uint32_t TlsIndexOff = -1; uint32_t TlsIndexOff = -1;
uintX_t Size = 0; uintX_t Size = 0;
}; };

View File

@ -800,6 +800,7 @@ void X86_64TargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type,
break; break;
case R_X86_64_64: case R_X86_64_64:
case R_X86_64_DTPOFF64: case R_X86_64_DTPOFF64:
case R_X86_64_GLOB_DAT:
case R_X86_64_PC64: case R_X86_64_PC64:
case R_X86_64_SIZE64: case R_X86_64_SIZE64:
write64le(Loc, Val); write64le(Loc, Val);
@ -1319,6 +1320,7 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
write32le(Loc, Val); write32le(Loc, Val);
break; break;
case R_AARCH64_ABS64: case R_AARCH64_ABS64:
case R_AARCH64_GLOB_DAT:
case R_AARCH64_PREL64: case R_AARCH64_PREL64:
write64le(Loc, Val); write64le(Loc, Val);
break; break;
@ -1685,6 +1687,7 @@ void ARMTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
switch (Type) { switch (Type) {
case R_ARM_ABS32: case R_ARM_ABS32:
case R_ARM_BASE_PREL: case R_ARM_BASE_PREL:
case R_ARM_GLOB_DAT:
case R_ARM_GOTOFF32: case R_ARM_GOTOFF32:
case R_ARM_GOT_BREL: case R_ARM_GOT_BREL:
case R_ARM_GOT_PREL: case R_ARM_GOT_PREL:
@ -1696,6 +1699,7 @@ void ARMTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
case R_ARM_TLS_LDM32: case R_ARM_TLS_LDM32:
case R_ARM_TLS_LDO32: case R_ARM_TLS_LDO32:
case R_ARM_TLS_LE32: case R_ARM_TLS_LE32:
case R_ARM_TLS_TPOFF32:
write32le(Loc, Val); write32le(Loc, Val);
break; break;
case R_ARM_PREL31: case R_ARM_PREL31: