[lld] 7f1955d - [ELF] Support mixed TLSDESC and TLS GD
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 10 10:03:26 PST 2022
Author: Fangrui Song
Date: 2022-01-10T10:03:21-08:00
New Revision: 7f1955dc96407cbee58b8a78a21f56372db334d6
URL: https://github.com/llvm/llvm-project/commit/7f1955dc96407cbee58b8a78a21f56372db334d6
DIFF: https://github.com/llvm/llvm-project/commit/7f1955dc96407cbee58b8a78a21f56372db334d6.diff
LOG: [ELF] Support mixed TLSDESC and TLS GD
We only support both TLSDESC and TLS GD for x86 so this is an x86-specific
problem. If both are used, only one R_X86_64_TLSDESC is produced and TLS GD
accesses will incorrectly reference R_X86_64_TLSDESC. Fix this by introducing
SymbolAux::tlsDescIdx.
Reviewed By: ikudrin
Differential Revision: https://reviews.llvm.org/D116900
Added:
Modified:
lld/ELF/InputSection.cpp
lld/ELF/Relocations.cpp
lld/ELF/Symbols.h
lld/ELF/SyntheticSections.cpp
lld/ELF/SyntheticSections.h
lld/test/ELF/x86-64-tlsdesc-gd-mixed.s
Removed:
################################################################################
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index bd1079c9a1dbe..ae7ddb50793b2 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -823,14 +823,13 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
case R_SIZE:
return sym.getSize() + a;
case R_TLSDESC:
- return in.got->getGlobalDynAddr(sym) + a;
+ return in.got->getTlsDescAddr(sym) + a;
case R_TLSDESC_PC:
- return in.got->getGlobalDynAddr(sym) + a - p;
+ return in.got->getTlsDescAddr(sym) + a - p;
case R_TLSDESC_GOTPLT:
- return in.got->getGlobalDynAddr(sym) + a - in.gotPlt->getVA();
+ return in.got->getTlsDescAddr(sym) + a - in.gotPlt->getVA();
case R_AARCH64_TLSDESC_PAGE:
- return getAArch64Page(in.got->getGlobalDynAddr(sym) + a) -
- getAArch64Page(p);
+ return getAArch64Page(in.got->getTlsDescAddr(sym) + a) - getAArch64Page(p);
case R_TLSGD_GOT:
return in.got->getGlobalDynOffset(sym) + a;
case R_TLSGD_GOTPLT:
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 7c099700733f9..7dbefaf7d93e2 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1609,13 +1609,12 @@ void elf::postScanRelocations() {
bool isLocalInExecutable = !sym.isPreemptible && !config->shared;
if (sym.needsTlsDesc) {
- in.got->addDynTlsEntry(sym);
+ in.got->addTlsDescEntry(sym);
mainPart->relaDyn->addAddendOnlyRelocIfNonPreemptible(
- target->tlsDescRel, *in.got, in.got->getGlobalDynOffset(sym), sym,
+ target->tlsDescRel, *in.got, in.got->getTlsDescOffset(sym), sym,
target->tlsDescRel);
}
- if (sym.needsTlsGd && !sym.needsTlsDesc) {
- // TODO Support mixed TLSDESC and TLS GD.
+ if (sym.needsTlsGd) {
in.got->addDynTlsEntry(sym);
uint64_t off = in.got->getGlobalDynOffset(sym);
if (isLocalInExecutable)
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index d9935c3a7c4b6..2198bc29d19fe 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -61,6 +61,7 @@ struct StringRefZ {
struct SymbolAux {
uint32_t gotIdx = -1;
uint32_t pltIdx = -1;
+ uint32_t tlsDescIdx = -1;
uint32_t tlsGdIdx = -1;
};
@@ -206,6 +207,9 @@ class Symbol {
uint32_t getPltIdx() const {
return auxIdx == uint32_t(-1) ? uint32_t(-1) : symAux[auxIdx].pltIdx;
}
+ uint32_t getTlsDescIdx() const {
+ return auxIdx == uint32_t(-1) ? uint32_t(-1) : symAux[auxIdx].tlsDescIdx;
+ }
uint32_t getTlsGdIdx() const {
return auxIdx == uint32_t(-1) ? uint32_t(-1) : symAux[auxIdx].tlsGdIdx;
}
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 6af10237fb83a..d0f3c87ac8c7f 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -654,6 +654,13 @@ void GotSection::addEntry(Symbol &sym) {
symAux.back().gotIdx = numEntries++;
}
+bool GotSection::addTlsDescEntry(Symbol &sym) {
+ assert(sym.auxIdx == symAux.size() - 1);
+ symAux.back().tlsDescIdx = numEntries;
+ numEntries += 2;
+ return true;
+}
+
bool GotSection::addDynTlsEntry(Symbol &sym) {
assert(sym.auxIdx == symAux.size() - 1);
symAux.back().tlsGdIdx = numEntries;
@@ -672,6 +679,14 @@ bool GotSection::addTlsIndex() {
return true;
}
+uint32_t GotSection::getTlsDescOffset(const Symbol &sym) const {
+ return sym.getTlsDescIdx() * config->wordsize;
+}
+
+uint64_t GotSection::getTlsDescAddr(const Symbol &sym) const {
+ return getVA() + getTlsDescOffset(sym);
+}
+
uint64_t GotSection::getGlobalDynAddr(const Symbol &b) const {
return this->getVA() + b.getTlsGdIdx() * config->wordsize;
}
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 7f4562a92017b..6a6a2dd136a10 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -129,8 +129,11 @@ class GotSection : public SyntheticSection {
void writeTo(uint8_t *buf) override;
void addEntry(Symbol &sym);
+ bool addTlsDescEntry(Symbol &sym);
bool addDynTlsEntry(Symbol &sym);
bool addTlsIndex();
+ uint32_t getTlsDescOffset(const Symbol &sym) const;
+ uint64_t getTlsDescAddr(const Symbol &sym) const;
uint64_t getGlobalDynAddr(const Symbol &b) const;
uint64_t getGlobalDynOffset(const Symbol &b) const;
diff --git a/lld/test/ELF/x86-64-tlsdesc-gd-mixed.s b/lld/test/ELF/x86-64-tlsdesc-gd-mixed.s
index f6bfe5bbba1cb..7727db354f072 100644
--- a/lld/test/ELF/x86-64-tlsdesc-gd-mixed.s
+++ b/lld/test/ELF/x86-64-tlsdesc-gd-mixed.s
@@ -3,9 +3,11 @@
# RUN: ld.lld -shared %t.o -o %t.so
# RUN: llvm-readobj -r %t.so | FileCheck %s --check-prefix=RELA
-## FIXME Both TLSDESC and DTPMOD64/DTPOFF64 should be present.
+## Both TLSDESC and DTPMOD64/DTPOFF64 should be present.
# RELA: .rela.dyn {
-# RELA-NEXT: 0x2430 R_X86_64_TLSDESC a 0x0
+# RELA-NEXT: 0x[[#%X,ADDR:]] R_X86_64_TLSDESC a 0x0
+# RELA-NEXT: 0x[[#ADDR+16]] R_X86_64_DTPMOD64 a 0x0
+# RELA-NEXT: 0x[[#ADDR+24]] R_X86_64_DTPOFF64 a 0x0
# RELA-NEXT: }
leaq a at tlsdesc(%rip), %rax
More information about the llvm-commits
mailing list