diff --git a/bfd/ChangeLog b/bfd/ChangeLog index fae51f3a2b..68e5032488 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2016-12-01 Yury Norov + + PR ld/20868 + * elfnn-aarch64.c (elfNN_aarch64_tls_relax): Use 32-bit accesses + to the GOT when operating in 32-bit mode. + 2016-12-01 Ma Jiang PR ld/16720 diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 99b2a04f15..ffa8e6a997 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -5841,24 +5841,29 @@ 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)); /* 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/ChangeLog b/ld/ChangeLog index 9484e74f7f..446a4afa9a 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,11 @@ +2016-12-01 Yury Norov + + PR ld/20868 + * testsuite/ld-aarch64/tls-relax-gd-ie-ilp32.d: New test. + * testsuite/ld-aarch64/relocs-ilp32.ld: Linker script for the new + test. + * testsuite/ld-aarch64/aarch64-elf.exp: Run the new test. + 2016-11-28 Andrew Burgess * emulparams/arclinux_prof.sh: Remove duplicate TEMPLATE_NAME. diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp index d4d7f5a0b8..8e425d214f 100644 --- a/ld/testsuite/ld-aarch64/aarch64-elf.exp +++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp @@ -189,6 +189,7 @@ run_dump_test "farcall-bl-section" 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-ilp32" run_dump_test "tls-relax-gd-ie" run_dump_test "tls-relax-large-gd-ie" run_dump_test "tls-relax-large-gd-ie-be" diff --git a/ld/testsuite/ld-aarch64/relocs-ilp32.ld b/ld/testsuite/ld-aarch64/relocs-ilp32.ld new file mode 100644 index 0000000000..7174aff236 --- /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 0000000000..ab08c6161b --- /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\]