diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 19 | ||||
-rw-r--r-- | bfd/bfd-in.h | 13 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 13 | ||||
-rw-r--r-- | bfd/elfnn-aarch64.c | 73 |
4 files changed, 95 insertions, 23 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 7d22cc0..2e7158f 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,22 @@ +2019-05-21 Tamar Christina <tamar.christina@arm.com> + + PR ld/24373 + * bfd-in.h (enum erratum_84319_opts): New + (bfd_elf64_aarch64_set_options, bfd_elf32_aarch64_set_options): Change + int to enum erratum_84319_opts. + * bfd-in2.h: Regenerate. + * elfnn-aarch64.c (struct elf_aarch64_link_hash_table): Change + fix_erratum_843419 to use new enum, remove fix_erratum_843419_adr. + (_bfd_aarch64_add_stub_entry_after): Conditionally create erratum stub. + (aarch64_size_one_stub): Conditionally size erratum 843419 stubs. + (_bfd_aarch64_resize_stubs): Amend comment. + (elfNN_aarch64_size_stubs): Don't generate stubs when no workaround + requested. + (bfd_elfNN_aarch64_set_options): Use new fix_erratum_843419 enum. + (_bfd_aarch64_erratum_843419_branch_to_stub): Implement selection of + erratum workaround. + (clear_erratum_843419_entry): Update erratum conditional. + 2019-05-21 Senthil Kumar Selvaraj <senthilkumar.selvaraj@microchip.com> PR ld/24571 diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h index b753a9e..890a79d 100644 --- a/bfd/bfd-in.h +++ b/bfd/bfd-in.h @@ -1027,12 +1027,21 @@ typedef struct aarch64_enable_bti_type bti_type; } aarch64_bti_pac_info; +/* An enum to define what kind of erratum fixes we should apply. This gives the + user a bit more control over the sequences we generate. */ +typedef enum +{ + ERRAT_NONE = (1 << 0), /* No erratum workarounds allowed. */ + ERRAT_ADR = (1 << 1), /* Erratum workarounds using ADR allowed. */ + ERRAT_ADRP = (1 << 2), /* Erratum workarounds using ADRP are allowed. */ +} erratum_84319_opts; + extern void bfd_elf64_aarch64_set_options - (bfd *, struct bfd_link_info *, int, int, int, int, int, int, + (bfd *, struct bfd_link_info *, int, int, int, int, erratum_84319_opts, int, aarch64_bti_pac_info); extern void bfd_elf32_aarch64_set_options - (bfd *, struct bfd_link_info *, int, int, int, int, int, int, + (bfd *, struct bfd_link_info *, int, int, int, int, erratum_84319_opts, int, aarch64_bti_pac_info); /* ELF AArch64 mapping symbol support. */ diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 9f60f57..65e2e01 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1034,12 +1034,21 @@ typedef struct aarch64_enable_bti_type bti_type; } aarch64_bti_pac_info; +/* An enum to define what kind of erratum fixes we should apply. This gives the + user a bit more control over the sequences we generate. */ +typedef enum +{ + ERRAT_NONE = (1 << 0), /* No erratum workarounds allowed. */ + ERRAT_ADR = (1 << 1), /* Erratum workarounds using ADR allowed. */ + ERRAT_ADRP = (1 << 2), /* Erratum workarounds using ADRP are allowed. */ +} erratum_84319_opts; + extern void bfd_elf64_aarch64_set_options - (bfd *, struct bfd_link_info *, int, int, int, int, int, int, + (bfd *, struct bfd_link_info *, int, int, int, int, erratum_84319_opts, int, aarch64_bti_pac_info); extern void bfd_elf32_aarch64_set_options - (bfd *, struct bfd_link_info *, int, int, int, int, int, int, + (bfd *, struct bfd_link_info *, int, int, int, int, erratum_84319_opts, int, aarch64_bti_pac_info); /* ELF AArch64 mapping symbol support. */ diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 8940f4e..2931018 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -2628,10 +2628,7 @@ struct elf_aarch64_link_hash_table int fix_erratum_835769; /* Fix erratum 843419. */ - int fix_erratum_843419; - - /* Enable ADRP->ADR rewrite for erratum 843419 workaround. */ - int fix_erratum_843419_adr; + erratum_84319_opts fix_erratum_843419; /* Don't apply link-time values for dynamic relocations. */ int no_apply_dynamic_relocs; @@ -3229,7 +3226,10 @@ _bfd_aarch64_add_stub_entry_after (const char *stub_name, asection *stub_sec; struct elf_aarch64_stub_hash_entry *stub_entry; - stub_sec = _bfd_aarch64_get_stub_for_link_section (link_section, htab); + stub_sec = NULL; + /* Only create the actual stub if we will end up needing it. */ + if (htab->fix_erratum_843419 & ERRAT_ADRP) + stub_sec = _bfd_aarch64_get_stub_for_link_section (link_section, htab); stub_entry = aarch64_stub_hash_lookup (&htab->stub_hash_table, stub_name, TRUE, FALSE); if (stub_entry == NULL) @@ -3374,14 +3374,15 @@ aarch64_build_one_stub (struct bfd_hash_entry *gen_entry, we know stub section sizes. */ static bfd_boolean -aarch64_size_one_stub (struct bfd_hash_entry *gen_entry, - void *in_arg ATTRIBUTE_UNUSED) +aarch64_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) { struct elf_aarch64_stub_hash_entry *stub_entry; + struct elf_aarch64_link_hash_table *htab; int size; /* Massage our args to the form they really have. */ stub_entry = (struct elf_aarch64_stub_hash_entry *) gen_entry; + htab = (struct elf_aarch64_link_hash_table *) in_arg; switch (stub_entry->stub_type) { @@ -3395,7 +3396,11 @@ aarch64_size_one_stub (struct bfd_hash_entry *gen_entry, size = sizeof (aarch64_erratum_835769_stub); break; case aarch64_stub_erratum_843419_veneer: - size = sizeof (aarch64_erratum_843419_stub); + { + if (htab->fix_erratum_843419 == ERRAT_ADR) + return TRUE; + size = sizeof (aarch64_erratum_843419_stub); + } break; default: abort (); @@ -4060,8 +4065,10 @@ _bfd_aarch64_resize_stubs (struct elf_aarch64_link_hash_table *htab) /* Ensure all stub sections have a size which is a multiple of 4096. This is important in order to ensure that the insertion of stub sections does not in itself move existing code around - in such a way that new errata sequences are created. */ - if (htab->fix_erratum_843419) + in such a way that new errata sequences are created. We only do this + when the ADRP workaround is enabled. If only the ADR workaround is + enabled then the stubs workaround won't ever be used. */ + if (htab->fix_erratum_843419 & ERRAT_ADRP) if (section->size) section->size = BFD_ALIGN (section->size, 0x1000); } @@ -4284,7 +4291,7 @@ elfNN_aarch64_size_stubs (bfd *output_bfd, (*htab->layout_sections_again) (); } - if (htab->fix_erratum_843419) + if (htab->fix_erratum_843419 != ERRAT_NONE) { bfd *input_bfd; @@ -4755,7 +4762,7 @@ bfd_elfNN_aarch64_set_options (struct bfd *output_bfd, int no_enum_warn, int no_wchar_warn, int pic_veneer, int fix_erratum_835769, - int fix_erratum_843419, + erratum_84319_opts fix_erratum_843419, int no_apply_dynamic_relocs, aarch64_bti_pac_info bp_info) { @@ -4764,8 +4771,10 @@ bfd_elfNN_aarch64_set_options (struct bfd *output_bfd, globals = elf_aarch64_hash_table (link_info); globals->pic_veneer = pic_veneer; globals->fix_erratum_835769 = fix_erratum_835769; + /* If the default options are used, then ERRAT_ADR will be set by default + which will enable the ADRP->ADR workaround for the erratum 843419 + workaround. */ globals->fix_erratum_843419 = fix_erratum_843419; - globals->fix_erratum_843419_adr = TRUE; globals->no_apply_dynamic_relocs = no_apply_dynamic_relocs; BFD_ASSERT (is_aarch64_elf (output_bfd)); @@ -5235,9 +5244,18 @@ _bfd_aarch64_erratum_843419_branch_to_stub (struct bfd_hash_entry *gen_entry, || stub_entry->stub_type != aarch64_stub_erratum_843419_veneer) return TRUE; - insn = bfd_getl32 (contents + stub_entry->target_value); - bfd_putl32 (insn, - stub_entry->stub_sec->contents + stub_entry->stub_offset); + BFD_ASSERT (((htab->fix_erratum_843419 & ERRAT_ADRP) && stub_entry->stub_sec) + || (htab->fix_erratum_843419 & ERRAT_ADR)); + + /* Only update the stub section if we have one. We should always have one if + we're allowed to use the ADRP errata workaround, otherwise it is not + required. */ + if (stub_entry->stub_sec) + { + insn = bfd_getl32 (contents + stub_entry->target_value); + bfd_putl32 (insn, + stub_entry->stub_sec->contents + stub_entry->stub_offset); + } place = (section->output_section->vma + section->output_offset + stub_entry->adrp_offset); @@ -5251,14 +5269,16 @@ _bfd_aarch64_erratum_843419_branch_to_stub (struct bfd_hash_entry *gen_entry, ((bfd_vma) _bfd_aarch64_decode_adrp_imm (insn) << 12, 33) - (place & 0xfff)); - if (htab->fix_erratum_843419_adr + if ((htab->fix_erratum_843419 & ERRAT_ADR) && (imm >= AARCH64_MIN_ADRP_IMM && imm <= AARCH64_MAX_ADRP_IMM)) { insn = (_bfd_aarch64_reencode_adr_imm (AARCH64_ADR_OP, imm) | AARCH64_RT (insn)); bfd_putl32 (insn, contents + stub_entry->adrp_offset); + /* Stub is not needed, don't map it out. */ + stub_entry->stub_type = aarch64_stub_none; } - else + else if (htab->fix_erratum_843419 & ERRAT_ADRP) { bfd_vma veneered_insn_loc; bfd_vma veneer_entry_loc; @@ -5285,6 +5305,21 @@ _bfd_aarch64_erratum_843419_branch_to_stub (struct bfd_hash_entry *gen_entry, branch_insn |= branch_offset; bfd_putl32 (branch_insn, contents + stub_entry->target_value); } + else + { + abfd = stub_entry->target_section->owner; + _bfd_error_handler + (_("%pB: error: erratum 843419 immediate 0x%lx " + "out of range for ADR (input file too large) and " + "--fix-cortex-a53-843419=adr used. Run the linker with " + "--fix-cortex-a53-843419=full instead"), abfd, imm); + bfd_set_error (bfd_error_bad_value); + /* This function is called inside a hashtable traversal and the error + handlers called above turn into non-fatal errors. Which means this + case ld returns an exit code 0 and also produces a broken object file. + To prevent this, issue a hard abort. */ + BFD_FAIL (); + } return TRUE; } @@ -6154,7 +6189,7 @@ 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) + if (globals->fix_erratum_843419 & ERRAT_ADRP) { struct erratum_843419_branch_to_stub_clear_data data; data.adrp_offset = adrp_offset; |