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]

[13/16][binutils][AARCH64]Add relocation support for large memory model. [BFD]Add TLSGD relaxation support


Hi all,

This patch adds TLSGD relaxation support into bfd linker. According the documentation, the following two relaxations can be done under different conditions.

Here is the TLSGD access sequence under large memory:

movz a0, #:tlsgd_g1:x             R_AARCH64_TLSGD_MOVW_G1
movk a0, #:tlsgd_g0:x             R_AARCH64_TLSGD_MOVW_G0_NC
add  a0, gp, a0
bl   __tls_get_addr                    R_AARCH64_CALL26
nop

It can be relaxed into following TLSLE code sequence :

movz a0, #:tprel_g2:x                  R_AARCH64_TLSLE_MOVW_TPREL_G2
movk a0, #:tprel_g1_nc:x R_AARCH64_TLSLE_MOVW_TPREL_G1_NC
movk a0, #:tprel_g0_nc:x R_AARCH64_TLSLE_MOVW_TPREL_G0_NC
mrs  a1, tpidr_el0
add  a0, a0, a1

Or into TLSIE code sequence:

movz a0, #:gottprel_g1:x R_AARCH64_TLSIE_MOVW_GOTTPREL_G1
movk a0, #:gottprel_g0_nc:x R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC
ldr  a0, [gp, a0]
mrs  a1, tpidr_el0
add  a0, a0, a1

Binutils and linker checked Okay, Okay to commit?

Regards,
Renlin Li

bfd/ChangeLog:

2015-09-08  Renlin Li <renlin.li@arm.com>

    * elfnn-aarch64.c(IS_AARCH64_TLS_RELAX_RELOC):
    Add relaxation support for TLSGD_MOVW_G0_NC and TLSGD_MOVW_G1.
    (aarch64_tls_transition_without_check): Likewise
    (elfNN_aarch64_tls_relax): Likwise.

ld/testsuite/ChangeLog:


2015-09-08  Renlin Li <renlin.li@arm.com>

    * ld-aarch64/aarch64-elf.exp: run new test
    * ld-aarch64/tls-relax-large-gd-ie.d: New.
    * ld-aarch64/tls-relax-large-gd-ie.s: New.
    * ld-aarch64/tls-relax-large-gd-le.d: New.
    * ld-aarch64/tls-relax-large-gd-le.s: New.
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 6937681..651df7a 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -197,6 +197,8 @@
   ((R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21		\
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADR_PREL21		\
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC		\
+   || (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC		\
+   || (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_MOVW_G1		\
    || (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	\
@@ -4212,6 +4214,18 @@ aarch64_tls_transition_without_check (bfd_reloc_code_real_type r_type,
       /* Instructions with these relocations will become NOPs.  */
       return BFD_RELOC_AARCH64_NONE;
 
+#if ARCH_SIZE == 64
+    case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC:
+      return is_local
+	? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC
+	: BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC;
+
+    case BFD_RELOC_AARCH64_TLSGD_MOVW_G1:
+      return is_local
+	? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2
+	: BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1;
+#endif
+
     default:
       break;
     }
@@ -5429,6 +5443,52 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
 	  return bfd_reloc_continue;
 	}
 
+#if ARCH_SIZE == 64
+    case BFD_RELOC_AARCH64_TLSGD_MOVW_G1:
+      BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (TLSGD_MOVW_G0_NC));
+      BFD_ASSERT (rel->r_offset + 12 == rel[2].r_offset);
+      BFD_ASSERT (ELFNN_R_TYPE (rel[2].r_info) == AARCH64_R (CALL26));
+
+      if (is_local)
+	{
+	  /* Large GD->LE relaxation:
+	     movz x0, #:tlsgd_g1:var    => movz x0, #:tprel_g2:var, lsl #32
+	     movk x0, #:tlsgd_g0_nc:var => movk x0, #:tprel_g1_nc:var, lsl #16
+	     add x0, gp, x0             => movk x0, #:tprel_g0_nc:var
+	     bl __tls_get_addr          => mrs x1, tpidr_el0
+	     nop                        => add x0, x0, x1
+	   */
+	  rel[2].r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info),
+					AARCH64_R (TLSLE_MOVW_TPREL_G0_NC));
+	  rel[2].r_offset = rel->r_offset + 8;
+
+	  bfd_putl32 (0xd2c00000, contents + rel->r_offset + 0);
+	  bfd_putl32 (0xf2a00000, contents + rel->r_offset + 4);
+	  bfd_putl32 (0xf2800000, contents + rel->r_offset + 8);
+	  bfd_putl32 (0xd53bd041, contents + rel->r_offset + 12);
+	  bfd_putl32 (0x8b000020, contents + rel->r_offset + 16);
+	}
+      else
+	{
+	  /* Large GD->IE relaxation:
+	     movz x0, #:tlsgd_g1:var    => movz x0, #:gottprel_g1:var, lsl #16
+	     movk x0, #:tlsgd_g0_nc:var => movk x0, #:gottprel_g0_nc:var
+	     add x0, gp, x0             => ldr x0, [gp, x0]
+	     bl __tls_get_addr          => mrs x1, tpidr_el0
+	     nop                        => add x0, x0, x1
+	   */
+	  rel[2].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+	  bfd_putl32 (0xd2a80000, contents + rel->r_offset + 0);
+	  bfd_putl32 (0x58000000, contents + rel->r_offset + 8);
+	  bfd_putl32 (0xd53bd041, contents + rel->r_offset + 12);
+	  bfd_putl32 (0x8b000020, contents + rel->r_offset + 16);
+	}
+      return bfd_reloc_continue;
+
+    case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC:
+      return bfd_reloc_continue;
+#endif
+
     case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
       return bfd_reloc_continue;
 
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index 3d7b846..b674d12 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -153,6 +153,8 @@ run_dump_test "tls-relax-all"
 run_dump_test "tls-relax-gd-le"
 run_dump_test "tls-relax-gdesc-le"
 run_dump_test "tls-relax-gd-ie"
+run_dump_test "tls-relax-large-gd-ie"
+run_dump_test "tls-relax-large-gd-le"
 run_dump_test "tls-relax-gdesc-ie"
 run_dump_test "tls-relax-ie-le"
 run_dump_test "tls-desc-ie"
diff --git a/ld/testsuite/ld-aarch64/tls-relax-large-gd-ie.d b/ld/testsuite/ld-aarch64/tls-relax-large-gd-ie.d
new file mode 100644
index 0000000..f3407ef
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-large-gd-ie.d
@@ -0,0 +1,16 @@
+#source: tls-relax-large-gd-ie.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+0000000000010000 <test>:
+ +10000:	58000121 	ldr	x1, 10024 <test\+0x24>
+ +10004:	10000102 	adr	x2, 10024 <test\+0x24>
+ +10008:	8b010041 	add	x1, x2, x1
+ +1000c:	d2a00000 	movz	x0, #0x0, lsl #16
+ +10010:	f2800100 	movk	x0, #0x8
+ +10014:	58000000 	ldr	x0, 10014 <test\+0x14>
+ +10018:	d53bd041 	mrs	x1, tpidr_el0
+ +1001c:	8b000020 	add	x0, x1, x0
+ +10020:	b9400000 	ldr	w0, \[x0\]
+ +10024:	0000ffdc 	.word	0x0000ffdc
+ +10028:	00000000 	.word	0x00000000
diff --git a/ld/testsuite/ld-aarch64/tls-relax-large-gd-ie.s b/ld/testsuite/ld-aarch64/tls-relax-large-gd-ie.s
new file mode 100644
index 0000000..8e0310d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-large-gd-ie.s
@@ -0,0 +1,20 @@
+	.global var
+	.section	.tdata,"awT",%progbits
+var:
+	.word	2
+
+	.text
+test:
+	ldr	x1, .Lgot
+	adr	x2, .Lgot
+	add	x1, x2, x1
+
+	movz	x0, #:tlsgd_g1:var
+	movk	x0, #:tlsgd_g0_nc:var
+	add	x0, x1, x0
+	bl	__tls_get_addr
+	nop
+	ldr	w0, [x0]
+
+.Lgot:
+	.dword _GLOBAL_OFFSET_TABLE_ - .
diff --git a/ld/testsuite/ld-aarch64/tls-relax-large-gd-le.d b/ld/testsuite/ld-aarch64/tls-relax-large-gd-le.d
new file mode 100644
index 0000000..acaea58
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-large-gd-le.d
@@ -0,0 +1,16 @@
+#source: tls-relax-large-gd-le.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+0000000000010000 <test>:
+ +10000:	58000121 	ldr	x1, 10024 <test\+0x24>
+ +10004:	10000102 	adr	x2, 10024 <test\+0x24>
+ +10008:	8b010041 	add	x1, x2, x1
+ +1000c:	d2c00000 	movz	x0, #0x0, lsl #32
+ +10010:	f2a00000 	movk	x0, #0x0, lsl #16
+ +10014:	f2800200 	movk	x0, #0x10
+ +10018:	d53bd041 	mrs	x1, tpidr_el0
+ +1001c:	8b000020 	add	x0, x1, x0
+ +10020:	b9400000 	ldr	w0, \[x0\]
+ +10024:	0000ffdc 	.word	0x0000ffdc
+ +10028:	00000000 	.word	0x00000000
diff --git a/ld/testsuite/ld-aarch64/tls-relax-large-gd-le.s b/ld/testsuite/ld-aarch64/tls-relax-large-gd-le.s
new file mode 100644
index 0000000..781f6cc
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-large-gd-le.s
@@ -0,0 +1,19 @@
+	.section	.tdata
+var:
+	.word	2
+
+	.text
+test:
+	ldr	x1, .Lgot
+	adr	x2, .Lgot
+	add	x1, x2, x1
+
+	movz	x0, #:tlsgd_g1:var
+	movk	x0, #:tlsgd_g0_nc:var
+	add	x0, x1, x0
+	bl	__tls_get_addr
+	nop
+	ldr	w0, [x0]
+
+.Lgot:
+	.dword _GLOBAL_OFFSET_TABLE_ - .




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