diff options
Diffstat (limited to 'lld/ELF')
-rw-r--r-- | lld/ELF/InputSection.cpp | 2 | ||||
-rw-r--r-- | lld/ELF/OutputSections.cpp | 3 | ||||
-rw-r--r-- | lld/ELF/Target.cpp | 28 | ||||
-rw-r--r-- | lld/ELF/Target.h | 4 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 2 |
5 files changed, 34 insertions, 5 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index dd5eb310387..8fafec3211a 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -151,6 +151,8 @@ void InputSectionBase<ELFT>::relocate( } else if (!Target->relocNeedsCopy(Type, Body) && isa<SharedSymbol<ELFT>>(Body)) { continue; + } else if (Target->isTlsDynReloc(Type)) { + continue; } Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA + getAddend<ELFT>(RI)); diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index f8ea29f068d..6563b1a61ca 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -241,7 +241,8 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) { Config->Mips64EL); else P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), - NeedsCopy ? Target->getCopyReloc() : Type, + NeedsCopy ? Target->getCopyReloc() + : Target->getDynReloc(Type), Config->Mips64EL); } else { P->setSymbolAndType(0, Target->getRelativeReloc(), Config->Mips64EL); diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 33cea220a37..6c0a2224cd5 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -46,6 +46,8 @@ namespace { class X86TargetInfo final : public TargetInfo { public: X86TargetInfo(); + unsigned getDynReloc(unsigned Type) const override; + bool isTlsDynReloc(unsigned Type) const override; void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override; void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr) const override; @@ -62,6 +64,7 @@ class X86_64TargetInfo final : public TargetInfo { public: X86_64TargetInfo(); unsigned getPltRefReloc(unsigned Type) const override; + bool isTlsDynReloc(unsigned Type) const override; void writeGotPltHeaderEntries(uint8_t *Buf) const override; void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override; void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, @@ -182,6 +185,20 @@ X86TargetInfo::X86TargetInfo() { PltReloc = R_386_JUMP_SLOT; } +unsigned X86TargetInfo::getDynReloc(unsigned Type) const { + if (Type == R_386_TLS_LE) + return R_386_TLS_TPOFF; + if (Type == R_386_TLS_LE_32) + return R_386_TLS_TPOFF32; + return Type; +} + +bool X86TargetInfo::isTlsDynReloc(unsigned Type) const { + if (Type == R_386_TLS_LE || Type == R_386_TLS_LE_32) + return Config->Shared; + return false; +} + void X86TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {} void X86TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr) const {} @@ -225,6 +242,12 @@ void X86TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, case R_386_32: add32le(Loc, SA); break; + case R_386_TLS_LE: + write32le(Loc, SA - Out<ELF32LE>::TlsPhdr->p_memsz); + break; + case R_386_TLS_LE_32: + write32le(Loc, Out<ELF32LE>::TlsPhdr->p_memsz - SA); + break; default: error("unrecognized reloc " + Twine(Type)); } @@ -242,7 +265,6 @@ X86_64TargetInfo::X86_64TargetInfo() { TlsGlobalDynamicReloc = R_X86_64_TLSGD; TlsModuleIndexReloc = R_X86_64_DTPMOD64; TlsOffsetReloc = R_X86_64_DTPOFF64; - TlsPcRelGotReloc = R_X86_64_GOTTPOFF; LazyRelocations = true; PltEntrySize = 16; PltZeroEntrySize = 16; @@ -300,6 +322,10 @@ bool X86_64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const { relocNeedsPlt(Type, S); } +bool X86_64TargetInfo::isTlsDynReloc(unsigned Type) const { + return Type == R_X86_64_GOTTPOFF; +} + unsigned X86_64TargetInfo::getPltRefReloc(unsigned Type) const { if (Type == R_X86_64_PLT32) return R_X86_64_PC32; diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index c8b75425a6c..34b95e98625 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -28,7 +28,6 @@ public: unsigned getPltReloc() const { return PltReloc; } unsigned getRelativeReloc() const { return RelativeReloc; } unsigned getTlsGotReloc() const { return TlsGotReloc; } - unsigned getTlsPcRelGotReloc() const { return TlsPcRelGotReloc; } bool isTlsLocalDynamicReloc(unsigned Type) const { return Type == TlsLocalDynamicReloc; } @@ -42,6 +41,8 @@ public: bool supportsLazyRelocations() const { return LazyRelocations; } unsigned getGotHeaderEntriesNum() const { return GotHeaderEntriesNum; } unsigned getGotPltHeaderEntriesNum() const { return GotPltHeaderEntriesNum; } + virtual unsigned getDynReloc(unsigned Type) const { return Type; } + virtual bool isTlsDynReloc(unsigned Type) const { return false; } virtual unsigned getGotRefReloc(unsigned Type) const; virtual unsigned getPltRefReloc(unsigned Type) const; virtual void writeGotHeaderEntries(uint8_t *Buf) const; @@ -84,7 +85,6 @@ protected: unsigned TlsGlobalDynamicReloc = 0; unsigned TlsModuleIndexReloc; unsigned TlsOffsetReloc; - unsigned TlsPcRelGotReloc = 0; unsigned PltEntrySize = 8; unsigned PltZeroEntrySize = 0; unsigned GotHeaderEntriesNum = 0; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index fba35fbb0ce..626f29f5d73 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -229,7 +229,7 @@ void Writer<ELFT>::scanRelocs( continue; } - if ((Body && Body->isTLS()) && Type != Target->getTlsPcRelGotReloc()) + if ((Body && Body->isTLS()) && !Target->isTlsDynReloc(Type)) continue; bool NeedsGot = false; |