[PATCHv2] [Bug 20868] ld: aarch64: fix GD->IE relaxation in ilp32 mode
Yury Norov
ynorov@caviumnetworks.com
Mon Nov 28 17:46:00 GMT 2016
LD detects the access to TLS that it can optimize, but does it wrong
in ilp32 mode - actual address differs from expected.
It's because ld 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
v2: add test to the testsuite.
* bfd/elfnn-aarch64.c: Fix gd-ie relocation in ilp32 mode
* ld/testsuite/ld-aarch64/aarch64-elf.exp: Add new test
* ld/testsuite/ld-aarch64/relocs-ilp32.ld: New file
* ld/testsuite/ld-aarch64/tls-relax-gd-ie-ilp32.d: Likewise.
Signed-off-by: Yury Norov <ynorov@caviumnetworks.com>
---
bfd/elfnn-aarch64.c | 20 +++++++++++++++-----
ld/testsuite/ld-aarch64/aarch64-elf.exp | 1 +
ld/testsuite/ld-aarch64/relocs-ilp32.ld | 19 +++++++++++++++++++
ld/testsuite/ld-aarch64/tls-relax-gd-ie-ilp32.d | 10 ++++++++++
4 files changed, 45 insertions(+), 5 deletions(-)
create mode 100644 ld/testsuite/ld-aarch64/relocs-ilp32.ld
create mode 100644 ld/testsuite/ld-aarch64/tls-relax-gd-ie-ilp32.d
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;
}
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index d4d7f5a..e2d064f 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -190,6 +190,7 @@ 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-gd-ie-ilp32"
run_dump_test "tls-relax-large-gd-ie"
run_dump_test "tls-relax-large-gd-ie-be"
run_dump_test "tls-relax-large-gd-le"
diff --git a/ld/testsuite/ld-aarch64/relocs-ilp32.ld b/ld/testsuite/ld-aarch64/relocs-ilp32.ld
new file mode 100644
index 0000000..98044f7
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/relocs-ilp32.ld
@@ -0,0 +1,19 @@
+/* Script for ld testsuite */
+OUTPUT_ARCH(aarch64:ilp32)
+ENTRY(_start)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ PROVIDE (__executable_start = 0x8000); . = 0x10000;
+ .text :
+ {
+ *(.before)
+ *(.text)
+ *(.after)
+ } =0
+ . = 0x20000;
+ .got : { *(.got) *(.got.plt)}
+ . = 0x12340000;
+ .far : { *(.far) }
+ .ARM.attributes 0 : { *(.ARM.atttributes) }
+}
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gd-ie-ilp32.d b/ld/testsuite/ld-aarch64/tls-relax-gd-ie-ilp32.d
new file mode 100644
index 0000000..ab08c61
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/tls-relax-gd-ie-ilp32.d
@@ -0,0 +1,10 @@
+#source: tls-relax-gd-ie.s
+#as: -mabi=ilp32
+#ld: -m [aarch64_choose_ilp32_emul] -T relocs-ilp32.ld -e0
+#objdump: -dr
+#...
+ +10000: 90000080 adrp x0, 20000 <_GLOBAL_OFFSET_TABLE_>
+ +10004: b9400400 ldr w0, \[x0, #4\]
+ +10008: d53bd041 mrs x1, tpidr_el0
+ +1000c: 0b000020 add w0, w1, w0
+ +10010: b9400000 ldr w0, \[x0\]
--
2.7.4
More information about the Binutils
mailing list