This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] [Bug 20868] ld: aarch64: fix GD->IE relaxation in ilp32 mode
- From: Yury Norov <ynorov at caviumnetworks dot com>
- To: <binutils at sourceware dot org>
- Cc: Yury Norov <ynorov at caviumnetworks dot com>, Jiong Wang <jiwang at gcc dot gnu dot org>, Ramana Radhakrishnan <ramana dot gcc at googlemail dot com>, Andrew Pinski <pinskia at gmail dot com>
- Date: Sun, 27 Nov 2016 19:19:34 +0530
- Subject: [PATCH] [Bug 20868] ld: aarch64: fix GD->IE relaxation in ilp32 mode
- Authentication-results: sourceware.org; auth=none
- Authentication-results: spf=none (sender IP is ) smtp.mailfrom=Yuri dot Norov at caviumnetworks dot com;
- Spamdiagnosticmetadata: NSPM
- Spamdiagnosticoutput: 1:99
LD detects the access to TLS that it can optimize, but does it wrong
in ilp32 mode - actual address differs from expected.
The reason for is is that it calculates the address with
"ldr x0, [x0, #:gottprel_lo12:var]" which is correct for lp64, but for ilp32
it should be "ldr w0, [x0, #:gottprel_lo12:var]". This patch fixes it
by checking arch info. Also it replaces "add x0, x1, x0" with "add w0, w1, w0".
This instruction doesn't make troubles now, but in ilp32 mode 32-bit registers
should be used in this case.
Test that reproduses the bug is here:
https://sourceware.org/bugzilla/attachment.cgi?id=9669
Signed-off-by: Yury Norov <ynorov@caviumnetworks.com>
---
bfd/elfnn-aarch64.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 99b2a04..c1da097 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -5841,10 +5841,12 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
else
{
/* GD->IE relaxation
- ADD x0, #:tlsgd_lo12:var => ldr x0, [x0, #:gottprel_lo12:var]
+ ADD x0, #:tlsgd_lo12:var => ldr R0, [x0, #:gottprel_lo12:var]
BL __tls_get_addr => mrs x1, tpidr_el0
R_AARCH64_CALL26
- NOP => add x0, x1, x0
+ NOP => add R0, R1, R0
+
+ Where R is x for lp64 mode, and w for ilp32 mode.
*/
BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (CALL26));
@@ -5852,13 +5854,21 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
/* Remove the relocation on the BL instruction. */
rel[1].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
- bfd_putl32 (0xf9400000, contents + rel->r_offset);
-
/* We choose to fixup the BL and NOP instructions using the
offset from the second relocation to allow flexibility in
scheduling instructions between the ADD and BL. */
+ if (bfd_get_arch_info (input_bfd)->mach & bfd_mach_aarch64_ilp32)
+ {
+ bfd_putl32 (0xb9400000, contents + rel->r_offset);
+ bfd_putl32 (0x0b000020, contents + rel[1].r_offset + 4);
+ }
+ else
+ {
+ bfd_putl32 (0xf9400000, contents + rel->r_offset);
+ bfd_putl32 (0x8b000020, contents + rel[1].r_offset + 4);
+ }
+
bfd_putl32 (0xd53bd041, contents + rel[1].r_offset);
- bfd_putl32 (0x8b000020, contents + rel[1].r_offset + 4);
return bfd_reloc_continue;
}
--
2.7.4