[lld] r363927 - [ELF][ARM] Merge handleARMTlsRelocation() into handleTlsRelocation()

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 20 06:53:12 PDT 2019


Author: maskray
Date: Thu Jun 20 06:53:11 2019
New Revision: 363927

URL: http://llvm.org/viewvc/llvm-project?rev=363927&view=rev
Log:
[ELF][ARM] Merge handleARMTlsRelocation() into handleTlsRelocation()

ARM and RISC-V do not support TLS relaxations. However, for General
Dynamic and Local Dynamic models, if we are producing an executable and
the symbol is non-preemptable, we know it must be defined and the
R_ARM_TLS_DTPMOD32/R_RISCV_TLS_DTPMOD{32,64} dynamic relocation can be
omitted because it is always 1. This may be necessary for static linking
as DTPMOD may not be expected at load time.

Merge handleARMTlsRelocation() into handleTlsRelocation(). This requires
more logic to R_TLSGD_PC and R_TLSLD_PC. Because we use SymbolicRel to
resolve the relocation at link time, R_ARM_TLS_DTPMOD32 can be deleted
from relocateOne(). It cannot be used as a static relocation type.

As a bonus, the additional logic in R_TLSGD_PC code can be shared by the
TLS support for RISC-V (D63220).

Reviewed By: ruiu

Differential Revision: https://reviews.llvm.org/D63333

Modified:
    lld/trunk/ELF/Arch/ARM.cpp
    lld/trunk/ELF/Relocations.cpp

Modified: lld/trunk/ELF/Arch/ARM.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/ARM.cpp?rev=363927&r1=363926&r2=363927&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/ARM.cpp (original)
+++ lld/trunk/ELF/Arch/ARM.cpp Thu Jun 20 06:53:11 2019
@@ -395,9 +395,6 @@ void ARM::relocateOne(uint8_t *Loc, RelT
   case R_ARM_TLS_DTPOFF32:
     write32le(Loc, Val);
     break;
-  case R_ARM_TLS_DTPMOD32:
-    write32le(Loc, 1);
-    break;
   case R_ARM_PREL31:
     checkInt(Loc, Val, 31, Type);
     write32le(Loc, (read32le(Loc) & 0x80000000) | (Val & ~0x80000000));

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=363927&r1=363926&r2=363927&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Thu Jun 20 06:53:11 2019
@@ -147,63 +147,12 @@ static unsigned handleMipsTlsRelocation(
   return 0;
 }
 
-// This function is similar to the `handleMipsTlsRelocation`. ARM also does not
-// support any relaxations for TLS relocations. ARM is logically similar to Mips
-// in how it handles TLS, but Mips uses its own custom GOT which handles some
-// of the cases that ARM uses GOT relocations for.
+// Notes about General Dynamic and Local Dynamic TLS models below. They may
+// require the generation of a pair of GOT entries that have associated dynamic
+// relocations. The pair of GOT entries created are of the form GOT[e0] Module
+// Index (Used to find pointer to TLS block at run-time) GOT[e1] Offset of
+// symbol in TLS block.
 //
-// We look for TLS global dynamic and local dynamic relocations, these may
-// require the generation of a pair of GOT entries that have associated
-// dynamic relocations. When the results of the dynamic relocations can be
-// resolved at static link time we do so. This is necessary for static linking
-// as there will be no dynamic loader to resolve them at load-time.
-//
-// The pair of GOT entries created are of the form
-// GOT[e0] Module Index (Used to find pointer to TLS block at run-time)
-// GOT[e1] Offset of symbol in TLS block
-static unsigned handleARMTlsRelocation(RelType Type, Symbol &Sym,
-                                       InputSectionBase &C, uint64_t Offset,
-                                       int64_t Addend, RelExpr Expr) {
-  // The Dynamic TLS Module Index Relocation for a symbol defined in an
-  // executable is always 1. If the target Symbol is not preemptible then
-  // we know the offset into the TLS block at static link time.
-  bool NeedDynId = Sym.IsPreemptible || Config->Shared;
-  bool NeedDynOff = Sym.IsPreemptible;
-
-  auto AddTlsReloc = [&](uint64_t Off, RelType Type, Symbol *Dest, bool Dyn) {
-    if (Dyn)
-      Main->RelaDyn->addReloc(Type, In.Got, Off, Dest);
-    else
-      In.Got->Relocations.push_back({R_ABS, Type, Off, 0, Dest});
-  };
-
-  // Local Dynamic is for access to module local TLS variables, while still
-  // being suitable for being dynamically loaded via dlopen.
-  // GOT[e0] is the module index, with a special value of 0 for the current
-  // module. GOT[e1] is unused. There only needs to be one module index entry.
-  if (Expr == R_TLSLD_PC && In.Got->addTlsIndex()) {
-    AddTlsReloc(In.Got->getTlsIndexOff(), Target->TlsModuleIndexRel,
-                NeedDynId ? nullptr : &Sym, NeedDynId);
-    C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
-    return 1;
-  }
-
-  // Global Dynamic is the most general purpose access model. When we know
-  // the module index and offset of symbol in TLS block we can fill these in
-  // using static GOT relocations.
-  if (Expr == R_TLSGD_PC) {
-    if (In.Got->addDynTlsEntry(Sym)) {
-      uint64_t Off = In.Got->getGlobalDynOffset(Sym);
-      AddTlsReloc(Off, Target->TlsModuleIndexRel, &Sym, NeedDynId);
-      AddTlsReloc(Off + Config->Wordsize, Target->TlsOffsetRel, &Sym,
-                  NeedDynOff);
-    }
-    C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
-    return 1;
-  }
-  return 0;
-}
-
 // Returns the number of relocations processed.
 template <class ELFT>
 static unsigned
@@ -212,8 +161,6 @@ handleTlsRelocation(RelType Type, Symbol
   if (!Sym.isTls())
     return 0;
 
-  if (Config->EMachine == EM_ARM)
-    return handleARMTlsRelocation(Type, Sym, C, Offset, Addend, Expr);
   if (Config->EMachine == EM_MIPS)
     return handleMipsTlsRelocation(Type, Sym, C, Offset, Addend, Expr);
 
@@ -230,10 +177,25 @@ handleTlsRelocation(RelType Type, Symbol
     return 1;
   }
 
+  bool CanRelax = Config->EMachine != EM_ARM;
+
+  // If we are producing an executable and the symbol is non-preemptable, it
+  // must be defined and the code sequence can be relaxed to use Local-Exec.
+  //
+  // ARM and RISC-V do not support any relaxations for TLS relocations, however,
+  // we can omit the DTPMOD dynamic relocations and resolve them at link time
+  // because them are always 1. This may be necessary for static linking as
+  // DTPMOD may not be expected at load time.
+  bool IsLocalInExecutable = !Sym.IsPreemptible && !Config->Shared;
+
+  // Local Dynamic is for access to module local TLS variables, while still
+  // being suitable for being dynamically loaded via dlopen. GOT[e0] is the
+  // module index, with a special value of 0 for the current module. GOT[e1] is
+  // unused. There only needs to be one module index entry.
   if (oneof<R_TLSLD_GOT, R_TLSLD_GOTPLT, R_TLSLD_PC, R_TLSLD_HINT>(
           Expr)) {
     // Local-Dynamic relocs can be relaxed to Local-Exec.
-    if (!Config->Shared) {
+    if (CanRelax && !Config->Shared) {
       C.Relocations.push_back(
           {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_LD_TO_LE), Type,
            Offset, Addend, &Sym});
@@ -241,9 +203,14 @@ handleTlsRelocation(RelType Type, Symbol
     }
     if (Expr == R_TLSLD_HINT)
       return 1;
-    if (In.Got->addTlsIndex())
-      Main->RelaDyn->addReloc(Target->TlsModuleIndexRel, In.Got,
-                              In.Got->getTlsIndexOff(), nullptr);
+    if (In.Got->addTlsIndex()) {
+      if (IsLocalInExecutable)
+        In.Got->Relocations.push_back(
+            {R_ADDEND, Target->SymbolicRel, In.Got->getTlsIndexOff(), 1, &Sym});
+      else
+        Main->RelaDyn->addReloc(Target->TlsModuleIndexRel, In.Got,
+                                In.Got->getTlsIndexOff(), nullptr);
+    }
     C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
     return 1;
   }
@@ -271,10 +238,16 @@ handleTlsRelocation(RelType Type, Symbol
 
   if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
             R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC>(Expr)) {
-    if (Config->Shared) {
+    if (!CanRelax || Config->Shared) {
       if (In.Got->addDynTlsEntry(Sym)) {
         uint64_t Off = In.Got->getGlobalDynOffset(Sym);
-        Main->RelaDyn->addReloc(Target->TlsModuleIndexRel, In.Got, Off, &Sym);
+
+        if (IsLocalInExecutable)
+          // Write one to the GOT slot.
+          In.Got->Relocations.push_back(
+              {R_ADDEND, Target->SymbolicRel, Off, 1, &Sym});
+        else
+          Main->RelaDyn->addReloc(Target->TlsModuleIndexRel, In.Got, Off, &Sym);
 
         // If the symbol is preemptible we need the dynamic linker to write
         // the offset too.
@@ -313,7 +286,7 @@ handleTlsRelocation(RelType Type, Symbol
   // defined.
   if (oneof<R_GOT, R_GOTPLT, R_GOT_PC, R_AARCH64_GOT_PAGE_PC, R_GOT_OFF,
             R_TLSIE_HINT>(Expr) &&
-      !Config->Shared && !Sym.IsPreemptible) {
+      CanRelax && IsLocalInExecutable) {
     C.Relocations.push_back({R_RELAX_TLS_IE_TO_LE, Type, Offset, Addend, &Sym});
     return 1;
   }




More information about the llvm-commits mailing list