]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - ld/emultempl/armelf.em
Emit a warning when -z relro is unsupported
[thirdparty/binutils-gdb.git] / ld / emultempl / armelf.em
index 78224f4389c1870a47ea7c548a43f1beac496073..34372ba7b0b64055097325f39cf1959de1e75cb3 100644 (file)
@@ -1,7 +1,5 @@
 # This shell script emits a C file. -*- C -*-
-#   Copyright 1991, 1993, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-#   2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-#   Free Software Foundation, Inc.
+#   Copyright (C) 1991-2020 Free Software Foundation, Inc.
 #
 # This file is part of the GNU Binutils.
 #
@@ -21,7 +19,7 @@
 # MA 02110-1301, USA.
 #
 
-# This file is sourced from elf32.em, and defines extra arm-elf
+# This file is sourced from elf.em, and defines extra arm-elf
 # specific routines.
 #
 test -z "$TARGET2_TYPE" && TARGET2_TYPE="rel"
@@ -29,20 +27,28 @@ fragment <<EOF
 
 #include "ldctor.h"
 #include "elf/arm.h"
+#include "elf32-arm.h"
 
-static char *thumb_entry_symbol = NULL;
-static int byteswap_code = 0;
-static int target1_is_rel = 0${TARGET1_IS_REL};
-static char *target2_type = "${TARGET2_TYPE}";
-static int fix_v4bx = 0;
-static int use_blx = 0;
-static bfd_arm_vfp11_fix vfp11_denorm_fix = BFD_ARM_VFP11_FIX_DEFAULT;
-static int fix_cortex_a8 = -1;
-static int no_enum_size_warning = 0;
-static int no_wchar_size_warning = 0;
-static int pic_veneer = 0;
-static int merge_exidx_entries = -1;
-static int fix_arm1176 = 1;
+static struct elf32_arm_params params =
+{
+  NULL,                                /* thumb_entry_symbol */
+  0,                           /* byteswap_code */
+  0${TARGET1_IS_REL},          /* target1_is_rel */
+  "${TARGET2_TYPE}",           /* target2_type */
+  0,                           /* fix_v4bx */
+  0,                           /* use_blx */
+  BFD_ARM_VFP11_FIX_DEFAULT,   /* vfp11_denorm_fix */
+  BFD_ARM_STM32L4XX_FIX_NONE,  /* stm32l4xx_fix */
+  0,                           /* no_enum_size_warning */
+  0,                           /* no_wchar_size_warning */
+  0,                           /* pic_veneer */
+  -1,                          /* fix_cortex_a8 */
+  1,                           /* fix_arm1176 */
+  -1,                          /* merge_exidx_entries */
+  0,                           /* cmse_implib */
+  NULL                         /* in_implib_bfd */
+};
+static char *in_implib_filename = NULL;
 
 static void
 gld${EMULATION_NAME}_before_parse (void)
@@ -52,20 +58,50 @@ gld${EMULATION_NAME}_before_parse (void)
 #endif /* not TARGET_ */
   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
+gld${EMULATION_NAME}_set_symbols (void)
+{
+  /* PR 19106: The section resizing code in gldarmelf_after_allocation
+     is effectively the same as relaxation, so prevent early memory
+     region checks which produce bogus error messages.
+     Note - this test has nothing to do with symbols.  It is just here
+     because this is the first emulation routine that is called after
+     the command line has been parsed.  */
+  if (!bfd_link_relocatable (&link_info))
+    TARGET_ENABLE_RELAXATION;
 }
 
 static void
 arm_elf_before_allocation (void)
 {
-  bfd_elf32_arm_set_byteswap_code (&link_info, byteswap_code);
+  bfd_elf32_arm_set_byteswap_code (&link_info, params.byteswap_code);
 
   /* Choose type of VFP11 erratum fix, or warn if specified fix is unnecessary
      due to architecture version.  */
   bfd_elf32_arm_set_vfp11_fix (link_info.output_bfd, &link_info);
 
+  /* Choose type of STM32L4XX erratum fix, or warn if specified fix is
+     unnecessary due to architecture version.  */
+  bfd_elf32_arm_set_stm32l4xx_fix (link_info.output_bfd, &link_info);
+
   /* Auto-select Cortex-A8 erratum fix if it wasn't explicitly specified.  */
   bfd_elf32_arm_set_cortex_a8_fix (link_info.output_bfd, &link_info);
 
+  /* Ensure the output sections of veneers needing a dedicated one is not
+     removed.  */
+  bfd_elf32_arm_keep_private_stub_output_sections (&link_info);
+
   /* We should be able to set the size of the interworking stub section.  We
      can't do it until later if we have dynamic sections, though.  */
   if (elf_hash_table (&link_info)->dynobj == NULL)
@@ -73,14 +109,17 @@ arm_elf_before_allocation (void)
       /* Here we rummage through the found bfds to collect glue information.  */
       LANG_FOR_EACH_INPUT_STATEMENT (is)
        {
-          /* Initialise mapping tables for code/data.  */
-          bfd_elf32_arm_init_maps (is->the_bfd);
+         /* Initialise mapping tables for code/data.  */
+         bfd_elf32_arm_init_maps (is->the_bfd);
 
          if (!bfd_elf32_arm_process_before_allocation (is->the_bfd,
                                                        &link_info)
-             || !bfd_elf32_arm_vfp11_erratum_scan (is->the_bfd, &link_info))
+             || !bfd_elf32_arm_vfp11_erratum_scan (is->the_bfd, &link_info)
+             || !bfd_elf32_arm_stm32l4xx_erratum_scan (is->the_bfd,
+                                                       &link_info))
            /* xgettext:c-format */
-           einfo (_("Errors encountered processing file %s"), is->filename);
+           einfo (_("%P: errors encountered processing file %s\n"),
+                  is->filename);
        }
 
       /* We have seen it all.  Allocate it, and carry on.  */
@@ -183,41 +222,57 @@ hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
    immediately after INPUT_SECTION.  */
 
 static asection *
-elf32_arm_add_stub_section (const char *stub_sec_name,
-                           asection *input_section)
+elf32_arm_add_stub_section (const char * stub_sec_name,
+                           asection *   output_section,
+                           asection *   after_input_section,
+                           unsigned int alignment_power)
 {
   asection *stub_sec;
   flagword flags;
-  asection *output_section;
-  const char *secname;
   lang_output_section_statement_type *os;
   struct hook_stub_info info;
 
   flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
-          | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP);
+          | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP
+          | SEC_LINKER_CREATED);
   stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
                                                 stub_sec_name, flags);
   if (stub_sec == NULL)
     goto err_ret;
 
-  bfd_set_section_alignment (stub_file->the_bfd, stub_sec, 3);
+  bfd_set_section_alignment (stub_sec, alignment_power);
 
-  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;
+  info.input_section = after_input_section;
   lang_list_init (&info.add);
-  lang_add_section (&info.add, stub_sec, os);
+  lang_add_section (&info.add, stub_sec, NULL, os);
 
   if (info.add.head == NULL)
     goto err_ret;
 
-  if (hook_in_stub (&info, &os->children.head))
-    return stub_sec;
+  if (after_input_section == NULL)
+    {
+      lang_statement_union_type **lp = &os->children.head;
+      lang_statement_union_type *l, *lprev = NULL;
+
+      for (; (l = *lp) != NULL; lp = &l->header.next, lprev = l);
+
+      if (lprev)
+       lprev->header.next = info.add.head;
+      else
+       os->children.head = info.add.head;
+
+      return stub_sec;
+    }
+  else
+    {
+      if (hook_in_stub (&info, &os->children.head))
+       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;
 }
 
@@ -229,7 +284,7 @@ gldarm_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;
 }
 
@@ -254,93 +309,98 @@ compare_output_sec_vma (const void *a, const void *b)
   asection *asec = *(asection **) a, *bsec = *(asection **) b;
   asection *aout = asec->output_section, *bout = bsec->output_section;
   bfd_vma avma, bvma;
-  
+
   /* If there's no output section for some reason, compare equal.  */
   if (!aout || !bout)
     return 0;
-  
+
   avma = aout->vma + asec->output_offset;
   bvma = bout->vma + bsec->output_offset;
-  
+
   if (avma > bvma)
     return 1;
   else if (avma < bvma)
     return -1;
-  
+
   return 0;
 }
 
 static void
 gld${EMULATION_NAME}_after_allocation (void)
 {
-  if (!link_info.relocatable)
+  int ret;
+
+  /* Build a sorted list of input text sections, then use that to process
+     the unwind table index.  */
+  unsigned int list_size = 10;
+  asection **sec_list = (asection **)
+      xmalloc (list_size * sizeof (asection *));
+  unsigned int sec_count = 0;
+
+  LANG_FOR_EACH_INPUT_STATEMENT (is)
     {
-      /* Build a sorted list of input text sections, then use that to process
-        the unwind table index.  */
-      unsigned int list_size = 10;
-      asection **sec_list = (asection **)
-          xmalloc (list_size * sizeof (asection *));
-      unsigned int sec_count = 0;
+      bfd *abfd = is->the_bfd;
+      asection *sec;
 
-      LANG_FOR_EACH_INPUT_STATEMENT (is)
+      if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
+       continue;
+
+      for (sec = abfd->sections; sec != NULL; sec = sec->next)
        {
-         bfd *abfd = is->the_bfd;
-         asection *sec;
-         
-         if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
-           continue;
-         
-         for (sec = abfd->sections; sec != NULL; sec = sec->next)
+         asection *out_sec = sec->output_section;
+
+         if (out_sec
+             && elf_section_data (sec)
+             && elf_section_type (sec) == SHT_PROGBITS
+             && (elf_section_flags (sec) & SHF_EXECINSTR) != 0
+             && (sec->flags & SEC_EXCLUDE) == 0
+             && sec->sec_info_type != SEC_INFO_TYPE_JUST_SYMS
+             && out_sec != bfd_abs_section_ptr)
            {
-             asection *out_sec = sec->output_section;
-
-             if (out_sec
-                 && elf_section_data (sec)
-                 && elf_section_type (sec) == SHT_PROGBITS
-                 && (elf_section_flags (sec) & SHF_EXECINSTR) != 0
-                 && (sec->flags & SEC_EXCLUDE) == 0
-                 && sec->sec_info_type != SEC_INFO_TYPE_JUST_SYMS
-                 && out_sec != bfd_abs_section_ptr)
+             if (sec_count == list_size)
                {
-                 if (sec_count == list_size)
-                   {
-                     list_size *= 2;
-                     sec_list = (asection **) 
-                          xrealloc (sec_list, list_size * sizeof (asection *));
-                   }
-
-                 sec_list[sec_count++] = sec;
+                 list_size *= 2;
+                 sec_list = (asection **)
+                     xrealloc (sec_list, list_size * sizeof (asection *));
                }
+
+             sec_list[sec_count++] = sec;
            }
        }
-       
-      qsort (sec_list, sec_count, sizeof (asection *), &compare_output_sec_vma);
-      
-      if (elf32_arm_fix_exidx_coverage (sec_list, sec_count, &link_info,
-                                          merge_exidx_entries))
-       need_laying_out = 1;
-      
-      free (sec_list);
     }
 
+  qsort (sec_list, sec_count, sizeof (asection *), &compare_output_sec_vma);
+
+  if (elf32_arm_fix_exidx_coverage (sec_list, sec_count, &link_info,
+                                   params.merge_exidx_entries))
+    need_laying_out = 1;
+
+  free (sec_list);
+
   /* 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 = elf32_arm_setup_section_lists (link_info.output_bfd, & link_info);
-
+      ret = elf32_arm_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;
            }
 
@@ -354,14 +414,14 @@ gld${EMULATION_NAME}_after_allocation (void)
                                      & elf32_arm_add_stub_section,
                                      & gldarm_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
@@ -372,27 +432,31 @@ gld${EMULATION_NAME}_finish (void)
   {
     LANG_FOR_EACH_INPUT_STATEMENT (is)
       {
-        /* Figure out where VFP11 erratum veneers (and the labels returning
-           from same) have been placed.  */
-        bfd_elf32_arm_vfp11_fix_veneer_locations (is->the_bfd, &link_info);
+       /* Figure out where VFP11 erratum veneers (and the labels returning
+          from same) have been placed.  */
+       bfd_elf32_arm_vfp11_fix_veneer_locations (is->the_bfd, &link_info);
+
+        /* Figure out where STM32L4XX erratum veneers (and the labels returning
+          from them) have been placed.  */
+       bfd_elf32_arm_stm32l4xx_fix_veneer_locations (is->the_bfd, &link_info);
       }
   }
 
-  if (! link_info.relocatable)
+  if (!bfd_link_relocatable (&link_info))
     {
       /* Now build the linker stubs.  */
       if (stub_file->the_bfd->sections != NULL)
        {
          if (! elf32_arm_build_stubs (& link_info))
-           einfo ("%X%P: can not build stubs: %E\n");
+           einfo (_("%X%P: can not build stubs: %E\n"));
        }
     }
 
   finish_default ();
 
-  if (thumb_entry_symbol)
+  if (params.thumb_entry_symbol)
     {
-      h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol,
+      h = bfd_link_hash_lookup (link_info.hash, params.thumb_entry_symbol,
                                FALSE, FALSE, TRUE);
     }
   else
@@ -405,7 +469,8 @@ gld${EMULATION_NAME}_finish (void)
       h = bfd_link_hash_lookup (link_info.hash, entry_symbol.name,
                                FALSE, FALSE, TRUE);
       eh = (struct elf_link_hash_entry *)h;
-      if (!h || eh->target_internal != ST_BRANCH_TO_THUMB)
+      if (!h || ARM_GET_SYM_BRANCH_TYPE (eh->target_internal)
+               != ST_BRANCH_TO_THUMB)
        return;
     }
 
@@ -421,8 +486,7 @@ gld${EMULATION_NAME}_finish (void)
       /* Special procesing is required for a Thumb entry symbol.  The
         bottom bit of its address must be set.  */
       val = (h->u.def.value
-            + bfd_get_section_vma (link_info.output_bfd,
-                                   h->u.def.section->output_section)
+            + bfd_section_vma (h->u.def.section->output_section)
             + h->u.def.section->output_offset);
 
       val |= 1;
@@ -434,15 +498,15 @@ gld${EMULATION_NAME}_finish (void)
 
       sprintf_vma (buffer + 2, val);
 
-      if (thumb_entry_symbol != NULL && entry_symbol.name != NULL
+      if (params.thumb_entry_symbol != NULL && entry_symbol.name != NULL
          && entry_from_cmdline)
        einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
-              thumb_entry_symbol, entry_symbol.name);
+              params.thumb_entry_symbol, entry_symbol.name);
       entry_symbol.name = buffer;
     }
   else
     einfo (_("%P: warning: cannot find thumb start symbol %s\n"),
-          thumb_entry_symbol);
+          h->root.string);
 }
 
 /* This is a convenient point to tell BFD about target specific flags.
@@ -456,31 +520,38 @@ arm_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 ARM binaries.\n");
+      einfo (_("%F%P: error: cannot change output format "
+              "whilst linking %s binaries\n"), "ARM");
       return;
     }
 
-  bfd_elf32_arm_set_target_relocs (link_info.output_bfd, &link_info,
-                                  target1_is_rel,
-                                  target2_type, fix_v4bx, use_blx,
-                                  vfp11_denorm_fix, no_enum_size_warning,
-                                  no_wchar_size_warning,
-                                  pic_veneer, fix_cortex_a8, 
-                                  fix_arm1176);
+  if (in_implib_filename)
+    {
+      params.in_implib_bfd = bfd_openr (in_implib_filename,
+                                       bfd_get_target (link_info.output_bfd));
+
+      if (params.in_implib_bfd == NULL)
+       einfo (_("%F%P: %s: can't open: %E\n"), in_implib_filename);
+
+      if (!bfd_check_format (params.in_implib_bfd, bfd_object))
+       einfo (_("%F%P: %s: not a relocatable file: %E\n"), in_implib_filename);
+    }
+
+  bfd_elf32_arm_set_target_params (link_info.output_bfd, &link_info, &params);
 
   stub_file = lang_add_input_file ("linker stubs",
-                                  lang_input_file_is_fake_enum,
-                                  NULL);
+                                  lang_input_file_is_fake_enum,
+                                  NULL);
   stub_file->the_bfd = bfd_create ("linker stubs", link_info.output_bfd);
   if (stub_file->the_bfd == NULL
       || ! bfd_set_arch_mach (stub_file->the_bfd,
-                             bfd_get_arch (link_info.output_bfd),
-                             bfd_get_mach (link_info.output_bfd)))
+                             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;
     }
+
   stub_file->the_bfd->flags |= BFD_LINKER_CREATED;
   ldlang_add_file (stub_file);
 
@@ -489,26 +560,6 @@ arm_elf_create_output_section_statements (void)
   bfd_elf32_arm_get_bfd_for_interworking (stub_file->the_bfd, &link_info);
 }
 
-/* Avoid processing the fake stub_file in vercheck, stat_needed and
-   check_needed routines.  */
-
-static void (*real_func) (lang_input_statement_type *);
-
-static void arm_for_each_input_file_wrapper (lang_input_statement_type *l)
-{
-  if (l != stub_file)
-    (*real_func) (l);
-}
-
-static void
-arm_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
-{
-  real_func = func;
-  lang_for_each_input_file (&arm_for_each_input_file_wrapper);
-}
-
-#define lang_for_each_input_file arm_lang_for_each_input_file
-
 EOF
 
 # Define some shell vars to insert bits of code into the standard elf
@@ -526,13 +577,17 @@ PARSE_AND_LIST_PROLOGUE='
 #define OPTION_NO_ENUM_SIZE_WARNING    309
 #define OPTION_PIC_VENEER              310
 #define OPTION_FIX_V4BX_INTERWORKING   311
-#define OPTION_STUBGROUP_SIZE           312
+#define OPTION_STUBGROUP_SIZE          312
 #define OPTION_NO_WCHAR_SIZE_WARNING   313
 #define OPTION_FIX_CORTEX_A8           314
 #define OPTION_NO_FIX_CORTEX_A8                315
-#define OPTION_NO_MERGE_EXIDX_ENTRIES   316
+#define OPTION_NO_MERGE_EXIDX_ENTRIES  316
 #define OPTION_FIX_ARM1176             317
 #define OPTION_NO_FIX_ARM1176          318
+#define OPTION_LONG_PLT                        319
+#define OPTION_STM32L4XX_FIX           320
+#define OPTION_CMSE_IMPLIB             321
+#define OPTION_IN_IMPLIB               322
 '
 
 PARSE_AND_LIST_SHORTOPTS=p
@@ -548,6 +603,7 @@ PARSE_AND_LIST_LONGOPTS='
   { "fix-v4bx-interworking", no_argument, NULL, OPTION_FIX_V4BX_INTERWORKING},
   { "use-blx", no_argument, NULL, OPTION_USE_BLX},
   { "vfp11-denorm-fix", required_argument, NULL, OPTION_VFP11_DENORM_FIX},
+  { "fix-stm32l4xx-629360", optional_argument, NULL, OPTION_STM32L4XX_FIX},
   { "no-enum-size-warning", no_argument, NULL, OPTION_NO_ENUM_SIZE_WARNING},
   { "pic-veneer", no_argument, NULL, OPTION_PIC_VENEER},
   { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
@@ -557,6 +613,9 @@ PARSE_AND_LIST_LONGOPTS='
   { "no-merge-exidx-entries", no_argument, NULL, OPTION_NO_MERGE_EXIDX_ENTRIES },
   { "fix-arm1176", no_argument, NULL, OPTION_FIX_ARM1176 },
   { "no-fix-arm1176", no_argument, NULL, OPTION_NO_FIX_ARM1176 },
+  { "long-plt", no_argument, NULL, OPTION_LONG_PLT },
+  { "cmse-implib", no_argument, NULL, OPTION_CMSE_IMPLIB },
+  { "in-implib", required_argument, NULL, OPTION_IN_IMPLIB },
 '
 
 PARSE_AND_LIST_OPTIONS='
@@ -569,20 +628,27 @@ PARSE_AND_LIST_OPTIONS='
   fprintf (file, _("  --fix-v4bx-interworking     Rewrite BX rn branch to ARMv4 interworking veneer\n"));
   fprintf (file, _("  --use-blx                   Enable use of BLX instructions\n"));
   fprintf (file, _("  --vfp11-denorm-fix          Specify how to fix VFP11 denorm erratum\n"));
+  fprintf (file, _("  --fix-stm32l4xx-629360      Specify how to fix STM32L4XX 629360 erratum\n"));
   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\n"
                   "                                wchar_t sizes\n"));
   fprintf (file, _("  --pic-veneer                Always generate PIC interworking veneers\n"));
+  fprintf (file, _("  --long-plt                  Generate long .plt entries\n"
+           "                              to handle large .plt/.got displacements\n"));
+  fprintf (file, _("  --cmse-implib               Make import library to be a secure gateway import\n"
+                   "                                library as per ARMv8-M Security Extensions\n"));
+  fprintf (file, _("  --in-implib                 Import library whose symbols address must\n"
+                   "                                remain stable\n"));
   fprintf (file, _("\
   --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"));
+                                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, _("  --[no-]fix-cortex-a8        Disable/enable Cortex-A8 Thumb-2 branch erratum fix\n"));
   fprintf (file, _("  --no-merge-exidx-entries    Disable merging exidx entries\n"));
   fprintf (file, _("  --[no-]fix-arm1176          Disable/enable ARM1176 BLX immediate erratum fix\n"));
@@ -594,88 +660,113 @@ PARSE_AND_LIST_ARGS_CASES='
       break;
 
     case OPTION_THUMB_ENTRY:
-      thumb_entry_symbol = optarg;
+      params.thumb_entry_symbol = optarg;
       break;
 
     case OPTION_BE8:
-      byteswap_code = 1;
+      params.byteswap_code = 1;
       break;
 
     case OPTION_TARGET1_REL:
-      target1_is_rel = 1;
+      params.target1_is_rel = 1;
       break;
 
     case OPTION_TARGET1_ABS:
-      target1_is_rel = 0;
+      params.target1_is_rel = 0;
       break;
 
     case OPTION_TARGET2:
-      target2_type = optarg;
+      params.target2_type = optarg;
       break;
 
     case OPTION_FIX_V4BX:
-      fix_v4bx = 1;
+      params.fix_v4bx = 1;
       break;
 
     case OPTION_FIX_V4BX_INTERWORKING:
-      fix_v4bx = 2;
+      params.fix_v4bx = 2;
       break;
 
     case OPTION_USE_BLX:
-      use_blx = 1;
+      params.use_blx = 1;
       break;
 
     case OPTION_VFP11_DENORM_FIX:
       if (strcmp (optarg, "none") == 0)
-        vfp11_denorm_fix = BFD_ARM_VFP11_FIX_NONE;
+       params.vfp11_denorm_fix = BFD_ARM_VFP11_FIX_NONE;
       else if (strcmp (optarg, "scalar") == 0)
-        vfp11_denorm_fix = BFD_ARM_VFP11_FIX_SCALAR;
+       params.vfp11_denorm_fix = BFD_ARM_VFP11_FIX_SCALAR;
       else if (strcmp (optarg, "vector") == 0)
-        vfp11_denorm_fix = BFD_ARM_VFP11_FIX_VECTOR;
+       params.vfp11_denorm_fix = BFD_ARM_VFP11_FIX_VECTOR;
+      else
+       einfo (_("%P: unrecognized VFP11 fix type '\''%s'\''\n"), optarg);
+      break;
+
+    case OPTION_STM32L4XX_FIX:
+      if (!optarg)
+       params.stm32l4xx_fix = BFD_ARM_STM32L4XX_FIX_DEFAULT;
+      else if (strcmp (optarg, "none") == 0)
+       params.stm32l4xx_fix = BFD_ARM_STM32L4XX_FIX_NONE;
+      else if (strcmp (optarg, "default") == 0)
+       params.stm32l4xx_fix = BFD_ARM_STM32L4XX_FIX_DEFAULT;
+      else if (strcmp (optarg, "all") == 0)
+       params.stm32l4xx_fix = BFD_ARM_STM32L4XX_FIX_ALL;
       else
-        einfo (_("Unrecognized VFP11 fix type '\''%s'\''.\n"), optarg);
+       einfo (_("%P: unrecognized STM32L4XX fix type '\''%s'\''\n"), optarg);
       break;
 
     case OPTION_NO_ENUM_SIZE_WARNING:
-      no_enum_size_warning = 1;
+      params.no_enum_size_warning = 1;
       break;
 
     case OPTION_NO_WCHAR_SIZE_WARNING:
-      no_wchar_size_warning = 1;
+      params.no_wchar_size_warning = 1;
       break;
 
     case OPTION_PIC_VENEER:
-      pic_veneer = 1;
+      params.pic_veneer = 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;
 
     case OPTION_FIX_CORTEX_A8:
-      fix_cortex_a8 = 1;
+      params.fix_cortex_a8 = 1;
       break;
 
     case OPTION_NO_FIX_CORTEX_A8:
-      fix_cortex_a8 = 0;
+      params.fix_cortex_a8 = 0;
       break;
 
    case OPTION_NO_MERGE_EXIDX_ENTRIES:
-      merge_exidx_entries = 0;
+      params.merge_exidx_entries = 0;
       break;
 
    case OPTION_FIX_ARM1176:
-      fix_arm1176 = 1;
+      params.fix_arm1176 = 1;
       break;
 
    case OPTION_NO_FIX_ARM1176:
-      fix_arm1176 = 0;
+      params.fix_arm1176 = 0;
+      break;
+
+   case OPTION_LONG_PLT:
+      bfd_elf32_arm_use_long_plt ();
+      break;
+
+   case OPTION_CMSE_IMPLIB:
+      params.cmse_implib = 1;
+      break;
+
+   case OPTION_IN_IMPLIB:
+      in_implib_filename = optarg;
       break;
 '
 
@@ -687,6 +778,7 @@ LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=arm_elf_create_output_section_statements
 
 # Replace the elf before_parse function with our own.
 LDEMUL_BEFORE_PARSE=gld"${EMULATION_NAME}"_before_parse
+LDEMUL_SET_SYMBOLS=gld"${EMULATION_NAME}"_set_symbols
 
 # Call the extra arm-elf function
 LDEMUL_FINISH=gld${EMULATION_NAME}_finish