This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH v3] [Bug 20868] ld: aarch64: fix GD->IE relaxation in ilp32 mode


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.
v3: detect arch at compile time.

	PR 20868
        * 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>
Acked-by: Jiong Wang <jiwang@gcc.gnu.org>
---
 bfd/elfnn-aarch64.c                             | 16 +++++++++++-----
 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, 41 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..781a720 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,17 @@ 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.  */
-	  bfd_putl32 (0xd53bd041, contents + rel[1].r_offset);
+#if ARCH_SIZE == 32
+	  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);
+#endif
+	  bfd_putl32 (0xd53bd041, contents + rel[1].r_offset);
 	  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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]