]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - ld/emultempl/aarch64elf.em
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / ld / emultempl / aarch64elf.em
index 25935d0bc2150021fa0f4916d71e8ef408610b75..bda5afcb1e935d9a10c3267b370e939caf5cf916 100644 (file)
@@ -1,5 +1,5 @@
 # This shell script emits a C file. -*- C -*-
-#   Copyright 2009-2012  Free Software Foundation, Inc.
+#   Copyright (C) 2009-2021 Free Software Foundation, Inc.
 #   Contributed by ARM Ltd.
 #
 # This file is part of the GNU Binutils.
 # see <http://www.gnu.org/licenses/>.
 #
 
-# This file is sourced from elf32.em, and defines extra aarch64-elf
+# This file is sourced from elf.em, and defines extra aarch64-elf
 # specific routines.
 #
 fragment <<EOF
 
 #include "ldctor.h"
 #include "elf/aarch64.h"
+#include "elfxx-aarch64.h"
 
 static int no_enum_size_warning = 0;
 static int no_wchar_size_warning = 0;
 static int pic_veneer = 0;
+static int fix_erratum_835769 = 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;
 
 static void
 gld${EMULATION_NAME}_before_parse (void)
@@ -40,6 +46,14 @@ gld${EMULATION_NAME}_before_parse (void)
   input_flags.dynamic = ${DYNAMIC_LINK-TRUE};
   config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
   config.separate_code = `if test "x${SEPARATE_CODE}" = xyes ; then echo TRUE ; else echo FALSE ; fi`;
+  link_info.check_relocs_after_open_input = TRUE;
+EOF
+if test -n "$COMMONPAGESIZE"; then
+fragment <<EOF
+  link_info.relro = DEFAULT_LD_Z_RELRO;
+EOF
+fi
+fragment <<EOF
 }
 
 static void
@@ -51,10 +65,10 @@ aarch64_elf_before_allocation (void)
     {
       /* Here we rummage through the found bfds to collect information.  */
       LANG_FOR_EACH_INPUT_STATEMENT (is)
-       {
-          /* Initialise mapping tables for code/data.  */
-          bfd_elf64_aarch64_init_maps (is->the_bfd);
-       }
+      {
+       /* Initialise mapping tables for code/data.  */
+       bfd_elf${ELFSIZE}_aarch64_init_maps (is->the_bfd);
+      }
     }
 
   /* Call the standard elf routine.  */
@@ -147,19 +161,18 @@ hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
 }
 
 
-/* Call-back for elf64_aarch64_size_stubs.  */
+/* Call-back for elf${ELFSIZE}_aarch64_size_stubs.  */
 
 /* Create a new stub section, and arrange for it to be linked
    immediately after INPUT_SECTION.  */
 
 static asection *
-elf64_aarch64_add_stub_section (const char *stub_sec_name,
-                               asection *input_section)
+elf${ELFSIZE}_aarch64_add_stub_section (const char *stub_sec_name,
+                                       asection *input_section)
 {
   asection *stub_sec;
   flagword flags;
   asection *output_section;
-  const char *secname;
   lang_output_section_statement_type *os;
   struct hook_stub_info info;
 
@@ -170,11 +183,12 @@ elf64_aarch64_add_stub_section (const char *stub_sec_name,
   if (stub_sec == NULL)
     goto err_ret;
 
-  bfd_set_section_alignment (stub_file->the_bfd, stub_sec, 3);
+  /* Long branch stubs contain a 64-bit address, so the section requires
+     8 byte alignment.  */
+  bfd_set_section_alignment (stub_sec, 3);
 
   output_section = input_section->output_section;
-  secname = bfd_get_section_name (output_section->owner, output_section);
-  os = lang_output_section_find (secname);
+  os = lang_output_section_get (output_section);
 
   info.input_section = input_section;
   lang_list_init (&info.add);
@@ -187,11 +201,11 @@ elf64_aarch64_add_stub_section (const char *stub_sec_name,
     return stub_sec;
 
  err_ret:
-  einfo ("%X%P: can not make stub section: %E\n");
+  einfo (_("%X%P: can not make stub section: %E\n"));
   return NULL;
 }
 
-/* Another call-back for elf_arm_size_stubs.  */
+/* Another call-back for elf${ELFSIZE}_aarch64_size_stubs.  */
 
 static void
 gldaarch64_layout_sections_again (void)
@@ -199,7 +213,7 @@ gldaarch64_layout_sections_again (void)
   /* If we have changed sizes of the stub sections, then we need
      to recalculate all the section offsets.  This may mean we need to
      add even more stubs.  */
-  gld${EMULATION_NAME}_map_segments (TRUE);
+  ldelf_map_segments (TRUE);
   need_laying_out = -1;
 }
 
@@ -210,69 +224,77 @@ build_section_lists (lang_statement_union_type *statement)
     {
       asection *i = statement->input_section.section;
 
-      if (!((lang_input_statement_type *) i->owner->usrdata)->flags.just_syms
+      if (!bfd_input_just_syms (i->owner)
          && (i->flags & SEC_EXCLUDE) == 0
          && i->output_section != NULL
          && i->output_section->owner == link_info.output_bfd)
-       elf64_aarch64_next_input_section (& link_info, i);
+       elf${ELFSIZE}_aarch64_next_input_section (& link_info, i);
     }
 }
 
 static void
 gld${EMULATION_NAME}_after_allocation (void)
 {
+  int ret;
+
   /* bfd_elf32_discard_info just plays with debugging sections,
      ie. doesn't affect any code, so we can delay resizing the
      sections.  It's likely we'll resize everything in the process of
      adding stubs.  */
-  if (bfd_elf_discard_info (link_info.output_bfd, & link_info))
+  ret = bfd_elf_discard_info (link_info.output_bfd, & link_info);
+  if (ret < 0)
+    {
+      einfo (_("%X%P: .eh_frame/.stab edit: %E\n"));
+      return;
+    }
+  else if (ret > 0)
     need_laying_out = 1;
 
   /* If generating a relocatable output file, then we don't
      have to examine the relocs.  */
-  if (stub_file != NULL && !link_info.relocatable)
+  if (stub_file != NULL && !bfd_link_relocatable (&link_info))
     {
-      int ret = elf64_aarch64_setup_section_lists (link_info.output_bfd,
-                                                  & link_info);
-
+      ret = elf${ELFSIZE}_aarch64_setup_section_lists (link_info.output_bfd,
+                                                      &link_info);
       if (ret != 0)
        {
          if (ret < 0)
            {
-             einfo ("%X%P: could not compute sections lists for stub generation: %E\n");
+             einfo (_("%X%P: could not compute sections lists "
+                      "for stub generation: %E\n"));
              return;
            }
 
          lang_for_each_statement (build_section_lists);
 
          /* Call into the BFD backend to do the real work.  */
-         if (! elf64_aarch64_size_stubs (link_info.output_bfd,
+         if (! elf${ELFSIZE}_aarch64_size_stubs (link_info.output_bfd,
                                          stub_file->the_bfd,
                                          & link_info,
                                          group_size,
-                                         & elf64_aarch64_add_stub_section,
+                                         & elf${ELFSIZE}_aarch64_add_stub_section,
                                          & gldaarch64_layout_sections_again))
            {
-             einfo ("%X%P: cannot size stub section: %E\n");
+             einfo (_("%X%P: can not size stub section: %E\n"));
              return;
            }
        }
     }
 
   if (need_laying_out != -1)
-    gld${EMULATION_NAME}_map_segments (need_laying_out);
+    ldelf_map_segments (need_laying_out);
 }
 
 static void
 gld${EMULATION_NAME}_finish (void)
 {
-  if (! link_info.relocatable)
+  if (!bfd_link_relocatable (&link_info))
     {
       /* Now build the linker stubs.  */
       if (stub_file->the_bfd->sections != NULL)
        {
-         if (! elf64_aarch64_build_stubs (& link_info))
-           einfo ("%X%P: can not build stubs: %E\n");
+         if (! elf${ELFSIZE}_aarch64_build_stubs (& link_info))
+           einfo (_("%X%P: can not build stubs: %E\n"));
        }
     }
 
@@ -290,14 +312,22 @@ aarch64_elf_create_output_section_statements (void)
         These will only be created if the output format is an arm format,
         hence we do not support linking and changing output formats at the
         same time.  Use a link followed by objcopy to change output formats.  */
-      einfo ("%F%X%P: error: Cannot change output format whilst linking AArch64 binaries.\n");
+      einfo (_("%F%P: error: cannot change output format "
+              "whilst linking %s binaries\n"), "AArch64");
       return;
     }
 
-  bfd_elf64_aarch64_set_options (link_info.output_bfd, &link_info,
+  aarch64_bti_pac_info bp_info;
+  bp_info.plt_type = plt_type;
+  bp_info.bti_type = bti_type;
+
+  bfd_elf${ELFSIZE}_aarch64_set_options (link_info.output_bfd, &link_info,
                                 no_enum_size_warning,
                                 no_wchar_size_warning,
-                                pic_veneer);
+                                pic_veneer,
+                                fix_erratum_835769, fix_erratum_843419,
+                                no_apply_dynamic_relocs,
+                                bp_info);
 
   stub_file = lang_add_input_file ("linker stubs",
                                   lang_input_file_is_fake_enum,
@@ -308,7 +338,7 @@ aarch64_elf_create_output_section_statements (void)
                              bfd_get_arch (link_info.output_bfd),
                              bfd_get_mach (link_info.output_bfd)))
     {
-      einfo ("%X%P: can not create BFD %E\n");
+      einfo (_("%F%P: can not create BFD: %E\n"));
       return;
     }
 
@@ -316,26 +346,6 @@ aarch64_elf_create_output_section_statements (void)
   ldlang_add_file (stub_file);
 }
 
-/* Avoid processing the fake stub_file in vercheck, stat_needed and
-   check_needed routines.  */
-
-static void (*real_func) (lang_input_statement_type *);
-
-static void aarch64_for_each_input_file_wrapper (lang_input_statement_type *l)
-{
-  if (l != stub_file)
-    (*real_func) (l);
-}
-
-static void
-aarch64_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
-{
-  real_func = func;
-  lang_for_each_input_file (&aarch64_for_each_input_file_wrapper);
-}
-
-#define lang_for_each_input_file aarch64_lang_for_each_input_file
-
 EOF
 
 # Define some shell vars to insert bits of code into the standard elf
@@ -344,8 +354,11 @@ EOF
 PARSE_AND_LIST_PROLOGUE='
 #define OPTION_NO_ENUM_SIZE_WARNING    309
 #define OPTION_PIC_VENEER              310
-#define OPTION_STUBGROUP_SIZE           311
+#define OPTION_STUBGROUP_SIZE          311
 #define OPTION_NO_WCHAR_SIZE_WARNING   312
+#define OPTION_FIX_ERRATUM_835769      313
+#define OPTION_FIX_ERRATUM_843419      314
+#define OPTION_NO_APPLY_DYNAMIC_RELOCS 315
 '
 
 PARSE_AND_LIST_SHORTOPTS=p
@@ -356,24 +369,53 @@ PARSE_AND_LIST_LONGOPTS='
   { "pic-veneer", no_argument, NULL, OPTION_PIC_VENEER},
   { "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", optional_argument, NULL, OPTION_FIX_ERRATUM_843419},
+  { "no-apply-dynamic-relocs", no_argument, NULL, OPTION_NO_APPLY_DYNAMIC_RELOCS},
 '
 
 PARSE_AND_LIST_OPTIONS='
   fprintf (file, _("  --no-enum-size-warning      Don'\''t warn about objects with incompatible\n"
                   "                                enum sizes\n"));
-  fprintf (file, _("  --no-wchar-size-warning     Don'\''t warn about objects with incompatible"
+  fprintf (file, _("  --no-wchar-size-warning     Don'\''t warn about objects with incompatible\n"
                   "                                wchar_t sizes\n"));
   fprintf (file, _("  --pic-veneer                Always generate PIC interworking veneers\n"));
   fprintf (file, _("\
-   --stub-group-size=N   Maximum size of a group of input sections that can be\n\
-                           handled by one stub section.  A negative value\n\
-                           locates all stubs after their branches (with a\n\
-                           group size of -N), while a positive value allows\n\
-                           two groups of input sections, one before, and one\n\
-                           after each stub section.  Values of +/-1 indicate\n\
-                           the linker should choose suitable defaults.\n"
-                  ));
+  --stub-group-size=N         Maximum size of a group of input sections that\n\
+                                can be handled by one stub section.  A negative\n\
+                                value locates all stubs after their branches\n\
+                                (with a group size of -N), while a positive\n\
+                                value allows two groups of input sections, one\n\
+                                before, and one after each stub section.\n\
+                                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[=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, _("  -z force-bti                  Turn on Branch Target Identification mechanism and generate PLTs with BTI. Generate warnings for missing BTI on inputs\n"));
+  fprintf (file, _("  -z pac-plt                    Protect PLTs with Pointer Authentication.\n"));
+'
+
+PARSE_AND_LIST_ARGS_CASE_Z_AARCH64='
+      else if (strcmp (optarg, "force-bti") == 0)
+       {
+         plt_type |= PLT_BTI;
+         bti_type = BTI_WARN;
+       }
+      else if (strcmp (optarg, "pac-plt") == 0)
+       plt_type |= PLT_PAC;
 '
+PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_AARCH64"
 
 PARSE_AND_LIST_ARGS_CASES='
     case '\'p\'':
@@ -392,13 +434,37 @@ PARSE_AND_LIST_ARGS_CASES='
       pic_veneer = 1;
       break;
 
+    case OPTION_FIX_ERRATUM_835769:
+      fix_erratum_835769 = 1;
+      break;
+
+    case OPTION_FIX_ERRATUM_843419:
+      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:
+      no_apply_dynamic_relocs = 1;
+      break;
+
     case OPTION_STUBGROUP_SIZE:
       {
        const char *end;
 
-        group_size = bfd_scan_vma (optarg, &end, 0);
-        if (*end)
-         einfo (_("%P%F: invalid number `%s'\''\n"), optarg);
+       group_size = bfd_scan_vma (optarg, &end, 0);
+       if (*end)
+         einfo (_("%F%P: invalid number `%s'\''\n"), optarg);
       }
       break;
 '