This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[AArch64] Relax TLS local dynamic traditional into local executable
- From: Jiong Wang <jiong dot wang at arm dot com>
- To: Binutils <binutils at sourceware dot org>
- Date: Tue, 25 Aug 2015 14:03:56 +0100
- Subject: [AArch64] Relax TLS local dynamic traditional into local executable
- Authentication-results: sourceware.org; auth=none
This patch add the linker relaxation from TLS local dynamic traditional
model into local executable on AArch64 tiny/small model.
After this relaxation, we don't need to invoke the runtime resolver.
The linker relaxation logic will be:
Code sequence I (tiny):
0x00 adr x0, :tlsldm:x
0x04 bl __tls_get_addr
|
V
0x00 mrs x0, tpidr_el0
0x04 add x0, x0, TCB_SIZE
Code sequence II (small):
0x00 adrp a0, :tlsldm:x
0x04 add a0, #:tlsldm_lo12:x
0x08 bl __tls_get_addr
|
V
0x00 mrs x0, tpidr_el0
0x04 add x0, x0, TCB_SIZE
0x08 nop
For local dynamic model, the TLS instruction sequences is composed of
two parts, the first part calcuate module base address, the second part
add variable offset to get final address.
For linker relaxation, we only need to touch the first part. When relax
from local dynamic into local executable, we don't need to invoke
runtime resolver to get module base address. As for local executable,
the "module" should be initial TLS module, thus the module base address
can be calculated by "tp + TCB_SIZE" as tp points to start of initial
TLS module start, we need to skip the thread control block to point to
real module contents for variable.
After the relaxation, the relocation for the 'bl' instruction should be
removed also, as we don't need any relocation anymore.
ok for trunk?
2015-08-25 Jiong Wang <jiong.wang@arm.com>
bfd/
* elfnn-aarch64.c (aarch64_tls_transition_without_check): Support
three TLS local dynamic traditional relocations types.
(elfNN_aarch64_tls_relax): Support TLS local dynamic traditional to
local executable relaxation.
ld/testsuite/
* ld-aarch64/tls-relax-ld-le-tiny.s: New testcase.
* ld-aarch64/tls-relax-ld-le-small.s: Likewise.
* ld-aarch64/tls-relax-ld-le-tiny.d: New expectation file.
* ld-aarch64/tls-relax-ld-le-small.d: Likewise.
* ld-aarch64/aarch64-elf.exp: Run new testcases.
--
Regards,
Jiong
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 9935308..89d5c72 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -213,6 +213,9 @@
|| (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_TLSLD_ADD_LO12_NC \
+ || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21 \
+ || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADR_PREL21 \
|| (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21 \
|| (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21 \
|| (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LD_PREL19 \
@@ -4390,6 +4393,11 @@ aarch64_tls_transition_without_check (bfd_reloc_code_real_type r_type,
/* Instructions with these relocations will become NOPs. */
return BFD_RELOC_AARCH64_NONE;
+ case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21:
+ case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21:
+ return is_local ? BFD_RELOC_AARCH64_NONE : r_type;
+
default:
break;
}
@@ -5616,6 +5624,51 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
}
return bfd_reloc_continue;
+ case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21:
+ /* LD->LE relaxation (tiny):
+ adr x0, :tlsldm:x => mrs x0, tpidr_el0
+ bl __tls_get_addr => add x0, x0, TCB_SIZE
+ */
+ if (is_local)
+ {
+ BFD_ASSERT (rel->r_offset + 4 == rel[1].r_offset);
+ BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (CALL26));
+ /* No need of CALL26 relocation for tls_get_addr. */
+ rel[1].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+ bfd_putl32 (0xd53bd040, contents + rel->r_offset + 0);
+ bfd_putl32 (0x91004000, contents + rel->r_offset + 4);
+ return bfd_reloc_ok;
+ }
+ return bfd_reloc_continue;
+
+ case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21:
+ /* LD->LE relaxation (small):
+ adrp x0, :tlsldm:x => mrs x0, tpidr_el0
+ */
+ if (is_local)
+ {
+ bfd_putl32 (0xd53bd040, contents + rel->r_offset);
+ return bfd_reloc_ok;
+ }
+ return bfd_reloc_continue;
+
+ case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC:
+ /* LD->LE relaxation (small):
+ add x0, #:tlsldm_lo12:x => add x0, x0, TCB_SIZE
+ bl __tls_get_addr => nop
+ */
+ if (is_local)
+ {
+ BFD_ASSERT (rel->r_offset + 4 == rel[1].r_offset);
+ BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (CALL26));
+ /* No need of CALL26 relocation for tls_get_addr. */
+ rel[1].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+ bfd_putl32 (0x91004000, contents + rel->r_offset + 0);
+ bfd_putl32 (0xd503201f, contents + rel->r_offset + 4);
+ return bfd_reloc_ok;
+ }
+ return bfd_reloc_continue;
+
default:
return bfd_reloc_continue;
}
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index cbbe6a9..955484e 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -178,6 +178,8 @@ run_dump_test "tls-relax-gdesc-le"
run_dump_test "tls-relax-gd-ie"
run_dump_test "tls-relax-gdesc-ie"
run_dump_test "tls-relax-ie-le"
+run_dump_test "tls-relax-ld-le-small"
+run_dump_test "tls-relax-ld-le-tiny"
run_dump_test "tls-desc-ie"
run_dump_test "tls-relax-gdesc-ie-2"
run_dump_test "tls-relax-gdesc-le-2"
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ld-le-small.d b/ld/testsuite/ld-aarch64/tls-relax-ld-le-small.d
new file mode 100644
index 0000000..fa64829
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ld-le-small.d
@@ -0,0 +1,13 @@
+#source: tls-relax-ld-le-small.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000: 910003fd mov x29, sp
+ +10004: d53bd040 mrs x0, tpidr_el0
+ +10008: 91004000 add x0, x0, #0x10
+ +1000c: d503201f nop
+ +10010: d503201f nop
+ +10014: 91400001 add x1, x0, #0x0, lsl #12
+ +10018: 91000021 add x1, x1, #0x0
+ +1001c: 90000000 adrp x0, 10000 <.*>
+ +10020: d65f03c0 ret
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ld-le-small.s b/ld/testsuite/ld-aarch64/tls-relax-ld-le-small.s
new file mode 100644
index 0000000..ea58500
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ld-le-small.s
@@ -0,0 +1,27 @@
+ .cpu generic+fp+simd
+ .section .text.startup,"ax",%progbits
+ .align 2
+ .p2align 3,,7
+ .global main
+ .type main, %function
+main:
+ add x29, sp, 0
+ adrp x0, :tlsldm:global_a0
+ add x0, x0, #:tlsldm_lo12_nc:global_a0
+ bl __tls_get_addr
+ nop
+ add x1, x0, #:dtprel_hi12:global_a0, lsl #12
+ add x1, x1, #:dtprel_lo12_nc:global_a0
+ adrp x0, .LC0
+ ret
+ .size main, .-main
+ .section .rodata.str1.8,"aMS",%progbits,1
+ .align 3
+.LC0:
+ .string "Hello world %d\n"
+ .section .tdata,"awT",%progbits
+ .align 2
+ .type global_a0, %object
+ .size global_a0, 4
+global_a0:
+ .word 16
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny.d b/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny.d
new file mode 100644
index 0000000..db22677
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny.d
@@ -0,0 +1,12 @@
+#source: tls-relax-ld-le-tiny.s
+#ld: -T relocs.ld -e0
+#objdump: -dr
+#...
+ +10000: 910003fd mov x29, sp
+ +10004: d53bd040 mrs x0, tpidr_el0
+ +10008: 91004000 add x0, x0, #0x10
+ +1000c: d503201f nop
+ +10010: 91400001 add x1, x0, #0x0, lsl #12
+ +10014: 91000021 add x1, x1, #0x0
+ +10018: 90000000 adrp x0, 10000 <main>
+ +1001c: d65f03c0 ret
diff --git a/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny.s b/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny.s
new file mode 100644
index 0000000..2336f69
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-ld-le-tiny.s
@@ -0,0 +1,26 @@
+ .cpu generic+fp+simd
+ .section .text.startup,"ax",%progbits
+ .align 2
+ .p2align 3,,7
+ .global main
+ .type main, %function
+main:
+ add x29, sp, 0
+ adr x0, :tlsldm:global_a0
+ bl __tls_get_addr
+ nop
+ add x1, x0, #:dtprel_hi12:global_a0, lsl #12
+ add x1, x1, #:dtprel_lo12_nc:global_a0
+ adrp x0, .LC0
+ ret
+ .size main, .-main
+ .section .rodata.str1.8,"aMS",%progbits,1
+ .align 3
+.LC0:
+ .string "Hello world %d\n"
+ .section .tdata,"awT",%progbits
+ .align 2
+ .type global_a0, %object
+ .size global_a0, 4
+global_a0:
+ .word 16