diff options
-rw-r--r-- | bfd/ChangeLog | 12 | ||||
-rw-r--r-- | bfd/elfnn-aarch64.c | 78 | ||||
-rw-r--r-- | ld/ChangeLog | 7 | ||||
-rw-r--r-- | ld/testsuite/ld-aarch64/aarch64-elf.exp | 1 | ||||
-rw-r--r-- | ld/testsuite/ld-aarch64/erratum843419_tls_ie.d | 49 | ||||
-rw-r--r-- | ld/testsuite/ld-aarch64/erratum843419_tls_ie.s | 43 |
6 files changed, 185 insertions, 5 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index fd08c72..4ee7695 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,15 @@ +2018-11-27 Tamar Christina <tamar.christina@arm.com> + + PR ld/23904 + * elfnn-aarch64.c (_bfd_aarch64_adrp_p): Use existing constants. + (_bfd_aarch64_erratum_843419_branch_to_stub): Use _bfd_aarch64_adrp_p. + (struct erratum_835769_branch_to_stub_clear_data): New. + (_bfd_aarch64_erratum_843419_clear_stub): New. + (clear_erratum_843419_entry): New. + (elfNN_aarch64_tls_relax): Use it. + (elfNN_aarch64_relocate_section): Pass input_section. + (aarch64_map_one_stub): Handle branch type none as valid. + 2018-11-27 Mark Wielaard <mark@klomp.org> PR binutils/23919 diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index e2cfa86..083f90b 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -3845,7 +3845,7 @@ _bfd_aarch64_erratum_835769_scan (bfd *input_bfd, static bfd_boolean _bfd_aarch64_adrp_p (uint32_t insn) { - return ((insn & 0x9f000000) == 0x90000000); + return ((insn & AARCH64_ADRP_OP_MASK) == AARCH64_ADRP_OP); } @@ -5077,7 +5077,7 @@ _bfd_aarch64_erratum_843419_branch_to_stub (struct bfd_hash_entry *gen_entry, + stub_entry->adrp_offset); insn = bfd_getl32 (contents + stub_entry->adrp_offset); - if ((insn & AARCH64_ADRP_OP_MASK) != AARCH64_ADRP_OP) + if (!_bfd_aarch64_adrp_p (insn)) abort (); bfd_signed_vma imm = @@ -5941,6 +5941,64 @@ bad_ifunc_reloc: # define movz_hw_R0 (0x52c00000) #endif +/* Structure to hold payload for _bfd_aarch64_erratum_843419_clear_stub, + it is used to identify the stub information to reset. */ + +struct erratum_843419_branch_to_stub_clear_data +{ + bfd_vma adrp_offset; + asection *output_section; +}; + +/* Clear the erratum information for GEN_ENTRY if the ADRP_OFFSET and + section inside IN_ARG matches. The clearing is done by setting the + stub_type to none. */ + +static bfd_boolean +_bfd_aarch64_erratum_843419_clear_stub (struct bfd_hash_entry *gen_entry, + void *in_arg) +{ + struct elf_aarch64_stub_hash_entry *stub_entry + = (struct elf_aarch64_stub_hash_entry *) gen_entry; + struct erratum_843419_branch_to_stub_clear_data *data + = (struct erratum_843419_branch_to_stub_clear_data *) in_arg; + + if (stub_entry->target_section != data->output_section + || stub_entry->stub_type != aarch64_stub_erratum_843419_veneer + || stub_entry->adrp_offset != data->adrp_offset) + return TRUE; + + /* Change the stub type instead of removing the entry, removing from the hash + table would be slower and we have already reserved the memory for the entry + so there wouldn't be much gain. Changing the stub also keeps around a + record of what was there before. */ + stub_entry->stub_type = aarch64_stub_none; + + /* We're done and there could have been only one matching stub at that + particular offset, so abort further traversal. */ + return FALSE; +} + +/* TLS Relaxations may relax an adrp sequence that matches the erratum 843419 + sequence. In this case the erratum no longer applies and we need to remove + the entry from the pending stub generation. This clears matching adrp insn + at ADRP_OFFSET in INPUT_SECTION in the stub table defined in GLOBALS. */ + +static void +clear_erratum_843419_entry (struct elf_aarch64_link_hash_table *globals, + bfd_vma adrp_offset, asection *input_section) +{ + if (globals->fix_erratum_843419) + { + struct erratum_843419_branch_to_stub_clear_data data; + data.adrp_offset = adrp_offset; + data.output_section = input_section; + + bfd_hash_traverse (&globals->stub_hash_table, + _bfd_aarch64_erratum_843419_clear_stub, &data); + } +} + /* Handle TLS relaxations. Relaxing is possible for symbols that use R_AARCH64_TLSDESC_ADR_{PAGE, LD64_LO12_NC, ADD_LO12_NC} during a static link. @@ -5951,8 +6009,9 @@ bad_ifunc_reloc: static bfd_reloc_status_type elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals, - bfd *input_bfd, bfd_byte *contents, - Elf_Internal_Rela *rel, struct elf_link_hash_entry *h) + bfd *input_bfd, asection *input_section, + bfd_byte *contents, Elf_Internal_Rela *rel, + struct elf_link_hash_entry *h) { bfd_boolean is_local = h == NULL; unsigned int r_type = ELFNN_R_TYPE (rel->r_info); @@ -5973,6 +6032,9 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals, Where R is x for LP64, and w for ILP32. */ bfd_putl32 (movz_R0, contents + rel->r_offset); + /* We have relaxed the adrp into a mov, we may have to clear any + pending erratum fixes. */ + clear_erratum_843419_entry (globals, rel->r_offset, input_section); return bfd_reloc_continue; } else @@ -6263,6 +6325,9 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals, { insn = bfd_getl32 (contents + rel->r_offset); bfd_putl32 (movz_R0 | (insn & 0x1f), contents + rel->r_offset); + /* We have relaxed the adrp into a mov, we may have to clear any + pending erratum fixes. */ + clear_erratum_843419_entry (globals, rel->r_offset, input_section); } return bfd_reloc_continue; @@ -6487,7 +6552,8 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, howto = elfNN_aarch64_howto_from_bfd_reloc (bfd_r_type); BFD_ASSERT (howto != NULL); r_type = howto->type; - r = elfNN_aarch64_tls_relax (globals, input_bfd, contents, rel, h); + r = elfNN_aarch64_tls_relax (globals, input_bfd, input_section, + contents, rel, h); unresolved_reloc = 0; } else @@ -8074,6 +8140,8 @@ aarch64_map_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) if (!elfNN_aarch64_output_map_sym (osi, AARCH64_MAP_INSN, addr)) return FALSE; break; + case aarch64_stub_none: + break; default: abort (); diff --git a/ld/ChangeLog b/ld/ChangeLog index ca81d06..57579f7 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,10 @@ +2018-11-27 Tamar Christina <tamar.christina@arm.com> + + PR ld/23904 + * testsuite/ld-aarch64/aarch64-elf.exp: Add erratum843419_tls_ie. + * testsuite/ld-aarch64/erratum843419_tls_ie.d: New test. + * testsuite/ld-aarch64/erratum843419_tls_ie.s: New test. + 2018-11-16 Nick Clifton <nickc@redhat.com> * po/es.po: Updated Spanish translation. diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp index 1bbc064..3912ef1 100644 --- a/ld/testsuite/ld-aarch64/aarch64-elf.exp +++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp @@ -86,6 +86,7 @@ run_ld_link_tests $aarch64elftests run_ld_link_tests eh-frame-merge-lp64 run_dump_test "erratum843419" +run_dump_test "erratum843419_tls_ie" # Relocation Tests run_dump_test_lp64 "weak-undefined" diff --git a/ld/testsuite/ld-aarch64/erratum843419_tls_ie.d b/ld/testsuite/ld-aarch64/erratum843419_tls_ie.d new file mode 100644 index 0000000..eba5a20 --- /dev/null +++ b/ld/testsuite/ld-aarch64/erratum843419_tls_ie.d @@ -0,0 +1,49 @@ +#source: erratum843419_tls_ie.s +#as: +#ld: --fix-cortex-a53-843419 -e0 --section-start .e843419=0x20000000 -Ttext=0x400000 -Tdata=0x40000000 +#objdump: -dr +#... + +Disassembly of section .e843419: + +0*20000000 <farbranch>: +[ ]*20000000: d10043ff sub sp, sp, #0x10 +[ ]*20000004: d28001a7 mov x7, #0xd // #13 +[ ]*20000008: b9000fe7 str w7, \[sp, #12\] +[ ]*2000000c: 140003fb b 20000ff8 <e843419> + ... + +0*20000ff8 <e843419>: +[ ]*20000ff8: d2a00000 movz x0, #0x0, lsl #16 +[ ]*20000ffc: f800c007 stur x7, \[x0, #12\] +[ ]*20001000: d2800128 mov x8, #0x9 // #9 +[ ]*20001004: f2800208 movk x8, #0x10 +[ ]*20001008: 8b050020 add x0, x1, x5 +[ ]*2000100c: b9400fe7 ldr w7, \[sp, #12\] +[ ]*20001010: 0b0700e0 add w0, w7, w7 +[ ]*20001014: 910043ff add sp, sp, #0x10 +[ ]*20001018: d65f03c0 ret +[ ]*2000101c: 00000000 .inst 0x00000000 ; undefined +[ ]*20001020: 14000400 b 20002020 <e843419\+0x1028> +[ ]*20001024: d503201f nop +[ ]*20001028: 00000000 .inst 0x00000000 ; undefined +[ ]*2000102c: 17fffff7 b 20001008 <e843419\+0x10> + ... + +Disassembly of section .text: + +0*400000 <main>: +[ ]*400000: d10043ff sub sp, sp, #0x10 +[ ]*400004: d28001a7 mov x7, #0xd // #13 +[ ]*400008: b9000fe7 str w7, \[sp, #12\] +[ ]*40000c: 14000005 b 400020 <__farbranch_veneer> +[ ]*400010: d65f03c0 ret +[ ]*400014: d503201f nop +[ ]*400018: 14000400 b 401018 <__farbranch_veneer\+0xff8> +[ ]*40001c: d503201f nop + +0*400020 <__farbranch_veneer>: +[ ]*400020: 900fe010 adrp x16, 20000000 <farbranch> +[ ]*400024: 91000210 add x16, x16, #0x0 +[ ]*400028: d61f0200 br x16 + ... diff --git a/ld/testsuite/ld-aarch64/erratum843419_tls_ie.s b/ld/testsuite/ld-aarch64/erratum843419_tls_ie.s new file mode 100644 index 0000000..6032244 --- /dev/null +++ b/ld/testsuite/ld-aarch64/erratum843419_tls_ie.s @@ -0,0 +1,43 @@ + .text + .align 2 + .global main + .type main, %function +main: + sub sp, sp, #16 + mov x7, 13 + str w7, [sp,12] + b farbranch + ret + .size main, .-main + + .section .e843419, "xa" + .align 2 + .global farbranch + .type farbranch, %function +farbranch: + sub sp, sp, #16 + mov x7, 13 + str w7, [sp,12] + b e843419 + .fill 4072,1,0 +e843419: + adrp x0, :gottprel:l_tlsievar + str x7, [x0,12] + mov x8, 9 + str x8, [x0, :gottprel_lo12:l_tlsievar] + + add x0, x1, x5 + ldr w7, [sp,12] + add w0, w7, w7 + add sp, sp, 16 + ret + .size farbranch, .-farbranch + +# --- + + .section .tbss,"awT",%nobits + .align 2 + .type l_tlsievar, %object + .size l_tlsievar, 4 +l_tlsievar: + .zero 4 |