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

Jiong Wang jiong.wang@foss.arm.com
Mon Nov 28 15:03:00 GMT 2016


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:
> https://sourceware.org/bugzilla/attachment.cgi?id=9669
>
> Signed-off-by: Yury Norov <ynorov@caviumnetworks.com>
> ---
>   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,
>         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;
>   	}
>   



More information about the Binutils mailing list