aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog12
-rw-r--r--bfd/elfnn-aarch64.c53
-rw-r--r--ld/testsuite/ChangeLog6
-rw-r--r--ld/testsuite/ld-aarch64/aarch64-elf.exp1
-rw-r--r--ld/testsuite/ld-aarch64/tls-relax-large-ie-le.d14
-rw-r--r--ld/testsuite/ld-aarch64/tls-relax-large-ie-le.s19
6 files changed, 103 insertions, 2 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index aef8fe3..162c801 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,17 @@
2015-10-02 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.
+
+2015-10-02 Renlin Li <renlin.li@arm.com>
+
* elfnn-aarch64.c (aarch64_tls_transition_without_check): Add
relax transitions for TLSDESC_ADD, TLSDESC_LDR, TLSDESC_OFF_G0_NC,
TLSDESC_OFF_G1.
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index aa22c3e..f3489d5 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -228,6 +228,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_TLSLD_ADD_LO12_NC \
|| (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21 \
|| (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADR_PREL21)
@@ -4493,6 +4494,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:
@@ -5627,7 +5633,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);
@@ -5793,6 +5800,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:
@@ -6151,7 +6199,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/ChangeLog b/ld/testsuite/ChangeLog
index 43b688f..b078d3a 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,5 +1,11 @@
2015-10-02 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.
+
+2015-10-02 Renlin Li <renlin.li@arm.com>
+
* ld-aarch64/aarch64-elf.exp: Run new test.
* ld-aarch64/tls-large-desc.d: New.
* ld-aarch64/tls-large-desc.s: New.
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index 5c55dc7..5d42710 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -185,6 +185,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-relax-ld-le-small"
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..c5c12a1
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-large-ie-le.s
@@ -0,0 +1,19 @@
+ .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