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