[lld] r276095 - Support for standard model ARM TLS

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 20 01:52:28 PDT 2016


Author: psmith
Date: Wed Jul 20 03:52:27 2016
New Revision: 276095

URL: http://llvm.org/viewvc/llvm-project?rev=276095&view=rev
Log:
Support for standard model ARM TLS
    
Add relocations and identification functions for the Initial Exec
and Global Dynamic TLS model defined in Addenda to, and Errata in,
the ABI for the ARM Architecture.
    
ARM uses variant 1 of the thread local storage data
structures as defined in ELF Handling for Thread-Local Storage.
    
The "experimental" descriptor based model that can be selected in
gcc, but not clang with -mtls-dialect=gnu2 is not supported.
    
The relocations R_ARM_TLS_LE12 and R_ARM_TLS_IE12GP are not
supported, I know of no ARM Toolchain that supports these relocations
as they limit the size of the TLS block.
    
No code relaxation is supported as the standard ARM TLS model puts
the relocations on literal data.
    
Support for the local dynamic model will come in a follow up patch.

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


Added:
    lld/trunk/test/ELF/arm-tls-gd32.s   (with props)
    lld/trunk/test/ELF/arm-tls-ie32.s   (with props)
    lld/trunk/test/ELF/arm-tls-le32.s   (with props)
Modified:
    lld/trunk/ELF/Target.cpp

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=276095&r1=276094&r2=276095&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Wed Jul 20 03:52:27 2016
@@ -178,6 +178,8 @@ public:
   RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override;
   uint32_t getDynRel(uint32_t Type) const override;
   uint64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override;
+  bool isTlsGlobalDynamicRel(uint32_t Type) const override;
+  bool isTlsInitialExecRel(uint32_t Type) const override;
   void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override;
   void writePltHeader(uint8_t *Buf) const override;
   void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
@@ -1491,6 +1493,8 @@ ARMTargetInfo::ARMTargetInfo() {
   GotPltEntrySize = 4;
   PltEntrySize = 16;
   PltHeaderSize = 20;
+  // ARM uses Variant 1 TLS
+  TcbSize = 8;
 }
 
 RelExpr ARMTargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const {
@@ -1514,8 +1518,11 @@ RelExpr ARMTargetInfo::getRelExpr(uint32
     // GOT(S) + A - GOT_ORG
     return R_GOT_OFF;
   case R_ARM_GOT_PREL:
-    // GOT(S) + - GOT_ORG
+  case R_ARM_TLS_IE32:
+    // GOT(S) + A - P
     return R_GOT_PC;
+  case R_ARM_TLS_GD32:
+    return R_TLSGD_PC;
   case R_ARM_BASE_PREL:
     // B(S) + A - P
     // FIXME: currently B(S) assumed to be .got, this may not hold for all
@@ -1528,6 +1535,8 @@ RelExpr ARMTargetInfo::getRelExpr(uint32
   case R_ARM_THM_MOVW_PREL_NC:
   case R_ARM_THM_MOVT_PREL:
     return R_PC;
+  case R_ARM_TLS_LE32:
+    return R_TLS;
   }
 }
 
@@ -1613,6 +1622,9 @@ void ARMTargetInfo::relocateOne(uint8_t
   case R_ARM_GOT_BREL:
   case R_ARM_GOT_PREL:
   case R_ARM_REL32:
+  case R_ARM_TLS_GD32:
+  case R_ARM_TLS_IE32:
+  case R_ARM_TLS_LE32:
     write32le(Loc, Val);
     break;
   case R_ARM_PREL31:
@@ -1736,6 +1748,9 @@ uint64_t ARMTargetInfo::getImplicitAdden
   case R_ARM_GOT_BREL:
   case R_ARM_GOT_PREL:
   case R_ARM_REL32:
+  case R_ARM_TLS_GD32:
+  case R_ARM_TLS_IE32:
+  case R_ARM_TLS_LE32:
     return SignExtend64<32>(read32le(Buf));
   case R_ARM_PREL31:
     return SignExtend64<31>(read32le(Buf));
@@ -1793,6 +1808,14 @@ uint64_t ARMTargetInfo::getImplicitAdden
   }
 }
 
+bool ARMTargetInfo::isTlsGlobalDynamicRel(uint32_t Type) const {
+  return Type == R_ARM_TLS_GD32;
+}
+
+bool ARMTargetInfo::isTlsInitialExecRel(uint32_t Type) const {
+  return Type == R_ARM_TLS_IE32;
+}
+
 template <class ELFT> MipsTargetInfo<ELFT>::MipsTargetInfo() {
   GotPltHeaderEntriesNum = 2;
   PageSize = 65536;

Added: lld/trunk/test/ELF/arm-tls-gd32.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-tls-gd32.s?rev=276095&view=auto
==============================================================================
--- lld/trunk/test/ELF/arm-tls-gd32.s (added)
+++ lld/trunk/test/ELF/arm-tls-gd32.s Wed Jul 20 03:52:27 2016
@@ -0,0 +1,106 @@
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi
+// RUN: ld.lld %t.o -o %t.so -shared
+// RUN: llvm-readobj -s -dyn-relocations %t.so | FileCheck --check-prefix=SEC %s
+// RUN: llvm-objdump -d -triple=armv7a-linux-gnueabi %t.so | FileCheck %s
+// REQUIRES: arm
+
+// Test the handling of the global-dynamic TLS model. Dynamic Loader finds
+// module index R_ARM_TLS_DTPMOD32 and the offset within the module
+// R_ARM_TLS_DTPOFF32. One of the variables is hidden which permits relaxation
+// to local dynamic
+
+ .text
+ .syntax unified
+ .globl  func
+ .p2align        2
+ .type   func,%function
+func:
+.L0:
+ nop
+.L1:
+ nop
+.L2:
+ nop
+
+ .p2align        2
+// Generate R_ARM_TLS_GD32 relocations
+// Allocates a pair of GOT entries dynamically relocated by R_ARM_TLS_DTPMOD32
+// and R_ARM_TLS_DTPOFF32 respectively. The literal contains the offset of the
+// first GOT entry from the place
+.Lt0: .word   x(TLSGD) + (. - .L0 - 8)
+.Lt1: .word   y(TLSGD) + (. - .L1 - 8)
+.Lt2: .word   z(TLSGD) + (. - .L2 - 8)
+
+// __thread int x = 10
+// __thread int y;
+// __thread int z __attribute((visibility("hidden")))
+
+ .hidden z
+ .globl  z
+ .globl  y
+ .globl  x
+
+ .section       .tbss,"awT",%nobits
+ .p2align  2
+.TLSSTART:
+ .type  z, %object
+z:
+ .space 4
+ .type  y, %object
+y:
+ .space 4
+ .section       .tdata,"awT",%progbits
+ .p2align 2
+ .type  x, %object
+x:
+ .word  10
+
+// SEC:      Name: .tdata
+// SEC-NEXT: Type: SHT_PROGBITS
+// SEC-NEXT: Flags [
+// SEC-NEXT:   SHF_ALLOC
+// SEC-NEXT:   SHF_TLS
+// SEC-NEXT:   SHF_WRITE
+// SEC-NEXT:  ]
+// SEC-NEXT: Address: 0x2000
+// SEC:      Size: 4
+// SEC:      Name: .tbss
+// SEC-NEXT: Type: SHT_NOBITS
+// SEC-NEXT: Flags [
+// SEC-NEXT:   SHF_ALLOC
+// SEC-NEXT:   SHF_TLS
+// SEC-NEXT:   SHF_WRITE
+// SEC-NEXT: ]
+// SEC-NEXT: Address: 0x2004
+// SEC:      Size: 8
+
+// SEC:      Name: .got
+// SEC-NEXT: Type: SHT_PROGBITS
+// SEC-NEXT: Flags [
+// SEC-NEXT:   SHF_ALLOC
+// SEC-NEXT:   SHF_WRITE
+// SEC-NEXT: ]
+// SEC-NEXT: Address: 0x204C
+// SEC:      Size: 24
+
+// SEC: Dynamic Relocations {
+// SEC-NEXT: 0x205C R_ARM_TLS_DTPMOD32 -
+// SEC-NEXT: 0x204C R_ARM_TLS_DTPMOD32 x
+// SEC-NEXT: 0x2050 R_ARM_TLS_DTPOFF32 x
+// SEC-NEXT: 0x2054 R_ARM_TLS_DTPMOD32 y
+// SEC-NEXT: 0x2058 R_ARM_TLS_DTPOFF32 y
+
+
+// CHECK: Disassembly
+// CHECK-NEXT: func:
+// CHECK-NEXT:    1000:      00 f0 20 e3     nop
+// CHECK-NEXT:    1004:      00 f0 20 e3     nop
+// CHECK-NEXT:    1008:      00 f0 20 e3     nop
+
+// (0x204c - 0x100c) + (0x100c - 0x1000 - 8) = 0x1044
+// CHECK:    100c:	44 10 00 00
+// (0x2054 - 0x1010) + (0x1010 - 0x1004 - 8) = 0x1048
+// CHECK-NEXT:    1010:	48 10 00 00
+// (0x205c - 0x1014) + (0x1014 - 0x1008 - 8) = 0x104c
+// CHECK-NEXT:    1014:	4c 10 00 00
+

Propchange: lld/trunk/test/ELF/arm-tls-gd32.s
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lld/trunk/test/ELF/arm-tls-gd32.s
------------------------------------------------------------------------------
    svn:keywords = Rev Date Author URL Id

Added: lld/trunk/test/ELF/arm-tls-ie32.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-tls-ie32.s?rev=276095&view=auto
==============================================================================
--- lld/trunk/test/ELF/arm-tls-ie32.s (added)
+++ lld/trunk/test/ELF/arm-tls-ie32.s Wed Jul 20 03:52:27 2016
@@ -0,0 +1,96 @@
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi
+// RUN: ld.lld %t.o -o %t.so -shared
+// RUN: llvm-readobj -s -dyn-relocations %t.so | FileCheck --check-prefix=SEC %s
+// RUN: llvm-objdump -d -triple=armv7a-linux-gnueabi %t.so | FileCheck %s
+// REQUIRES: arm
+
+// Test the handling of the initial-exec TLS model. Relative location within
+// static TLS is a run-time constant computed by dynamic loader as a result
+// of the R_ARM_TLS_TPOFF32 relocation.
+
+ .syntax unified
+ .arm
+ .globl func
+ .type  func,%function
+ .p2align 2
+func:
+.L0:
+ nop
+.L1:
+ nop
+.L2:
+ nop
+
+ .p2align 2
+// Generate R_ARM_TLS_IE32 static relocations
+// Allocates a GOT entry dynamically relocated by R_ARM_TLS_TPOFF32
+// literal contains the offset of the GOT entry from the place
+.Lt0: .word  x(gottpoff) + (. - .L0 - 8)
+.Lt1: .word  y(gottpoff) + (. - .L1 - 8)
+.Lt2: .word  .TLSSTART(gottpoff) + (. - .L2 - 8)
+
+// __thread int x = 10
+// __thread int y;
+// __thread int z __attribute((visibility("hidden")))
+ .hidden z
+ .globl  z
+ .globl  y
+ .globl  x
+
+ .section       .tbss,"awT",%nobits
+ .p2align  2
+.TLSSTART:
+ .type  z, %object
+z:
+ .space 4
+ .type  y, %object
+y:
+ .space 4
+ .section       .tdata,"awT",%progbits
+ .p2align 2
+ .type  x, %object
+x:
+ .word  10
+
+// SEC:      Name: .tdata
+// SEC-NEXT: Type: SHT_PROGBITS
+// SEC-NEXT: Flags [
+// SEC-NEXT:   SHF_ALLOC
+// SEC-NEXT:   SHF_TLS
+// SEC-NEXT:   SHF_WRITE
+// SEC:      Size: 4
+// SEC:      Name: .tbss
+// SEC-NEXT: Type: SHT_NOBITS
+// SEC-NEXT: Flags [
+// SEC-NEXT:   SHF_ALLOC
+// SEC-NEXT:   SHF_TLS
+// SEC-NEXT:   SHF_WRITE
+// SEC: Size: 8
+
+// SEC:      Name: .got
+// SEC-NEXT: Type: SHT_PROGBITS
+// SEC-NEXT: Flags [
+// SEC-NEXT:    SHF_ALLOC
+// SEC-NEXT:    SHF_WRITE
+// SEC-NEXT: ]
+// SEC-NEXT: Address: 0x204C
+// SEC:      Size: 12
+
+
+// SEC: Dynamic Relocations {
+// SEC:  0x2054 R_ARM_TLS_TPOFF32
+// SEC:  0x204C R_ARM_TLS_TPOFF32 x
+// SEC:  0x2050 R_ARM_TLS_TPOFF32 y
+
+// CHECK: Disassembly of section .text:
+// CHECK-NEXT: func:
+// CHECK-NEXT:    1000: 00 f0 20 e3     nop
+// CHECK-NEXT:    1004: 00 f0 20 e3     nop
+// CHECK-NEXT:    1008: 00 f0 20 e3     nop
+
+// (0x204c - 0x100c) + (0x100c - 0x1000 - 8) = 0x1044
+// CHECK:         100c: 44 10 00 00
+// (0x2050 - 0x1010) + (0x1010 - 0x1004 - 8) = 0x1044
+// CHECK-NEXT:    1010: 44 10 00 00
+// (0x2054 - 0x1014) + (0x1014 - 0x1008 - 8) = 0x1044
+// CHECK-NEXT:    1014: 44 10 00 00

Propchange: lld/trunk/test/ELF/arm-tls-ie32.s
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lld/trunk/test/ELF/arm-tls-ie32.s
------------------------------------------------------------------------------
    svn:keywords = Rev Date Author URL Id

Added: lld/trunk/test/ELF/arm-tls-le32.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-tls-le32.s?rev=276095&view=auto
==============================================================================
--- lld/trunk/test/ELF/arm-tls-le32.s (added)
+++ lld/trunk/test/ELF/arm-tls-le32.s Wed Jul 20 03:52:27 2016
@@ -0,0 +1,77 @@
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi
+// RUN: ld.lld %t.o -o %t
+// RUN: llvm-readobj -s -dyn-relocations %t | FileCheck --check-prefix=SEC %s
+// RUN: llvm-objdump -d -triple=armv7a-linux-gnueabi %t | FileCheck %s
+// REQUIRES: arm
+
+// Test the handling of the local exec TLS model. TLS can be resolved
+// statically for an application. The code sequences assume a thread pointer
+// in r9
+
+ .text
+ .syntax unified
+ .globl  _start
+ .p2align        2
+ .type   _start,%function
+_start:
+ .p2align        2
+// Generate R_ARM_TLS_LE32 relocations. These resolve statically to the offset
+// of the variable from the thread pointer
+.Lt0: .word   x(TPOFF)
+.Lt1: .word   y(TPOFF)
+.Lt2: .word   z(TPOFF)
+
+// __thread int x = 10
+// __thread int y;
+// __thread int z __attribute((visibility("hidden")))
+
+ .hidden z
+ .globl  z
+ .globl  y
+ .globl  x
+
+ .section       .tbss,"awT",%nobits
+ .p2align  2
+.TLSSTART:
+ .type  z, %object
+z:
+ .space 4
+ .type  y, %object
+y:
+ .space 4
+ .section       .tdata,"awT",%progbits
+ .p2align 2
+ .type  x, %object
+x:
+ .word  10
+
+// SEC:      Name: .tdata
+// SEC-NEXT: Type: SHT_PROGBITS
+// SEC-NEXT: Flags [
+// SEC-NEXT:   SHF_ALLOC
+// SEC-NEXT:   SHF_TLS
+// SEC-NEXT:   SHF_WRITE
+// SEC-NEXT:  ]
+// SEC-NEXT: Address: 0x12000
+// SEC:      Size: 4
+// SEC:      Name: .tbss
+// SEC-NEXT: Type: SHT_NOBITS
+// SEC-NEXT: Flags [
+// SEC-NEXT:   SHF_ALLOC
+// SEC-NEXT:   SHF_TLS
+// SEC-NEXT:   SHF_WRITE
+// SEC-NEXT: ]
+// SEC-NEXT: Address: 0x12004
+// SEC:      Size: 8
+
+// SEC: Dynamic Relocations {
+// SEC-NEXT: }
+
+// CHECK: Disassembly of section .text:
+// CHECK-NEXT: _start:
+// offset of x from Thread pointer = (TcbSize + 0x0 = 0x8)
+// CHECK-NEXT:   11000:         08 00 00 00
+// offset of z from Thread pointer = (TcbSize + 0x8 = 0x10)
+// CHECK-NEXT:   11004:         10 00 00 00
+// offset of y from Thread pointer = (TcbSize + 0x4 = 0xc)
+// CHECK-NEXT:   11008:         0c 00 00 00

Propchange: lld/trunk/test/ELF/arm-tls-le32.s
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lld/trunk/test/ELF/arm-tls-le32.s
------------------------------------------------------------------------------
    svn:keywords = Rev Date Author URL Id




More information about the llvm-commits mailing list