aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog19
-rw-r--r--bfd/bfd-in.h13
-rw-r--r--bfd/bfd-in2.h13
-rw-r--r--bfd/elfnn-aarch64.c73
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;