[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