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]

[16/16][binutils][AARCH64]Add relocation support for large memory model. [LD]Add TLSIE relaxation support.


Hi all,

This patch add the TLSIE to TLSLE relax for large memory model. We can do the following relaxation if the symbol is local.

     mrs tp, tpidr_el0
     movz tx, #:gottprel_g1:var       => movz tx, #:tprel_g2:var, lsl #32
     movk tx, #:gottprel_g0_nc:var  => movk tx, #:tprel_g1_nc:var, lsl #16
ldr tx, [gp, tx] => movk tx, #:tprel_g0_nc:var
     add tx, tx, tp

At the moment, the offset from TP is already known. One addition argument is added to elfNN_aarch64_tls_relax function to pass this information inside. And during the relaxation, it's directly encoded into the instruction word, and the relocation are removed, mark them as resolved.

binutils, ld regresstion test Okay without issues.

Regards,
Renlin Li

bfd/ChangeLog:

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

    * elfnn-aarch64.c (IS_AARCH64_TLS_RELAX_RELOC): Add
        TLSIE_MOVW_GOTTPREL_G1.
    (aarch64_tls_transition_without_check): Add
        TLSIE_MOVW_GOTTPREL_G1 to TLSLE_MOVW_TPREL_G2
        transition for local symbol.
    (elfNN_aarch64_tls_relax): Add a argument to pass tp offset.
        Add TLSIE_MOVW_GOTTPREL_G1 relaxation.
    (elfNN_aarch64_relocate_section): Call elfNN_aarch64_tls_relax
        with new argument.

ld/testsuite/ChangeLog:

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

    * ld-aarch64/aarch64-elf.exp (tls-relax-large-le-ie): Run new test.
    * ld-aarch64/tls-relax-large-ie-le.d: New.
    * ld-aarch64/tls-relax-large-ie-le.s: New.
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 0c0216f..2aed593 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -202,6 +202,7 @@
    || (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_TLSIE_MOVW_GOTTPREL_G1	\
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADD			\
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC		\
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21		\
@@ -4244,6 +4245,11 @@ aarch64_tls_transition_without_check (bfd_reloc_code_real_type r_type,
       return is_local
 	? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2
 	: BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1;
+
+    case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1:
+      return is_local
+	? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2
+	: r_type;
 #endif
 
     default:
@@ -5352,7 +5358,8 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
 static bfd_reloc_status_type
 elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
 			 bfd *input_bfd, bfd_byte *contents,
-			 Elf_Internal_Rela *rel, struct elf_link_hash_entry *h)
+			 Elf_Internal_Rela *rel, struct elf_link_hash_entry *h,
+			 bfd_vma relocation ATTRIBUTE_UNUSED)
 {
   bfd_boolean is_local = h == NULL;
   unsigned int r_type = ELFNN_R_TYPE (rel->r_info);
@@ -5518,6 +5525,47 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
 
     case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC:
       return bfd_reloc_continue;
+
+    case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1:
+      if (is_local)
+	{
+	  /* Large IE->LE relaxation:
+	     mrs tp, tpidr_el0
+	     movz tx, #:gottprel_g1:var    => movz tx, #:tprel_g2:var, lsl #32
+	     movk tx, #:gottprel_g0_nc:var => movk tx, #:tprel_g1_nc:var, lsl #16
+	     ldr tx, [gp, tx]		   => movk tx, #:tprel_g0_nc:var
+	     add tx, tx, tp
+	   */
+	  uint32_t value;
+	  BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info)
+		      == AARCH64_R (TLSIE_MOVW_GOTTPREL_G0_NC));
+	  BFD_ASSERT (rel->r_offset + 4 == rel[1].r_offset);
+
+	  value = (relocation & ~(bfd_vma) 0xffffffff) >>  32;
+	  insn = bfd_getl32 (contents + rel->r_offset);
+	  insn &= 0xff80001f;
+	  insn |= (0x400000 + (value << 5));
+	  bfd_putl32 (insn, contents + rel->r_offset + 0);
+
+	  value = (relocation & (bfd_vma) 0xffff0000) >> 16;
+	  insn = bfd_getl32 (contents + rel->r_offset + 4);
+	  insn &= 0xff80001f;
+	  insn |= (0x200000 + (value << 5));
+	  bfd_putl32 (insn, contents + rel->r_offset + 4);
+
+	  value = relocation & (bfd_vma) 0xffff;
+	  insn = bfd_getl32 (contents + rel->r_offset + 4);
+	  insn &= 0xff80001f;
+	  insn |= (value << 5);
+	  bfd_putl32 (insn, contents + rel->r_offset + 8);
+
+	  /* Relocations are already resolved here.  */
+	  rel->r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+	  rel[1].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+	  return bfd_reloc_ok;
+	}
+
+      return bfd_reloc_continue;
 #endif
 
     case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
@@ -5836,7 +5884,8 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
 	  howto = elfNN_aarch64_howto_from_bfd_reloc (bfd_r_type);
 	  BFD_ASSERT (howto != NULL);
 	  r_type = howto->type;
-	  r = elfNN_aarch64_tls_relax (globals, input_bfd, contents, rel, h);
+	  r = elfNN_aarch64_tls_relax (globals, input_bfd, contents, rel, h,
+				       relocation - tpoff_base (info));
 	  unresolved_reloc = 0;
 	}
       else
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index c693146..aaee069 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -157,6 +157,7 @@ run_dump_test "tls-relax-large-gd-ie"
 run_dump_test "tls-relax-large-gd-le"
 run_dump_test "tls-relax-large-desc-ie"
 run_dump_test "tls-relax-large-desc-le"
+run_dump_test "tls-relax-large-ie-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-ie-le.d b/ld/testsuite/ld-aarch64/tls-relax-large-ie-le.d
new file mode 100644
index 0000000..6bf211b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-large-ie-le.d
@@ -0,0 +1,14 @@
+#source: tls-relax-large-ie-le.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+0000000000010000 <test>:
+  +10000:	d53bd041 	mrs	x1, tpidr_el0
+  +10004:	d2c00006 	movz	x6, #0x0, lsl #32
+  +10008:	f2a00006 	movk	x6, #0x0, lsl #16
+  +1000c:	f2800206 	movk	x6, #0x10
+  +10010:	8b0100c6 	add	x6, x6, x1
+  +10014:	d2c00007 	movz	x7, #0x0, lsl #32
+  +10018:	f2a00007 	movk	x7, #0x0, lsl #16
+  +1001c:	f2800287 	movk	x7, #0x14
+  +10020:	8b0100e7 	add	x7, x7, x1
diff --git a/ld/testsuite/ld-aarch64/tls-relax-large-ie-le.s b/ld/testsuite/ld-aarch64/tls-relax-large-ie-le.s
new file mode 100644
index 0000000..dba52c8
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-large-ie-le.s
@@ -0,0 +1,20 @@
+	.section	.tdata,"awT"
+x:
+	.word	2
+y:
+	.word	4
+
+	.text
+test:
+	mrs	x1, tpidr_el0
+
+	movz	x6, #:gottprel_g1:x
+	movk	x6, #:gottprel_g0_nc:x
+	ldr	x6, [x2, x6]
+	add	x6, x6, x1
+
+	movz	x7, #:gottprel_g1:y
+	movk	x7, #:gottprel_g0_nc:y
+	ldr	x7, [x2, x7]
+	add	x7, x7, x1
+



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