+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
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. */
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. */
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;
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)
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)
{
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 ();
/* 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);
}
(*htab->layout_sections_again) ();
}
- if (htab->fix_erratum_843419)
+ if (htab->fix_erratum_843419 != ERRAT_NONE)
{
bfd *input_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)
{
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));
|| 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);
((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;
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;
}
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;
+2019-05-21 Tamar Christina <tamar.christina@arm.com>
+
+ PR ld/24373
+ * emultempl/aarch64elf.em (PARSE_AND_LIST_LONGOPTS): Add optional args
+ to flags.
+ * NEWS: Add changes to flag.
+ (PARSE_AND_LIST_OPTIONS): Update help descriptions.
+ (PARSE_AND_LIST_ARGS_CASES): Add new options to parser.
+ * testsuite/ld-aarch64/aarch64-elf.exp: Add new run_dump_tests.
+ * testsuite/ld-aarch64/erratum843419-adr.d: New test.
+ * testsuite/ld-aarch64/erratum843419-adrp.d: New test.
+ * testsuite/ld-aarch64/erratum843419-far-adr.d: New test.
+ * testsuite/ld-aarch64/erratum843419-far-full.d: New test.
+ * testsuite/ld-aarch64/erratum843419-far.s: New test.
+ * testsuite/ld-aarch64/erratum843419-full.d: New test.
+ * testsuite/ld-aarch64/erratum843419-near.s: New test.
+ * testsuite/ld-aarch64/erratum843419-no-args.d: New test.
+
2019-05-21 Senthil Kumar Selvaraj <senthilkumar.selvaraj@microchip.com>
PR ld/24571
* Add command-line option --no-print-map-discarded.
+* The Cortex-A53 Erratum 843419 workaround now supports a choice of which
+ workaround to use. The option --fix-cortex-a53-843419 now takes an
+ optional argument --fix-cortex-a53-843419[=full|adr|adrp] which can be
+ used to force a particular workaround to be used. See --help for AArch64
+ for more details.
+
Changes in 2.33:
* Add target handlers for AArch64 for ELF GNU program properties.
static int no_wchar_size_warning = 0;
static int pic_veneer = 0;
static int fix_erratum_835769 = 0;
-static int fix_erratum_843419 = 0;
+static erratum_84319_opts fix_erratum_843419 = ERRAT_NONE;
static int no_apply_dynamic_relocs = 0;
static aarch64_plt_type plt_type = PLT_NORMAL;
static aarch64_enable_bti_type bti_type = BTI_NONE;
{ "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
{ "no-wchar-size-warning", no_argument, NULL, OPTION_NO_WCHAR_SIZE_WARNING},
{ "fix-cortex-a53-835769", no_argument, NULL, OPTION_FIX_ERRATUM_835769},
- { "fix-cortex-a53-843419", no_argument, NULL, OPTION_FIX_ERRATUM_843419},
+ { "fix-cortex-a53-843419", optional_argument, NULL, OPTION_FIX_ERRATUM_843419},
{ "no-apply-dynamic-relocs", no_argument, NULL, OPTION_NO_APPLY_DYNAMIC_RELOCS},
{ "force-bti", no_argument, NULL, OPTION_FORCE_BTI},
{ "pac-plt", no_argument, NULL, OPTION_PAC_PLT},
Values of +/-1 indicate the linker should\n\
choose suitable defaults.\n"));
fprintf (file, _(" --fix-cortex-a53-835769 Fix erratum 835769\n"));
- fprintf (file, _(" --fix-cortex-a53-843419 Fix erratum 843419\n"));
+ fprintf (file, _("\
+ --fix-cortex-a53-843419[=full|adr|adrp] Fix erratum 843419 and optionally specify which workaround to use.\n\
+ full (default): Use both ADRP and ADR workaround, this will \n\
+ increase the size of your binaries.\n\
+ adr: Only use the ADR workaround, this will not cause any increase\n\
+ in binary size but linking will fail if the referenced address is\n\
+ out of range of an ADR instruction. This will remove the need of using\n\
+ a veneer and results in both performance and size benefits.\n\
+ adrp: Use only the ADRP workaround, this will never rewrite your ADRP\n\
+ instruction into an ADR. As such the workaround will always use a\n\
+ veneer and this will give you both a performance and size overhead.\n"));
fprintf (file, _(" --no-apply-dynamic-relocs Do not apply link-time values for dynamic relocations\n"));
fprintf (file, _(" --force-bti Turn on Branch Target Identification mechanism and generate PLTs with BTI. Generate warnings for missing BTI on inputs\n"));
fprintf (file, _(" --pac-plt Protect PLTs with Pointer Authentication.\n"));
break;
case OPTION_FIX_ERRATUM_843419:
- fix_erratum_843419 = 1;
+ fix_erratum_843419 = ERRAT_ADR | ERRAT_ADRP;
+ if (optarg && *optarg)
+ {
+ if (strcmp ("full", optarg) == 0)
+ fix_erratum_843419 = ERRAT_ADR | ERRAT_ADRP;
+ else if (strcmp ("adrp", optarg) == 0)
+ fix_erratum_843419 = ERRAT_ADRP;
+ else if (strcmp ("adr", optarg) == 0)
+ fix_erratum_843419 = ERRAT_ADR;
+ else
+ einfo (_("%P: error: unrecognized option for "
+ "--fix-cortex-a53-843419: %s\n"), optarg);
+ }
break;
case OPTION_NO_APPLY_DYNAMIC_RELOCS:
run_dump_test "erratum843419"
run_dump_test "erratum843419_tls_ie"
+run_dump_test "erratum843419-adr"
+run_dump_test "erratum843419-adrp"
+run_dump_test "erratum843419-far-adr"
+run_dump_test "erratum843419-far-full"
+run_dump_test "erratum843419-full"
+run_dump_test "erratum843419-no-args"
# Relocation Tests
run_dump_test_lp64 "weak-undefined"
--- /dev/null
+#source: erratum843419-near.s
+#as:
+#ld: -Ttext=0x400000 --fix-cortex-a53-843419=adr
+#objdump: -dr
+#...
+
+Disassembly of section \.text:
+
+0*400000 <_start>:
+ ...
+ 400ffc: 10038020 adr x0, 408000 <_start\+0x8000>
+ 401000: f9000042 str x2, \[x2\]
+ 401004: d2800002 mov x2, #0x0 // #0
+ 401008: f9402001 ldr x1, \[x0, #64\]
+ 40100c: d503201f nop
--- /dev/null
+#source: erratum843419-near.s
+#as:
+#ld: -Ttext=0x400000 --fix-cortex-a53-843419=adrp
+#objdump: -dr
+#...
+
+Disassembly of section \.text:
+
+0*400000 <_start>:
+ ...
+ 400ffc: 90000040 adrp x0, 408000 <e843419@0002_00000010_1008\+0x6fe8>
+ 401000: f9000042 str x2, \[x2\]
+ 401004: d2800002 mov x2, #0x0 // #0
+ 401008: 14000004 b 401018 <e843419@0002_00000010_1008>
+ 40100c: d503201f nop
+ 401010: 14000400 b 402010 <e843419@0002_00000010_1008\+0xff8>
+ 401014: d503201f nop
+
+0*401018 <e843419@0002_00000010_1008>:
+ 401018: f9402001 ldr x1, \[x0, #64\]
+ 40101c: 17fffffc b 40100c <_start\+0x100c>
+ ...
--- /dev/null
+#source: erratum843419-far.s
+#as:
+#ld: -Ttext=0x400000 --fix-cortex-a53-843419=adr
+#error: .*: erratum 843419 immediate 0x7ffff004 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.*
+#...
--- /dev/null
+#source: erratum843419-far.s
+#as:
+#ld: -Ttext=0x400000 --fix-cortex-a53-843419=full
+#objdump: -dr
+#...
+
+Disassembly of section \.text:
+
+0*400000 <_start>:
+ ...
+ 400ffc: 90400000 adrp x0, 80400000 <__bss_end__\+0x7ffedff0>
+ 401000: f9000042 str x2, \[x2\]
+ 401004: d2800002 mov x2, #0x0 // #0
+ 401008: 14000004 b 401018 <e843419@0002_00000010_1008>
+ 40100c: d503201f nop
+ 401010: 14000400 b 402010 <e843419@0002_00000010_1008\+0xff8>
+ 401014: d503201f nop
+
+0*401018 <e843419@0002_00000010_1008>:
+ 401018: f9402001 ldr x1, \[x0, #64\]
+ 40101c: 17fffffc b 40100c <_start\+0x100c>
+ ...
--- /dev/null
+.balign 0x1000
+.globl _start
+_start:
+ .skip 0xffc
+ adrp x0, _start + 0x80000000
+ str x2, [x2]
+ mov x2, #0
+ ldr x1, [x0, #0x40]
+ nop
--- /dev/null
+#source: erratum843419-near.s
+#as:
+#ld: -Ttext=0x400000 --fix-cortex-a53-843419=full
+#objdump: -dr
+#...
+
+Disassembly of section \.text:
+
+0*400000 <_start>:
+ ...
+ 400ffc: 10038020 adr x0, 408000 <_start\+0x8000>
+ 401000: f9000042 str x2, \[x2\]
+ 401004: d2800002 mov x2, #0x0 // #0
+ 401008: f9402001 ldr x1, \[x0, #64\]
+ 40100c: d503201f nop
+ 401010: 14000400 b 402010 <_start\+0x2010>
+ 401014: d503201f nop
+ 401018: f9402001 ldr x1, \[x0, #64\]
+ 40101c: 17fffffc b 40100c <_start\+0x100c>
+ ...
--- /dev/null
+.balign 0x1000
+.globl _start
+_start:
+ .skip 0xffc
+ adrp x0, _start + 0x8000
+ str x2, [x2]
+ mov x2, #0
+ ldr x1, [x0, #0x40]
+ nop
--- /dev/null
+#source: erratum843419-near.s
+#as:
+#ld: -Ttext=0x400000 --fix-cortex-a53-843419
+#objdump: -dr
+#...
+
+Disassembly of section \.text:
+
+0*400000 <_start>:
+ ...
+ 400ffc: 10038020 adr x0, 408000 <_start\+0x8000>
+ 401000: f9000042 str x2, \[x2\]
+ 401004: d2800002 mov x2, #0x0 // #0
+ 401008: f9402001 ldr x1, \[x0, #64\]
+ 40100c: d503201f nop
+ 401010: 14000400 b 402010 <_start\+0x2010>
+ 401014: d503201f nop
+ 401018: f9402001 ldr x1, \[x0, #64\]
+ 40101c: 17fffffc b 40100c <_start\+0x100c>
+ ...