[PATCH] D26238: [LLD][ARM] Correct ARM TLS GOT entries without dynamic relocations.
Rafael EspĂndola via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 18 14:12:34 PST 2016
> The difficulty with this approach at the time was how to avoid writing the relocation into the file as well as statically resolving it. I thought that this would probably be messier than localising it here. With the new refactoring this might be easier so it will be worth taking another look.
I gave it a quick try to handle the x86_64 case. The patch is
attached. It is still pretty incomplete, but I think it is promising
in making it explicit that sometimes the dynamic linker computes a
value, sometimes lld computes the value.
Cheers,
Rafael
-------------- next part --------------
diff --git a/ELF/Relocations.cpp b/ELF/Relocations.cpp
index 8bcf4d2..ba9fc5f 100644
--- a/ELF/Relocations.cpp
+++ b/ELF/Relocations.cpp
@@ -188,10 +188,13 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body,
// If the symbol is preemptible we need the dynamic linker to write
// the offset too.
+ uintX_t OffsetOff = Off + (uintX_t)sizeof(uintX_t);
if (isPreemptible(Body, Type))
In<ELFT>::RelaDyn->addReloc({Target->TlsOffsetRel, In<ELFT>::Got,
- Off + (uintX_t)sizeof(uintX_t), false,
- &Body, 0});
+ OffsetOff, false, &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});
return 1;
@@ -778,16 +781,19 @@ static void scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
continue;
In<ELFT>::Got->addEntry(Body);
+ uintX_t Off = Body.getGotOffset<ELFT>();
+ uint32_t DynType;
+ if (Body.isTls())
+ DynType = Target->TlsGotRel;
+ else if (!Preemptible && Config->Pic && !isAbsolute<ELFT>(Body))
+ DynType = Target->RelativeRel;
+ else
+ DynType = Target->GotRel;
+
if (Preemptible || (Config->Pic && !isAbsolute<ELFT>(Body))) {
- uint32_t DynType;
- if (Body.isTls())
- DynType = Target->TlsGotRel;
- else if (Preemptible)
- DynType = Target->GotRel;
- else
- DynType = Target->RelativeRel;
- AddDyn({DynType, In<ELFT>::Got, Body.getGotOffset<ELFT>(), !Preemptible,
- &Body, 0});
+ AddDyn({DynType, In<ELFT>::Got, Off, !Preemptible, &Body, 0});
+ } else {
+ In<ELFT>::Got->Relocations.push_back({R_ABS, DynType, Off, 0, &Body});
}
continue;
}
diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp
index 8f66ade..cc57690 100644
--- a/ELF/SyntheticSections.cpp
+++ b/ELF/SyntheticSections.cpp
@@ -350,17 +350,16 @@ GotSection<ELFT>::GotSection()
Target->GotEntrySize, ".got") {}
template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody &Sym) {
- Sym.GotIndex = Entries.size();
- Entries.push_back(&Sym);
+ Sym.GotIndex = NumEntries;
+ ++NumEntries;
}
template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) {
if (Sym.GlobalDynIndex != -1U)
return false;
- Sym.GlobalDynIndex = Entries.size();
+ Sym.GlobalDynIndex = NumEntries;
// Global Dynamic TLS entries take two GOT slots.
- Entries.push_back(nullptr);
- Entries.push_back(&Sym);
+ NumEntries += 2;
return true;
}
@@ -369,9 +368,8 @@ template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) {
template <class ELFT> bool GotSection<ELFT>::addTlsIndex() {
if (TlsIndexOff != uint32_t(-1))
return false;
- TlsIndexOff = Entries.size() * sizeof(uintX_t);
- Entries.push_back(nullptr);
- Entries.push_back(nullptr);
+ TlsIndexOff = NumEntries * sizeof(uintX_t);
+ NumEntries += 2;
return true;
}
@@ -388,20 +386,13 @@ GotSection<ELFT>::getGlobalDynOffset(const SymbolBody &B) const {
}
template <class ELFT> void GotSection<ELFT>::finalize() {
- Size = Entries.size() * sizeof(uintX_t);
+ Size = NumEntries * sizeof(uintX_t);
}
template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) {
- for (const SymbolBody *B : Entries) {
- 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);
- }
+ // dup?
+ uint8_t *BufEnd = Buf + Size;
+ this->relocate(Buf, BufEnd);
}
template <class ELFT>
diff --git a/ELF/SyntheticSections.h b/ELF/SyntheticSections.h
index e441f99..085a872 100644
--- a/ELF/SyntheticSections.h
+++ b/ELF/SyntheticSections.h
@@ -149,7 +149,7 @@ public:
void addEntry(SymbolBody &Sym);
bool addDynTlsEntry(SymbolBody &Sym);
bool addTlsIndex();
- bool empty() const { return Entries.empty(); }
+ bool empty() const { return NumEntries == 0; }
uintX_t getGlobalDynAddr(const SymbolBody &B) const;
uintX_t getGlobalDynOffset(const SymbolBody &B) const;
@@ -161,7 +161,7 @@ public:
bool HasGotOffRel = false;
private:
- std::vector<const SymbolBody *> Entries;
+ size_t NumEntries = 0;
uint32_t TlsIndexOff = -1;
uintX_t Size = 0;
};
diff --git a/ELF/Target.cpp b/ELF/Target.cpp
index bcada08..ed50e6f 100644
--- a/ELF/Target.cpp
+++ b/ELF/Target.cpp
@@ -804,6 +804,7 @@ void X86_64TargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type,
case R_X86_64_DTPOFF64:
case R_X86_64_SIZE64:
case R_X86_64_PC64:
+ case R_X86_64_GLOB_DAT:
write64le(Loc, Val);
break;
default:
More information about the llvm-commits
mailing list