aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRenlin Li <renlin.li@arm.com>2015-10-02 17:22:36 +0100
committerRenlin Li <renlin.li@arm.com>2015-10-02 17:56:09 +0100
commitac734732481451698ee23990aaa64907e56dd082 (patch)
tree22387bf9cc94b8cbb190e1b08e20ee4d954b2dd0
parent[BFD][AARCH64]Create GOT section for TLSLE_MOVW_TPREL_G(1, 1_NC, 2). (diff)
downloadbinutils-gdb-ac734732481451698ee23990aaa64907e56dd082.tar.gz
binutils-gdb-ac734732481451698ee23990aaa64907e56dd082.tar.bz2
binutils-gdb-ac734732481451698ee23990aaa64907e56dd082.zip
[BFD][AARCH64]Add TLSGD relaxation support under large memory model.
bfd/ 2015-10-02 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/ 2015-10-02 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.
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elfnn-aarch64.c60
-rw-r--r--ld/testsuite/ChangeLog8
-rw-r--r--ld/testsuite/ld-aarch64/aarch64-elf.exp2
-rw-r--r--ld/testsuite/ld-aarch64/tls-relax-large-gd-ie.d16
-rw-r--r--ld/testsuite/ld-aarch64/tls-relax-large-gd-ie.s20
-rw-r--r--ld/testsuite/ld-aarch64/tls-relax-large-gd-le.d16
-rw-r--r--ld/testsuite/ld-aarch64/tls-relax-large-gd-le.s19
8 files changed, 148 insertions, 0 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index ecf5d56c70f..bad620e0a7e 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,12 @@
2015-10-02 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.
+
+2015-10-02 Renlin Li <renlin.li@arm.com>
+
* elfnn-aarch64.c (elfNN_aarch64_check_relocs): Create GOT section
for TLSLE_MOVW_TPREL_G(1, 1_NC, 2) relocation.
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index d71a76f0b01..cff77cef88e 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -218,6 +218,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 \
@@ -4460,6 +4462,18 @@ aarch64_tls_transition_without_check (bfd_reloc_code_real_type r_type,
case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21:
return is_local ? BFD_RELOC_AARCH64_NONE : r_type;
+#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;
}
@@ -5692,6 +5706,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/ChangeLog b/ld/testsuite/ChangeLog
index e486bbaf106..a95de8c4201 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,5 +1,13 @@
2015-10-02 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.
+
+2015-10-02 Renlin Li <renlin.li@arm.com>
+
* ld-aarch64/tls-large-ie.d: New.
* ld-aarch64/tls-large-ie.s: New.
* ld-aarch64/aarch64-elf.exp: Run new test.
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index d0da92f46f0..f51de9c2068 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -181,6 +181,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-relax-ld-le-small"
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 00000000000..f3407efb212
--- /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 00000000000..8e0310d6b3f
--- /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 00000000000..acaea58c153
--- /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 00000000000..781f6cc3403
--- /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_ - .