[lld] r271569 - Start adding tlsdesc support for aarch64.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 2 12:49:54 PDT 2016


Author: rafael
Date: Thu Jun  2 14:49:53 2016
New Revision: 271569

URL: http://llvm.org/viewvc/llvm-project?rev=271569&view=rev
Log:
Start adding tlsdesc support for aarch64.

This is mostly extracted from http://reviews.llvm.org/D18960.

The general idea for tlsdesc is that the two GD got entries are used
for a function pointer and its argument. The dynamic linker sets
both. In the non-dlopen case the dynamic linker sets the function to
the identity and the argument to the offset in the tls block.

All that the static linker has to do in the non-dlopen case is
relocate the code to point to the got entries and create a dynamic
relocation.

The dlopen case is more complicated, but can be implemented in another patch.

Added:
    lld/trunk/test/ELF/aarch64-tlsdesc.s
Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/ELF/Relocations.h
    lld/trunk/ELF/Target.cpp
    lld/trunk/ELF/Target.h

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=271569&r1=271568&r2=271569&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Thu Jun  2 14:49:53 2016
@@ -193,6 +193,11 @@ getSymVA(uint32_t Type, typename ELFT::u
            Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t);
   case R_TLSGD_PC:
     return Out<ELFT>::Got->getGlobalDynAddr(Body) + A - P;
+  case R_TLSDESC:
+    return Out<ELFT>::Got->getGlobalDynAddr(Body) + A;
+  case R_TLSDESC_PAGE:
+    return getAArch64Page(Out<ELFT>::Got->getGlobalDynAddr(Body) + A) -
+           getAArch64Page(P);
   case R_PLT:
     return Body.getPltVA<ELFT>() + A;
   case R_PLT_PC:

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=271569&r1=271568&r2=271569&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Thu Jun  2 14:49:53 2016
@@ -62,7 +62,7 @@ static bool refersToGotEntry(RelExpr Exp
   return Expr == R_GOT || Expr == R_GOT_OFF || Expr == R_MIPS_GOT_LOCAL ||
          Expr == R_MIPS_GOT_LOCAL_PAGE || Expr == R_GOT_PAGE_PC ||
          Expr == R_GOT_PC || Expr == R_GOT_FROM_END || Expr == R_TLSGD ||
-         Expr == R_TLSGD_PC;
+         Expr == R_TLSGD_PC || Expr == R_TLSDESC || Expr == R_TLSDESC_PAGE;
 }
 
 static bool isPreemptible(const SymbolBody &Body, uint32_t Type) {
@@ -94,6 +94,19 @@ static unsigned handleTlsRelocation(uint
     return 0;
 
   typedef typename ELFT::uint uintX_t;
+
+  if ((Expr == R_TLSDESC || Expr == R_TLSDESC_PAGE || Expr == R_HINT) &&
+      Config->Shared) {
+    if (Out<ELFT>::Got->addDynTlsEntry(Body)) {
+      uintX_t Off = Out<ELFT>::Got->getGlobalDynOffset(Body);
+      Out<ELFT>::RelaDyn->addReloc(
+          {Target->TlsDescRel, Out<ELFT>::Got, Off, false, &Body, 0});
+    }
+    if (Expr != R_HINT)
+      C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
+    return 1;
+  }
+
   if (Expr == R_TLSLD_PC || Expr == R_TLSLD) {
     // Local-Dynamic relocs can be relaxed to Local-Exec.
     if (!Config->Shared) {
@@ -116,7 +129,8 @@ static unsigned handleTlsRelocation(uint
     return 1;
   }
 
-  if (Target->isTlsGlobalDynamicRel(Type)) {
+  if (Expr == R_TLSDESC_PAGE || Expr == R_TLSDESC || Expr == R_HINT ||
+      Target->isTlsGlobalDynamicRel(Type)) {
     if (Config->Shared) {
       if (Out<ELFT>::Got->addDynTlsEntry(Body)) {
         uintX_t Off = Out<ELFT>::Got->getGlobalDynOffset(Body);
@@ -254,12 +268,12 @@ static bool isStaticLinkTimeConstant(Rel
   if (E == R_SIZE || E == R_GOT_FROM_END || E == R_GOT_OFF ||
       E == R_MIPS_GOT_LOCAL || E == R_MIPS_GOT_LOCAL_PAGE ||
       E == R_GOT_PAGE_PC || E == R_GOT_PC || E == R_PLT_PC || E == R_TLSGD_PC ||
-      E == R_TLSGD || E == R_PPC_PLT_OPD)
+      E == R_TLSGD || E == R_PPC_PLT_OPD || E == R_TLSDESC_PAGE || E == R_HINT)
     return true;
 
   // These never do, except if the entire file is position dependent or if
   // only the low bits are used.
-  if (E == R_GOT || E == R_PLT)
+  if (E == R_GOT || E == R_PLT || E == R_TLSDESC)
     return Target->usesOnlyLowPageBits(Type) || !Config->Pic;
 
   if (isPreemptible(Body, Type))
@@ -493,10 +507,6 @@ static void scanRelocs(InputSectionBase<
     uint32_t Type = RI.getType(Config->Mips64EL);
 
     RelExpr Expr = Target->getRelExpr(Type, Body);
-    // Ignore "hint" relocation because it is for optional code optimization.
-    if (Expr == R_HINT)
-      continue;
-
     uintX_t Offset = C.getOffset(RI.r_offset);
     if (Offset == (uintX_t)-1)
       continue;
@@ -519,6 +529,10 @@ static void scanRelocs(InputSectionBase<
       continue;
     }
 
+    // Ignore "hint" relocation because it is for optional code optimization.
+    if (Expr == R_HINT)
+      continue;
+
     if (needsPlt(Expr) || Expr == R_THUNK || refersToGotEntry(Expr) ||
         !isPreemptible(Body, Type)) {
       // If the relocation points to something in the file, we can process it.

Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=271569&r1=271568&r2=271569&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Thu Jun  2 14:49:53 2016
@@ -47,6 +47,8 @@ enum RelExpr {
   R_SIZE,
   R_THUNK,
   R_TLS,
+  R_TLSDESC,
+  R_TLSDESC_PAGE,
   R_TLSGD,
   R_TLSGD_PC,
   R_TLSLD,

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=271569&r1=271568&r2=271569&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Thu Jun  2 14:49:53 2016
@@ -147,7 +147,6 @@ public:
   AArch64TargetInfo();
   RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override;
   uint32_t getDynRel(uint32_t Type) const override;
-  bool isTlsGlobalDynamicRel(uint32_t Type) const override;
   bool isTlsInitialExecRel(uint32_t Type) const override;
   void writeGotPlt(uint8_t *Buf, uint64_t Plt) const override;
   void writePltZero(uint8_t *Buf) const override;
@@ -1076,6 +1075,7 @@ AArch64TargetInfo::AArch64TargetInfo() {
   IRelativeRel = R_AARCH64_IRELATIVE;
   GotRel = R_AARCH64_GLOB_DAT;
   PltRel = R_AARCH64_JUMP_SLOT;
+  TlsDescRel = R_AARCH64_TLSDESC;
   TlsGotRel = R_AARCH64_TLS_TPREL64;
   PltEntrySize = 16;
   PltZeroSize = 32;
@@ -1091,6 +1091,16 @@ RelExpr AArch64TargetInfo::getRelExpr(ui
   default:
     return R_ABS;
 
+  case R_AARCH64_TLSDESC_ADR_PAGE21:
+    return R_TLSDESC_PAGE;
+
+  case R_AARCH64_TLSDESC_LD64_LO12_NC:
+  case R_AARCH64_TLSDESC_ADD_LO12_NC:
+    return R_TLSDESC;
+
+  case R_AARCH64_TLSDESC_CALL:
+    return R_HINT;
+
   case R_AARCH64_TLSLE_ADD_TPREL_HI12:
   case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
     return R_TLS;
@@ -1128,18 +1138,13 @@ bool AArch64TargetInfo::usesOnlyLowPageB
   case R_AARCH64_LDST32_ABS_LO12_NC:
   case R_AARCH64_LDST64_ABS_LO12_NC:
   case R_AARCH64_LDST8_ABS_LO12_NC:
+  case R_AARCH64_TLSDESC_ADD_LO12_NC:
+  case R_AARCH64_TLSDESC_LD64_LO12_NC:
   case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
     return true;
   }
 }
 
-bool AArch64TargetInfo::isTlsGlobalDynamicRel(uint32_t Type) const {
-  return Type == R_AARCH64_TLSDESC_ADR_PAGE21 ||
-         Type == R_AARCH64_TLSDESC_LD64_LO12_NC ||
-         Type == R_AARCH64_TLSDESC_ADD_LO12_NC ||
-         Type == R_AARCH64_TLSDESC_CALL;
-}
-
 bool AArch64TargetInfo::isTlsInitialExecRel(uint32_t Type) const {
   return Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 ||
          Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
@@ -1239,6 +1244,7 @@ void AArch64TargetInfo::relocateOne(uint
   case R_AARCH64_ADR_GOT_PAGE:
   case R_AARCH64_ADR_PREL_PG_HI21:
   case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+  case R_AARCH64_TLSDESC_ADR_PAGE21:
     checkInt<33>(Val, Type);
     updateAArch64Addr(Loc, Val >> 12);
     break;
@@ -1257,6 +1263,7 @@ void AArch64TargetInfo::relocateOne(uint
     break;
   case R_AARCH64_LD64_GOT_LO12_NC:
   case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+  case R_AARCH64_TLSDESC_LD64_LO12_NC:
     checkAlignment<8>(Val, Type);
     or32le(Loc, (Val & 0xFF8) << 7);
     break;
@@ -1284,6 +1291,7 @@ void AArch64TargetInfo::relocateOne(uint
     updateAArch64Add(Loc, Val >> 12);
     break;
   case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+  case R_AARCH64_TLSDESC_ADD_LO12_NC:
     updateAArch64Add(Loc, Val);
     break;
   default:

Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=271569&r1=271568&r2=271569&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Thu Jun  2 14:49:53 2016
@@ -73,6 +73,7 @@ public:
   uint32_t PltRel;
   uint32_t RelativeRel;
   uint32_t IRelativeRel;
+  uint32_t TlsDescRel;
   uint32_t TlsGotRel = 0;
   uint32_t TlsModuleIndexRel;
   uint32_t TlsOffsetRel;

Added: lld/trunk/test/ELF/aarch64-tlsdesc.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-tlsdesc.s?rev=271569&view=auto
==============================================================================
--- lld/trunk/test/ELF/aarch64-tlsdesc.s (added)
+++ lld/trunk/test/ELF/aarch64-tlsdesc.s Thu Jun  2 14:49:53 2016
@@ -0,0 +1,24 @@
+// REQUIRES: aarch64
+// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-linux %s -o %t.o
+// RUN: ld.lld -shared %t.o -o %t.so
+// RUN: llvm-objdump -d %t.so | FileCheck %s
+// RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=REL %s
+
+        adrp    x0, :tlsdesc:a
+        ldr     x1, [x0, :tlsdesc_lo12:a]
+        add     x0, x0, :tlsdesc_lo12:a
+        .tlsdesccall a
+        blr     x1
+
+// CHECK:      1000: {{.*}}  adrp    x0, #4096
+// CHECK-NEXT: 1004: {{.*}}  ldr     x1, [x0, #144]
+// CHECK-NEXT: 1008: {{.*}}  add     x0, x0, #144
+// CHECK-NEXT: 100c: {{.*}}  blr     x1
+
+// 0x1000 + 4096 + 144 = 0x2090
+
+// REL:      Relocations [
+// REL-NEXT:   Section (4) .rela.dyn {
+// REL-NEXT:     0x2090 R_AARCH64_TLSDESC a 0x0
+// REL-NEXT:   }
+// REL-NEXT: ]




More information about the llvm-commits mailing list