This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[AArch64] Relax TLS local dynamic traditional into local executable


This patch add the linker relaxation from TLS local dynamic traditional
model into local executable on AArch64 tiny/small model.

After this relaxation, we don't need to invoke the runtime resolver.

The linker relaxation logic will be:

Code sequence I (tiny):

    0x00 adr  x0, :tlsldm:x
    0x04 bl   __tls_get_addr
         |
         V
    0x00 mrs  x0, tpidr_el0
    0x04 add  x0, x0, TCB_SIZE

Code sequence II (small):

    0x00 adrp a0, :tlsldm:x
    0x04 add  a0, #:tlsldm_lo12:x
    0x08 bl   __tls_get_addr
         |
         V
    0x00 mrs  x0, tpidr_el0
    0x04 add  x0, x0, TCB_SIZE
    0x08 nop

For local dynamic model, the TLS instruction sequences is composed of
two parts, the first part calcuate module base address, the second part
add variable offset to get final address.

For linker relaxation, we only need to touch the first part. When relax
from local dynamic into local executable, we don't need to invoke
runtime resolver to get module base address. As for local executable,
the "module" should be initial TLS module, thus the module base address
can be calculated by "tp + TCB_SIZE" as tp points to start of initial
TLS module start, we need to skip the thread control block to point to
real module contents for variable.

After the relaxation, the relocation for the 'bl' instruction should be
removed also, as we don't need any relocation anymore.

ok for trunk?

2015-08-25  Jiong Wang  <jiong.wang@arm.com>

bfd/
  * elfnn-aarch64.c (aarch64_tls_transition_without_check): Support
  three TLS local dynamic traditional relocations types.
  (elfNN_aarch64_tls_relax): Support TLS local dynamic traditional to
  local executable relaxation.

ld/testsuite/
  * ld-aarch64/tls-relax-ld-le-tiny.s: New testcase.
  * ld-aarch64/tls-relax-ld-le-small.s: Likewise.
  * ld-aarch64/tls-relax-ld-le-tiny.d: New expectation file.
  * ld-aarch64/tls-relax-ld-le-small.d: Likewise.
  * ld-aarch64/aarch64-elf.exp: Run new testcases.
  
-- 
Regards,
Jiong

diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 9935308..89d5c72 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -213,6 +213,9 @@
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21	\
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19	\
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_LDNN_GOTTPREL_LO12_NC	\
+   || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC		\
+   || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21		\
+   || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADR_PREL21		\
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21		\
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21		\
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LD_PREL19		\
@@ -4390,6 +4393,11 @@ aarch64_tls_transition_without_check (bfd_reloc_code_real_type r_type,
       /* Instructions with these relocations will become NOPs.  */
       return BFD_RELOC_AARCH64_NONE;
 
+    case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC:
+    case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21:
+    case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21:
+      return is_local ? BFD_RELOC_AARCH64_NONE : r_type;
+
     default:
       break;
     }
@@ -5616,6 +5624,51 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
 	}
       return bfd_reloc_continue;
 
+    case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21:
+      /* LD->LE relaxation (tiny):
+	 adr  x0, :tlsldm:x  => mrs x0, tpidr_el0
+	 bl   __tls_get_addr => add x0, x0, TCB_SIZE
+       */
+      if (is_local)
+	{
+	  BFD_ASSERT (rel->r_offset + 4 == rel[1].r_offset);
+	  BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (CALL26));
+	  /* No need of CALL26 relocation for tls_get_addr.  */
+	  rel[1].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+	  bfd_putl32 (0xd53bd040, contents + rel->r_offset + 0);
+	  bfd_putl32 (0x91004000, contents + rel->r_offset + 4);
+	  return bfd_reloc_ok;
+	}
+      return bfd_reloc_continue;
+
+    case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21:
+      /* LD->LE relaxation (small):
+	 adrp  x0, :tlsldm:x       => mrs x0, tpidr_el0
+       */
+      if (is_local)
+	{
+	  bfd_putl32 (0xd53bd040, contents + rel->r_offset);
+	  return bfd_reloc_ok;
+	}
+      return bfd_reloc_continue;
+
+    case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC:
+      /* LD->LE relaxation (small):
+	 add   x0, #:tlsldm_lo12:x => add x0, x0, TCB_SIZE
+	 bl   __tls_get_addr       => nop
+       */
+      if (is_local)
+	{
+	  BFD_ASSERT (rel->r_offset + 4 == rel[1].r_offset);
+	  BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (CALL26));
+	  /* No need of CALL26 relocation for tls_get_addr.  */
+	  rel[1].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+	  bfd_putl32 (0x91004000, contents + rel->r_offset + 0);
+	  bfd_putl32 (0xd503201f, contents + rel->r_offset + 4);
+	  return bfd_reloc_ok;
+	}
+      return bfd_reloc_continue;
+
     default:
       return bfd_reloc_continue;
     }
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index cbbe6a9..955484e 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -178,6 +178,8 @@ run_dump_test "tls-relax-gdesc-le"
 run_dump_test "tls-relax-gd-ie"
 run_dump_test "tls-relax-gdesc-ie"
 run_dump_test "tls-relax-ie-le"
+run_dump_test "tls-relax-ld-le-small"
+run_dump_test "tls-relax-ld-le-tiny"
 run_dump_test "tls-desc-ie"
 run_dump_test "tls-relax-gdesc-ie-2"
 run_dump_test "tls-relax-gdesc-le-2"
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ld-le-small.d b/ld/testsuite/ld-aarch64/tls-relax-ld-le-small.d
new file mode 100644
index 0000000..fa64829
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ld-le-small.d
@@ -0,0 +1,13 @@
+#source: tls-relax-ld-le-small.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	910003fd 	mov	x29, sp
+ +10004:	d53bd040 	mrs	x0, tpidr_el0
+ +10008:	91004000 	add	x0, x0, #0x10
+ +1000c:	d503201f 	nop
+ +10010:	d503201f 	nop
+ +10014:	91400001 	add	x1, x0, #0x0, lsl #12
+ +10018:	91000021 	add	x1, x1, #0x0
+ +1001c:	90000000 	adrp	x0, 10000 <.*>
+ +10020:	d65f03c0 	ret
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ld-le-small.s b/ld/testsuite/ld-aarch64/tls-relax-ld-le-small.s
new file mode 100644
index 0000000..ea58500
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ld-le-small.s
@@ -0,0 +1,27 @@
+	.cpu generic+fp+simd
+	.section	.text.startup,"ax",%progbits
+	.align	2
+	.p2align 3,,7
+	.global	main
+	.type	main, %function
+main:
+	add	x29, sp, 0
+	adrp	x0, :tlsldm:global_a0
+	add	x0, x0, #:tlsldm_lo12_nc:global_a0
+	bl	__tls_get_addr
+	nop
+	add	x1, x0, #:dtprel_hi12:global_a0, lsl #12
+	add	x1, x1, #:dtprel_lo12_nc:global_a0
+	adrp	x0, .LC0
+	ret
+	.size	main, .-main
+	.section	.rodata.str1.8,"aMS",%progbits,1
+	.align	3
+.LC0:
+	.string	"Hello world %d\n"
+	.section	.tdata,"awT",%progbits
+	.align	2
+	.type	global_a0, %object
+	.size	global_a0, 4
+global_a0:
+	.word	16
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny.d b/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny.d
new file mode 100644
index 0000000..db22677
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny.d
@@ -0,0 +1,12 @@
+#source: tls-relax-ld-le-tiny.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000:	910003fd 	mov	x29, sp
+ +10004:	d53bd040 	mrs	x0, tpidr_el0
+ +10008:	91004000 	add	x0, x0, #0x10
+ +1000c:	d503201f 	nop
+ +10010:	91400001 	add	x1, x0, #0x0, lsl #12
+ +10014:	91000021 	add	x1, x1, #0x0
+ +10018:	90000000 	adrp	x0, 10000 <main>
+ +1001c:	d65f03c0 	ret
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny.s b/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny.s
new file mode 100644
index 0000000..2336f69
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny.s
@@ -0,0 +1,26 @@
+	.cpu generic+fp+simd
+	.section	.text.startup,"ax",%progbits
+	.align	2
+	.p2align 3,,7
+	.global	main
+	.type	main, %function
+main:
+	add	x29, sp, 0
+	adr     x0, :tlsldm:global_a0
+	bl	__tls_get_addr
+	nop
+	add	x1, x0, #:dtprel_hi12:global_a0, lsl #12
+	add	x1, x1, #:dtprel_lo12_nc:global_a0
+	adrp	x0, .LC0
+	ret
+	.size	main, .-main
+	.section	.rodata.str1.8,"aMS",%progbits,1
+	.align	3
+.LC0:
+	.string	"Hello world %d\n"
+	.section	.tdata,"awT",%progbits
+	.align	2
+	.type	global_a0, %object
+	.size	global_a0, 4
+global_a0:
+	.word	16

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]