This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[16/16][binutils][AARCH64]Add relocation support for large memory model. [LD]Add TLSIE relaxation support.
- From: Renlin Li <renlin dot li at arm dot com>
- To: "binutils at sourceware dot org" <binutils at sourceware dot org>
- Cc: Nicholas Clifton <nickc at redhat dot com>, Marcus Shawcroft <Marcus dot Shawcroft at arm dot com>, Jiong Wang <jiong dot wang at arm dot com>
- Date: Tue, 08 Sep 2015 19:04:35 +0100
- Subject: [16/16][binutils][AARCH64]Add relocation support for large memory model. [LD]Add TLSIE relaxation support.
- Authentication-results: sourceware.org; auth=none
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
+