This is the mail archive of the 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]

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

On 27/11/16 13:49, Yury Norov wrote:
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:

Signed-off-by: Yury Norov <>
  bfd/elfnn-aarch64.c | 20 +++++++++++++++-----

I think a similar testcase as testsuite/ld-aarch64/tls-relax-gd-ie.d
should be added for ILP32.

  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,
  	  /* 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
-	     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;

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