ARM: support tlscall relocations
authorSaleem Abdulrasool <compnerd@compnerd.org>
Thu, 30 Jan 2014 04:02:31 +0000 (04:02 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Thu, 30 Jan 2014 04:02:31 +0000 (04:02 +0000)
This adds support for TLS CALL relocations.  TLS CALL relocations are used to
indicate to the linker to generate appropriate entries to resolve TLS references
via an appropriate function invocation (e.g. __tls_get_addr(PLT)).

In order to accomodate the linker relaxation of the TLS access model for the
references (GD/LD -> IE, IE -> LE), the relocation addend must be incomplete.
This requires that the partial inplace value is also incomplete (i.e. 0).  We
simply avoid the offset value calculation at the time of the fixup adjustment in
the ARM assembler backend.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@200446 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCExpr.h
lib/MC/MCExpr.cpp
lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
test/MC/ARM/symbol-variants.s

index f556d6237ff2561ca0e43c08049bd753873a9849..b62252057f90b1f324a93d650392cbd58176cc58 100644 (file)
@@ -166,6 +166,7 @@ public:
     VK_ARM_TARGET2,
     VK_ARM_PREL31,
     VK_ARM_TLSLDO,         // symbol(tlsldo)
+    VK_ARM_TLSCALL,        // symbol(tlscall)
 
     VK_PPC_LO,             // symbol@l
     VK_PPC_HI,             // symbol@h
index 2052d55dc7ebec81ea9d28415d7ba23d16509a87..3772bceea57d424772585d56ce655ad67b3b5538 100644 (file)
@@ -185,6 +185,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
   case VK_ARM_TARGET2: return "target2";
   case VK_ARM_PREL31: return "prel31";
   case VK_ARM_TLSLDO: return "tlsldo";
+  case VK_ARM_TLSCALL: return "tlscall";
   case VK_PPC_LO: return "l";
   case VK_PPC_HI: return "h";
   case VK_PPC_HA: return "ha";
@@ -408,6 +409,8 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
     .Case("prel31", VK_ARM_PREL31)
     .Case("TLSLDO", VK_ARM_TLSLDO)
     .Case("tlsldo", VK_ARM_TLSLDO)
+    .Case("TLSCALL", VK_ARM_TLSCALL)
+    .Case("tlscall", VK_ARM_TLSCALL)
     .Default(VK_Invalid);
 }
 
index 305c7587cb16386256640e78e5023daa2b717e5b..7db700472cb00d9d36e40a43cec4fcc433ef8d3c 100644 (file)
@@ -380,6 +380,9 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
   case ARM::fixup_arm_blx:
     // These values don't encode the low two bits since they're always zero.
     // Offset by 8 just as above.
+    if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Fixup.getValue()))
+      if (SRE->getKind() == MCSymbolRefExpr::VK_ARM_TLSCALL)
+        return 0;
     return 0xffffff & ((Value - 8) >> 2);
   case ARM::fixup_t2_uncondbranch: {
     Value = Value - 4;
@@ -461,6 +464,9 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
     // Note that the halfwords are stored high first, low second; so we need
     // to transpose the fixup value here to map properly.
     uint32_t offset = (Value - 2) >> 2;
+    if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Fixup.getValue()))
+      if (SRE->getKind() == MCSymbolRefExpr::VK_ARM_TLSCALL)
+        offset = 0;
     uint32_t signBit = (offset & 0x400000) >> 22;
     uint32_t I1Bit = (offset & 0x200000) >> 21;
     uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit;
index 6fcc021a6c72c83b3d24940486022b8f68bb70b8..08c040235fdcbc7c280e084b1d31d20b69d1519f 100644 (file)
@@ -179,6 +179,9 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
       case MCSymbolRefExpr::VK_PLT:
         Type = ELF::R_ARM_PLT32;
         break;
+      case MCSymbolRefExpr::VK_ARM_TLSCALL:
+        Type = ELF::R_ARM_TLS_CALL;
+        break;
       default:
         Type = ELF::R_ARM_CALL;
         break;
@@ -211,7 +214,14 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
       break;
     case ARM::fixup_arm_thumb_bl:
     case ARM::fixup_arm_thumb_blx:
-      Type = ELF::R_ARM_THM_CALL;
+      switch (Modifier) {
+      case MCSymbolRefExpr::VK_ARM_TLSCALL:
+        Type = ELF::R_ARM_THM_TLS_CALL;
+        break;
+      default:
+        Type = ELF::R_ARM_THM_CALL;
+        break;
+      }
       break;
     }
   } else {
@@ -253,6 +263,9 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
       case MCSymbolRefExpr::VK_ARM_TLSLDO:
         Type = ELF::R_ARM_TLS_LDO32;
         break;
+      case MCSymbolRefExpr::VK_ARM_TLSCALL:
+        Type = ELF::R_ARM_TLS_CALL;
+        break;
       }
       break;
     case ARM::fixup_arm_ldst_pcrel_12:
index 1ab504cf65583e59d358ae7af9ff370e9e81b2da..f0bf4c4b7c0dca6b3942f3761d8ca3c0e35aafea 100644 (file)
@@ -70,3 +70,10 @@ bl f05(plt)
 .word f21(tlsldo)
 @CHECK: 80 R_ARM_TLS_LDO32 f20
 @CHECK: 84 R_ARM_TLS_LDO32 f21
+
+@ tlscall
+.word f22(TLSCALL)
+.word f23(tlscall)
+@ CHECK: 88 R_ARM_TLS_CALL f22
+@ CHECK: 92 R_ARM_TLS_CALL f23
+