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.

llvm-svn: 271569
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 53149ba..48fb403 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -62,7 +62,7 @@
   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 @@
     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 @@
     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 @@
   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 @@
     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 @@
       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.