ELF/AArch64: Fix dynamic relocation against local symbol in shared objects
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Mon, 19 Dec 2016 11:58:01 +0000 (11:58 +0000)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Mon, 19 Dec 2016 11:58:01 +0000 (11:58 +0000)
AArch64 TLSDESC for local symbol in shared objects are implemented in a
arch specific manner where the TLSDESC dynamic relocation addend is the
symbol VM inside the TLS block. For instance, with a shared library
created from the code:

--
static __thread int32_t x1;
static __thread int64_t x2;

int32_t foo1 (int32_t x)
{
  x1 += x;
  return x;
}

int64_t foo2 (int64_t x)
{
  x2 += x;
  return x;
}
--

The dynamic relocation should be create as:

Relocations [
  Section (N) .rela.dyn {
    <Address1> R_AARCH64_TLSDESC - 0x0
    <Address2> R_AARCH64_TLSDESC - 0x8
  }
]

Where 0x0 addend in first dynamic relocation is the address of 'x1'
in TLS block and '0x8' is the address of 'x2'.

Checked against test-suite on aarch64-linux-gnu.

llvm-svn: 290099

lld/ELF/Relocations.cpp
lld/test/ELF/aarch64-tlsdesc.s

index 26949a5..1c87acc 100644 (file)
@@ -155,8 +155,8 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body,
       Config->Shared) {
     if (In<ELFT>::Got->addDynTlsEntry(Body)) {
       uintX_t Off = In<ELFT>::Got->getGlobalDynOffset(Body);
-      In<ELFT>::RelaDyn->addReloc(
-          {Target->TlsDescRel, In<ELFT>::Got, Off, false, &Body, 0});
+      In<ELFT>::RelaDyn->addReloc({Target->TlsDescRel, In<ELFT>::Got, Off,
+                                   !Body.isPreemptible(), &Body, 0});
     }
     if (Expr != R_TLSDESC_CALL)
       C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
index 5fc50c4..09dfd04 100644 (file)
@@ -4,21 +4,69 @@
 // RUN: llvm-objdump -d %t.so | FileCheck %s
 // RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=REL %s
 
+       .text
         adrp    x0, :tlsdesc:a
         ldr     x1, [x0, :tlsdesc_lo12:a]
         add     x0, x0, :tlsdesc_lo12:a
         .tlsdesccall a
         blr     x1
 
+// Create relocation against local TLS symbols where linker should
+// create target specific dynamic TLSDESC relocation where addend is
+// the symbol VMA in tls block.
+
 // CHECK:      10000: {{.*}}  adrp    x0, #65536
 // CHECK-NEXT: 10004: {{.*}}  ldr     x1, [x0, #144]
 // CHECK-NEXT: 10008: {{.*}}  add     x0, x0, #144
 // CHECK-NEXT: 1000c: {{.*}}  blr     x1
 
+       adrp    x0, :tlsdesc:local1
+       ldr     x1, [x0, :tlsdesc_lo12:local1]
+       add     x0, x0, :tlsdesc_lo12:local1
+        .tlsdesccall a
+        blr     x1
+
+// CHECK:      10010: {{.*}}  adrp    x0, #65536
+// CHECK-NEXT: 10014: {{.*}}  ldr     x1, [x0, #160]
+// CHECK-NEXT: 10018: {{.*}}  add     x0, x0, #160
+// CHECK-NEXT: 1001c: {{.*}}  blr     x1
+
+       adrp    x0, :tlsdesc:local2
+       ldr     x1, [x0, :tlsdesc_lo12:local2]
+       add     x0, x0, :tlsdesc_lo12:local2
+        .tlsdesccall a
+        blr     x1
+
+// CHECK:      10020: {{.*}}  adrp    x0, #65536
+// CHECK-NEXT: 10024: {{.*}}  ldr     x1, [x0, #176]
+// CHECK-NEXT: 10028: {{.*}}  add     x0, x0, #176
+// CHECK-NEXT: 1002c: {{.*}}  blr     x1
+
+        .section .tbss,"awT",@nobits
+        .type   local1,@object
+        .p2align 2
+local1:
+        .word   0
+        .size   local1, 4
+
+        .type   local2,@object
+        .p2align 3
+local2:
+        .xword  0
+        .size   local2, 8
+
+
+// 0x1000 + 4096 + 160 = 0x20A0
+// 0x1000 + 4096 + 176 = 0x20B0
 // 0x1000 + 4096 + 144 = 0x2090
 
+// R_AARCH64_TLSDESC - 0x0 -> start of tls block
+// R_AARCH64_TLSDESC - 0x8 -> align (sizeof (local1), 8)
+
 // REL:      Relocations [
 // REL-NEXT:   Section (4) .rela.dyn {
+// REL-NEXT:     0x200A0 R_AARCH64_TLSDESC - 0x0
+// REL-NEXT:     0x200B0 R_AARCH64_TLSDESC - 0x8
 // REL-NEXT:     0x20090 R_AARCH64_TLSDESC a 0x0
 // REL-NEXT:   }
 // REL-NEXT: ]