public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [RFC PATCH, binutils, ARM 9/9] Add support for stable secure gateway veneers addresses
@ 2015-12-23  8:02 Thomas Preud'homme
  2016-04-04 14:23 ` [RFC PATCH, binutils, ARM 11/11] " Thomas Preudhomme
  0 siblings, 1 reply; 15+ messages in thread
From: Thomas Preud'homme @ 2015-12-23  8:02 UTC (permalink / raw)
  To: binutils

Hi,

[Posting patch series as RFC]

This patch is part of a patch series to add support for ARMv8-M security extension[1] to GNU ld. This specific patch adds support for allowing Secure Gateway veneers to have stable addresses when relinking a secure executable.

ARM v8-M security extensions allow code running in a device to be divided into secure and non-secure code expected to be developed by independent (teams of) people. To allow updating the secure code without the need to relink the non-secure code against it, it is necessary for the toolchain to provide a way to fix the addresses of the secure gateway veneers that serve as entry points for non-secure code to call secure code. This is also a requirement [2] to claim support for ARM v8-M security extensions.

This patch adds a --in-implib=<in_implib_filename> option which, when used in conjunction of --cmse-implib will ensure that the veneers whose symbols are defined in the import library $in_implib_filename will remain at the same address in the executable. In the absence of a --out-implib option, the code will warn about new secure gateway veneers being created, otherwise these are allowed.


[1] Software requirements for ARMv8-M security extension are described in document ARM-ECM-0359818 [2]
[2] Available on http://infocenter.arm.com in Developer guides and articles > Software development > ARM®v8-M Security Extensions: Requirements on Development Tools
[3] See requirement 15 of ARM-ECM-0359818 [2]

ChangeLog entries are as follow:


*** bfd/ChangeLog ***

2015-10-30  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new parameter for
        the input import library bfd.
        * bfd-in2.h: Regenerate.
        * elf32-arm.c (struct elf32_arm_link_hash_table): New in_implib_bfd
        and new_cmse_veneers_offset fields.
        (stub_hash_newfunc): Initialize stub_offset to -1.
        (elf32_arm_add_stub): Likewise.
        (arm_build_one_stub): Only allocate a stub_offset is it's -1.
        (elf32_arm_create_stub): Change stub_changed parameter into an integer
        pointer parameter cmse_stub_created to count the number of stub
        created.
        (cmse_entry_fct_p): New function.
        (arm_list_new_cmse_stub): Likewise.
        (set_cmse_veneer_addr_from_implib): Likewise.
        (elf32_arm_size_stubs): Define cmse_stub_created, pass its address to
        cmse_scan instead of that of cmse_stub_changed to compute the number
        of stub created and use it to initialize stub_changed.  Call
        set_cmse_veneer_addr_from_implib after cmse_scan.  Use
        htab->new_cmse_veneers_offset to initialize size of secure gateway
        veneers section.  Initialize stub_offset of Cortex-A8 erratum fix to
        -1.  Use ret to hold return value.
        (elf32_arm_build_stubs): Use htab->new_cmse_veneers_offset to
        initialize size of secure gateway veneers section.  Add comment to
        stress the importance of zeroing veneer section content.
        (bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd parameter to
        initialize eponymous field in struct elf32_arm_link_hash_table.


*** ld/ChangeLog ***

2015-11-02  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * emultempl/armelf.em (in_implib_filename): Declare and initialize new
        variable.
        (arm_elf_create_output_section_statements): Open import input library
        file for writing and pass resulting in_implib_bfd to
        bfd_elf32_arm_set_target_relocs.
        (PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option.
        (PARSE_AND_LIST_LONGOPTS): Define --in-implib option.
        (PARSE_AND_LIST_OPTIONS): Add help message for --in-implib option.
        (PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case.
        * ld.texinfo (--cmse-implib): Update to mention --in-implib.
        (--in-implib): Document new option.


*** ld/testsuite/ChangeLog ***

2015-10-30  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * ld-arm/arm-elf.exp (Secure gateway import library generation): add
        --defsym VER=1 to gas CLI.
        (Secure gateway import library generation: errors): Likewise.
        (Input secure gateway import library): New test.
        (Input secure gateway import library: no output import library):
        Likewise.
        (Input secure gateway import library: earlier stub section base):
        Likewise.
        (Input secure gateway import library: later stub section base):
        Likewise.
        (Input secure gateway import library: entry function change):
        Likewise.
        * ld-arm/cmse-implib.s: Add input import library testing.
        * ld-arm/cmse-implib.rd: Update accordingly.
        * ld-arm/cmse-new-implib.out: New file.
        * ld-arm/cmse-new-implib.rd: Likewise.
        * ld-arm/cmse-new-later-implib.out: Likewise.
        * ld-arm/cmse-new-wrong-implib.out: Likewise.
        * ld-arm/cmse-new-implib-no-output.out: Likewise.


diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index d4f0bf4..b12946c 100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.h
@@ -895,7 +895,7 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation
 
 void bfd_elf32_arm_set_target_relocs
   (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix,
-   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
+   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
 
 extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
   (bfd *, struct bfd_link_info *);
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 864988d..406fd6b 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -902,7 +902,7 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation
 
 void bfd_elf32_arm_set_target_relocs
   (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix,
-   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
+   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
 
 extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
   (bfd *, struct bfd_link_info *);
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 37aede1..90f1333 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -3075,6 +3075,10 @@ struct elf32_arm_link_hash_table
      as per ARMv8-M security extensions.  */
   int cmse_implib;
 
+  /* The import library whose symbols' address must remain stable in
+     the import library generated.  */
+  bfd *in_implib_bfd;
+
   /* The index of the next unused R_ARM_TLS_DESC slot in .rel.plt.  */
   bfd_vma next_tls_desc_index;
 
@@ -3136,6 +3140,10 @@ struct elf32_arm_link_hash_table
   /* Input stub section holding secure gateway veneers.  */
   asection *cmse_stub_sec;
 
+  /* Offset in cmse_stub_sec where new SG veneers (not in input import library)
+     start to be allocated.  */
+  bfd_vma new_cmse_veneers_offset;
+
   /* Number of elements in stub_group.  */
   unsigned int top_id;
 
@@ -3383,7 +3391,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
       /* Initialize the local fields.  */
       eh = (struct elf32_arm_stub_hash_entry *) entry;
       eh->stub_sec = NULL;
-      eh->stub_offset = 0;
+      eh->stub_offset = (bfd_vma) -1;
       eh->source_value = 0;
       eh->target_value = 0;
       eh->target_section = NULL;
@@ -4200,7 +4208,7 @@ elf32_arm_add_stub (const char *stub_name, asection *section,
     }
 
   stub_entry->stub_sec = stub_sec;
-  stub_entry->stub_offset = 0;
+  stub_entry->stub_offset = (bfd_vma) -1;
   stub_entry->id_sec = link_sec;
 
   return stub_entry;
@@ -4334,13 +4342,10 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
   bfd *stub_bfd;
   bfd_byte *loc;
   bfd_vma sym_value;
-  int template_size;
-  int size;
+  int i, size, template_size, just_allocated = 0, nrelocs = 0;
   const insn_sequence *template_sequence;
-  int i;
   int stub_reloc_idx[MAXRELOCS] = {-1, -1};
   int stub_reloc_offset[MAXRELOCS] = {0, 0};
-  int nrelocs = 0;
 
   /* Massage our args to the form they really have.  */
   stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
@@ -4357,8 +4362,12 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
     /* We have to do less-strictly-aligned fixes last.  */
     return TRUE;
 
-  /* Make a note of the offset within the stubs for this entry.  */
-  stub_entry->stub_offset = stub_sec->size;
+  /* Assign a slot at the end of section if none assigned yet.  */
+  if (stub_entry->stub_offset == (bfd_vma) -1)
+    {
+      stub_entry->stub_offset = stub_sec->size;
+      just_allocated = 1;
+    }
   loc = stub_sec->contents + stub_entry->stub_offset;
 
   stub_bfd = stub_sec->owner;
@@ -4432,7 +4441,8 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
 	}
     }
 
-  stub_sec->size += size;
+  if (just_allocated)
+    stub_sec->size += size;
 
   /* Stub size has already been computed in arm_size_one_stub. Check
      consistency.  */
@@ -4550,6 +4560,10 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry,
   stub_entry->stub_template = template_sequence;
   stub_entry->stub_template_size = template_size;
 
+  /* Already accounted for.  */
+  if (stub_entry->stub_offset != (bfd_vma) -1)
+    return TRUE;
+
   size = (size + 7) & ~7;
   stub_entry->stub_sec->size += size;
 
@@ -5211,15 +5225,15 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
 
 /* Scan symbols in INPUT_BFD for secure gateway veneers to create.  OUT_ATTR
    gives the output attributes, SYM_HASHES the symbol index to hash entry
-   mapping while HTAB gives the name to hash entry mapping.
+   mapping while HTAB gives the name to hash entry mapping. *CMSE_STUB_CREATED
+   is increased by the number of secure gateway veneer created.
 
-   If any secure gateway veneer is created, *STUB_CHANGED is set to TRUE.  The
-   return value gives whether a stub failed to be allocated.  */
+   The return value gives whether a stub failed to be allocated.  */
 
 static bfd_boolean
 cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
 	   obj_attribute *out_attr, struct elf_link_hash_entry **sym_hashes,
-	   bfd_boolean *stub_changed)
+	   int *cmse_stub_created)
 {
   const struct elf_backend_data *bed;
   Elf_Internal_Shdr *symtab_hdr;
@@ -5379,7 +5393,7 @@ cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
       else
 	{
 	  BFD_ASSERT (new_stub);
-	  *stub_changed = TRUE;
+	  (*cmse_stub_created)++;
 	}
     }
 
@@ -5388,6 +5402,246 @@ cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
   return ret;
 }
 
+/* Return whether a symbol identified by its linker HASH entry is an entry
+   function, ie can be called from non secure code without using a veneer.  */
+
+static bfd_boolean
+cmse_entry_fct_p (struct elf32_arm_link_hash_entry *hash)
+{
+  uint32_t first_insn;
+  asection *section;
+  file_ptr offset;
+  bfd *abfd;
+
+  /* Defined symbol of function type.  */
+  if (hash->root.root.type != bfd_link_hash_defined
+      && hash->root.root.type != bfd_link_hash_defweak)
+    return FALSE;
+  if (hash->root.type != STT_FUNC)
+    return FALSE;
+
+  /* Read first instruction.  */
+  section = hash->root.root.u.def.section;
+  abfd = section->owner;
+  offset = hash->root.root.u.def.value - section->vma;
+  if (!bfd_get_section_contents (abfd, section, &first_insn, offset,
+				 sizeof (first_insn)))
+    return FALSE;
+
+  /* Start by SG instruction.  */
+  return first_insn == 0xe97fe97f;
+}
+
+/* Output the name (in symbol table) of the veneer GEN_ENTRY if it is a new
+   secure gateway veneers (ie. the veneers was not in the input import library)
+   and there is no output import library (GEN_INFO->out_implib_bfd is NULL.  */
+
+static bfd_boolean
+arm_list_new_cmse_stub (struct bfd_hash_entry *gen_entry, void *gen_info)
+{
+  struct elf32_arm_stub_hash_entry *stub_entry;
+  struct bfd_link_info *info;
+
+  /* Massage our args to the form they really have.  */
+  stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
+  info = (struct bfd_link_info *) gen_info;
+
+  if (info->out_implib_bfd)
+    return TRUE;
+
+  if (stub_entry->stub_type != arm_stub_cmse_branch_thumb_only)
+    return TRUE;
+
+  if (stub_entry->stub_offset == (bfd_vma) -1)
+    (*_bfd_error_handler) ("  %s", stub_entry->output_name);
+
+  return TRUE;
+}
+
+/* Set offset of secure gateway veneers so that their address remain identical
+   to the one in the input import library referred by HTAB->in_implib_bfd.  A
+   warning is issued for veneers that disappeared (present in input import
+   library but absent from the executable being linked) or if new veneers
+   appeared and there is no output import library (INFO->out_implib_bfd is NULL
+   and CMSE_STUB_CREATED is bigger than the number of secure gateway veneers
+   found in the input import library.
+
+   The function returns whether an error occured and
+   HTAB->new_cmse_veneers_offset is set to the biggest veneer observed set for
+   new veneers to be layed out after.  */
+
+static bfd_boolean
+set_cmse_veneer_addr_from_implib (struct bfd_link_info *info,
+				  struct elf32_arm_link_hash_table *htab,
+				  int cmse_stub_created)
+{
+  long symsize;
+  char *sym_name;
+  flagword flags;
+  long i, symcount;
+  bfd *in_implib_bfd;
+  bfd_boolean ret = TRUE;
+  Elf_Internal_Sym *intsym;
+  int cmse_stub_template_size;
+  bfd_size_type cmse_stub_size;
+  asymbol **sympp = NULL, *sym;
+  asection *cmse_stub_out_sec;
+  struct elf32_arm_link_hash_entry *hash;
+  const insn_sequence *cmse_stub_template;
+  struct elf32_arm_stub_hash_entry *stub_entry;
+  bfd_vma veneer_value, stub_offset, new_cmse_veneers_offset, stub_sec_vma = 0;
+
+  /* No input secure gateway import library.  */
+  if (!htab->in_implib_bfd)
+    return TRUE;
+  else if (!htab->cmse_implib)
+    return FALSE;
+
+  /* Get symbol table size.  */
+  in_implib_bfd = htab->in_implib_bfd;
+  symsize = bfd_get_symtab_upper_bound (in_implib_bfd);
+  if (symsize < 0)
+    return FALSE;
+
+  /* Read in the input secure gateway import library's symbol table.  */
+  sympp = (asymbol **) xmalloc (symsize);
+  symcount = bfd_canonicalize_symtab (in_implib_bfd, sympp);
+  if (symcount < 0)
+    {
+      ret = FALSE;
+      goto free_sym_buf;
+    }
+
+  htab->new_cmse_veneers_offset = 0;
+  cmse_stub_size =
+    find_stub_size_and_template (arm_stub_cmse_branch_thumb_only,
+				 &cmse_stub_template,
+				 &cmse_stub_template_size);
+  cmse_stub_out_sec =
+    bfd_get_section_by_name (htab->obfd, CMSE_STUB_OUT_SEC_NAME);
+  if (cmse_stub_out_sec == NULL)
+    {
+      (*_bfd_error_handler) (_("No address assigned to the secure gateway "
+			       "veneers output section %s"),
+			       CMSE_STUB_OUT_SEC_NAME);
+      stub_sec_vma = 0;
+      ret = FALSE;
+    }
+  else
+    stub_sec_vma = cmse_stub_out_sec->vma;
+
+  /* Set addresses of veneers mentionned in input secure gateway import
+     library's symbol table.  */
+  for (i = 0; i < symcount; i++)
+    {
+      sym = sympp[i];
+      flags = sym->flags;
+      intsym = &((elf_symbol_type *) sym)->internal_elf_sym;
+
+      if (sym->section != bfd_abs_section_ptr
+	  || !(flags & (BSF_GLOBAL | BSF_WEAK))
+	  || (flags & BSF_FUNCTION) != BSF_FUNCTION
+	  || (ARM_GET_SYM_BRANCH_TYPE (intsym->st_target_internal)
+	      != ST_BRANCH_TO_THUMB))
+	{
+	  (*_bfd_error_handler) (_("%B: invalid import library entry: `%s'."),
+				 in_implib_bfd, sym_name);
+	  (*_bfd_error_handler) (_("Symbol should be absolute, global and "
+				   "refer to Thumb functions."));
+	  ret = FALSE;
+	  continue;
+	}
+
+      sym_name = (char *) bfd_asymbol_name (sym);
+      veneer_value = bfd_asymbol_value (sym);
+      stub_offset = veneer_value - stub_sec_vma;
+      stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, sym_name,
+					 FALSE, FALSE);
+      hash = (struct elf32_arm_link_hash_entry *)
+	elf_link_hash_lookup (&(htab)->root, sym_name, FALSE, FALSE, TRUE);
+
+      /* Stub entry should have been created by cmse_scan or the symbol be of
+	 a secure function callable from non secure code.  */
+      if (!stub_entry && !hash)
+	(*_bfd_error_handler)
+	  (_("Entry function `%s' disappeared from secure code."), sym_name);
+      /* Symbol found is not callable from non secure code.  */
+      else if (!stub_entry)
+	{
+	  if (!cmse_entry_fct_p (hash))
+	    {
+	      (*_bfd_error_handler) (_("`%s' refers to a non entry function."),
+				     sym_name);
+	      ret = FALSE;
+	    }
+	  continue;
+	}
+      else
+	{
+	  /* Only stub for SG veneers should have been created.  */
+	  BFD_ASSERT (stub_entry->stub_type == arm_stub_cmse_branch_thumb_only);
+
+	  /* Check visibility hasn't changed.  */
+	  if (!!(flags & BSF_GLOBAL)
+	      != (hash->root.root.type == bfd_link_hash_defined))
+	    (*_bfd_error_handler)
+	      (_("%B: visibility of symbol `%s' has changed."), in_implib_bfd,
+	       sym_name);
+
+	  stub_entry->stub_offset = stub_offset;
+	}
+
+      /* Size should match that of a SG veneer.  */
+      if (intsym->st_size != cmse_stub_size)
+	{
+	  (*_bfd_error_handler) (_("%B: incorrect size for symbol `%s'."),
+				 in_implib_bfd, sym_name);
+	  ret = FALSE;
+	}
+
+      /* Previous veneer address is before current SG veneer section.  */
+      if (veneer_value < stub_sec_vma)
+	{
+	  (*_bfd_error_handler)
+	    (_("Veneer for entry function `%s' before veneer section start."),
+	     sym_name);
+	  if (stub_entry)
+	    stub_entry->stub_offset = 0; /* Avoid offset underflow.  */
+	  ret = FALSE;
+	}
+
+      /* Complain if stub offset not a multiple of stub size.  */
+      if (stub_offset % cmse_stub_size)
+	{
+	  (*_bfd_error_handler)
+	    (_("Offset of veneer for entry function `%s' not a multiple of "
+	       "its size."), sym_name);
+	  ret = FALSE;
+	}
+
+      if (!ret)
+	continue;
+
+      cmse_stub_created--;
+      new_cmse_veneers_offset = stub_offset + ((cmse_stub_size + 7) & ~7);
+      if (new_cmse_veneers_offset > htab->new_cmse_veneers_offset)
+	htab->new_cmse_veneers_offset = new_cmse_veneers_offset;
+    }
+
+  if (!info->out_implib_bfd && cmse_stub_created != 0)
+    {
+      BFD_ASSERT (cmse_stub_created > 0);
+      (*_bfd_error_handler)
+	(_("new entry function(s) introduced but no output import library "
+	   "specified:"));
+      bfd_hash_traverse (&htab->stub_hash_table, arm_list_new_cmse_stub, info);
+    }
+
+free_sym_buf:
+  free (sympp);
+  return ret;
+}
+
 /* Determine and set the size of the stub section for a final link.
 
    The basic idea here is to examine all the relocations looking for
@@ -5404,9 +5658,10 @@ elf32_arm_size_stubs (bfd *output_bfd,
 						      unsigned int),
 		      void (*layout_sections_again) (void))
 {
+  int cmse_stub_created = 0;
   obj_attribute *out_attr;
   bfd_size_type stub_group_size;
-  bfd_boolean stubs_always_after_branch, cmse_stub_changed = FALSE;
+  bfd_boolean stubs_always_after_branch, ret = TRUE;
   struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
   struct a8_erratum_fix *a8_fixes = NULL;
   unsigned int num_a8_fixes = 0, a8_fix_table_size = 10;
@@ -5449,9 +5704,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
 	  struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
 
 	  if (!cmse_scan (input_bfd, htab, out_attr, sym_hashes,
-			  &cmse_stub_changed))
+			  &cmse_stub_created))
 	    goto error_ret_free_local;
 	}
+      if (!set_cmse_veneer_addr_from_implib (info, htab, cmse_stub_created))
+	ret = FALSE;
     }
 
   /* The Cortex-A8 erratum fix depends on stubs not being in the same 4K page
@@ -5496,11 +5753,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
       bfd *input_bfd;
       unsigned int bfd_indx;
       asection *stub_sec;
-      bfd_boolean stub_changed = cmse_stub_changed;
+      bfd_boolean stub_changed = cmse_stub_created != 0;
       unsigned prev_num_a8_fixes = num_a8_fixes;
 
       num_a8_fixes = 0;
-      cmse_stub_changed = FALSE;
+      cmse_stub_created = 0;
       for (input_bfd = info->input_bfds, bfd_indx = 0;
 	   input_bfd != NULL;
 	   input_bfd = input_bfd->link.next, bfd_indx++)
@@ -5851,7 +6108,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
 	  if (!strstr (stub_sec->name, STUB_SUFFIX))
 	    continue;
 
-	  stub_sec->size = 0;
+	  /* Append new SG veneers after those in input import library.  */
+	  if (stub_sec == htab->cmse_stub_sec)
+	    stub_sec->size = htab->new_cmse_veneers_offset;
+	  else
+	    stub_sec->size = 0;
 	}
 
       bfd_hash_traverse (&htab->stub_hash_table, arm_size_one_stub, htab);
@@ -5908,7 +6169,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
 	    }
 
 	  stub_entry->stub_sec = stub_sec;
-	  stub_entry->stub_offset = 0;
+	  stub_entry->stub_offset = (bfd_vma) -1;
 	  stub_entry->id_sec = link_sec;
 	  stub_entry->stub_type = a8_fixes[i].stub_type;
 	  stub_entry->source_value = a8_fixes[i].offset;
@@ -5936,7 +6197,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
       htab->a8_erratum_fixes = NULL;
       htab->num_a8_erratum_fixes = 0;
     }
-  return TRUE;
+  return ret;
 
  error_ret_free_local:
   return FALSE;
@@ -5969,12 +6230,19 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
       if (!strstr (stub_sec->name, STUB_SUFFIX))
 	continue;
 
-      /* Allocate memory to hold the linker stubs.  */
+      /* Allocate memory to hold the linker stubs.  Zeroing the stub section
+	 ensures that a non secure application branching to a removed SG veneer
+	 will cause an error.  */
       size = stub_sec->size;
       stub_sec->contents = (unsigned char *) bfd_zalloc (htab->stub_bfd, size);
       if (stub_sec->contents == NULL && size != 0)
 	return FALSE;
-      stub_sec->size = 0;
+
+      /* Append new SG veneers after those in input import library.  */
+      if (stub_sec == htab->cmse_stub_sec)
+	stub_sec->size = htab->new_cmse_veneers_offset;
+      else
+	stub_sec->size = 0;
     }
 
   /* Build the stubs as directed by the stub hash table.  */
@@ -7940,7 +8208,8 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd,
 				 bfd_arm_stm32l4xx_fix stm32l4xx_fix,
 				 int no_enum_warn, int no_wchar_warn,
 				 int pic_veneer, int fix_cortex_a8,
-				 int fix_arm1176, int cmse_implib)
+				 int fix_arm1176, int cmse_implib,
+				 bfd *in_implib_bfd)
 {
   struct elf32_arm_link_hash_table *globals;
 
@@ -7968,6 +8237,7 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd,
   globals->fix_cortex_a8 = fix_cortex_a8;
   globals->fix_arm1176 = fix_arm1176;
   globals->cmse_implib = cmse_implib;
+  globals->in_implib_bfd = in_implib_bfd;
 
   BFD_ASSERT (is_arm_elf (output_bfd));
   elf_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
index ec6dca2..0e4d1bd 100644
--- a/ld/emultempl/armelf.em
+++ b/ld/emultempl/armelf.em
@@ -43,6 +43,7 @@ static int pic_veneer = 0;
 static int merge_exidx_entries = -1;
 static int fix_arm1176 = 1;
 static int cmse_implib = 0;
+static char *in_implib_filename = NULL;
 
 static void
 gld${EMULATION_NAME}_before_parse (void)
@@ -495,6 +496,8 @@ gld${EMULATION_NAME}_finish (void)
 static void
 arm_elf_create_output_section_statements (void)
 {
+  bfd *in_implib_bfd;
+
   if (strstr (bfd_get_target (link_info.output_bfd), "arm") == NULL)
     {
       /* The arm backend needs special fields in the output hash structure.
@@ -505,6 +508,20 @@ arm_elf_create_output_section_statements (void)
       return;
     }
 
+  if (in_implib_filename)
+    {
+      in_implib_bfd = bfd_openr (in_implib_filename,
+				 bfd_get_target (link_info.output_bfd));
+
+      if (in_implib_bfd == NULL)
+	einfo ("%F%s: Can't open: %E\n", in_implib_filename);
+
+      if (!bfd_check_format (in_implib_bfd, bfd_object))
+	einfo ("%F%s: Not a relocatable file: %E\n", in_implib_filename);
+    }
+  else
+    in_implib_bfd = NULL;
+
   bfd_elf32_arm_set_target_relocs (link_info.output_bfd, &link_info,
 				   target1_is_rel,
 				   target2_type, fix_v4bx, use_blx,
@@ -512,7 +529,7 @@ arm_elf_create_output_section_statements (void)
 				   no_enum_size_warning,
 				   no_wchar_size_warning,
 				   pic_veneer, fix_cortex_a8,
-				   fix_arm1176, cmse_implib);
+				   fix_arm1176, cmse_implib, in_implib_bfd);
 
   stub_file = lang_add_input_file ("linker stubs",
  				   lang_input_file_is_fake_enum,
@@ -582,6 +599,7 @@ PARSE_AND_LIST_PROLOGUE='
 #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
@@ -609,6 +627,7 @@ PARSE_AND_LIST_LONGOPTS='
   { "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='
@@ -631,6 +650,8 @@ PARSE_AND_LIST_OPTIONS='
            "                              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\
@@ -755,6 +776,10 @@ PARSE_AND_LIST_ARGS_CASES='
    case OPTION_CMSE_IMPLIB:
       cmse_implib = 1;
       break;
+
+   case OPTION_IN_IMPLIB:
+      in_implib_filename = optarg;
+      break;
 '
 
 # We have our own before_allocation etc. functions, but they call
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 234716b..851c7fa 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -6806,10 +6806,20 @@ entries which only support 512Mb of code.
 
 @kindex --cmse-implib
 @cindex Secure gateway import library
-The @samp{--cmse-implib} option requests that the import library
-specified by @samp{--out-implib} option is a secure gateway import
-library, suitable for linking a non-secure executable against secure
-code as per ARMv8-M security extensions.
+The @samp{--cmse-implib} option requests that the import libraries
+specified by the @samp{--out-implib} and @samp{--in-implib} options are
+secure gateway import libraries, suitable for linking a non-secure
+executable against secure code as per ARMv8-M security extensions.
+
+@kindex --in-implib
+@cindex Input import library
+The @samp{--in-implib} option specifies an import library whose symbols
+must keep the same address in the executable being produced.  A warning
+is given if @samp{--out-implib} is not specified but new symbols would
+end up in the output import library if it was.  Otherwise, if
+@samp{--out-implib} is specified, the symbols are silently added to the
+output import library.  This option is only effective for Secure
+Gateway import libraries, ie. when @samp{--cmse-implib} is specified.
 
 @ifclear GENERIC
 @lowersections
diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
index 95b8881..5c6de60 100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -607,16 +607,48 @@ set armeabitests_nonacl {
      "cmse-veneers-mainline"}
     {"Secure gateway import library generation: errors"
      "--section-start .sgstubs=0x20000 --out-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
-     "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1"
+     "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1 --defsym VER=1"
      {cmse-implib.s}
      {{ld cmse-implib-errors.out}}
      "cmse-implib"}
     {"Secure gateway import library generation"
      "--section-start .sgstubs=0x20000 --out-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
-     "-march=armv8-m.base -mthumb"
+     "-march=armv8-m.base -mthumb --defsym VER=1"
      {cmse-implib.s}
      {{readelf {-s tmpdir/cmse-implib.lib} cmse-implib.rd}}
      "cmse-implib"}
+    {"Input secure gateway import library"
+     "--section-start .sgstubs=0x20000 --out-implib=tmpdir/cmse-new-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=2"
+     {cmse-implib.s}
+     {{ld cmse-new-implib.out}
+      {readelf {-s tmpdir/cmse-new-implib.lib} cmse-new-implib.rd}}
+     "cmse-new-implib"}
+    {"Input secure gateway import library: no output import library"
+     "--section-start .sgstubs=0x20000 --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=2"
+     {cmse-implib.s}
+     {{ld cmse-new-implib-no-output.out}}
+     "cmse-new-implib-no-output"}
+    {"Input secure gateway import library: earlier stub section base"
+     "--section-start .sgstubs=0x19000 --out-implib=tmpdir/cmse-new-earlier-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=2"
+     {cmse-implib.s}
+     {{ld cmse-new-implib.out}
+      {readelf {-s tmpdir/cmse-new-earlier-implib.lib} cmse-new-implib.rd}}
+     "cmse-new-earlier-implib"}
+    {"Input secure gateway import library: later stub section base"
+     "--section-start .sgstubs=0x30000 --out-implib=tmpdir/cmse-new-later-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=2"
+     {cmse-implib.s}
+     {{ld cmse-new-later-implib.out}}
+     "cmse-new-later-implib"}
+    {"Input secure gateway import library: entry function change"
+     "--section-start .sgstubs=0x20000 --out-implib=tmpdir/cmse-new-wrong-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=3"
+     {cmse-implib.s}
+     {{ld cmse-new-wrong-implib.out}}
+     "cmse-new-wrong-implib"}
 
     {"R_ARM_THM_JUMP19 Relocation veneers: Short"
      "--section-start destsect=0x000108002 --section-start .text=0x8000" ""
diff --git a/ld/testsuite/ld-arm/cmse-implib.rd b/ld/testsuite/ld-arm/cmse-implib.rd
index 8b11637..c5f7aef 100644
--- a/ld/testsuite/ld-arm/cmse-implib.rd
+++ b/ld/testsuite/ld-arm/cmse-implib.rd
@@ -1,11 +1,12 @@
 File: tmpdir/cmse-implib.lib
 
-Symbol table '.symtab' contains 4 entries:
+Symbol table '.symtab' contains 5 entries:
    Num:    Value  Size Type    Bind   Vis      Ndx Name
      0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
-     1: 00020001     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer1
-     2: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct
+     1: 00020001     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer3
+     2: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
      3: 00020009     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer2
+     4: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
 
 File: tmpdir/cmse-implib
 
diff --git a/ld/testsuite/ld-arm/cmse-implib.s b/ld/testsuite/ld-arm/cmse-implib.s
index 99fa90c..a841130 100644
--- a/ld/testsuite/ld-arm/cmse-implib.s
+++ b/ld/testsuite/ld-arm/cmse-implib.s
@@ -1,17 +1,17 @@
 	.syntax unified
 	.text
 
-.macro	entry	name, entry_fct
+.macro	entry	name, vis, entry_fct
 	.align	2
-	.global	\name
-	.global	__acle_se_\name
+	.\vis	\name
+	.\vis	__acle_se_\name
 	.thumb
 	.thumb_func
 	.type	\name, %function
 	.type	__acle_se_\name, %function
 \name:
 .ifnb \entry_fct
-	sg
+	\entry_fct
 .endif
 __acle_se_\name:
 	nop
@@ -20,11 +20,28 @@ __acle_se_\name:
 .endm
 
 	@ Valid setups for veneer generation
-	entry exported_entry_veneer1
-	entry exported_entry_veneer2
+.if (VER >= 2)
+	entry exported_entry_veneer1, global
+.endif
+.if (VER < 3)
+	entry exported_entry_veneer2, global
+.else
+	entry exported_entry_veneer2, weak
+.endif
+.if (VER == 1)
+	entry exported_entry_veneer3, global
+.else
+	entry exported_entry_veneer4, global
+.endif
 
 	@ Valid setup for entry function without veneer generation
-	entry exported_entry_fct, entry_fct
+	entry exported_entry_fct1, global, sg
+.if (VER < 3)
+	entry exported_entry_fct2, global, sg
+.else
+	@ Invalid setup for entry function without veneer generation
+	entry exported_entry_fct2, global, nop
+.endif
 
 	@ Normal symbol not exported to SG import library
 	.align	2
diff --git a/ld/testsuite/ld-arm/cmse-new-implib-no-output.out b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
new file mode 100644
index 0000000..0590b71
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
@@ -0,0 +1,4 @@
+.*: Entry function `exported_entry_veneer3' disappeared from secure code.
+.*: new entry function\(s\) introduced but no output import library specified:
+.*:   exported_entry_veneer4
+.*:   exported_entry_veneer1
diff --git a/ld/testsuite/ld-arm/cmse-new-implib.out b/ld/testsuite/ld-arm/cmse-new-implib.out
new file mode 100644
index 0000000..c8af280
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-implib.out
@@ -0,0 +1 @@
+.*: Entry function `exported_entry_veneer3' disappeared from secure code.
diff --git a/ld/testsuite/ld-arm/cmse-new-implib.rd b/ld/testsuite/ld-arm/cmse-new-implib.rd
new file mode 100644
index 0000000..9ff0fd8
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-implib.rd
@@ -0,0 +1,14 @@
+File: tmpdir/cmse-new-.*implib.lib
+
+Symbol table '.symtab' contains 6 entries:
+   Num:    Value  Size Type    Bind   Vis      Ndx Name
+     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
+     1: 00020011     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer4
+     2: 00020019     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer1
+     3: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
+     4: 00020009     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer2
+     5: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
+
+File: tmpdir/cmse-new-.*implib
+
+#...
diff --git a/ld/testsuite/ld-arm/cmse-new-later-implib.out b/ld/testsuite/ld-arm/cmse-new-later-implib.out
new file mode 100644
index 0000000..9652759
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-later-implib.out
@@ -0,0 +1,4 @@
+.*: Entry function `exported_entry_veneer3' disappeared from secure code.
+.*: Veneer for entry function `exported_entry_veneer3' before veneer section start.
+.*: Veneer for entry function `exported_entry_veneer2' before veneer section start.
+.*: cannot size stub section: Invalid operation
diff --git a/ld/testsuite/ld-arm/cmse-new-wrong-implib.out b/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
new file mode 100644
index 0000000..95733b2
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
@@ -0,0 +1,4 @@
+.*: Entry function `exported_entry_veneer3' disappeared from secure code.
+.*: .*: visibility of symbol `exported_entry_veneer2' has changed.
+.*: `exported_entry_fct2' refers to a non entry function.
+.*: cannot size stub section: Invalid operation


The patch doesn't show any regression when running the binutils-gdb testsuite for the arm-none-eabi target.

Any comments?

Best regards,

Thomas

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ARM 11/11] Add support for stable secure gateway veneers addresses
  2015-12-23  8:02 [RFC PATCH, binutils, ARM 9/9] Add support for stable secure gateway veneers addresses Thomas Preud'homme
@ 2016-04-04 14:23 ` Thomas Preudhomme
  2016-05-18 16:41   ` [PATCH, " Thomas Preudhomme
  2016-07-07 12:52   ` [RFC PATCH, " Richard Earnshaw (lists)
  0 siblings, 2 replies; 15+ messages in thread
From: Thomas Preudhomme @ 2016-04-04 14:23 UTC (permalink / raw)
  To: binutils

On Wednesday 23 December 2015 16:02:48 Thomas Preud'homme wrote:
> Hi,
> 
> [Posting patch series as RFC]
> 
> This patch is part of a patch series to add support for ARMv8-M security
> extension[1] to GNU ld. This specific patch adds support for allowing
> Secure Gateway veneers to have stable addresses when relinking a secure
> executable.
> 
> ARM v8-M security extensions allow code running in a device to be divided
> into secure and non-secure code expected to be developed by independent
> (teams of) people. To allow updating the secure code without the need to
> relink the non-secure code against it, it is necessary for the toolchain to
> provide a way to fix the addresses of the secure gateway veneers that serve
> as entry points for non-secure code to call secure code. This is also a
> requirement [2] to claim support for ARM v8-M security extensions.
> 
> This patch adds a --in-implib=<in_implib_filename> option which, when used
> in conjunction of --cmse-implib will ensure that the veneers whose symbols
> are defined in the import library $in_implib_filename will remain at the
> same address in the executable. In the absence of a --out-implib option,
> the code will warn about new secure gateway veneers being created,
> otherwise these are allowed.
> 
> 
> [1] Software requirements for ARMv8-M security extension are described in
> document ARM-ECM-0359818 [2] [2] Available on http://infocenter.arm.com in
> Developer guides and articles > Software development > ARM®v8-M Security
> Extensions: Requirements on Development Tools [3] See requirement 15 of
> ARM-ECM-0359818 [2]

Please find an updated patch below.

*** bfd/ChangeLog ***

2016-02-18  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new parameter for
        the input import library bfd.
        * bfd-in2.h: Regenerate.
        * elf32-arm.c (struct elf32_arm_link_hash_table): New in_implib_bfd
        and new_cmse_stub_offset fields.
        (stub_hash_newfunc): Initialize stub_offset and stub_template_size to
        -1.
        (elf32_arm_add_stub): Likewise for stub_offset.
        (arm_new_stubs_start_offset_ptr): New function.
        (arm_build_one_stub): Only allocate a stub_offset if it is -1.  Allow
        empty veneers to have zero relocations.
        (arm_size_one_stub): Only initialize stub size and template
        information for non empty veneers.  Do not update veneer section size
        if veneer already has an offset.
        (elf32_arm_create_stub): Return the stub entry pointer or NULL instead
        of a boolean indicating success or failure.
        (cmse_scan): Change stub_changed parameter into an integer pointer
        parameter cmse_stub_created to count the number of stub created and
        adapt to change of return value in elf32_arm_create_stub.
        (cmse_entry_fct_p): New function.
        (arm_list_new_cmse_stub): Likewise.
        (set_cmse_veneer_addr_from_implib): Likewise.
        (elf32_arm_size_stubs): Define cmse_stub_created, pass its address to
        cmse_scan instead of that of cmse_stub_changed to compute the number
        of stub created and use it to initialize stub_changed.  Call
        set_cmse_veneer_addr_from_implib after all cmse_scan.  Adapt to change
        of return value in elf32_arm_create_stub.  Use
        arm_stub_section_start_offset () if not NULL to initialize size of
        secure gateway veneers section.  Initialize stub_offset of Cortex-A8
        erratum fix to -1.  Use ret to hold return value.
        (elf32_arm_build_stubs): Use arm_stub_section_start_offset () if not
        NULL to initialize size of secure gateway veneers section.  Adapt
        comment to stress the importance of zeroing veneer section content.
        (bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd parameter to
        initialize eponymous field in struct elf32_arm_link_hash_table.


*** ld/ChangeLog ***

2016-02-18  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * emultempl/armelf.em (in_implib_filename): Declare and initialize new
        variable. 
        (arm_elf_create_output_section_statements): Open import input library
        file for writing and pass resulting in_implib_bfd to
        bfd_elf32_arm_set_target_relocs.
        (PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option.
        (PARSE_AND_LIST_LONGOPTS): Define --in-implib option.
        (PARSE_AND_LIST_OPTIONS): Add help message for --in-implib option.
        (PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case.
        * ld.texinfo (--cmse-implib): Update to mention --in-implib.
        (--in-implib): Document new option.
        * testsuite/ld-arm/arm-elf.exp
        (Secure gateway import library generation): add --defsym VER=1 to gas
        CLI.
        (Secure gateway import library generation: errors): Likewise.
        (Input secure gateway import library): New test.
        (Input secure gateway import library: no output import library):
        Likewise. 
        (Input secure gateway import library: earlier stub section base):
        Likewise.
        (Input secure gateway import library: later stub section base):
        Likewise.
        (Input secure gateway import library: veneer comeback): Likewise.
        (Input secure gateway import library: entry function change): 
        Likewise.
        * testsuite/ld-arm/cmse-implib.s: Add input import library testing.
        * testsuite/ld-arm/cmse-implib.rd: Update accordingly.
        * testsuite/ld-arm/cmse-new-implib.out: New file.
        * testsuite/ld-arm/cmse-new-implib.rd: Likewise.
        * testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise.
        * testsuite/ld-arm/cmse-new-earlier-later-implib.out: Likewise.
        * testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise.
        * testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise.


diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index 
7e3483b9984b04c534e53f2f9026abf26d37592a..423c534a954c541e227e731e9256f08f9fa62014 
100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.h
@@ -895,7 +895,7 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation
 
 void bfd_elf32_arm_set_target_relocs
   (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix,
-   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
+   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
 
 extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
   (bfd *, struct bfd_link_info *);
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 
55e1cdde2d0a899238a224c6915d20197b72f085..3a67fa637f5c709cddf3767496e4ac8796287765 
100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -902,7 +902,7 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation
 
 void bfd_elf32_arm_set_target_relocs
   (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix,
-   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
+   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
 
 extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
   (bfd *, struct bfd_link_info *);
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 
0357fdab5cc77c3b0e983d1cb9b0285753bd5c65..be1d7224148f95bf097bb3fea63de2081f93aab9 
100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -3127,6 +3127,10 @@ struct elf32_arm_link_hash_table
      as per ARMv8-M Security Extensions.  */
   int cmse_implib;
 
+  /* The import library whose symbols' address must remain stable in
+     the import library generated.  */
+  bfd *in_implib_bfd;
+
   /* The index of the next unused R_ARM_TLS_DESC slot in .rel.plt.  */
   bfd_vma next_tls_desc_index;
 
@@ -3188,6 +3192,10 @@ struct elf32_arm_link_hash_table
   /* Input stub section holding secure gateway veneers.  */
   asection *cmse_stub_sec;
 
+  /* Offset in cmse_stub_sec where new SG veneers (not in input import 
library)
+     start to be allocated.  */
+  bfd_vma new_cmse_stub_offset;
+
   /* Number of elements in stub_group.  */
   unsigned int top_id;
 
@@ -3439,7 +3447,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
       /* Initialize the local fields.  */
       eh = (struct elf32_arm_stub_hash_entry *) entry;
       eh->stub_sec = NULL;
-      eh->stub_offset = 0;
+      eh->stub_offset = (bfd_vma) -1;
       eh->source_value = 0;
       eh->target_value = 0;
       eh->target_section = NULL;
@@ -3447,7 +3455,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
       eh->stub_type = arm_stub_none;
       eh->stub_size = 0;
       eh->stub_template = NULL;
-      eh->stub_template_size = 0;
+      eh->stub_template_size = -1;
       eh->h = NULL;
       eh->id_sec = NULL;
       eh->output_name = NULL;
@@ -4361,7 +4369,7 @@ elf32_arm_add_stub (const char *stub_name, asection 
*section,
     }
 
   stub_entry->stub_sec = stub_sec;
-  stub_entry->stub_offset = 0;
+  stub_entry->stub_offset = (bfd_vma) -1;
   stub_entry->id_sec = link_sec;
 
   return stub_entry;
@@ -4525,6 +4533,46 @@ arm_dedicated_stub_section_padding (enum 
elf32_arm_stub_type stub_type)
   abort ();  /* Should be unreachable.  */
 }
 
+/* If veneers of type STUB_TYPE should go in a dedicated output section,
+   returns the address of the hash table field in HTAB holding the offset at
+   which new veneers should be layed out in the stub section.  */
+
+static bfd_vma*
+arm_new_stubs_start_offset_ptr (struct elf32_arm_link_hash_table *htab,
+				enum elf32_arm_stub_type stub_type)
+{
+  switch (stub_type)
+    {
+    case arm_stub_a8_veneer_b_cond:
+    case arm_stub_a8_veneer_b:
+    case arm_stub_a8_veneer_bl:
+    case arm_stub_long_branch_any_any:
+    case arm_stub_long_branch_v4t_arm_thumb:
+    case arm_stub_long_branch_thumb_only:
+    case arm_stub_long_branch_v4t_thumb_thumb:
+    case arm_stub_long_branch_v4t_thumb_arm:
+    case arm_stub_short_branch_v4t_thumb_arm:
+    case arm_stub_long_branch_any_arm_pic:
+    case arm_stub_long_branch_any_thumb_pic:
+    case arm_stub_long_branch_v4t_thumb_thumb_pic:
+    case arm_stub_long_branch_v4t_arm_thumb_pic:
+    case arm_stub_long_branch_v4t_thumb_arm_pic:
+    case arm_stub_long_branch_thumb_only_pic:
+    case arm_stub_long_branch_any_tls_pic:
+    case arm_stub_long_branch_v4t_thumb_tls_pic:
+    case arm_stub_a8_veneer_blx:
+    case arm_stub_long_branch_arm_nacl:
+    case arm_stub_long_branch_arm_nacl_pic:
+      return NULL;
+
+    case arm_stub_cmse_branch_thumb_only:
+      return &htab->new_cmse_stub_offset;
+
+    default:
+      abort ();  /* Should be unreachable.  */
+    }
+}
+
 static bfd_boolean
 arm_build_one_stub (struct bfd_hash_entry *gen_entry,
 		    void * in_arg)
@@ -4544,6 +4592,7 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
   int stub_reloc_idx[MAXRELOCS] = {-1, -1};
   int stub_reloc_offset[MAXRELOCS] = {0, 0};
   int nrelocs = 0;
+  int just_allocated = 0;
 
   /* Massage our args to the form they really have.  */
   stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
@@ -4560,8 +4609,12 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
     /* We have to do less-strictly-aligned fixes last.  */
     return TRUE;
 
-  /* Make a note of the offset within the stubs for this entry.  */
-  stub_entry->stub_offset = stub_sec->size;
+  /* Assign a slot at the end of section if none assigned yet.  */
+  if (stub_entry->stub_offset == (bfd_vma) -1)
+    {
+      stub_entry->stub_offset = stub_sec->size;
+      just_allocated = 1;
+    }
   loc = stub_sec->contents + stub_entry->stub_offset;
 
   stub_bfd = stub_sec->owner;
@@ -4635,7 +4688,8 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
 	}
     }
 
-  stub_sec->size += size;
+  if (just_allocated)
+    stub_sec->size += size;
 
   /* Stub size has already been computed in arm_size_one_stub. Check
      consistency.  */
@@ -4647,7 +4701,7 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
 
   /* Assume there is at least one and at most MAXRELOCS entries to relocate
      in each stub.  */
-  BFD_ASSERT (nrelocs != 0 && nrelocs <= MAXRELOCS);
+  BFD_ASSERT (size == 0 || (nrelocs != 0 && nrelocs <= MAXRELOCS));
 
   for (i = 0; i < nrelocs; i++)
     {
@@ -4749,9 +4803,17 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry,
   size = find_stub_size_and_template (stub_entry->stub_type, 
&template_sequence,
 				      &template_size);
 
-  stub_entry->stub_size = size;
-  stub_entry->stub_template = template_sequence;
-  stub_entry->stub_template_size = template_size;
+  /* Initialized to -1.  Null size indicates a zeroed out veneer.  */
+  if (stub_entry->stub_template_size)
+    {
+      stub_entry->stub_size = size;
+      stub_entry->stub_template = template_sequence;
+      stub_entry->stub_template_size = template_size;
+    }
+
+  /* Already accounted for.  */
+  if (stub_entry->stub_offset != (bfd_vma) -1)
+    return TRUE;
 
   size = (size + 7) & ~7;
   stub_entry->stub_sec->size += size;
@@ -5316,10 +5378,10 @@ cortex_a8_erratum_scan (bfd *input_bfd,
    and *NEW_STUB is set to FALSE.  Otherwise, *NEW_STUB is set to
    TRUE and the stub entry is initialized.
 
-   Returns whether the stub could be successfully created or updated, or 
FALSE
-   if an error occured.  */
+   Returns the stub that was created or updated, or NULL if an error
+   occured.  */
 
-static bfd_boolean
+static struct elf32_arm_stub_hash_entry *
 elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
 		       enum elf32_arm_stub_type stub_type, asection *section,
 		       Elf_Internal_Rela *irela, asection *sym_sec,
@@ -5350,7 +5412,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table 
*htab,
       stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash, irela,
 				       stub_type);
       if (!stub_name)
-	return FALSE;
+	return NULL;
     }
 
   stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, stub_name, 
FALSE,
@@ -5361,7 +5423,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table 
*htab,
       if (!sym_claimed)
 	free (stub_name);
       stub_entry->target_value = sym_value;
-      return TRUE;
+      return stub_entry;
     }
 
   stub_entry = elf32_arm_add_stub (stub_name, section, htab, stub_type);
@@ -5369,7 +5431,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table 
*htab,
     {
       if (!sym_claimed)
 	free (stub_name);
-      return FALSE;
+      return NULL;
     }
 
   stub_entry->target_value = sym_value;
@@ -5390,7 +5452,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table 
*htab,
       if (stub_entry->output_name == NULL)
 	{
 	  free (stub_name);
-	  return FALSE;
+	  return NULL;
 	}
 
       /* For historical reasons, use the existing names for ARM-to-Thumb and
@@ -5410,7 +5472,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table 
*htab,
     }
 
   *new_stub = TRUE;
-  return TRUE;
+  return stub_entry;
 }
 
 /* Scan symbols in INPUT_BFD to identify secure entry functions needing a
@@ -5427,14 +5489,15 @@ elf32_arm_create_stub (struct 
elf32_arm_link_hash_table *htab,
 
    OUT_ATTR gives the output attributes, SYM_HASHES the symbol index to hash
    entry mapping while HTAB gives the name to hash entry mapping.
+   *CMSE_STUB_CREATED is increased by the number of secure gateway veneer
+   created.
 
-   If any secure gateway veneer is created, *STUB_CHANGED is set to TRUE.  
The
-   return value gives whether a stub failed to be allocated.  */
+   The return value gives whether a stub failed to be allocated.  */
 
 static bfd_boolean
 cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
 	   obj_attribute *out_attr, struct elf_link_hash_entry **sym_hashes,
-	   bfd_boolean *stub_changed)
+	   int *cmse_stub_created)
 {
   const struct elf_backend_data *bed;
   Elf_Internal_Shdr *symtab_hdr;
@@ -5445,7 +5508,8 @@ cmse_scan (bfd *input_bfd, struct 
elf32_arm_link_hash_table *htab,
   char *sym_name, *lsym_name;
   bfd_vma sym_value;
   asection *section;
-  bfd_boolean is_v8m, new_stub, created_stub, cmse_invalid, ret = TRUE;
+  struct elf32_arm_stub_hash_entry *stub_entry;
+  bfd_boolean is_v8m, new_stub, cmse_invalid, ret = TRUE;
 
   bed = get_elf_backend_data (input_bfd);
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
@@ -5586,17 +5650,17 @@ cmse_scan (bfd *input_bfd, struct 
elf32_arm_link_hash_table *htab,
       if (!ret)
 	continue;
       branch_type = ARM_GET_SYM_BRANCH_TYPE (hash->root.target_internal);
-      created_stub
+      stub_entry
 	= elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
 				 NULL, NULL, section, hash, sym_name,
 				 sym_value, branch_type, &new_stub);
 
-      if (!created_stub)
+      if (stub_entry == NULL)
 	 ret = FALSE;
       else
 	{
 	  BFD_ASSERT (new_stub);
-	  *stub_changed = TRUE;
+	  (*cmse_stub_created)++;
 	}
     }
 
@@ -5605,6 +5669,273 @@ cmse_scan (bfd *input_bfd, struct 
elf32_arm_link_hash_table *htab,
   return ret;
 }
 
+/* Return whether a symbol identified by its linker HASH entry is an entry
+   function, ie can be called from non secure code without using a veneer.  
*/
+
+static bfd_boolean
+cmse_entry_fct_p (struct elf32_arm_link_hash_entry *hash)
+{
+  uint32_t first_insn;
+  asection *section;
+  file_ptr offset;
+  bfd *abfd;
+
+  /* Defined symbol of function type.  */
+  if (hash->root.root.type != bfd_link_hash_defined
+      && hash->root.root.type != bfd_link_hash_defweak)
+    return FALSE;
+  if (hash->root.type != STT_FUNC)
+    return FALSE;
+
+  /* Read first instruction.  */
+  section = hash->root.root.u.def.section;
+  abfd = section->owner;
+  offset = hash->root.root.u.def.value - section->vma;
+  if (!bfd_get_section_contents (abfd, section, &first_insn, offset,
+				 sizeof (first_insn)))
+    return FALSE;
+
+  /* Start by SG instruction.  */
+  return first_insn == 0xe97fe97f;
+}
+
+/* Output the name (in symbol table) of the veneer GEN_ENTRY if it is a new
+   secure gateway veneers (ie. the veneers was not in the input import 
library)
+   and there is no output import library (GEN_INFO->out_implib_bfd is NULL.  
*/
+
+static bfd_boolean
+arm_list_new_cmse_stub (struct bfd_hash_entry *gen_entry, void *gen_info)
+{
+  struct elf32_arm_stub_hash_entry *stub_entry;
+  struct bfd_link_info *info;
+
+  /* Massage our args to the form they really have.  */
+  stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
+  info = (struct bfd_link_info *) gen_info;
+
+  if (info->out_implib_bfd)
+    return TRUE;
+
+  if (stub_entry->stub_type != arm_stub_cmse_branch_thumb_only)
+    return TRUE;
+
+  if (stub_entry->stub_offset == (bfd_vma) -1)
+    (*_bfd_error_handler) ("  %s", stub_entry->output_name);
+
+  return TRUE;
+}
+
+/* Set offset of secure gateway veneers so that their address remain identical
+   to the one in the input import library referred by HTAB->in_implib_bfd.  A
+   warning is issued for veneers that disappeared (present in input import
+   library but absent from the executable being linked) or if new veneers
+   appeared and there is no output import library (INFO->out_implib_bfd is 
NULL
+   and *CMSE_STUB_CREATED is bigger than the number of secure gateway veneers
+   found in the input import library.
+
+   The function returns whether an error occured.  If no error occured,
+   *CMSE_STUB_CREATED gives the number of SG veneers created by both 
cmse_scan
+   and this function and HTAB->new_cmse_stub_offset is set to the biggest
+   veneer observed set for new veneers to be layed out after.  */
+
+static bfd_boolean
+set_cmse_veneer_addr_from_implib (struct bfd_link_info *info,
+				  struct elf32_arm_link_hash_table *htab,
+				  int *cmse_stub_created)
+{
+  long symsize;
+  char *sym_name;
+  flagword flags;
+  long i, symcount;
+  bfd *in_implib_bfd;
+  asection *stub_out_sec;
+  bfd_boolean ret = TRUE;
+  Elf_Internal_Sym *intsym;
+  const char *out_sec_name;
+  bfd_size_type cmse_stub_size;
+  asymbol **sympp = NULL, *sym;
+  struct elf32_arm_link_hash_entry *hash;
+  const insn_sequence *cmse_stub_template;
+  struct elf32_arm_stub_hash_entry *stub_entry;
+  int cmse_stub_template_size, new_cmse_stubs_created = *cmse_stub_created;
+  bfd_vma veneer_value, stub_offset, next_cmse_stub_offset;
+  bfd_vma cmse_stub_array_start = (bfd_vma) -1, cmse_stub_sec_vma = 0;
+
+  /* No input secure gateway import library.  */
+  if (!htab->in_implib_bfd)
+    return TRUE;
+  else if (!htab->cmse_implib)
+    return FALSE;
+
+  /* Get symbol table size.  */
+  in_implib_bfd = htab->in_implib_bfd;
+  symsize = bfd_get_symtab_upper_bound (in_implib_bfd);
+  if (symsize < 0)
+    return FALSE;
+
+  /* Read in the input secure gateway import library's symbol table.  */
+  sympp = (asymbol **) xmalloc (symsize);
+  symcount = bfd_canonicalize_symtab (in_implib_bfd, sympp);
+  if (symcount < 0)
+    {
+      ret = FALSE;
+      goto free_sym_buf;
+    }
+
+  htab->new_cmse_stub_offset = 0;
+  cmse_stub_size =
+    find_stub_size_and_template (arm_stub_cmse_branch_thumb_only,
+				 &cmse_stub_template,
+				 &cmse_stub_template_size);
+  out_sec_name =
+    arm_dedicated_stub_output_section_name (arm_stub_cmse_branch_thumb_only);
+  stub_out_sec =
+    bfd_get_section_by_name (htab->obfd, out_sec_name);
+  if (stub_out_sec != NULL)
+    cmse_stub_sec_vma = stub_out_sec->vma;
+
+  /* Set addresses of veneers mentionned in input secure gateway import
+     library's symbol table.  */
+  for (i = 0; i < symcount; i++)
+    {
+      sym = sympp[i];
+      flags = sym->flags;
+      sym_name = (char *) bfd_asymbol_name (sym);
+      intsym = &((elf_symbol_type *) sym)->internal_elf_sym;
+
+      if (sym->section != bfd_abs_section_ptr
+	  || !(flags & (BSF_GLOBAL | BSF_WEAK))
+	  || (flags & BSF_FUNCTION) != BSF_FUNCTION
+	  || (ARM_GET_SYM_BRANCH_TYPE (intsym->st_target_internal)
+	      != ST_BRANCH_TO_THUMB))
+	{
+	  (*_bfd_error_handler) (_("%B: invalid import library entry: `%s'."),
+				 in_implib_bfd, sym_name);
+	  (*_bfd_error_handler) (_("Symbol should be absolute, global and "
+				   "refer to Thumb functions."));
+	  ret = FALSE;
+	  continue;
+	}
+
+      veneer_value = bfd_asymbol_value (sym);
+      stub_offset = veneer_value - cmse_stub_sec_vma;
+      stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, sym_name,
+					 FALSE, FALSE);
+      hash = (struct elf32_arm_link_hash_entry *)
+	elf_link_hash_lookup (&(htab)->root, sym_name, FALSE, FALSE, TRUE);
+
+      /* Stub entry should have been created by cmse_scan or the symbol be of
+	 a secure function callable from non secure code.  */
+      if (!stub_entry && !hash)
+	{
+	  bfd_boolean new_stub;
+
+	  (*_bfd_error_handler)
+	    (_("Entry function `%s' disappeared from secure code."), sym_name);
+	  hash = (struct elf32_arm_link_hash_entry *)
+	    elf_link_hash_lookup (&(htab)->root, sym_name, TRUE, TRUE, TRUE);
+	  stub_entry
+	    = elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
+				     NULL, NULL, bfd_abs_section_ptr, hash,
+				     sym_name, veneer_value,
+				     ST_BRANCH_TO_THUMB, &new_stub);
+	  if (stub_entry == NULL)
+	    ret = FALSE;
+	  else
+	  {
+	    BFD_ASSERT (new_stub);
+	    new_cmse_stubs_created++;
+	    (*cmse_stub_created)++;
+	  }
+	  stub_entry->stub_template_size = stub_entry->stub_size = 0;
+	  stub_entry->stub_offset = stub_offset;
+	}
+      /* Symbol found is not callable from non secure code.  */
+      else if (!stub_entry)
+	{
+	  if (!cmse_entry_fct_p (hash))
+	    {
+	      (*_bfd_error_handler) (_("`%s' refers to a non entry function."),
+				     sym_name);
+	      ret = FALSE;
+	    }
+	  continue;
+	}
+      else
+	{
+	  /* Only stub for SG veneers should have been created.  */
+	  BFD_ASSERT (stub_entry->stub_type == arm_stub_cmse_branch_thumb_only);
+
+	  /* Check visibility hasn't changed.  */
+	  if (!!(flags & BSF_GLOBAL)
+	      != (hash->root.root.type == bfd_link_hash_defined))
+	    (*_bfd_error_handler)
+	      (_("%B: visibility of symbol `%s' has changed."), in_implib_bfd,
+	       sym_name);
+
+	  stub_entry->stub_offset = stub_offset;
+	}
+
+      /* Size should match that of a SG veneer.  */
+      if (intsym->st_size != cmse_stub_size)
+	{
+	  (*_bfd_error_handler) (_("%B: incorrect size for symbol `%s'."),
+				 in_implib_bfd, sym_name);
+	  ret = FALSE;
+	}
+
+      /* Previous veneer address is before current SG veneer section.  */
+      if (veneer_value < cmse_stub_sec_vma)
+	{
+	  /* Avoid offset underflow.  */
+	  if (stub_entry)
+	    stub_entry->stub_offset = 0;
+	  stub_offset = 0;
+	  ret = FALSE;
+	}
+
+      /* Complain if stub offset not a multiple of stub size.  */
+      if (stub_offset % cmse_stub_size)
+	{
+	  (*_bfd_error_handler)
+	    (_("Offset of veneer for entry function `%s' not a multiple of "
+	       "its size."), sym_name);
+	  ret = FALSE;
+	}
+
+      if (!ret)
+	continue;
+
+      new_cmse_stubs_created--;
+      if (veneer_value < cmse_stub_array_start)
+	cmse_stub_array_start = veneer_value;
+      next_cmse_stub_offset = stub_offset + ((cmse_stub_size + 7) & ~7);
+      if (next_cmse_stub_offset > htab->new_cmse_stub_offset)
+	htab->new_cmse_stub_offset = next_cmse_stub_offset;
+    }
+
+  if (!info->out_implib_bfd && new_cmse_stubs_created != 0)
+    {
+      BFD_ASSERT (new_cmse_stubs_created > 0);
+      (*_bfd_error_handler)
+	(_("new entry function(s) introduced but no output import library "
+	   "specified:"));
+      bfd_hash_traverse (&htab->stub_hash_table, arm_list_new_cmse_stub, 
info);
+    }
+
+  if (cmse_stub_array_start != cmse_stub_sec_vma)
+    {
+      (*_bfd_error_handler)
+	(_("Start address of `%s' is different from previous link."),
+	 out_sec_name);
+      ret = FALSE;
+    }
+
+free_sym_buf:
+  free (sympp);
+  return ret;
+}
+
 /* Determine and set the size of the stub section for a final link.
 
    The basic idea here is to examine all the relocations looking for
@@ -5621,7 +5952,9 @@ elf32_arm_size_stubs (bfd *output_bfd,
 						      unsigned int),
 		      void (*layout_sections_again) (void))
 {
+  bfd_boolean ret = TRUE;
   obj_attribute *out_attr;
+  int cmse_stub_created = 0;
   bfd_size_type stub_group_size;
   bfd_boolean m_profile, stubs_always_after_branch, first_veneer_scan = TRUE;
   struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
@@ -5654,6 +5987,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
 
   out_attr = elf_known_obj_attributes_proc (output_bfd);
   m_profile = out_attr[Tag_CPU_arch_profile].i == 'M';
+
   /* The Cortex-A8 erratum fix depends on stubs not being in the same 4K page
      as the first half of a 32-bit branch straddling two 4K pages.  This is a
      crude way of enforcing that.  */
@@ -5727,8 +6061,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
 
 	      sym_hashes = elf_sym_hashes (input_bfd);
 	      if (!cmse_scan (input_bfd, htab, out_attr, sym_hashes,
-			      &stub_changed))
+			      &cmse_stub_created))
 		goto error_ret_free_local;
+
+	      if (cmse_stub_created != 0)
+		stub_changed = TRUE;
 	    }
 
 	  /* Walk over each section attached to the input bfd.  */
@@ -5954,6 +6291,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
 		  do
 		    {
 		      bfd_boolean new_stub;
+		      struct elf32_arm_stub_hash_entry *stub_entry;
 
 		      /* Determine what (if any) linker stub is needed.  */
 		      stub_type = arm_type_of_stub (info, section, irela,
@@ -5965,12 +6303,13 @@ elf32_arm_size_stubs (bfd *output_bfd,
 
 		      /* We've either created a stub for this reloc already,
 			 or we are about to.  */
-		      created_stub =
+		      stub_entry =
 			elf32_arm_create_stub (htab, stub_type, section, irela,
 					       sym_sec, hash,
 					       (char *) sym_name, sym_value,
 					       branch_type, &new_stub);
 
+		      created_stub = stub_entry != NULL;
 		      if (!created_stub || !new_stub)
 			{
 			  if (!created_stub)
@@ -6044,6 +6383,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
 	    }
 	}
 
+      if (first_veneer_scan
+	  && !set_cmse_veneer_addr_from_implib (info, htab,
+						&cmse_stub_created))
+	ret = FALSE;
+
       if (prev_num_a8_fixes != num_a8_fixes)
 	stub_changed = TRUE;
 
@@ -6063,6 +6407,23 @@ elf32_arm_size_stubs (bfd *output_bfd,
 	  stub_sec->size = 0;
 	}
 
+      /* Append new SG veneers after those in input import library.  */
+      for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
+	   stub_type++)
+	{
+	  bfd_vma *start_offset_p;
+	  asection **stub_sec_p;
+
+	  start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type);
+	  stub_sec_p = arm_dedicated_stub_input_section_ptr (htab, stub_type);
+	  if (start_offset_p == NULL)
+	    continue;
+
+	  BFD_ASSERT (stub_sec_p != NULL);
+	  if (*stub_sec_p != NULL)
+	    (*stub_sec_p)->size = *start_offset_p;
+	}
+
       /* Compute stub section size, considering padding.  */
       bfd_hash_traverse (&htab->stub_hash_table, arm_size_one_stub, htab);
       for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
@@ -6131,7 +6492,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
 	    }
 
 	  stub_entry->stub_sec = stub_sec;
-	  stub_entry->stub_offset = 0;
+	  stub_entry->stub_offset = (bfd_vma) -1;
 	  stub_entry->id_sec = link_sec;
 	  stub_entry->stub_type = a8_fixes[i].stub_type;
 	  stub_entry->source_value = a8_fixes[i].offset;
@@ -6159,7 +6520,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
       htab->a8_erratum_fixes = NULL;
       htab->num_a8_erratum_fixes = 0;
     }
-  return TRUE;
+  return ret;
 
  error_ret_free_local:
   return FALSE;
@@ -6176,6 +6537,7 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
 {
   asection *stub_sec;
   struct bfd_hash_table *table;
+  enum elf32_arm_stub_type stub_type;
   struct elf32_arm_link_hash_table *htab;
 
   htab = elf32_arm_hash_table (info);
@@ -6193,14 +6555,33 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
 	continue;
 
       /* Allocate memory to hold the linker stubs.  Zeroing the stub sections
-	 must at least be done for stub section requiring padding.  */
+	 must at least be done for stub section requiring padding and for SG
+	 veneers to ensure that a non secure code branching to a removed SG
+	 veneer causes an error.  */
       size = stub_sec->size;
       stub_sec->contents = (unsigned char *) bfd_zalloc (htab->stub_bfd, 
size);
       if (stub_sec->contents == NULL && size != 0)
 	return FALSE;
+
       stub_sec->size = 0;
     }
 
+  /* Append new SG veneers after those in input import library.  */
+  for (stub_type = arm_stub_none + 1; stub_type < max_stub_type; stub_type++)
+    {
+      bfd_vma *start_offset_p;
+      asection **stub_sec_p;
+
+      start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type);
+      stub_sec_p = arm_dedicated_stub_input_section_ptr (htab, stub_type);
+      if (start_offset_p == NULL)
+	continue;
+
+      BFD_ASSERT (stub_sec_p != NULL);
+      if (*stub_sec_p != NULL)
+	(*stub_sec_p)->size = *start_offset_p;
+    }
+
   /* Build the stubs as directed by the stub hash table.  */
   table = &htab->stub_hash_table;
   bfd_hash_traverse (table, arm_build_one_stub, info);
@@ -8183,7 +8564,8 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd,
 				 bfd_arm_stm32l4xx_fix stm32l4xx_fix,
 				 int no_enum_warn, int no_wchar_warn,
 				 int pic_veneer, int fix_cortex_a8,
-				 int fix_arm1176, int cmse_implib)
+				 int fix_arm1176, int cmse_implib,
+				 bfd *in_implib_bfd)
 {
   struct elf32_arm_link_hash_table *globals;
 
@@ -8211,6 +8593,7 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd,
   globals->fix_cortex_a8 = fix_cortex_a8;
   globals->fix_arm1176 = fix_arm1176;
   globals->cmse_implib = cmse_implib;
+  globals->in_implib_bfd = in_implib_bfd;
 
   BFD_ASSERT (is_arm_elf (output_bfd));
   elf_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
index 
c21f6a82335a58a0ab37f3719c73c95e73e6211c..2346bb42444895605d10b7b7e21cca2dcaa38700 
100644
--- a/ld/emultempl/armelf.em
+++ b/ld/emultempl/armelf.em
@@ -43,6 +43,7 @@ static int pic_veneer = 0;
 static int merge_exidx_entries = -1;
 static int fix_arm1176 = 1;
 static int cmse_implib = 0;
+static char *in_implib_filename = NULL;
 
 static void
 gld${EMULATION_NAME}_before_parse (void)
@@ -498,6 +499,8 @@ gld${EMULATION_NAME}_finish (void)
 static void
 arm_elf_create_output_section_statements (void)
 {
+  bfd *in_implib_bfd;
+
   if (strstr (bfd_get_target (link_info.output_bfd), "arm") == NULL)
     {
       /* The arm backend needs special fields in the output hash structure.
@@ -508,6 +511,20 @@ arm_elf_create_output_section_statements (void)
       return;
     }
 
+  if (in_implib_filename)
+    {
+      in_implib_bfd = bfd_openr (in_implib_filename,
+				 bfd_get_target (link_info.output_bfd));
+
+      if (in_implib_bfd == NULL)
+	einfo ("%F%s: Can't open: %E\n", in_implib_filename);
+
+      if (!bfd_check_format (in_implib_bfd, bfd_object))
+	einfo ("%F%s: Not a relocatable file: %E\n", in_implib_filename);
+    }
+  else
+    in_implib_bfd = NULL;
+
   bfd_elf32_arm_set_target_relocs (link_info.output_bfd, &link_info,
 				   target1_is_rel,
 				   target2_type, fix_v4bx, use_blx,
@@ -515,7 +532,7 @@ arm_elf_create_output_section_statements (void)
 				   no_enum_size_warning,
 				   no_wchar_size_warning,
 				   pic_veneer, fix_cortex_a8,
-				   fix_arm1176, cmse_implib);
+				   fix_arm1176, cmse_implib, in_implib_bfd);
 
   stub_file = lang_add_input_file ("linker stubs",
  				   lang_input_file_is_fake_enum,
@@ -585,6 +602,7 @@ PARSE_AND_LIST_PROLOGUE='
 #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
@@ -612,6 +630,7 @@ PARSE_AND_LIST_LONGOPTS='
   { "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='
@@ -634,6 +653,8 @@ PARSE_AND_LIST_OPTIONS='
            "                              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\
@@ -758,6 +779,10 @@ PARSE_AND_LIST_ARGS_CASES='
    case OPTION_CMSE_IMPLIB:
       cmse_implib = 1;
       break;
+
+   case OPTION_IN_IMPLIB:
+      in_implib_filename = optarg;
+      break;
 '
 
 # We have our own before_allocation etc. functions, but they call
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 
82b40355a698958d84b566c09901960370139b27..eda43065f42e28bc4793bd5df78e45bd21cc1817 
100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -6817,6 +6817,18 @@ specified by the @samp{--out-implib} and @samp{--in-
implib} options are
 secure gateway import libraries, suitable for linking a non-secure
 executable against secure code as per ARMv8-M Security Extensions.
 
+@kindex --in-implib=@var{file}
+@cindex Input import library
+The @samp{--in-implib=file} specifies an input import library whose symbols
+must keep the same address in the executable being produced.  A warning is
+given if no @samp{--out-implib} is given but new symbols have been introduced
+in the executable that should be listed in its import library.  Otherwise, if
+@samp{--out-implib} is specified, the symbols are silently added to the output
+import library.  A warning is also given if some symbols present in the input
+import library have disappeared from the executable.  This option is only
+effective for Secure Gateway import libraries, ie. when @samp{--cmse-implib} 
is
+specified.
+
 @ifclear GENERIC
 @lowersections
 @end ifclear
diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
index 
da4bf7e0302de9f1c76bbacf8b64a9318d44c46a..f15a8d42f3d5a4f87f21df2b229e30a1143fe7ac 
100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -663,16 +663,53 @@ set armeabitests_nonacl {
      "cmse-veneers-mainline"}
     {"Secure gateway import library generation: errors"
      "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-
implib.lib --cmse-implib" ""
-     "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1"
+     "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1 --defsym VER=1"
      {cmse-implib.s}
      {{ld cmse-implib-errors.out}}
      "cmse-implib"}
     {"Secure gateway import library generation"
      "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-
implib.lib --cmse-implib" ""
-     "-march=armv8-m.base -mthumb"
+     "-march=armv8-m.base -mthumb --defsym VER=1"
      {cmse-implib.s}
      {{readelf {-s tmpdir/cmse-implib.lib} cmse-implib.rd}}
      "cmse-implib"}
+    {"Input secure gateway import library"
+     "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-new-
implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=2"
+     {cmse-implib.s}
+     {{ld cmse-new-implib.out}
+      {readelf {-s tmpdir/cmse-new-implib.lib} cmse-new-implib.rd}}
+     "cmse-new-implib"}
+    {"Input secure gateway import library: no output import library"
+     "--section-start .gnu.sgstubs=0x20000 --in-implib=tmpdir/cmse-implib.lib 
--cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=2"
+     {cmse-implib.s}
+     {{ld cmse-new-implib-no-output.out}}
+     "cmse-new-implib-no-output"}
+    {"Input secure gateway import library: earlier stub section base"
+     "--section-start .gnu.sgstubs=0x19000 --out-implib=tmpdir/cmse-new-
earlier-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=2"
+     {cmse-implib.s}
+     {{ld cmse-new-earlier-later-implib.out}}
+     "cmse-new-earlier-implib"}
+    {"Input secure gateway import library: later stub section base"
+     "--section-start .gnu.sgstubs=0x30000 --out-implib=tmpdir/cmse-new-
later-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=2"
+     {cmse-implib.s}
+     {{ld cmse-new-earlier-later-implib.out}}
+     "cmse-new-later-implib"}
+    {"Input secure gateway import library: veneer comeback"
+     "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-new-
comeback-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=3"
+     {cmse-implib.s}
+     {{readelf {-s tmpdir/cmse-new-comeback-implib.lib} cmse-new-comeback-
implib.rd}}
+     "cmse-new-comeback-implib"}
+    {"Input secure gateway import library: entry function change"
+     "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-new-
wrong-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=4"
+     {cmse-implib.s}
+     {{ld cmse-new-wrong-implib.out}}
+     "cmse-new-wrong-implib"}
 
     {"R_ARM_THM_JUMP19 Relocation veneers: Short"
      "--section-start destsect=0x000108002 --section-start .text=0x8000" ""
diff --git a/ld/testsuite/ld-arm/cmse-implib.s b/ld/testsuite/ld-arm/cmse-
implib.s
index 
a42da63fffebe5322be83f278931754262b0f7ae..9dd783939891478351a5f7ccb1480980a77dca68 
100644
--- a/ld/testsuite/ld-arm/cmse-implib.s
+++ b/ld/testsuite/ld-arm/cmse-implib.s
@@ -20,12 +20,29 @@ __acle_se_\name:
 .endm
 
 	@ Valid setups for veneer generation
+.if (VER >= 2)
+	entry exported_entry_veneer1, global
+.endif
+.if (VER != 4)
 	entry exported_entry_veneer2, global
+.else
+	entry exported_entry_veneer2, weak
+.endif
+.if (VER != 2)
 	entry exported_entry_veneer3, global
+.endif
+.if (VER > 1)
+	entry exported_entry_veneer4, global
+.endif
 
 	@ Valid setup for entry function without veneer generation
 	entry exported_entry_fct1, global, sg
+.if (VER != 4)
 	entry exported_entry_fct2, global, sg
+.else
+	@ Invalid setup for entry function without veneer generation
+	entry exported_entry_fct2, global, nop
+.endif
 
 	@ Normal symbol not exported to SG import library
 	.align	2
diff --git a/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd b/ld/testsuite/ld-
arm/cmse-new-comeback-implib.rd
new file mode 100644
index 
0000000000000000000000000000000000000000..c88d9d5104244abc8ceba4d552e1ef0e400c37d1
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd
@@ -0,0 +1,15 @@
+File: tmpdir/cmse-new-.*implib.lib
+
+Symbol table '.symtab' contains 7 entries:
+   Num:    Value  Size Type    Bind   Vis      Ndx Name
+     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
+     1: 00020001     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer3
+     2: 00020011     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer4
+     3: 00020019     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer1
+     4: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
+     5: 00020009     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer2
+     6: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
+
+File: tmpdir/cmse-new-.*implib
+
+#...
diff --git a/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out 
b/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
new file mode 100644
index 
0000000000000000000000000000000000000000..b49ad0ac0770a17c39c2d119d1f0c5854a5bd8cc
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
@@ -0,0 +1,3 @@
+.*: Entry function `exported_entry_veneer3' disappeared from secure code.
+.*: Start address of `.gnu.sgstubs' is different from previous link.
+.*: cannot size stub section: Invalid operation
diff --git a/ld/testsuite/ld-arm/cmse-new-implib-no-output.out 
b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
new file mode 100644
index 
0000000000000000000000000000000000000000..0590b71c844da3687b29b93797abda5172ab8d99
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
@@ -0,0 +1,4 @@
+.*: Entry function `exported_entry_veneer3' disappeared from secure code.
+.*: new entry function\(s\) introduced but no output import library specified:
+.*:   exported_entry_veneer4
+.*:   exported_entry_veneer1
diff --git a/ld/testsuite/ld-arm/cmse-new-implib.out b/ld/testsuite/ld-
arm/cmse-new-implib.out
new file mode 100644
index 
0000000000000000000000000000000000000000..c8af2807e7c1a7eeb1fc156fbf4508cf7a7e932d
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-implib.out
@@ -0,0 +1 @@
+.*: Entry function `exported_entry_veneer3' disappeared from secure code.
diff --git a/ld/testsuite/ld-arm/cmse-new-implib.rd b/ld/testsuite/ld-arm/cmse-
new-implib.rd
new file mode 100644
index 
0000000000000000000000000000000000000000..9ff0fd87937571f86f99ee940a91a3f67352242a
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-implib.rd
@@ -0,0 +1,14 @@
+File: tmpdir/cmse-new-.*implib.lib
+
+Symbol table '.symtab' contains 6 entries:
+   Num:    Value  Size Type    Bind   Vis      Ndx Name
+     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
+     1: 00020011     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer4
+     2: 00020019     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer1
+     3: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
+     4: 00020009     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer2
+     5: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
+
+File: tmpdir/cmse-new-.*implib
+
+#...
diff --git a/ld/testsuite/ld-arm/cmse-new-wrong-implib.out b/ld/testsuite/ld-
arm/cmse-new-wrong-implib.out
new file mode 100644
index 
0000000000000000000000000000000000000000..2afe4078e78606d24f05dda6ff1c5e6a54d42512
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
@@ -0,0 +1,3 @@
+.*: .*: visibility of symbol `exported_entry_veneer2' has changed.
+.*: `exported_entry_fct2' refers to a non entry function.
+.*: cannot size stub section: Invalid operation


Is this ok for master branch?

Best regards,

Thomas

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH, binutils, ARM 11/11] Add support for stable secure gateway veneers addresses
  2016-04-04 14:23 ` [RFC PATCH, binutils, ARM 11/11] " Thomas Preudhomme
@ 2016-05-18 16:41   ` Thomas Preudhomme
  2016-07-07 12:52   ` [RFC PATCH, " Richard Earnshaw (lists)
  1 sibling, 0 replies; 15+ messages in thread
From: Thomas Preudhomme @ 2016-05-18 16:41 UTC (permalink / raw)
  To: binutils; +Cc: richard.earnshaw, nickc

[CCing Richard Earnshaw and Nick Clifton who reviewed previous ARMv8-M 
patches]

On Monday 04 April 2016 15:23 Thomas Preud'homme wrote:
> On Wednesday 23 December 2015 16:02:48 Thomas Preud'homme wrote:
> > Hi,
> >
> > [Posting patch series as RFC]
> >
> > This patch is part of a patch series to add support for ARMv8-M
> > security extension[1] to GNU ld. This specific patch adds support for
> > allowing Secure Gateway veneers to have stable addresses when
> > relinking a secure executable.
> >
> > ARM v8-M security extensions allow code running in a device to be
> > divided into secure and non-secure code expected to be developed by
> > independent (teams of) people. To allow updating the secure code
> > without the need to relink the non-secure code against it, it is
> > necessary for the toolchain to provide a way to fix the addresses of
> > the secure gateway veneers that serve as entry points for non-secure
> > code to call secure code. This is also a requirement [2] to claim support 
for
> ARM v8-M security extensions.
> >
> > This patch adds a --in-implib=<in_implib_filename> option which, when
> > used in conjunction of --cmse-implib will ensure that the veneers
> > whose symbols are defined in the import library $in_implib_filename
> > will remain at the same address in the executable. In the absence of a
> > --out-implib option, the code will warn about new secure gateway
> > veneers being created, otherwise these are allowed.
> >
> >
> > [1] Software requirements for ARMv8-M security extension are described
> > in document ARM-ECM-0359818 [2] [2] Available on
> > http://infocenter.arm.com in Developer guides and articles > Software
> > development > ARM®v8-M Security
> > Extensions: Requirements on Development Tools [3] See requirement 15
> > of
> > ARM-ECM-0359818 [2]
> 
> Please find an updated patch below.

Please find an updated patch below, following the fix to the issue hilighted by 
Christophe Lyon in patch 2/11 (Factor our stub creation in ARM backend).

ChangeLog entries are unchanged:

*** bfd/ChangeLog ***

2016-02-18  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new parameter for
        the input import library bfd.
        * bfd-in2.h: Regenerate.
        * elf32-arm.c (struct elf32_arm_link_hash_table): New in_implib_bfd
        and new_cmse_stub_offset fields.
        (stub_hash_newfunc): Initialize stub_offset and stub_template_size to
        -1.
        (elf32_arm_add_stub): Likewise for stub_offset.
        (arm_new_stubs_start_offset_ptr): New function.
        (arm_build_one_stub): Only allocate a stub_offset if it is -1.  Allow
        empty veneers to have zero relocations.
        (arm_size_one_stub): Only initialize stub size and template
        information for non empty veneers.  Do not update veneer section size
        if veneer already has an offset.
        (elf32_arm_create_stub): Return the stub entry pointer or NULL instead
        of a boolean indicating success or failure.
        (cmse_scan): Change stub_changed parameter into an integer pointer
        parameter cmse_stub_created to count the number of stub created and
        adapt to change of return value in elf32_arm_create_stub.
        (cmse_entry_fct_p): New function.
        (arm_list_new_cmse_stub): Likewise.
        (set_cmse_veneer_addr_from_implib): Likewise.
        (elf32_arm_size_stubs): Define cmse_stub_created, pass its address to
        cmse_scan instead of that of cmse_stub_changed to compute the number
        of stub created and use it to initialize stub_changed.  Call
        set_cmse_veneer_addr_from_implib after all cmse_scan.  Adapt to change
        of return value in elf32_arm_create_stub.  Use
        arm_stub_section_start_offset () if not NULL to initialize size of
        secure gateway veneers section.  Initialize stub_offset of Cortex-A8
        erratum fix to -1.  Use ret to hold return value.
        (elf32_arm_build_stubs): Use arm_stub_section_start_offset () if not
        NULL to initialize size of secure gateway veneers section.  Adapt
        comment to stress the importance of zeroing veneer section content.
        (bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd parameter to
        initialize eponymous field in struct elf32_arm_link_hash_table.


*** ld/ChangeLog ***

2016-02-18  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * emultempl/armelf.em (in_implib_filename): Declare and initialize new
        variable. 
        (arm_elf_create_output_section_statements): Open import input library
        file for writing and pass resulting in_implib_bfd to
        bfd_elf32_arm_set_target_relocs.
        (PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option.
        (PARSE_AND_LIST_LONGOPTS): Define --in-implib option.
        (PARSE_AND_LIST_OPTIONS): Add help message for --in-implib option.
        (PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case.
        * ld.texinfo (--cmse-implib): Update to mention --in-implib.
        (--in-implib): Document new option.
        * testsuite/ld-arm/arm-elf.exp
        (Secure gateway import library generation): add --defsym VER=1 to gas
        CLI.
        (Secure gateway import library generation: errors): Likewise.
        (Input secure gateway import library): New test.
        (Input secure gateway import library: no output import library):
        Likewise. 
        (Input secure gateway import library: earlier stub section base):
        Likewise.
        (Input secure gateway import library: later stub section base):
        Likewise.
        (Input secure gateway import library: veneer comeback): Likewise.
        (Input secure gateway import library: entry function change): 
        Likewise.
        * testsuite/ld-arm/cmse-implib.s: Add input import library testing.
        * testsuite/ld-arm/cmse-implib.rd: Update accordingly.
        * testsuite/ld-arm/cmse-new-implib.out: New file.
        * testsuite/ld-arm/cmse-new-implib.rd: Likewise.
        * testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise.
        * testsuite/ld-arm/cmse-new-earlier-later-implib.out: Likewise.
        * testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise.
        * testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise.


diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index 
d7f77d7650b8f4f23f2106c61c72fc238575d35a..140ddf463f6fffb00bace2f96b8365b71c962152 
100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.h
@@ -895,7 +895,7 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation
 
 void bfd_elf32_arm_set_target_relocs
   (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix,
-   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
+   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
 
 extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
   (bfd *, struct bfd_link_info *);
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 
c7ba6427a5fd02a53a7bcbc042ac741456ddb213..b3db448d56ba850d998bcd21a4d9adc8aeabdd2e 
100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -902,7 +902,7 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation
 
 void bfd_elf32_arm_set_target_relocs
   (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix,
-   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
+   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
 
 extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
   (bfd *, struct bfd_link_info *);
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 
1c9d97c4fa6af07a858d67f541e51fc49c4d40ee..d2a5de46b0819b7f1ad433507bfa86107befc3c1 
100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -3128,6 +3128,10 @@ struct elf32_arm_link_hash_table
      as per ARMv8-M Security Extensions.  */
   int cmse_implib;
 
+  /* The import library whose symbols' address must remain stable in
+     the import library generated.  */
+  bfd *in_implib_bfd;
+
   /* The index of the next unused R_ARM_TLS_DESC slot in .rel.plt.  */
   bfd_vma next_tls_desc_index;
 
@@ -3189,6 +3193,10 @@ struct elf32_arm_link_hash_table
   /* Input stub section holding secure gateway veneers.  */
   asection *cmse_stub_sec;
 
+  /* Offset in cmse_stub_sec where new SG veneers (not in input import 
library)
+     start to be allocated.  */
+  bfd_vma new_cmse_stub_offset;
+
   /* Number of elements in stub_group.  */
   unsigned int top_id;
 
@@ -3440,7 +3448,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
       /* Initialize the local fields.  */
       eh = (struct elf32_arm_stub_hash_entry *) entry;
       eh->stub_sec = NULL;
-      eh->stub_offset = 0;
+      eh->stub_offset = (bfd_vma) -1;
       eh->source_value = 0;
       eh->target_value = 0;
       eh->target_section = NULL;
@@ -3448,7 +3456,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
       eh->stub_type = arm_stub_none;
       eh->stub_size = 0;
       eh->stub_template = NULL;
-      eh->stub_template_size = 0;
+      eh->stub_template_size = -1;
       eh->h = NULL;
       eh->id_sec = NULL;
       eh->output_name = NULL;
@@ -4362,7 +4370,7 @@ elf32_arm_add_stub (const char *stub_name, asection 
*section,
     }
 
   stub_entry->stub_sec = stub_sec;
-  stub_entry->stub_offset = 0;
+  stub_entry->stub_offset = (bfd_vma) -1;
   stub_entry->id_sec = link_sec;
 
   return stub_entry;
@@ -4526,6 +4534,46 @@ arm_dedicated_stub_section_padding (enum 
elf32_arm_stub_type stub_type)
   abort ();  /* Should be unreachable.  */
 }
 
+/* If veneers of type STUB_TYPE should go in a dedicated output section,
+   returns the address of the hash table field in HTAB holding the offset at
+   which new veneers should be layed out in the stub section.  */
+
+static bfd_vma*
+arm_new_stubs_start_offset_ptr (struct elf32_arm_link_hash_table *htab,
+				enum elf32_arm_stub_type stub_type)
+{
+  switch (stub_type)
+    {
+    case arm_stub_a8_veneer_b_cond:
+    case arm_stub_a8_veneer_b:
+    case arm_stub_a8_veneer_bl:
+    case arm_stub_long_branch_any_any:
+    case arm_stub_long_branch_v4t_arm_thumb:
+    case arm_stub_long_branch_thumb_only:
+    case arm_stub_long_branch_v4t_thumb_thumb:
+    case arm_stub_long_branch_v4t_thumb_arm:
+    case arm_stub_short_branch_v4t_thumb_arm:
+    case arm_stub_long_branch_any_arm_pic:
+    case arm_stub_long_branch_any_thumb_pic:
+    case arm_stub_long_branch_v4t_thumb_thumb_pic:
+    case arm_stub_long_branch_v4t_arm_thumb_pic:
+    case arm_stub_long_branch_v4t_thumb_arm_pic:
+    case arm_stub_long_branch_thumb_only_pic:
+    case arm_stub_long_branch_any_tls_pic:
+    case arm_stub_long_branch_v4t_thumb_tls_pic:
+    case arm_stub_a8_veneer_blx:
+    case arm_stub_long_branch_arm_nacl:
+    case arm_stub_long_branch_arm_nacl_pic:
+      return NULL;
+
+    case arm_stub_cmse_branch_thumb_only:
+      return &htab->new_cmse_stub_offset;
+
+    default:
+      abort ();  /* Should be unreachable.  */
+    }
+}
+
 static bfd_boolean
 arm_build_one_stub (struct bfd_hash_entry *gen_entry,
 		    void * in_arg)
@@ -4545,6 +4593,7 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
   int stub_reloc_idx[MAXRELOCS] = {-1, -1};
   int stub_reloc_offset[MAXRELOCS] = {0, 0};
   int nrelocs = 0;
+  int just_allocated = 0;
 
   /* Massage our args to the form they really have.  */
   stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
@@ -4561,8 +4610,12 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
     /* We have to do less-strictly-aligned fixes last.  */
     return TRUE;
 
-  /* Make a note of the offset within the stubs for this entry.  */
-  stub_entry->stub_offset = stub_sec->size;
+  /* Assign a slot at the end of section if none assigned yet.  */
+  if (stub_entry->stub_offset == (bfd_vma) -1)
+    {
+      stub_entry->stub_offset = stub_sec->size;
+      just_allocated = 1;
+    }
   loc = stub_sec->contents + stub_entry->stub_offset;
 
   stub_bfd = stub_sec->owner;
@@ -4636,7 +4689,8 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
 	}
     }
 
-  stub_sec->size += size;
+  if (just_allocated)
+    stub_sec->size += size;
 
   /* Stub size has already been computed in arm_size_one_stub. Check
      consistency.  */
@@ -4648,7 +4702,7 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
 
   /* Assume there is at least one and at most MAXRELOCS entries to relocate
      in each stub.  */
-  BFD_ASSERT (nrelocs != 0 && nrelocs <= MAXRELOCS);
+  BFD_ASSERT (size == 0 || (nrelocs != 0 && nrelocs <= MAXRELOCS));
 
   for (i = 0; i < nrelocs; i++)
     {
@@ -4750,9 +4804,17 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry,
   size = find_stub_size_and_template (stub_entry->stub_type, 
&template_sequence,
 				      &template_size);
 
-  stub_entry->stub_size = size;
-  stub_entry->stub_template = template_sequence;
-  stub_entry->stub_template_size = template_size;
+  /* Initialized to -1.  Null size indicates a zeroed out veneer.  */
+  if (stub_entry->stub_template_size)
+    {
+      stub_entry->stub_size = size;
+      stub_entry->stub_template = template_sequence;
+      stub_entry->stub_template_size = template_size;
+    }
+
+  /* Already accounted for.  */
+  if (stub_entry->stub_offset != (bfd_vma) -1)
+    return TRUE;
 
   size = (size + 7) & ~7;
   stub_entry->stub_sec->size += size;
@@ -5317,10 +5379,10 @@ cortex_a8_erratum_scan (bfd *input_bfd,
    and *NEW_STUB is set to FALSE.  Otherwise, *NEW_STUB is set to
    TRUE and the stub entry is initialized.
 
-   Returns whether the stub could be successfully created or updated, or 
FALSE
-   if an error occured.  */
+   Returns the stub that was created or updated, or NULL if an error
+   occured.  */
 
-static bfd_boolean
+static struct elf32_arm_stub_hash_entry *
 elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
 		       enum elf32_arm_stub_type stub_type, asection *section,
 		       Elf_Internal_Rela *irela, asection *sym_sec,
@@ -5351,7 +5413,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table 
*htab,
       stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash, irela,
 				       stub_type);
       if (!stub_name)
-	return FALSE;
+	return NULL;
     }
 
   stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, stub_name, 
FALSE,
@@ -5362,7 +5424,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table 
*htab,
       if (!sym_claimed)
 	free (stub_name);
       stub_entry->target_value = sym_value;
-      return TRUE;
+      return stub_entry;
     }
 
   stub_entry = elf32_arm_add_stub (stub_name, section, htab, stub_type);
@@ -5370,7 +5432,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table 
*htab,
     {
       if (!sym_claimed)
 	free (stub_name);
-      return FALSE;
+      return NULL;
     }
 
   stub_entry->target_value = sym_value;
@@ -5391,7 +5453,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table 
*htab,
       if (stub_entry->output_name == NULL)
 	{
 	  free (stub_name);
-	  return FALSE;
+	  return NULL;
 	}
 
       /* For historical reasons, use the existing names for ARM-to-Thumb and
@@ -5411,7 +5473,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table 
*htab,
     }
 
   *new_stub = TRUE;
-  return TRUE;
+  return stub_entry;
 }
 
 /* Scan symbols in INPUT_BFD to identify secure entry functions needing a
@@ -5428,14 +5490,15 @@ elf32_arm_create_stub (struct 
elf32_arm_link_hash_table *htab,
 
    OUT_ATTR gives the output attributes, SYM_HASHES the symbol index to hash
    entry mapping while HTAB gives the name to hash entry mapping.
+   *CMSE_STUB_CREATED is increased by the number of secure gateway veneer
+   created.
 
-   If any secure gateway veneer is created, *STUB_CHANGED is set to TRUE.  
The
-   return value gives whether a stub failed to be allocated.  */
+   The return value gives whether a stub failed to be allocated.  */
 
 static bfd_boolean
 cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
 	   obj_attribute *out_attr, struct elf_link_hash_entry **sym_hashes,
-	   bfd_boolean *stub_changed)
+	   int *cmse_stub_created)
 {
   const struct elf_backend_data *bed;
   Elf_Internal_Shdr *symtab_hdr;
@@ -5446,7 +5509,8 @@ cmse_scan (bfd *input_bfd, struct 
elf32_arm_link_hash_table *htab,
   char *sym_name, *lsym_name;
   bfd_vma sym_value;
   asection *section;
-  bfd_boolean is_v8m, new_stub, created_stub, cmse_invalid, ret = TRUE;
+  struct elf32_arm_stub_hash_entry *stub_entry;
+  bfd_boolean is_v8m, new_stub, cmse_invalid, ret = TRUE;
 
   bed = get_elf_backend_data (input_bfd);
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
@@ -5587,17 +5651,17 @@ cmse_scan (bfd *input_bfd, struct 
elf32_arm_link_hash_table *htab,
       if (!ret)
 	continue;
       branch_type = ARM_GET_SYM_BRANCH_TYPE (hash->root.target_internal);
-      created_stub
+      stub_entry
 	= elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
 				 NULL, NULL, section, hash, sym_name,
 				 sym_value, branch_type, &new_stub);
 
-      if (!created_stub)
+      if (stub_entry == NULL)
 	 ret = FALSE;
       else
 	{
 	  BFD_ASSERT (new_stub);
-	  *stub_changed = TRUE;
+	  (*cmse_stub_created)++;
 	}
     }
 
@@ -5606,6 +5670,273 @@ cmse_scan (bfd *input_bfd, struct 
elf32_arm_link_hash_table *htab,
   return ret;
 }
 
+/* Return whether a symbol identified by its linker HASH entry is an entry
+   function, ie can be called from non secure code without using a veneer.  
*/
+
+static bfd_boolean
+cmse_entry_fct_p (struct elf32_arm_link_hash_entry *hash)
+{
+  uint32_t first_insn;
+  asection *section;
+  file_ptr offset;
+  bfd *abfd;
+
+  /* Defined symbol of function type.  */
+  if (hash->root.root.type != bfd_link_hash_defined
+      && hash->root.root.type != bfd_link_hash_defweak)
+    return FALSE;
+  if (hash->root.type != STT_FUNC)
+    return FALSE;
+
+  /* Read first instruction.  */
+  section = hash->root.root.u.def.section;
+  abfd = section->owner;
+  offset = hash->root.root.u.def.value - section->vma;
+  if (!bfd_get_section_contents (abfd, section, &first_insn, offset,
+				 sizeof (first_insn)))
+    return FALSE;
+
+  /* Start by SG instruction.  */
+  return first_insn == 0xe97fe97f;
+}
+
+/* Output the name (in symbol table) of the veneer GEN_ENTRY if it is a new
+   secure gateway veneers (ie. the veneers was not in the input import 
library)
+   and there is no output import library (GEN_INFO->out_implib_bfd is NULL.  
*/
+
+static bfd_boolean
+arm_list_new_cmse_stub (struct bfd_hash_entry *gen_entry, void *gen_info)
+{
+  struct elf32_arm_stub_hash_entry *stub_entry;
+  struct bfd_link_info *info;
+
+  /* Massage our args to the form they really have.  */
+  stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
+  info = (struct bfd_link_info *) gen_info;
+
+  if (info->out_implib_bfd)
+    return TRUE;
+
+  if (stub_entry->stub_type != arm_stub_cmse_branch_thumb_only)
+    return TRUE;
+
+  if (stub_entry->stub_offset == (bfd_vma) -1)
+    (*_bfd_error_handler) ("  %s", stub_entry->output_name);
+
+  return TRUE;
+}
+
+/* Set offset of secure gateway veneers so that their address remain identical
+   to the one in the input import library referred by HTAB->in_implib_bfd.  A
+   warning is issued for veneers that disappeared (present in input import
+   library but absent from the executable being linked) or if new veneers
+   appeared and there is no output import library (INFO->out_implib_bfd is 
NULL
+   and *CMSE_STUB_CREATED is bigger than the number of secure gateway veneers
+   found in the input import library.
+
+   The function returns whether an error occured.  If no error occured,
+   *CMSE_STUB_CREATED gives the number of SG veneers created by both 
cmse_scan
+   and this function and HTAB->new_cmse_stub_offset is set to the biggest
+   veneer observed set for new veneers to be layed out after.  */
+
+static bfd_boolean
+set_cmse_veneer_addr_from_implib (struct bfd_link_info *info,
+				  struct elf32_arm_link_hash_table *htab,
+				  int *cmse_stub_created)
+{
+  long symsize;
+  char *sym_name;
+  flagword flags;
+  long i, symcount;
+  bfd *in_implib_bfd;
+  asection *stub_out_sec;
+  bfd_boolean ret = TRUE;
+  Elf_Internal_Sym *intsym;
+  const char *out_sec_name;
+  bfd_size_type cmse_stub_size;
+  asymbol **sympp = NULL, *sym;
+  struct elf32_arm_link_hash_entry *hash;
+  const insn_sequence *cmse_stub_template;
+  struct elf32_arm_stub_hash_entry *stub_entry;
+  int cmse_stub_template_size, new_cmse_stubs_created = *cmse_stub_created;
+  bfd_vma veneer_value, stub_offset, next_cmse_stub_offset;
+  bfd_vma cmse_stub_array_start = (bfd_vma) -1, cmse_stub_sec_vma = 0;
+
+  /* No input secure gateway import library.  */
+  if (!htab->in_implib_bfd)
+    return TRUE;
+  else if (!htab->cmse_implib)
+    return FALSE;
+
+  /* Get symbol table size.  */
+  in_implib_bfd = htab->in_implib_bfd;
+  symsize = bfd_get_symtab_upper_bound (in_implib_bfd);
+  if (symsize < 0)
+    return FALSE;
+
+  /* Read in the input secure gateway import library's symbol table.  */
+  sympp = (asymbol **) xmalloc (symsize);
+  symcount = bfd_canonicalize_symtab (in_implib_bfd, sympp);
+  if (symcount < 0)
+    {
+      ret = FALSE;
+      goto free_sym_buf;
+    }
+
+  htab->new_cmse_stub_offset = 0;
+  cmse_stub_size =
+    find_stub_size_and_template (arm_stub_cmse_branch_thumb_only,
+				 &cmse_stub_template,
+				 &cmse_stub_template_size);
+  out_sec_name =
+    arm_dedicated_stub_output_section_name (arm_stub_cmse_branch_thumb_only);
+  stub_out_sec =
+    bfd_get_section_by_name (htab->obfd, out_sec_name);
+  if (stub_out_sec != NULL)
+    cmse_stub_sec_vma = stub_out_sec->vma;
+
+  /* Set addresses of veneers mentionned in input secure gateway import
+     library's symbol table.  */
+  for (i = 0; i < symcount; i++)
+    {
+      sym = sympp[i];
+      flags = sym->flags;
+      sym_name = (char *) bfd_asymbol_name (sym);
+      intsym = &((elf_symbol_type *) sym)->internal_elf_sym;
+
+      if (sym->section != bfd_abs_section_ptr
+	  || !(flags & (BSF_GLOBAL | BSF_WEAK))
+	  || (flags & BSF_FUNCTION) != BSF_FUNCTION
+	  || (ARM_GET_SYM_BRANCH_TYPE (intsym->st_target_internal)
+	      != ST_BRANCH_TO_THUMB))
+	{
+	  (*_bfd_error_handler) (_("%B: invalid import library entry: `%s'."),
+				 in_implib_bfd, sym_name);
+	  (*_bfd_error_handler) (_("Symbol should be absolute, global and "
+				   "refer to Thumb functions."));
+	  ret = FALSE;
+	  continue;
+	}
+
+      veneer_value = bfd_asymbol_value (sym);
+      stub_offset = veneer_value - cmse_stub_sec_vma;
+      stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, sym_name,
+					 FALSE, FALSE);
+      hash = (struct elf32_arm_link_hash_entry *)
+	elf_link_hash_lookup (&(htab)->root, sym_name, FALSE, FALSE, TRUE);
+
+      /* Stub entry should have been created by cmse_scan or the symbol be of
+	 a secure function callable from non secure code.  */
+      if (!stub_entry && !hash)
+	{
+	  bfd_boolean new_stub;
+
+	  (*_bfd_error_handler)
+	    (_("Entry function `%s' disappeared from secure code."), sym_name);
+	  hash = (struct elf32_arm_link_hash_entry *)
+	    elf_link_hash_lookup (&(htab)->root, sym_name, TRUE, TRUE, TRUE);
+	  stub_entry
+	    = elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
+				     NULL, NULL, bfd_abs_section_ptr, hash,
+				     sym_name, veneer_value,
+				     ST_BRANCH_TO_THUMB, &new_stub);
+	  if (stub_entry == NULL)
+	    ret = FALSE;
+	  else
+	  {
+	    BFD_ASSERT (new_stub);
+	    new_cmse_stubs_created++;
+	    (*cmse_stub_created)++;
+	  }
+	  stub_entry->stub_template_size = stub_entry->stub_size = 0;
+	  stub_entry->stub_offset = stub_offset;
+	}
+      /* Symbol found is not callable from non secure code.  */
+      else if (!stub_entry)
+	{
+	  if (!cmse_entry_fct_p (hash))
+	    {
+	      (*_bfd_error_handler) (_("`%s' refers to a non entry function."),
+				     sym_name);
+	      ret = FALSE;
+	    }
+	  continue;
+	}
+      else
+	{
+	  /* Only stub for SG veneers should have been created.  */
+	  BFD_ASSERT (stub_entry->stub_type == arm_stub_cmse_branch_thumb_only);
+
+	  /* Check visibility hasn't changed.  */
+	  if (!!(flags & BSF_GLOBAL)
+	      != (hash->root.root.type == bfd_link_hash_defined))
+	    (*_bfd_error_handler)
+	      (_("%B: visibility of symbol `%s' has changed."), in_implib_bfd,
+	       sym_name);
+
+	  stub_entry->stub_offset = stub_offset;
+	}
+
+      /* Size should match that of a SG veneer.  */
+      if (intsym->st_size != cmse_stub_size)
+	{
+	  (*_bfd_error_handler) (_("%B: incorrect size for symbol `%s'."),
+				 in_implib_bfd, sym_name);
+	  ret = FALSE;
+	}
+
+      /* Previous veneer address is before current SG veneer section.  */
+      if (veneer_value < cmse_stub_sec_vma)
+	{
+	  /* Avoid offset underflow.  */
+	  if (stub_entry)
+	    stub_entry->stub_offset = 0;
+	  stub_offset = 0;
+	  ret = FALSE;
+	}
+
+      /* Complain if stub offset not a multiple of stub size.  */
+      if (stub_offset % cmse_stub_size)
+	{
+	  (*_bfd_error_handler)
+	    (_("Offset of veneer for entry function `%s' not a multiple of "
+	       "its size."), sym_name);
+	  ret = FALSE;
+	}
+
+      if (!ret)
+	continue;
+
+      new_cmse_stubs_created--;
+      if (veneer_value < cmse_stub_array_start)
+	cmse_stub_array_start = veneer_value;
+      next_cmse_stub_offset = stub_offset + ((cmse_stub_size + 7) & ~7);
+      if (next_cmse_stub_offset > htab->new_cmse_stub_offset)
+	htab->new_cmse_stub_offset = next_cmse_stub_offset;
+    }
+
+  if (!info->out_implib_bfd && new_cmse_stubs_created != 0)
+    {
+      BFD_ASSERT (new_cmse_stubs_created > 0);
+      (*_bfd_error_handler)
+	(_("new entry function(s) introduced but no output import library "
+	   "specified:"));
+      bfd_hash_traverse (&htab->stub_hash_table, arm_list_new_cmse_stub, 
info);
+    }
+
+  if (cmse_stub_array_start != cmse_stub_sec_vma)
+    {
+      (*_bfd_error_handler)
+	(_("Start address of `%s' is different from previous link."),
+	 out_sec_name);
+      ret = FALSE;
+    }
+
+free_sym_buf:
+  free (sympp);
+  return ret;
+}
+
 /* Determine and set the size of the stub section for a final link.
 
    The basic idea here is to examine all the relocations looking for
@@ -5622,7 +5953,9 @@ elf32_arm_size_stubs (bfd *output_bfd,
 						      unsigned int),
 		      void (*layout_sections_again) (void))
 {
+  bfd_boolean ret = TRUE;
   obj_attribute *out_attr;
+  int cmse_stub_created = 0;
   bfd_size_type stub_group_size;
   bfd_boolean m_profile, stubs_always_after_branch, first_veneer_scan = TRUE;
   struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
@@ -5655,6 +5988,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
 
   out_attr = elf_known_obj_attributes_proc (output_bfd);
   m_profile = out_attr[Tag_CPU_arch_profile].i == 'M';
+
   /* The Cortex-A8 erratum fix depends on stubs not being in the same 4K page
      as the first half of a 32-bit branch straddling two 4K pages.  This is a
      crude way of enforcing that.  */
@@ -5728,8 +6062,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
 
 	      sym_hashes = elf_sym_hashes (input_bfd);
 	      if (!cmse_scan (input_bfd, htab, out_attr, sym_hashes,
-			      &stub_changed))
+			      &cmse_stub_created))
 		goto error_ret_free_local;
+
+	      if (cmse_stub_created != 0)
+		stub_changed = TRUE;
 	    }
 
 	  /* Walk over each section attached to the input bfd.  */
@@ -5961,6 +6298,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
 		  do
 		    {
 		      bfd_boolean new_stub;
+		      struct elf32_arm_stub_hash_entry *stub_entry;
 
 		      /* Determine what (if any) linker stub is needed.  */
 		      stub_type = arm_type_of_stub (info, section, irela,
@@ -5972,12 +6310,13 @@ elf32_arm_size_stubs (bfd *output_bfd,
 
 		      /* We've either created a stub for this reloc already,
 			 or we are about to.  */
-		      created_stub =
+		      stub_entry =
 			elf32_arm_create_stub (htab, stub_type, section, irela,
 					       sym_sec, hash,
 					       (char *) sym_name, sym_value,
 					       branch_type, &new_stub);
 
+		      created_stub = stub_entry != NULL;
 		      if (!created_stub)
 			goto error_ret_free_internal;
 		      else if (!new_stub)
@@ -6050,6 +6389,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
 	    }
 	}
 
+      if (first_veneer_scan
+	  && !set_cmse_veneer_addr_from_implib (info, htab,
+						&cmse_stub_created))
+	ret = FALSE;
+
       if (prev_num_a8_fixes != num_a8_fixes)
 	stub_changed = TRUE;
 
@@ -6069,6 +6413,23 @@ elf32_arm_size_stubs (bfd *output_bfd,
 	  stub_sec->size = 0;
 	}
 
+      /* Append new SG veneers after those in input import library.  */
+      for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
+	   stub_type++)
+	{
+	  bfd_vma *start_offset_p;
+	  asection **stub_sec_p;
+
+	  start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type);
+	  stub_sec_p = arm_dedicated_stub_input_section_ptr (htab, stub_type);
+	  if (start_offset_p == NULL)
+	    continue;
+
+	  BFD_ASSERT (stub_sec_p != NULL);
+	  if (*stub_sec_p != NULL)
+	    (*stub_sec_p)->size = *start_offset_p;
+	}
+
       /* Compute stub section size, considering padding.  */
       bfd_hash_traverse (&htab->stub_hash_table, arm_size_one_stub, htab);
       for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
@@ -6137,7 +6498,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
 	    }
 
 	  stub_entry->stub_sec = stub_sec;
-	  stub_entry->stub_offset = 0;
+	  stub_entry->stub_offset = (bfd_vma) -1;
 	  stub_entry->id_sec = link_sec;
 	  stub_entry->stub_type = a8_fixes[i].stub_type;
 	  stub_entry->source_value = a8_fixes[i].offset;
@@ -6165,7 +6526,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
       htab->a8_erratum_fixes = NULL;
       htab->num_a8_erratum_fixes = 0;
     }
-  return TRUE;
+  return ret;
 }
 
 /* Build all the stubs associated with the current output file.  The
@@ -6179,6 +6540,7 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
 {
   asection *stub_sec;
   struct bfd_hash_table *table;
+  enum elf32_arm_stub_type stub_type;
   struct elf32_arm_link_hash_table *htab;
 
   htab = elf32_arm_hash_table (info);
@@ -6196,14 +6558,33 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
 	continue;
 
       /* Allocate memory to hold the linker stubs.  Zeroing the stub sections
-	 must at least be done for stub section requiring padding.  */
+	 must at least be done for stub section requiring padding and for SG
+	 veneers to ensure that a non secure code branching to a removed SG
+	 veneer causes an error.  */
       size = stub_sec->size;
       stub_sec->contents = (unsigned char *) bfd_zalloc (htab->stub_bfd, 
size);
       if (stub_sec->contents == NULL && size != 0)
 	return FALSE;
+
       stub_sec->size = 0;
     }
 
+  /* Append new SG veneers after those in input import library.  */
+  for (stub_type = arm_stub_none + 1; stub_type < max_stub_type; stub_type++)
+    {
+      bfd_vma *start_offset_p;
+      asection **stub_sec_p;
+
+      start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type);
+      stub_sec_p = arm_dedicated_stub_input_section_ptr (htab, stub_type);
+      if (start_offset_p == NULL)
+	continue;
+
+      BFD_ASSERT (stub_sec_p != NULL);
+      if (*stub_sec_p != NULL)
+	(*stub_sec_p)->size = *start_offset_p;
+    }
+
   /* Build the stubs as directed by the stub hash table.  */
   table = &htab->stub_hash_table;
   bfd_hash_traverse (table, arm_build_one_stub, info);
@@ -8189,7 +8570,8 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd,
 				 bfd_arm_stm32l4xx_fix stm32l4xx_fix,
 				 int no_enum_warn, int no_wchar_warn,
 				 int pic_veneer, int fix_cortex_a8,
-				 int fix_arm1176, int cmse_implib)
+				 int fix_arm1176, int cmse_implib,
+				 bfd *in_implib_bfd)
 {
   struct elf32_arm_link_hash_table *globals;
 
@@ -8217,6 +8599,7 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd,
   globals->fix_cortex_a8 = fix_cortex_a8;
   globals->fix_arm1176 = fix_arm1176;
   globals->cmse_implib = cmse_implib;
+  globals->in_implib_bfd = in_implib_bfd;
 
   BFD_ASSERT (is_arm_elf (output_bfd));
   elf_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
index 
c21f6a82335a58a0ab37f3719c73c95e73e6211c..2346bb42444895605d10b7b7e21cca2dcaa38700 
100644
--- a/ld/emultempl/armelf.em
+++ b/ld/emultempl/armelf.em
@@ -43,6 +43,7 @@ static int pic_veneer = 0;
 static int merge_exidx_entries = -1;
 static int fix_arm1176 = 1;
 static int cmse_implib = 0;
+static char *in_implib_filename = NULL;
 
 static void
 gld${EMULATION_NAME}_before_parse (void)
@@ -498,6 +499,8 @@ gld${EMULATION_NAME}_finish (void)
 static void
 arm_elf_create_output_section_statements (void)
 {
+  bfd *in_implib_bfd;
+
   if (strstr (bfd_get_target (link_info.output_bfd), "arm") == NULL)
     {
       /* The arm backend needs special fields in the output hash structure.
@@ -508,6 +511,20 @@ arm_elf_create_output_section_statements (void)
       return;
     }
 
+  if (in_implib_filename)
+    {
+      in_implib_bfd = bfd_openr (in_implib_filename,
+				 bfd_get_target (link_info.output_bfd));
+
+      if (in_implib_bfd == NULL)
+	einfo ("%F%s: Can't open: %E\n", in_implib_filename);
+
+      if (!bfd_check_format (in_implib_bfd, bfd_object))
+	einfo ("%F%s: Not a relocatable file: %E\n", in_implib_filename);
+    }
+  else
+    in_implib_bfd = NULL;
+
   bfd_elf32_arm_set_target_relocs (link_info.output_bfd, &link_info,
 				   target1_is_rel,
 				   target2_type, fix_v4bx, use_blx,
@@ -515,7 +532,7 @@ arm_elf_create_output_section_statements (void)
 				   no_enum_size_warning,
 				   no_wchar_size_warning,
 				   pic_veneer, fix_cortex_a8,
-				   fix_arm1176, cmse_implib);
+				   fix_arm1176, cmse_implib, in_implib_bfd);
 
   stub_file = lang_add_input_file ("linker stubs",
  				   lang_input_file_is_fake_enum,
@@ -585,6 +602,7 @@ PARSE_AND_LIST_PROLOGUE='
 #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
@@ -612,6 +630,7 @@ PARSE_AND_LIST_LONGOPTS='
   { "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='
@@ -634,6 +653,8 @@ PARSE_AND_LIST_OPTIONS='
            "                              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\
@@ -758,6 +779,10 @@ PARSE_AND_LIST_ARGS_CASES='
    case OPTION_CMSE_IMPLIB:
       cmse_implib = 1;
       break;
+
+   case OPTION_IN_IMPLIB:
+      in_implib_filename = optarg;
+      break;
 '
 
 # We have our own before_allocation etc. functions, but they call
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 
e6813f287fe5ce4c916bf93f48b2e9edbc336570..5994d2efc7a2406d0dcddbd2fe7eeefab910534a 
100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -6866,6 +6866,18 @@ specified by the @samp{--out-implib} and @samp{--in-
implib} options are
 secure gateway import libraries, suitable for linking a non-secure
 executable against secure code as per ARMv8-M Security Extensions.
 
+@kindex --in-implib=@var{file}
+@cindex Input import library
+The @samp{--in-implib=file} specifies an input import library whose symbols
+must keep the same address in the executable being produced.  A warning is
+given if no @samp{--out-implib} is given but new symbols have been introduced
+in the executable that should be listed in its import library.  Otherwise, if
+@samp{--out-implib} is specified, the symbols are silently added to the output
+import library.  A warning is also given if some symbols present in the input
+import library have disappeared from the executable.  This option is only
+effective for Secure Gateway import libraries, ie. when @samp{--cmse-implib} 
is
+specified.
+
 @ifclear GENERIC
 @lowersections
 @end ifclear
diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
index 
2efc047a63d6d5e3250a3259e01633394f102ac0..019f00abf6e43883c052a1b3f5f4d913f2dc0039 
100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -661,16 +661,53 @@ set armeabitests_nonacl {
      "cmse-veneers-mainline"}
     {"Secure gateway import library generation: errors"
      "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-
implib.lib --cmse-implib" ""
-     "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1"
+     "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1 --defsym VER=1"
      {cmse-implib.s}
      {{ld cmse-implib-errors.out}}
      "cmse-implib"}
     {"Secure gateway import library generation"
      "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-
implib.lib --cmse-implib" ""
-     "-march=armv8-m.base -mthumb"
+     "-march=armv8-m.base -mthumb --defsym VER=1"
      {cmse-implib.s}
      {{readelf {-s tmpdir/cmse-implib.lib} cmse-implib.rd}}
      "cmse-implib"}
+    {"Input secure gateway import library"
+     "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-new-
implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=2"
+     {cmse-implib.s}
+     {{ld cmse-new-implib.out}
+      {readelf {-s tmpdir/cmse-new-implib.lib} cmse-new-implib.rd}}
+     "cmse-new-implib"}
+    {"Input secure gateway import library: no output import library"
+     "--section-start .gnu.sgstubs=0x20000 --in-implib=tmpdir/cmse-implib.lib 
--cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=2"
+     {cmse-implib.s}
+     {{ld cmse-new-implib-no-output.out}}
+     "cmse-new-implib-no-output"}
+    {"Input secure gateway import library: earlier stub section base"
+     "--section-start .gnu.sgstubs=0x19000 --out-implib=tmpdir/cmse-new-
earlier-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=2"
+     {cmse-implib.s}
+     {{ld cmse-new-earlier-later-implib.out}}
+     "cmse-new-earlier-implib"}
+    {"Input secure gateway import library: later stub section base"
+     "--section-start .gnu.sgstubs=0x30000 --out-implib=tmpdir/cmse-new-
later-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=2"
+     {cmse-implib.s}
+     {{ld cmse-new-earlier-later-implib.out}}
+     "cmse-new-later-implib"}
+    {"Input secure gateway import library: veneer comeback"
+     "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-new-
comeback-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=3"
+     {cmse-implib.s}
+     {{readelf {-s tmpdir/cmse-new-comeback-implib.lib} cmse-new-comeback-
implib.rd}}
+     "cmse-new-comeback-implib"}
+    {"Input secure gateway import library: entry function change"
+     "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-new-
wrong-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=4"
+     {cmse-implib.s}
+     {{ld cmse-new-wrong-implib.out}}
+     "cmse-new-wrong-implib"}
 
     {"R_ARM_THM_JUMP19 Relocation veneers: Short"
      "--section-start destsect=0x000108002 --section-start .text=0x8000" ""
diff --git a/ld/testsuite/ld-arm/cmse-implib.s b/ld/testsuite/ld-arm/cmse-
implib.s
index 
a42da63fffebe5322be83f278931754262b0f7ae..9dd783939891478351a5f7ccb1480980a77dca68 
100644
--- a/ld/testsuite/ld-arm/cmse-implib.s
+++ b/ld/testsuite/ld-arm/cmse-implib.s
@@ -20,12 +20,29 @@ __acle_se_\name:
 .endm
 
 	@ Valid setups for veneer generation
+.if (VER >= 2)
+	entry exported_entry_veneer1, global
+.endif
+.if (VER != 4)
 	entry exported_entry_veneer2, global
+.else
+	entry exported_entry_veneer2, weak
+.endif
+.if (VER != 2)
 	entry exported_entry_veneer3, global
+.endif
+.if (VER > 1)
+	entry exported_entry_veneer4, global
+.endif
 
 	@ Valid setup for entry function without veneer generation
 	entry exported_entry_fct1, global, sg
+.if (VER != 4)
 	entry exported_entry_fct2, global, sg
+.else
+	@ Invalid setup for entry function without veneer generation
+	entry exported_entry_fct2, global, nop
+.endif
 
 	@ Normal symbol not exported to SG import library
 	.align	2
diff --git a/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd b/ld/testsuite/ld-
arm/cmse-new-comeback-implib.rd
new file mode 100644
index 
0000000000000000000000000000000000000000..c88d9d5104244abc8ceba4d552e1ef0e400c37d1
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd
@@ -0,0 +1,15 @@
+File: tmpdir/cmse-new-.*implib.lib
+
+Symbol table '.symtab' contains 7 entries:
+   Num:    Value  Size Type    Bind   Vis      Ndx Name
+     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
+     1: 00020001     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer3
+     2: 00020011     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer4
+     3: 00020019     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer1
+     4: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
+     5: 00020009     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer2
+     6: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
+
+File: tmpdir/cmse-new-.*implib
+
+#...
diff --git a/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out 
b/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
new file mode 100644
index 
0000000000000000000000000000000000000000..b49ad0ac0770a17c39c2d119d1f0c5854a5bd8cc
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
@@ -0,0 +1,3 @@
+.*: Entry function `exported_entry_veneer3' disappeared from secure code.
+.*: Start address of `.gnu.sgstubs' is different from previous link.
+.*: cannot size stub section: Invalid operation
diff --git a/ld/testsuite/ld-arm/cmse-new-implib-no-output.out 
b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
new file mode 100644
index 
0000000000000000000000000000000000000000..0590b71c844da3687b29b93797abda5172ab8d99
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
@@ -0,0 +1,4 @@
+.*: Entry function `exported_entry_veneer3' disappeared from secure code.
+.*: new entry function\(s\) introduced but no output import library specified:
+.*:   exported_entry_veneer4
+.*:   exported_entry_veneer1
diff --git a/ld/testsuite/ld-arm/cmse-new-implib.out b/ld/testsuite/ld-
arm/cmse-new-implib.out
new file mode 100644
index 
0000000000000000000000000000000000000000..c8af2807e7c1a7eeb1fc156fbf4508cf7a7e932d
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-implib.out
@@ -0,0 +1 @@
+.*: Entry function `exported_entry_veneer3' disappeared from secure code.
diff --git a/ld/testsuite/ld-arm/cmse-new-implib.rd b/ld/testsuite/ld-arm/cmse-
new-implib.rd
new file mode 100644
index 
0000000000000000000000000000000000000000..9ff0fd87937571f86f99ee940a91a3f67352242a
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-implib.rd
@@ -0,0 +1,14 @@
+File: tmpdir/cmse-new-.*implib.lib
+
+Symbol table '.symtab' contains 6 entries:
+   Num:    Value  Size Type    Bind   Vis      Ndx Name
+     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
+     1: 00020011     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer4
+     2: 00020019     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer1
+     3: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
+     4: 00020009     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer2
+     5: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
+
+File: tmpdir/cmse-new-.*implib
+
+#...
diff --git a/ld/testsuite/ld-arm/cmse-new-wrong-implib.out b/ld/testsuite/ld-
arm/cmse-new-wrong-implib.out
new file mode 100644
index 
0000000000000000000000000000000000000000..2afe4078e78606d24f05dda6ff1c5e6a54d42512
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
@@ -0,0 +1,3 @@
+.*: .*: visibility of symbol `exported_entry_veneer2' has changed.
+.*: `exported_entry_fct2' refers to a non entry function.
+.*: cannot size stub section: Invalid operation


Best regards,

Thomas

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ARM 11/11] Add support for stable secure gateway veneers addresses
  2016-04-04 14:23 ` [RFC PATCH, binutils, ARM 11/11] " Thomas Preudhomme
  2016-05-18 16:41   ` [PATCH, " Thomas Preudhomme
@ 2016-07-07 12:52   ` Richard Earnshaw (lists)
       [not found]     ` <1735561.4TLJhTojVK@e108577-lin>
       [not found]     ` <4163700.8nzTNaTl0I@e108577-lin>
  1 sibling, 2 replies; 15+ messages in thread
From: Richard Earnshaw (lists) @ 2016-07-07 12:52 UTC (permalink / raw)
  To: Thomas Preudhomme, binutils

On 04/04/16 15:22, Thomas Preudhomme wrote:
> On Wednesday 23 December 2015 16:02:48 Thomas Preud'homme wrote:
>> Hi,
>>
>> [Posting patch series as RFC]
>>
>> This patch is part of a patch series to add support for ARMv8-M security
>> extension[1] to GNU ld. This specific patch adds support for allowing
>> Secure Gateway veneers to have stable addresses when relinking a secure
>> executable.
>>
>> ARM v8-M security extensions allow code running in a device to be divided
>> into secure and non-secure code expected to be developed by independent
>> (teams of) people. To allow updating the secure code without the need to
>> relink the non-secure code against it, it is necessary for the toolchain to
>> provide a way to fix the addresses of the secure gateway veneers that serve
>> as entry points for non-secure code to call secure code. This is also a
>> requirement [2] to claim support for ARM v8-M security extensions.
>>
>> This patch adds a --in-implib=<in_implib_filename> option which, when used
>> in conjunction of --cmse-implib will ensure that the veneers whose symbols
>> are defined in the import library $in_implib_filename will remain at the
>> same address in the executable. In the absence of a --out-implib option,
>> the code will warn about new secure gateway veneers being created,
>> otherwise these are allowed.
>>
>>
>> [1] Software requirements for ARMv8-M security extension are described in
>> document ARM-ECM-0359818 [2] [2] Available on http://infocenter.arm.com in
>> Developer guides and articles > Software development > ARM®v8-M Security
>> Extensions: Requirements on Development Tools [3] See requirement 15 of
>> ARM-ECM-0359818 [2]
> 
> Please find an updated patch below.

Comments inline.

> 
> *** bfd/ChangeLog ***
> 
> 2016-02-18  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> 
>         * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new parameter for
>         the input import library bfd.
>         * bfd-in2.h: Regenerate.
>         * elf32-arm.c (struct elf32_arm_link_hash_table): New in_implib_bfd
>         and new_cmse_stub_offset fields.
>         (stub_hash_newfunc): Initialize stub_offset and stub_template_size to
>         -1.
>         (elf32_arm_add_stub): Likewise for stub_offset.
>         (arm_new_stubs_start_offset_ptr): New function.
>         (arm_build_one_stub): Only allocate a stub_offset if it is -1.  Allow
>         empty veneers to have zero relocations.
>         (arm_size_one_stub): Only initialize stub size and template
>         information for non empty veneers.  Do not update veneer section size
>         if veneer already has an offset.
>         (elf32_arm_create_stub): Return the stub entry pointer or NULL instead
>         of a boolean indicating success or failure.
>         (cmse_scan): Change stub_changed parameter into an integer pointer
>         parameter cmse_stub_created to count the number of stub created and
>         adapt to change of return value in elf32_arm_create_stub.
>         (cmse_entry_fct_p): New function.
>         (arm_list_new_cmse_stub): Likewise.
>         (set_cmse_veneer_addr_from_implib): Likewise.
>         (elf32_arm_size_stubs): Define cmse_stub_created, pass its address to
>         cmse_scan instead of that of cmse_stub_changed to compute the number
>         of stub created and use it to initialize stub_changed.  Call
>         set_cmse_veneer_addr_from_implib after all cmse_scan.  Adapt to change
>         of return value in elf32_arm_create_stub.  Use
>         arm_stub_section_start_offset () if not NULL to initialize size of
>         secure gateway veneers section.  Initialize stub_offset of Cortex-A8
>         erratum fix to -1.  Use ret to hold return value.
>         (elf32_arm_build_stubs): Use arm_stub_section_start_offset () if not
>         NULL to initialize size of secure gateway veneers section.  Adapt
>         comment to stress the importance of zeroing veneer section content.
>         (bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd parameter to
>         initialize eponymous field in struct elf32_arm_link_hash_table.
> 
> 
> *** ld/ChangeLog ***
> 
> 2016-02-18  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> 
>         * emultempl/armelf.em (in_implib_filename): Declare and initialize new
>         variable. 
>         (arm_elf_create_output_section_statements): Open import input library
>         file for writing and pass resulting in_implib_bfd to
>         bfd_elf32_arm_set_target_relocs.
>         (PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option.
>         (PARSE_AND_LIST_LONGOPTS): Define --in-implib option.
>         (PARSE_AND_LIST_OPTIONS): Add help message for --in-implib option.
>         (PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case.
>         * ld.texinfo (--cmse-implib): Update to mention --in-implib.
>         (--in-implib): Document new option.
>         * testsuite/ld-arm/arm-elf.exp
>         (Secure gateway import library generation): add --defsym VER=1 to gas
>         CLI.
>         (Secure gateway import library generation: errors): Likewise.
>         (Input secure gateway import library): New test.
>         (Input secure gateway import library: no output import library):
>         Likewise. 
>         (Input secure gateway import library: earlier stub section base):
>         Likewise.
>         (Input secure gateway import library: later stub section base):
>         Likewise.
>         (Input secure gateway import library: veneer comeback): Likewise.
>         (Input secure gateway import library: entry function change): 
>         Likewise.
>         * testsuite/ld-arm/cmse-implib.s: Add input import library testing.
>         * testsuite/ld-arm/cmse-implib.rd: Update accordingly.
>         * testsuite/ld-arm/cmse-new-implib.out: New file.
>         * testsuite/ld-arm/cmse-new-implib.rd: Likewise.
>         * testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise.
>         * testsuite/ld-arm/cmse-new-earlier-later-implib.out: Likewise.
>         * testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise.
>         * testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise.
> 
> 
> diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
> index 
> 7e3483b9984b04c534e53f2f9026abf26d37592a..423c534a954c541e227e731e9256f08f9fa62014 
> 100644
> --- a/bfd/bfd-in.h
> +++ b/bfd/bfd-in.h
> @@ -895,7 +895,7 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation
>  
>  void bfd_elf32_arm_set_target_relocs
>    (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix,
> -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
> +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
>  
>  extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
>    (bfd *, struct bfd_link_info *);
> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
> index 
> 55e1cdde2d0a899238a224c6915d20197b72f085..3a67fa637f5c709cddf3767496e4ac8796287765 
> 100644
> --- a/bfd/bfd-in2.h
> +++ b/bfd/bfd-in2.h
> @@ -902,7 +902,7 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation
>  
>  void bfd_elf32_arm_set_target_relocs
>    (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix,
> -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
> +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);

This is *only* one more parameter to this function, but it now takes 15,
which seems excessive.

Some redesign may be in order here...

>  
>  extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
>    (bfd *, struct bfd_link_info *);
> diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
> index 
> 0357fdab5cc77c3b0e983d1cb9b0285753bd5c65..be1d7224148f95bf097bb3fea63de2081f93aab9 
> 100644
> --- a/bfd/elf32-arm.c
> +++ b/bfd/elf32-arm.c
> @@ -3127,6 +3127,10 @@ struct elf32_arm_link_hash_table
>       as per ARMv8-M Security Extensions.  */
>    int cmse_implib;
>  
> +  /* The import library whose symbols' address must remain stable in
> +     the import library generated.  */
> +  bfd *in_implib_bfd;
> +
>    /* The index of the next unused R_ARM_TLS_DESC slot in .rel.plt.  */
>    bfd_vma next_tls_desc_index;
>  
> @@ -3188,6 +3192,10 @@ struct elf32_arm_link_hash_table
>    /* Input stub section holding secure gateway veneers.  */
>    asection *cmse_stub_sec;
>  
> +  /* Offset in cmse_stub_sec where new SG veneers (not in input import 
> library)
> +     start to be allocated.  */
> +  bfd_vma new_cmse_stub_offset;
> +
>    /* Number of elements in stub_group.  */
>    unsigned int top_id;
>  
> @@ -3439,7 +3447,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
>        /* Initialize the local fields.  */
>        eh = (struct elf32_arm_stub_hash_entry *) entry;
>        eh->stub_sec = NULL;
> -      eh->stub_offset = 0;
> +      eh->stub_offset = (bfd_vma) -1;
>        eh->source_value = 0;
>        eh->target_value = 0;
>        eh->target_section = NULL;
> @@ -3447,7 +3455,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
>        eh->stub_type = arm_stub_none;
>        eh->stub_size = 0;
>        eh->stub_template = NULL;
> -      eh->stub_template_size = 0;
> +      eh->stub_template_size = -1;
>        eh->h = NULL;
>        eh->id_sec = NULL;
>        eh->output_name = NULL;
> @@ -4361,7 +4369,7 @@ elf32_arm_add_stub (const char *stub_name, asection 
> *section,
>      }
>  
>    stub_entry->stub_sec = stub_sec;
> -  stub_entry->stub_offset = 0;
> +  stub_entry->stub_offset = (bfd_vma) -1;
>    stub_entry->id_sec = link_sec;
>  
>    return stub_entry;
> @@ -4525,6 +4533,46 @@ arm_dedicated_stub_section_padding (enum 
> elf32_arm_stub_type stub_type)
>    abort ();  /* Should be unreachable.  */
>  }
>  
> +/* If veneers of type STUB_TYPE should go in a dedicated output section,
> +   returns the address of the hash table field in HTAB holding the offset at
> +   which new veneers should be layed out in the stub section.  */
> +
> +static bfd_vma*
> +arm_new_stubs_start_offset_ptr (struct elf32_arm_link_hash_table *htab,
> +				enum elf32_arm_stub_type stub_type)
> +{
> +  switch (stub_type)
> +    {
> +    case arm_stub_a8_veneer_b_cond:
> +    case arm_stub_a8_veneer_b:
> +    case arm_stub_a8_veneer_bl:
> +    case arm_stub_long_branch_any_any:
> +    case arm_stub_long_branch_v4t_arm_thumb:
> +    case arm_stub_long_branch_thumb_only:
> +    case arm_stub_long_branch_v4t_thumb_thumb:
> +    case arm_stub_long_branch_v4t_thumb_arm:
> +    case arm_stub_short_branch_v4t_thumb_arm:
> +    case arm_stub_long_branch_any_arm_pic:
> +    case arm_stub_long_branch_any_thumb_pic:
> +    case arm_stub_long_branch_v4t_thumb_thumb_pic:
> +    case arm_stub_long_branch_v4t_arm_thumb_pic:
> +    case arm_stub_long_branch_v4t_thumb_arm_pic:
> +    case arm_stub_long_branch_thumb_only_pic:
> +    case arm_stub_long_branch_any_tls_pic:
> +    case arm_stub_long_branch_v4t_thumb_tls_pic:
> +    case arm_stub_a8_veneer_blx:
> +    case arm_stub_long_branch_arm_nacl:
> +    case arm_stub_long_branch_arm_nacl_pic:
> +      return NULL;
> +
> +    case arm_stub_cmse_branch_thumb_only:
> +      return &htab->new_cmse_stub_offset;
> +
> +    default:
> +      abort ();  /* Should be unreachable.  */
> +    }
> +}
> +
>  static bfd_boolean
>  arm_build_one_stub (struct bfd_hash_entry *gen_entry,
>  		    void * in_arg)
> @@ -4544,6 +4592,7 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
>    int stub_reloc_idx[MAXRELOCS] = {-1, -1};
>    int stub_reloc_offset[MAXRELOCS] = {0, 0};
>    int nrelocs = 0;
> +  int just_allocated = 0;
>  
>    /* Massage our args to the form they really have.  */
>    stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
> @@ -4560,8 +4609,12 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
>      /* We have to do less-strictly-aligned fixes last.  */
>      return TRUE;
>  
> -  /* Make a note of the offset within the stubs for this entry.  */
> -  stub_entry->stub_offset = stub_sec->size;
> +  /* Assign a slot at the end of section if none assigned yet.  */
> +  if (stub_entry->stub_offset == (bfd_vma) -1)
> +    {
> +      stub_entry->stub_offset = stub_sec->size;
> +      just_allocated = 1;
> +    }
>    loc = stub_sec->contents + stub_entry->stub_offset;
>  
>    stub_bfd = stub_sec->owner;
> @@ -4635,7 +4688,8 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
>  	}
>      }
>  
> -  stub_sec->size += size;
> +  if (just_allocated)
> +    stub_sec->size += size;
>  
>    /* Stub size has already been computed in arm_size_one_stub. Check
>       consistency.  */
> @@ -4647,7 +4701,7 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
>  
>    /* Assume there is at least one and at most MAXRELOCS entries to relocate
>       in each stub.  */
> -  BFD_ASSERT (nrelocs != 0 && nrelocs <= MAXRELOCS);
> +  BFD_ASSERT (size == 0 || (nrelocs != 0 && nrelocs <= MAXRELOCS));

The comment no-longer matches the assert.  Direct use of size is also
confusing.  It might be clearer if you create a new bool variable which
is set to true iff size is zero and makes the code that follows easier
to comprehend.

>  
>    for (i = 0; i < nrelocs; i++)
>      {
> @@ -4749,9 +4803,17 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry,
>    size = find_stub_size_and_template (stub_entry->stub_type, 
> &template_sequence,
>  				      &template_size);
>  
> -  stub_entry->stub_size = size;
> -  stub_entry->stub_template = template_sequence;
> -  stub_entry->stub_template_size = template_size;
> +  /* Initialized to -1.  Null size indicates a zeroed out veneer.  */

Err, what's a zeroed out veneer?

> +  if (stub_entry->stub_template_size)
> +    {
> +      stub_entry->stub_size = size;
> +      stub_entry->stub_template = template_sequence;
> +      stub_entry->stub_template_size = template_size;
> +    }
> +
> +  /* Already accounted for.  */
> +  if (stub_entry->stub_offset != (bfd_vma) -1)
> +    return TRUE;
>  
>    size = (size + 7) & ~7;
>    stub_entry->stub_sec->size += size;
> @@ -5316,10 +5378,10 @@ cortex_a8_erratum_scan (bfd *input_bfd,
>     and *NEW_STUB is set to FALSE.  Otherwise, *NEW_STUB is set to
>     TRUE and the stub entry is initialized.
>  
> -   Returns whether the stub could be successfully created or updated, or 
> FALSE
> -   if an error occured.  */
> +   Returns the stub that was created or updated, or NULL if an error
> +   occured.  */

s/occured/occurred/  (at least according to my dictionary).


>  
> -static bfd_boolean
> +static struct elf32_arm_stub_hash_entry *
>  elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
>  		       enum elf32_arm_stub_type stub_type, asection *section,
>  		       Elf_Internal_Rela *irela, asection *sym_sec,
> @@ -5350,7 +5412,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table 
> *htab,
>        stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash, irela,
>  				       stub_type);
>        if (!stub_name)
> -	return FALSE;
> +	return NULL;
>      }
>  
>    stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, stub_name, 
> FALSE,
> @@ -5361,7 +5423,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table 
> *htab,
>        if (!sym_claimed)
>  	free (stub_name);
>        stub_entry->target_value = sym_value;
> -      return TRUE;
> +      return stub_entry;
>      }
>  
>    stub_entry = elf32_arm_add_stub (stub_name, section, htab, stub_type);
> @@ -5369,7 +5431,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table 
> *htab,
>      {
>        if (!sym_claimed)
>  	free (stub_name);
> -      return FALSE;
> +      return NULL;
>      }
>  
>    stub_entry->target_value = sym_value;
> @@ -5390,7 +5452,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table 
> *htab,
>        if (stub_entry->output_name == NULL)
>  	{
>  	  free (stub_name);
> -	  return FALSE;
> +	  return NULL;
>  	}
>  
>        /* For historical reasons, use the existing names for ARM-to-Thumb and
> @@ -5410,7 +5472,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table 
> *htab,
>      }
>  
>    *new_stub = TRUE;
> -  return TRUE;
> +  return stub_entry;
>  }
>  
>  /* Scan symbols in INPUT_BFD to identify secure entry functions needing a
> @@ -5427,14 +5489,15 @@ elf32_arm_create_stub (struct 
> elf32_arm_link_hash_table *htab,
>  
>     OUT_ATTR gives the output attributes, SYM_HASHES the symbol index to hash
>     entry mapping while HTAB gives the name to hash entry mapping.
> +   *CMSE_STUB_CREATED is increased by the number of secure gateway veneer
> +   created.
>  
> -   If any secure gateway veneer is created, *STUB_CHANGED is set to TRUE.  
> The
> -   return value gives whether a stub failed to be allocated.  */
> +   The return value gives whether a stub failed to be allocated.  */
>  
>  static bfd_boolean
>  cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
>  	   obj_attribute *out_attr, struct elf_link_hash_entry **sym_hashes,
> -	   bfd_boolean *stub_changed)
> +	   int *cmse_stub_created)
>  {
>    const struct elf_backend_data *bed;
>    Elf_Internal_Shdr *symtab_hdr;
> @@ -5445,7 +5508,8 @@ cmse_scan (bfd *input_bfd, struct 
> elf32_arm_link_hash_table *htab,
>    char *sym_name, *lsym_name;
>    bfd_vma sym_value;
>    asection *section;
> -  bfd_boolean is_v8m, new_stub, created_stub, cmse_invalid, ret = TRUE;
> +  struct elf32_arm_stub_hash_entry *stub_entry;
> +  bfd_boolean is_v8m, new_stub, cmse_invalid, ret = TRUE;
>  
>    bed = get_elf_backend_data (input_bfd);
>    symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
> @@ -5586,17 +5650,17 @@ cmse_scan (bfd *input_bfd, struct 
> elf32_arm_link_hash_table *htab,
>        if (!ret)
>  	continue;
>        branch_type = ARM_GET_SYM_BRANCH_TYPE (hash->root.target_internal);
> -      created_stub
> +      stub_entry
>  	= elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
>  				 NULL, NULL, section, hash, sym_name,
>  				 sym_value, branch_type, &new_stub);
>  
> -      if (!created_stub)
> +      if (stub_entry == NULL)
>  	 ret = FALSE;
>        else
>  	{
>  	  BFD_ASSERT (new_stub);
> -	  *stub_changed = TRUE;
> +	  (*cmse_stub_created)++;
>  	}
>      }
>  
> @@ -5605,6 +5669,273 @@ cmse_scan (bfd *input_bfd, struct 
> elf32_arm_link_hash_table *htab,
>    return ret;
>  }
>  
> +/* Return whether a symbol identified by its linker HASH entry is an entry
s/an entry/a secure code entry/

Entry function is ambiguous.

As a style point it's probably better to start with

Return TRUE iff a symbol ...



> +   function, ie can be called from non secure code without using a veneer.  
> */
> +
> +static bfd_boolean
> +cmse_entry_fct_p (struct elf32_arm_link_hash_entry *hash)
> +{
> +  uint32_t first_insn;
> +  asection *section;
> +  file_ptr offset;
> +  bfd *abfd;
> +
> +  /* Defined symbol of function type.  */
> +  if (hash->root.root.type != bfd_link_hash_defined
> +      && hash->root.root.type != bfd_link_hash_defweak)
> +    return FALSE;
> +  if (hash->root.type != STT_FUNC)
> +    return FALSE;
> +
> +  /* Read first instruction.  */
> +  section = hash->root.root.u.def.section;
> +  abfd = section->owner;
> +  offset = hash->root.root.u.def.value - section->vma;
> +  if (!bfd_get_section_contents (abfd, section, &first_insn, offset,
> +				 sizeof (first_insn)))
> +    return FALSE;
> +
> +  /* Start by SG instruction.  */
> +  return first_insn == 0xe97fe97f;
> +}
> +
> +/* Output the name (in symbol table) of the veneer GEN_ENTRY if it is a new
> +   secure gateway veneers (ie. the veneers was not in the input import 
> library)
> +   and there is no output import library (GEN_INFO->out_implib_bfd is NULL.  
> */
> +
> +static bfd_boolean
> +arm_list_new_cmse_stub (struct bfd_hash_entry *gen_entry, void *gen_info)
> +{
> +  struct elf32_arm_stub_hash_entry *stub_entry;
> +  struct bfd_link_info *info;
> +
> +  /* Massage our args to the form they really have.  */
> +  stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
> +  info = (struct bfd_link_info *) gen_info;
> +
> +  if (info->out_implib_bfd)
> +    return TRUE;
> +
> +  if (stub_entry->stub_type != arm_stub_cmse_branch_thumb_only)
> +    return TRUE;
> +
> +  if (stub_entry->stub_offset == (bfd_vma) -1)
> +    (*_bfd_error_handler) ("  %s", stub_entry->output_name);
> +
> +  return TRUE;
> +}
> +
> +/* Set offset of secure gateway veneers so that their address remain identical

Set the offset of each s g v so that *its* address remains...


> +   to the one in the input import library referred by HTAB->in_implib_bfd.  A
> +   warning is issued for veneers that disappeared (present in input import
> +   library but absent from the executable being linked) or if new veneers
> +   appeared and there is no output import library (INFO->out_implib_bfd is 
> NULL
> +   and *CMSE_STUB_CREATED is bigger than the number of secure gateway veneers
> +   found in the input import library.
> +
> +   The function returns whether an error occured.  If no error occured,
> +   *CMSE_STUB_CREATED gives the number of SG veneers created by both 
> cmse_scan
> +   and this function and HTAB->new_cmse_stub_offset is set to the biggest
> +   veneer observed set for new veneers to be layed out after.  */
> +
> +static bfd_boolean
> +set_cmse_veneer_addr_from_implib (struct bfd_link_info *info,
> +				  struct elf32_arm_link_hash_table *htab,
> +				  int *cmse_stub_created)
> +{
> +  long symsize;
> +  char *sym_name;
> +  flagword flags;
> +  long i, symcount;
> +  bfd *in_implib_bfd;
> +  asection *stub_out_sec;
> +  bfd_boolean ret = TRUE;
> +  Elf_Internal_Sym *intsym;
> +  const char *out_sec_name;
> +  bfd_size_type cmse_stub_size;
> +  asymbol **sympp = NULL, *sym;
> +  struct elf32_arm_link_hash_entry *hash;
> +  const insn_sequence *cmse_stub_template;
> +  struct elf32_arm_stub_hash_entry *stub_entry;
> +  int cmse_stub_template_size, new_cmse_stubs_created = *cmse_stub_created;
> +  bfd_vma veneer_value, stub_offset, next_cmse_stub_offset;
> +  bfd_vma cmse_stub_array_start = (bfd_vma) -1, cmse_stub_sec_vma = 0;
> +
> +  /* No input secure gateway import library.  */
> +  if (!htab->in_implib_bfd)
> +    return TRUE;
> +  else if (!htab->cmse_implib)
> +    return FALSE;
> +
> +  /* Get symbol table size.  */
> +  in_implib_bfd = htab->in_implib_bfd;
> +  symsize = bfd_get_symtab_upper_bound (in_implib_bfd);
> +  if (symsize < 0)
> +    return FALSE;
> +
> +  /* Read in the input secure gateway import library's symbol table.  */
> +  sympp = (asymbol **) xmalloc (symsize);
> +  symcount = bfd_canonicalize_symtab (in_implib_bfd, sympp);
> +  if (symcount < 0)
> +    {
> +      ret = FALSE;
> +      goto free_sym_buf;
> +    }
> +
> +  htab->new_cmse_stub_offset = 0;
> +  cmse_stub_size =
> +    find_stub_size_and_template (arm_stub_cmse_branch_thumb_only,
> +				 &cmse_stub_template,
> +				 &cmse_stub_template_size);
> +  out_sec_name =
> +    arm_dedicated_stub_output_section_name (arm_stub_cmse_branch_thumb_only);
> +  stub_out_sec =
> +    bfd_get_section_by_name (htab->obfd, out_sec_name);
> +  if (stub_out_sec != NULL)
> +    cmse_stub_sec_vma = stub_out_sec->vma;
> +
> +  /* Set addresses of veneers mentionned in input secure gateway import
> +     library's symbol table.  */
> +  for (i = 0; i < symcount; i++)
> +    {
> +      sym = sympp[i];
> +      flags = sym->flags;
> +      sym_name = (char *) bfd_asymbol_name (sym);
> +      intsym = &((elf_symbol_type *) sym)->internal_elf_sym;
> +
> +      if (sym->section != bfd_abs_section_ptr
> +	  || !(flags & (BSF_GLOBAL | BSF_WEAK))
> +	  || (flags & BSF_FUNCTION) != BSF_FUNCTION
> +	  || (ARM_GET_SYM_BRANCH_TYPE (intsym->st_target_internal)
> +	      != ST_BRANCH_TO_THUMB))
> +	{
> +	  (*_bfd_error_handler) (_("%B: invalid import library entry: `%s'."),
> +				 in_implib_bfd, sym_name);
> +	  (*_bfd_error_handler) (_("Symbol should be absolute, global and "
> +				   "refer to Thumb functions."));
> +	  ret = FALSE;
> +	  continue;
> +	}
> +
> +      veneer_value = bfd_asymbol_value (sym);
> +      stub_offset = veneer_value - cmse_stub_sec_vma;
> +      stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, sym_name,
> +					 FALSE, FALSE);
> +      hash = (struct elf32_arm_link_hash_entry *)
> +	elf_link_hash_lookup (&(htab)->root, sym_name, FALSE, FALSE, TRUE);
> +
> +      /* Stub entry should have been created by cmse_scan or the symbol be of
> +	 a secure function callable from non secure code.  */
> +      if (!stub_entry && !hash)
> +	{
> +	  bfd_boolean new_stub;
> +
> +	  (*_bfd_error_handler)
> +	    (_("Entry function `%s' disappeared from secure code."), sym_name);
> +	  hash = (struct elf32_arm_link_hash_entry *)
> +	    elf_link_hash_lookup (&(htab)->root, sym_name, TRUE, TRUE, TRUE);
> +	  stub_entry
> +	    = elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
> +				     NULL, NULL, bfd_abs_section_ptr, hash,
> +				     sym_name, veneer_value,
> +				     ST_BRANCH_TO_THUMB, &new_stub);
> +	  if (stub_entry == NULL)
> +	    ret = FALSE;
> +	  else
> +	  {
> +	    BFD_ASSERT (new_stub);
> +	    new_cmse_stubs_created++;
> +	    (*cmse_stub_created)++;
> +	  }
> +	  stub_entry->stub_template_size = stub_entry->stub_size = 0;
> +	  stub_entry->stub_offset = stub_offset;
> +	}
> +      /* Symbol found is not callable from non secure code.  */
> +      else if (!stub_entry)
> +	{
> +	  if (!cmse_entry_fct_p (hash))
> +	    {
> +	      (*_bfd_error_handler) (_("`%s' refers to a non entry function."),
> +				     sym_name);
> +	      ret = FALSE;
> +	    }
> +	  continue;
> +	}
> +      else
> +	{
> +	  /* Only stub for SG veneers should have been created.  */

stubs

> +	  BFD_ASSERT (stub_entry->stub_type == arm_stub_cmse_branch_thumb_only);
> +
> +	  /* Check visibility hasn't changed.  */
> +	  if (!!(flags & BSF_GLOBAL)
> +	      != (hash->root.root.type == bfd_link_hash_defined))
> +	    (*_bfd_error_handler)
> +	      (_("%B: visibility of symbol `%s' has changed."), in_implib_bfd,
> +	       sym_name);
> +
> +	  stub_entry->stub_offset = stub_offset;
> +	}
> +
> +      /* Size should match that of a SG veneer.  */
> +      if (intsym->st_size != cmse_stub_size)
> +	{
> +	  (*_bfd_error_handler) (_("%B: incorrect size for symbol `%s'."),
> +				 in_implib_bfd, sym_name);
> +	  ret = FALSE;
> +	}
> +
> +      /* Previous veneer address is before current SG veneer section.  */
> +      if (veneer_value < cmse_stub_sec_vma)
> +	{
> +	  /* Avoid offset underflow.  */
> +	  if (stub_entry)
> +	    stub_entry->stub_offset = 0;
> +	  stub_offset = 0;
> +	  ret = FALSE;
> +	}
> +
> +      /* Complain if stub offset not a multiple of stub size.  */
> +      if (stub_offset % cmse_stub_size)
> +	{
> +	  (*_bfd_error_handler)
> +	    (_("Offset of veneer for entry function `%s' not a multiple of "
> +	       "its size."), sym_name);
> +	  ret = FALSE;
> +	}
> +
> +      if (!ret)
> +	continue;
> +
> +      new_cmse_stubs_created--;
> +      if (veneer_value < cmse_stub_array_start)
> +	cmse_stub_array_start = veneer_value;
> +      next_cmse_stub_offset = stub_offset + ((cmse_stub_size + 7) & ~7);
> +      if (next_cmse_stub_offset > htab->new_cmse_stub_offset)
> +	htab->new_cmse_stub_offset = next_cmse_stub_offset;
> +    }
> +
> +  if (!info->out_implib_bfd && new_cmse_stubs_created != 0)
> +    {
> +      BFD_ASSERT (new_cmse_stubs_created > 0);
> +      (*_bfd_error_handler)
> +	(_("new entry function(s) introduced but no output import library "
> +	   "specified:"));
> +      bfd_hash_traverse (&htab->stub_hash_table, arm_list_new_cmse_stub, 
> info);
> +    }
> +
> +  if (cmse_stub_array_start != cmse_stub_sec_vma)
> +    {
> +      (*_bfd_error_handler)
> +	(_("Start address of `%s' is different from previous link."),
> +	 out_sec_name);
> +      ret = FALSE;
> +    }
> +
> +free_sym_buf:
> +  free (sympp);
> +  return ret;
> +}
> +
>  /* Determine and set the size of the stub section for a final link.
>  
>     The basic idea here is to examine all the relocations looking for
> @@ -5621,7 +5952,9 @@ elf32_arm_size_stubs (bfd *output_bfd,
>  						      unsigned int),
>  		      void (*layout_sections_again) (void))
>  {
> +  bfd_boolean ret = TRUE;
>    obj_attribute *out_attr;
> +  int cmse_stub_created = 0;
>    bfd_size_type stub_group_size;
>    bfd_boolean m_profile, stubs_always_after_branch, first_veneer_scan = TRUE;
>    struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
> @@ -5654,6 +5987,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
>  
>    out_attr = elf_known_obj_attributes_proc (output_bfd);
>    m_profile = out_attr[Tag_CPU_arch_profile].i == 'M';
> +
>    /* The Cortex-A8 erratum fix depends on stubs not being in the same 4K page
>       as the first half of a 32-bit branch straddling two 4K pages.  This is a
>       crude way of enforcing that.  */
> @@ -5727,8 +6061,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
>  
>  	      sym_hashes = elf_sym_hashes (input_bfd);
>  	      if (!cmse_scan (input_bfd, htab, out_attr, sym_hashes,
> -			      &stub_changed))
> +			      &cmse_stub_created))
>  		goto error_ret_free_local;
> +
> +	      if (cmse_stub_created != 0)
> +		stub_changed = TRUE;
>  	    }
>  
>  	  /* Walk over each section attached to the input bfd.  */
> @@ -5954,6 +6291,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
>  		  do
>  		    {
>  		      bfd_boolean new_stub;
> +		      struct elf32_arm_stub_hash_entry *stub_entry;
>  
>  		      /* Determine what (if any) linker stub is needed.  */
>  		      stub_type = arm_type_of_stub (info, section, irela,
> @@ -5965,12 +6303,13 @@ elf32_arm_size_stubs (bfd *output_bfd,
>  
>  		      /* We've either created a stub for this reloc already,
>  			 or we are about to.  */
> -		      created_stub =
> +		      stub_entry =
>  			elf32_arm_create_stub (htab, stub_type, section, irela,
>  					       sym_sec, hash,
>  					       (char *) sym_name, sym_value,
>  					       branch_type, &new_stub);
>  
> +		      created_stub = stub_entry != NULL;
>  		      if (!created_stub || !new_stub)
>  			{
>  			  if (!created_stub)
> @@ -6044,6 +6383,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
>  	    }
>  	}
>  
> +      if (first_veneer_scan
> +	  && !set_cmse_veneer_addr_from_implib (info, htab,
> +						&cmse_stub_created))
> +	ret = FALSE;
> +
>        if (prev_num_a8_fixes != num_a8_fixes)
>  	stub_changed = TRUE;
>  
> @@ -6063,6 +6407,23 @@ elf32_arm_size_stubs (bfd *output_bfd,
>  	  stub_sec->size = 0;
>  	}
>  
> +      /* Append new SG veneers after those in input import library.  */

...after those already in the input...

> +      for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
> +	   stub_type++)
> +	{
> +	  bfd_vma *start_offset_p;
> +	  asection **stub_sec_p;
> +
> +	  start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type);
> +	  stub_sec_p = arm_dedicated_stub_input_section_ptr (htab, stub_type);
> +	  if (start_offset_p == NULL)
> +	    continue;
> +
> +	  BFD_ASSERT (stub_sec_p != NULL);
> +	  if (*stub_sec_p != NULL)
> +	    (*stub_sec_p)->size = *start_offset_p;
> +	}
> +
>        /* Compute stub section size, considering padding.  */
>        bfd_hash_traverse (&htab->stub_hash_table, arm_size_one_stub, htab);
>        for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
> @@ -6131,7 +6492,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
>  	    }
>  
>  	  stub_entry->stub_sec = stub_sec;
> -	  stub_entry->stub_offset = 0;
> +	  stub_entry->stub_offset = (bfd_vma) -1;
>  	  stub_entry->id_sec = link_sec;
>  	  stub_entry->stub_type = a8_fixes[i].stub_type;
>  	  stub_entry->source_value = a8_fixes[i].offset;
> @@ -6159,7 +6520,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
>        htab->a8_erratum_fixes = NULL;
>        htab->num_a8_erratum_fixes = 0;
>      }
> -  return TRUE;
> +  return ret;
>  
>   error_ret_free_local:
>    return FALSE;
> @@ -6176,6 +6537,7 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
>  {
>    asection *stub_sec;
>    struct bfd_hash_table *table;
> +  enum elf32_arm_stub_type stub_type;
>    struct elf32_arm_link_hash_table *htab;
>  
>    htab = elf32_arm_hash_table (info);
> @@ -6193,14 +6555,33 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
>  	continue;
>  
>        /* Allocate memory to hold the linker stubs.  Zeroing the stub sections
> -	 must at least be done for stub section requiring padding.  */
> +	 must at least be done for stub section requiring padding and for SG
> +	 veneers to ensure that a non secure code branching to a removed SG
> +	 veneer causes an error.  */
>        size = stub_sec->size;
>        stub_sec->contents = (unsigned char *) bfd_zalloc (htab->stub_bfd, 
> size);
>        if (stub_sec->contents == NULL && size != 0)
>  	return FALSE;
> +
>        stub_sec->size = 0;
>      }
>  
> +  /* Append new SG veneers after those in input import library.  */

As above.

> +  for (stub_type = arm_stub_none + 1; stub_type < max_stub_type; stub_type++)
> +    {
> +      bfd_vma *start_offset_p;
> +      asection **stub_sec_p;
> +
> +      start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type);
> +      stub_sec_p = arm_dedicated_stub_input_section_ptr (htab, stub_type);
> +      if (start_offset_p == NULL)
> +	continue;
> +
> +      BFD_ASSERT (stub_sec_p != NULL);
> +      if (*stub_sec_p != NULL)
> +	(*stub_sec_p)->size = *start_offset_p;
> +    }
> +
>    /* Build the stubs as directed by the stub hash table.  */
>    table = &htab->stub_hash_table;
>    bfd_hash_traverse (table, arm_build_one_stub, info);
> @@ -8183,7 +8564,8 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd,
>  				 bfd_arm_stm32l4xx_fix stm32l4xx_fix,
>  				 int no_enum_warn, int no_wchar_warn,
>  				 int pic_veneer, int fix_cortex_a8,
> -				 int fix_arm1176, int cmse_implib)
> +				 int fix_arm1176, int cmse_implib,
> +				 bfd *in_implib_bfd)
>  {
>    struct elf32_arm_link_hash_table *globals;
>  
> @@ -8211,6 +8593,7 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd,
>    globals->fix_cortex_a8 = fix_cortex_a8;
>    globals->fix_arm1176 = fix_arm1176;
>    globals->cmse_implib = cmse_implib;
> +  globals->in_implib_bfd = in_implib_bfd;
>  
>    BFD_ASSERT (is_arm_elf (output_bfd));
>    elf_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
> diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
> index 
> c21f6a82335a58a0ab37f3719c73c95e73e6211c..2346bb42444895605d10b7b7e21cca2dcaa38700 
> 100644
> --- a/ld/emultempl/armelf.em
> +++ b/ld/emultempl/armelf.em
> @@ -43,6 +43,7 @@ static int pic_veneer = 0;
>  static int merge_exidx_entries = -1;
>  static int fix_arm1176 = 1;
>  static int cmse_implib = 0;
> +static char *in_implib_filename = NULL;
>  
>  static void
>  gld${EMULATION_NAME}_before_parse (void)
> @@ -498,6 +499,8 @@ gld${EMULATION_NAME}_finish (void)
>  static void
>  arm_elf_create_output_section_statements (void)
>  {
> +  bfd *in_implib_bfd;
> +
>    if (strstr (bfd_get_target (link_info.output_bfd), "arm") == NULL)
>      {
>        /* The arm backend needs special fields in the output hash structure.
> @@ -508,6 +511,20 @@ arm_elf_create_output_section_statements (void)
>        return;
>      }
>  
> +  if (in_implib_filename)
> +    {
> +      in_implib_bfd = bfd_openr (in_implib_filename,
> +				 bfd_get_target (link_info.output_bfd));
> +
> +      if (in_implib_bfd == NULL)
> +	einfo ("%F%s: Can't open: %E\n", in_implib_filename);
> +
> +      if (!bfd_check_format (in_implib_bfd, bfd_object))
> +	einfo ("%F%s: Not a relocatable file: %E\n", in_implib_filename);
> +    }
> +  else
> +    in_implib_bfd = NULL;
> +
>    bfd_elf32_arm_set_target_relocs (link_info.output_bfd, &link_info,
>  				   target1_is_rel,
>  				   target2_type, fix_v4bx, use_blx,
> @@ -515,7 +532,7 @@ arm_elf_create_output_section_statements (void)
>  				   no_enum_size_warning,
>  				   no_wchar_size_warning,
>  				   pic_veneer, fix_cortex_a8,
> -				   fix_arm1176, cmse_implib);
> +				   fix_arm1176, cmse_implib, in_implib_bfd);
>  
>    stub_file = lang_add_input_file ("linker stubs",
>   				   lang_input_file_is_fake_enum,
> @@ -585,6 +602,7 @@ PARSE_AND_LIST_PROLOGUE='
>  #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
> @@ -612,6 +630,7 @@ PARSE_AND_LIST_LONGOPTS='
>    { "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='
> @@ -634,6 +653,8 @@ PARSE_AND_LIST_OPTIONS='
>             "                              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\
> @@ -758,6 +779,10 @@ PARSE_AND_LIST_ARGS_CASES='
>     case OPTION_CMSE_IMPLIB:
>        cmse_implib = 1;
>        break;
> +
> +   case OPTION_IN_IMPLIB:
> +      in_implib_filename = optarg;
> +      break;
>  '
>  
>  # We have our own before_allocation etc. functions, but they call
> diff --git a/ld/ld.texinfo b/ld/ld.texinfo
> index 
> 82b40355a698958d84b566c09901960370139b27..eda43065f42e28bc4793bd5df78e45bd21cc1817 
> 100644
> --- a/ld/ld.texinfo
> +++ b/ld/ld.texinfo
> @@ -6817,6 +6817,18 @@ specified by the @samp{--out-implib} and @samp{--in-
> implib} options are
>  secure gateway import libraries, suitable for linking a non-secure
>  executable against secure code as per ARMv8-M Security Extensions.
>  
> +@kindex --in-implib=@var{file}
> +@cindex Input import library
> +The @samp{--in-implib=file} specifies an input import library whose symbols
> +must keep the same address in the executable being produced.  A warning is
> +given if no @samp{--out-implib} is given but new symbols have been introduced
> +in the executable that should be listed in its import library.  Otherwise, if
> +@samp{--out-implib} is specified, the symbols are silently added to the output

I think 'silently' is unnecessary here.

> +import library.  A warning is also given if some symbols present in the input
> +import library have disappeared from the executable.  This option is only
> +effective for Secure Gateway import libraries, ie. when @samp{--cmse-implib} 
> is
> +specified.
> +
>  @ifclear GENERIC
>  @lowersections
>  @end ifclear
> diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
> index 
> da4bf7e0302de9f1c76bbacf8b64a9318d44c46a..f15a8d42f3d5a4f87f21df2b229e30a1143fe7ac 
> 100644
> --- a/ld/testsuite/ld-arm/arm-elf.exp
> +++ b/ld/testsuite/ld-arm/arm-elf.exp
> @@ -663,16 +663,53 @@ set armeabitests_nonacl {
>       "cmse-veneers-mainline"}
>      {"Secure gateway import library generation: errors"
>       "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-
> implib.lib --cmse-implib" ""
> -     "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1"
> +     "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1 --defsym VER=1"
>       {cmse-implib.s}
>       {{ld cmse-implib-errors.out}}
>       "cmse-implib"}
>      {"Secure gateway import library generation"
>       "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-
> implib.lib --cmse-implib" ""
> -     "-march=armv8-m.base -mthumb"
> +     "-march=armv8-m.base -mthumb --defsym VER=1"
>       {cmse-implib.s}
>       {{readelf {-s tmpdir/cmse-implib.lib} cmse-implib.rd}}
>       "cmse-implib"}
> +    {"Input secure gateway import library"
> +     "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-new-
> implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> +     "-march=armv8-m.base -mthumb --defsym VER=2"
> +     {cmse-implib.s}
> +     {{ld cmse-new-implib.out}
> +      {readelf {-s tmpdir/cmse-new-implib.lib} cmse-new-implib.rd}}
> +     "cmse-new-implib"}
> +    {"Input secure gateway import library: no output import library"
> +     "--section-start .gnu.sgstubs=0x20000 --in-implib=tmpdir/cmse-implib.lib 
> --cmse-implib" ""
> +     "-march=armv8-m.base -mthumb --defsym VER=2"
> +     {cmse-implib.s}
> +     {{ld cmse-new-implib-no-output.out}}
> +     "cmse-new-implib-no-output"}
> +    {"Input secure gateway import library: earlier stub section base"
> +     "--section-start .gnu.sgstubs=0x19000 --out-implib=tmpdir/cmse-new-
> earlier-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> +     "-march=armv8-m.base -mthumb --defsym VER=2"
> +     {cmse-implib.s}
> +     {{ld cmse-new-earlier-later-implib.out}}
> +     "cmse-new-earlier-implib"}
> +    {"Input secure gateway import library: later stub section base"
> +     "--section-start .gnu.sgstubs=0x30000 --out-implib=tmpdir/cmse-new-
> later-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> +     "-march=armv8-m.base -mthumb --defsym VER=2"
> +     {cmse-implib.s}
> +     {{ld cmse-new-earlier-later-implib.out}}
> +     "cmse-new-later-implib"}
> +    {"Input secure gateway import library: veneer comeback"
> +     "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-new-
> comeback-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> +     "-march=armv8-m.base -mthumb --defsym VER=3"
> +     {cmse-implib.s}
> +     {{readelf {-s tmpdir/cmse-new-comeback-implib.lib} cmse-new-comeback-
> implib.rd}}
> +     "cmse-new-comeback-implib"}
> +    {"Input secure gateway import library: entry function change"
> +     "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-new-
> wrong-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> +     "-march=armv8-m.base -mthumb --defsym VER=4"
> +     {cmse-implib.s}
> +     {{ld cmse-new-wrong-implib.out}}
> +     "cmse-new-wrong-implib"}
>  
>      {"R_ARM_THM_JUMP19 Relocation veneers: Short"
>       "--section-start destsect=0x000108002 --section-start .text=0x8000" ""
> diff --git a/ld/testsuite/ld-arm/cmse-implib.s b/ld/testsuite/ld-arm/cmse-
> implib.s
> index 
> a42da63fffebe5322be83f278931754262b0f7ae..9dd783939891478351a5f7ccb1480980a77dca68 
> 100644
> --- a/ld/testsuite/ld-arm/cmse-implib.s
> +++ b/ld/testsuite/ld-arm/cmse-implib.s
> @@ -20,12 +20,29 @@ __acle_se_\name:
>  .endm
>  
>  	@ Valid setups for veneer generation
> +.if (VER >= 2)
> +	entry exported_entry_veneer1, global
> +.endif
> +.if (VER != 4)
>  	entry exported_entry_veneer2, global
> +.else
> +	entry exported_entry_veneer2, weak
> +.endif
> +.if (VER != 2)
>  	entry exported_entry_veneer3, global
> +.endif
> +.if (VER > 1)
> +	entry exported_entry_veneer4, global
> +.endif
>  
>  	@ Valid setup for entry function without veneer generation
>  	entry exported_entry_fct1, global, sg
> +.if (VER != 4)
>  	entry exported_entry_fct2, global, sg
> +.else
> +	@ Invalid setup for entry function without veneer generation
> +	entry exported_entry_fct2, global, nop
> +.endif
>  
>  	@ Normal symbol not exported to SG import library
>  	.align	2
> diff --git a/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd b/ld/testsuite/ld-
> arm/cmse-new-comeback-implib.rd
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..c88d9d5104244abc8ceba4d552e1ef0e400c37d1
> --- /dev/null
> +++ b/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd
> @@ -0,0 +1,15 @@
> +File: tmpdir/cmse-new-.*implib.lib
> +
> +Symbol table '.symtab' contains 7 entries:
> +   Num:    Value  Size Type    Bind   Vis      Ndx Name
> +     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
> +     1: 00020001     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer3
> +     2: 00020011     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer4
> +     3: 00020019     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer1
> +     4: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
> +     5: 00020009     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer2
> +     6: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
> +
> +File: tmpdir/cmse-new-.*implib
> +
> +#...
> diff --git a/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out 
> b/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..b49ad0ac0770a17c39c2d119d1f0c5854a5bd8cc
> --- /dev/null
> +++ b/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
> @@ -0,0 +1,3 @@
> +.*: Entry function `exported_entry_veneer3' disappeared from secure code.
> +.*: Start address of `.gnu.sgstubs' is different from previous link.
> +.*: cannot size stub section: Invalid operation
> diff --git a/ld/testsuite/ld-arm/cmse-new-implib-no-output.out 
> b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..0590b71c844da3687b29b93797abda5172ab8d99
> --- /dev/null
> +++ b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
> @@ -0,0 +1,4 @@
> +.*: Entry function `exported_entry_veneer3' disappeared from secure code.
> +.*: new entry function\(s\) introduced but no output import library specified:
> +.*:   exported_entry_veneer4
> +.*:   exported_entry_veneer1
> diff --git a/ld/testsuite/ld-arm/cmse-new-implib.out b/ld/testsuite/ld-
> arm/cmse-new-implib.out
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..c8af2807e7c1a7eeb1fc156fbf4508cf7a7e932d
> --- /dev/null
> +++ b/ld/testsuite/ld-arm/cmse-new-implib.out
> @@ -0,0 +1 @@
> +.*: Entry function `exported_entry_veneer3' disappeared from secure code.
> diff --git a/ld/testsuite/ld-arm/cmse-new-implib.rd b/ld/testsuite/ld-arm/cmse-
> new-implib.rd
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..9ff0fd87937571f86f99ee940a91a3f67352242a
> --- /dev/null
> +++ b/ld/testsuite/ld-arm/cmse-new-implib.rd
> @@ -0,0 +1,14 @@
> +File: tmpdir/cmse-new-.*implib.lib
> +
> +Symbol table '.symtab' contains 6 entries:
> +   Num:    Value  Size Type    Bind   Vis      Ndx Name
> +     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
> +     1: 00020011     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer4
> +     2: 00020019     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer1
> +     3: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
> +     4: 00020009     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer2
> +     5: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
> +
> +File: tmpdir/cmse-new-.*implib
> +
> +#...
> diff --git a/ld/testsuite/ld-arm/cmse-new-wrong-implib.out b/ld/testsuite/ld-
> arm/cmse-new-wrong-implib.out
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..2afe4078e78606d24f05dda6ff1c5e6a54d42512
> --- /dev/null
> +++ b/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
> @@ -0,0 +1,3 @@
> +.*: .*: visibility of symbol `exported_entry_veneer2' has changed.
> +.*: `exported_entry_fct2' refers to a non entry function.
> +.*: cannot size stub section: Invalid operation
> 
> 
> Is this ok for master branch?
> 
> Best regards,
> 
> Thomas
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ARM 11/11] Add support for stable secure gateway veneers addresses
       [not found]     ` <1735561.4TLJhTojVK@e108577-lin>
@ 2016-07-15  8:43       ` Thomas Preudhomme
  0 siblings, 0 replies; 15+ messages in thread
From: Thomas Preudhomme @ 2016-07-15  8:43 UTC (permalink / raw)
  To: Richard Earnshaw (lists); +Cc: binutils

Sorry please ignore that. I'll post an updated version soon. The patch no 
longer works when rebased on latest master branch. I already have a fix for 
that but realized it also misses a ld/NEWS entry.

Best regards,

Thomas

On Thursday 14 July 2016 10:30:52 Thomas Preudhomme wrote:
> Hi Richard,
> 
> How about this updated patch? I left the following issue for a follow-up
> 
> patch:
> > > diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
> > > index
> > > 55e1cdde2d0a899238a224c6915d20197b72f085..3a67fa637f5c709cddf3767496e4ac
> > > 87
> > > 96287765 100644
> > > --- a/bfd/bfd-in2.h
> > > +++ b/bfd/bfd-in2.h
> > > @@ -902,7 +902,7 @@ extern bfd_boolean
> > > bfd_elf32_arm_process_before_allocation>
> > > 
> > >  void bfd_elf32_arm_set_target_relocs
> > >  
> > >    (bfd *, struct bfd_link_info *, int, char *, int, int,
> > >    bfd_arm_vfp11_fix,
> > > 
> > > -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
> > > +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
> > 
> > This is *only* one more parameter to this function, but it now takes 15,
> > which seems excessive.
> > 
> > Some redesign may be in order here...
> 
> ChangeLog entries are:
> 
> *** bfd/ChangeLog ***
> 
> 2016-07-08  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> 
>         * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new parameter
> for the input import library bfd.
>         * bfd-in2.h: Regenerate.
>         * elf32-arm.c (struct elf32_arm_link_hash_table): New in_implib_bfd
>         and new_cmse_stub_offset fields.
>         (stub_hash_newfunc): Initialize stub_offset and stub_template_size
> to -1.
>         (elf32_arm_add_stub): Likewise for stub_offset.
>         (arm_new_stubs_start_offset_ptr): New function.
>         (arm_build_one_stub): Only allocate a stub_offset if it is -1. 
> Allow empty SG veneers to have zero relocations.
>         (arm_size_one_stub): Only initialize stub size and template
>         information for non empty veneers.  Do not update veneer section
> size if veneer already has an offset.
>         (elf32_arm_create_stub): Return the stub entry pointer or NULL
> instead of a boolean indicating success or failure.
>         (cmse_scan): Change stub_changed parameter into an integer pointer
>         parameter cmse_stub_created to count the number of stub created and
>         adapt to change of return value in elf32_arm_create_stub.
>         (cmse_entry_fct_p): New function.
>         (arm_list_new_cmse_stub): Likewise.
>         (set_cmse_veneer_addr_from_implib): Likewise.
>         (elf32_arm_size_stubs): Define cmse_stub_created, pass its address
> to cmse_scan instead of that of cmse_stub_changed to compute the number of
> stub created and use it to initialize stub_changed.  Call
> set_cmse_veneer_addr_from_implib after all cmse_scan.  Adapt to change of
> return value in elf32_arm_create_stub.  Use
>         arm_stub_section_start_offset () if not NULL to initialize size of
>         secure gateway veneers section.  Initialize stub_offset of Cortex-A8
> erratum fix to -1.  Use ret to hold return value.
>         (elf32_arm_build_stubs): Use arm_stub_section_start_offset () if not
> NULL to initialize size of secure gateway veneers section.  Adapt comment
> to stress the importance of zeroing veneer section content.
> (bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd parameter to
> initialize eponymous field in struct elf32_arm_link_hash_table.
> 
> 
> *** ld/ChangeLog ***
> 
> 2016-02-18  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> 
>         * emultempl/armelf.em (in_implib_filename): Declare and initialize
> new variable.
>         (arm_elf_create_output_section_statements): Open import input
> library file for writing and pass resulting in_implib_bfd to
>         bfd_elf32_arm_set_target_relocs.
>         (PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option.
>         (PARSE_AND_LIST_LONGOPTS): Define --in-implib option.
>         (PARSE_AND_LIST_OPTIONS): Add help message for --in-implib option.
>         (PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case.
>         * ld.texinfo (--cmse-implib): Update to mention --in-implib.
>         (--in-implib): Document new option.
>         * testsuite/ld-arm/arm-elf.exp
>         (Secure gateway import library generation): add --defsym VER=1 to
> gas CLI.
>         (Secure gateway import library generation: errors): Likewise.
>         (Input secure gateway import library): New test.
>         (Input secure gateway import library: no output import library):
>         Likewise.
>         (Input secure gateway import library: earlier stub section base):
>         Likewise.
>         (Input secure gateway import library: later stub section base):
>         Likewise.
>         (Input secure gateway import library: veneer comeback): Likewise.
>         (Input secure gateway import library: entry function change):
>         Likewise.
>         * testsuite/ld-arm/cmse-implib.s: Add input import library testing.
>         * testsuite/ld-arm/cmse-implib.rd: Update accordingly.
>         * testsuite/ld-arm/cmse-new-implib.out: New file.
>         * testsuite/ld-arm/cmse-new-implib.rd: Likewise.
>         * testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise.
>         * testsuite/ld-arm/cmse-new-earlier-later-implib.out: Likewise.
>         * testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise.
>         * testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise.
> 
> 
> Patch is in attachment. Is this ok for trunk?
> 
> Best regards,
> 
> Thomas
> 
> On Thursday 07 July 2016 13:52:00 Richard Earnshaw wrote:
> > On 04/04/16 15:22, Thomas Preudhomme wrote:
> > > On Wednesday 23 December 2015 16:02:48 Thomas Preud'homme wrote:
> > >> Hi,
> > >> 
> > >> [Posting patch series as RFC]
> > >> 
> > >> This patch is part of a patch series to add support for ARMv8-M
> > >> security
> > >> extension[1] to GNU ld. This specific patch adds support for allowing
> > >> Secure Gateway veneers to have stable addresses when relinking a secure
> > >> executable.
> > >> 
> > >> ARM v8-M security extensions allow code running in a device to be
> > >> divided
> > >> into secure and non-secure code expected to be developed by independent
> > >> (teams of) people. To allow updating the secure code without the need
> > >> to
> > >> relink the non-secure code against it, it is necessary for the
> > >> toolchain
> > >> to
> > >> provide a way to fix the addresses of the secure gateway veneers that
> > >> serve
> > >> as entry points for non-secure code to call secure code. This is also a
> > >> requirement [2] to claim support for ARM v8-M security extensions.
> > >> 
> > >> This patch adds a --in-implib=<in_implib_filename> option which, when
> > >> used
> > >> in conjunction of --cmse-implib will ensure that the veneers whose
> > >> symbols
> > >> are defined in the import library $in_implib_filename will remain at
> > >> the
> > >> same address in the executable. In the absence of a --out-implib
> > >> option,
> > >> the code will warn about new secure gateway veneers being created,
> > >> otherwise these are allowed.
> > >> 
> > >> 
> > >> [1] Software requirements for ARMv8-M security extension are described
> > >> in
> > >> document ARM-ECM-0359818 [2] [2] Available on http://infocenter.arm.com
> > >> in
> > >> Developer guides and articles > Software development > ARM®v8-M
> > >> Security
> > >> Extensions: Requirements on Development Tools [3] See requirement 15 of
> > >> ARM-ECM-0359818 [2]
> > > 
> > > Please find an updated patch below.
> > 
> > Comments inline.
> > 
> > > *** bfd/ChangeLog ***
> > > 
> > > 2016-02-18  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> > > 
> > >         * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new
> > >         parameter
> > >         for
> > >         the input import library bfd.
> > >         * bfd-in2.h: Regenerate.
> > >         * elf32-arm.c (struct elf32_arm_link_hash_table): New
> > >         in_implib_bfd
> > >         and new_cmse_stub_offset fields.
> > >         (stub_hash_newfunc): Initialize stub_offset and
> > >         stub_template_size
> > >         to
> > >         -1.
> > >         (elf32_arm_add_stub): Likewise for stub_offset.
> > >         (arm_new_stubs_start_offset_ptr): New function.
> > >         (arm_build_one_stub): Only allocate a stub_offset if it is -1.
> > >         Allow
> > >         empty veneers to have zero relocations.
> > >         (arm_size_one_stub): Only initialize stub size and template
> > >         information for non empty veneers.  Do not update veneer section
> > >         size
> > >         if veneer already has an offset.
> > >         (elf32_arm_create_stub): Return the stub entry pointer or NULL
> > >         instead
> > >         of a boolean indicating success or failure.
> > >         (cmse_scan): Change stub_changed parameter into an integer
> > >         pointer
> > >         parameter cmse_stub_created to count the number of stub created
> > >         and
> > >         adapt to change of return value in elf32_arm_create_stub.
> > >         (cmse_entry_fct_p): New function.
> > >         (arm_list_new_cmse_stub): Likewise.
> > >         (set_cmse_veneer_addr_from_implib): Likewise.
> > >         (elf32_arm_size_stubs): Define cmse_stub_created, pass its
> > >         address
> > >         to
> > >         cmse_scan instead of that of cmse_stub_changed to compute the
> > >         number
> > >         of stub created and use it to initialize stub_changed.  Call
> > >         set_cmse_veneer_addr_from_implib after all cmse_scan.  Adapt to
> > >         change
> > >         of return value in elf32_arm_create_stub.  Use
> > >         arm_stub_section_start_offset () if not NULL to initialize size
> > >         of
> > >         secure gateway veneers section.  Initialize stub_offset of
> > >         Cortex-A8
> > >         erratum fix to -1.  Use ret to hold return value.
> > >         (elf32_arm_build_stubs): Use arm_stub_section_start_offset () if
> > >         not
> > >         NULL to initialize size of secure gateway veneers section. 
> > >         Adapt
> > >         comment to stress the importance of zeroing veneer section
> > >         content.
> > >         (bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd
> > >         parameter
> > >         to
> > >         initialize eponymous field in struct elf32_arm_link_hash_table.
> > > 
> > > *** ld/ChangeLog ***
> > > 
> > > 2016-02-18  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> > > 
> > >         * emultempl/armelf.em (in_implib_filename): Declare and
> > >         initialize
> > >         new
> > >         variable.
> > >         (arm_elf_create_output_section_statements): Open import input
> > >         library
> > >         file for writing and pass resulting in_implib_bfd to
> > >         bfd_elf32_arm_set_target_relocs.
> > >         (PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option.
> > >         (PARSE_AND_LIST_LONGOPTS): Define --in-implib option.
> > >         (PARSE_AND_LIST_OPTIONS): Add help message for --in-implib
> > >         option.
> > >         (PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case.
> > >         * ld.texinfo (--cmse-implib): Update to mention --in-implib.
> > >         (--in-implib): Document new option.
> > >         * testsuite/ld-arm/arm-elf.exp
> > >         (Secure gateway import library generation): add --defsym VER=1
> > >         to
> > >         gas
> > >         CLI.
> > >         (Secure gateway import library generation: errors): Likewise.
> > >         (Input secure gateway import library): New test.
> > >         (Input secure gateway import library: no output import library):
> > >         Likewise.
> > >         (Input secure gateway import library: earlier stub section
> > >         base):
> > >         Likewise.
> > >         (Input secure gateway import library: later stub section base):
> > >         Likewise.
> > >         (Input secure gateway import library: veneer comeback):
> > >         Likewise.
> > >         (Input secure gateway import library: entry function change):
> > >         Likewise.
> > >         * testsuite/ld-arm/cmse-implib.s: Add input import library
> > >         testing.
> > >         * testsuite/ld-arm/cmse-implib.rd: Update accordingly.
> > >         * testsuite/ld-arm/cmse-new-implib.out: New file.
> > >         * testsuite/ld-arm/cmse-new-implib.rd: Likewise.
> > >         * testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise.
> > >         * testsuite/ld-arm/cmse-new-earlier-later-implib.out: Likewise.
> > >         * testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise.
> > >         * testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise.
> > > 
> > > diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
> > > index
> > > 7e3483b9984b04c534e53f2f9026abf26d37592a..423c534a954c541e227e731e9256f0
> > > 8f
> > > 9fa62014 100644
> > > --- a/bfd/bfd-in.h
> > > +++ b/bfd/bfd-in.h
> > > @@ -895,7 +895,7 @@ extern bfd_boolean
> > > bfd_elf32_arm_process_before_allocation>
> > > 
> > >  void bfd_elf32_arm_set_target_relocs
> > >  
> > >    (bfd *, struct bfd_link_info *, int, char *, int, int,
> > >    bfd_arm_vfp11_fix,
> > > 
> > > -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
> > > +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
> > > 
> > >  extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
> > >  
> > >    (bfd *, struct bfd_link_info *);
> > > 
> > > diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
> > > index
> > > 55e1cdde2d0a899238a224c6915d20197b72f085..3a67fa637f5c709cddf3767496e4ac
> > > 87
> > > 96287765 100644
> > > --- a/bfd/bfd-in2.h
> > > +++ b/bfd/bfd-in2.h
> > > @@ -902,7 +902,7 @@ extern bfd_boolean
> > > bfd_elf32_arm_process_before_allocation>
> > > 
> > >  void bfd_elf32_arm_set_target_relocs
> > >  
> > >    (bfd *, struct bfd_link_info *, int, char *, int, int,
> > >    bfd_arm_vfp11_fix,
> > > 
> > > -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
> > > +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
> > 
> > This is *only* one more parameter to this function, but it now takes 15,
> > which seems excessive.
> > 
> > Some redesign may be in order here...
> > 
> > >  extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
> > >  
> > >    (bfd *, struct bfd_link_info *);
> > > 
> > > diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
> > > index
> > > 0357fdab5cc77c3b0e983d1cb9b0285753bd5c65..be1d7224148f95bf097bb3fea63de2
> > > 08
> > > 1f93aab9 100644
> > > --- a/bfd/elf32-arm.c
> > > +++ b/bfd/elf32-arm.c
> > > @@ -3127,6 +3127,10 @@ struct elf32_arm_link_hash_table
> > > 
> > >       as per ARMv8-M Security Extensions.  */
> > >    
> > >    int cmse_implib;
> > > 
> > > +  /* The import library whose symbols' address must remain stable in
> > > +     the import library generated.  */
> > > +  bfd *in_implib_bfd;
> > > +
> > > 
> > >    /* The index of the next unused R_ARM_TLS_DESC slot in .rel.plt.  */
> > >    bfd_vma next_tls_desc_index;
> > > 
> > > @@ -3188,6 +3192,10 @@ struct elf32_arm_link_hash_table
> > > 
> > >    /* Input stub section holding secure gateway veneers.  */
> > >    asection *cmse_stub_sec;
> > > 
> > > +  /* Offset in cmse_stub_sec where new SG veneers (not in input import
> > > library)
> > > +     start to be allocated.  */
> > > +  bfd_vma new_cmse_stub_offset;
> > > +
> > > 
> > >    /* Number of elements in stub_group.  */
> > >    unsigned int top_id;
> > > 
> > > @@ -3439,7 +3447,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
> > > 
> > >        /* Initialize the local fields.  */
> > >        eh = (struct elf32_arm_stub_hash_entry *) entry;
> > >        eh->stub_sec = NULL;
> > > 
> > > -      eh->stub_offset = 0;
> > > +      eh->stub_offset = (bfd_vma) -1;
> > > 
> > >        eh->source_value = 0;
> > >        eh->target_value = 0;
> > >        eh->target_section = NULL;
> > > 
> > > @@ -3447,7 +3455,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
> > > 
> > >        eh->stub_type = arm_stub_none;
> > >        eh->stub_size = 0;
> > >        eh->stub_template = NULL;
> > > 
> > > -      eh->stub_template_size = 0;
> > > +      eh->stub_template_size = -1;
> > > 
> > >        eh->h = NULL;
> > >        eh->id_sec = NULL;
> > >        eh->output_name = NULL;
> > > 
> > > @@ -4361,7 +4369,7 @@ elf32_arm_add_stub (const char *stub_name,
> > > asection
> > > *section,
> > > 
> > >      }
> > >    
> > >    stub_entry->stub_sec = stub_sec;
> > > 
> > > -  stub_entry->stub_offset = 0;
> > > +  stub_entry->stub_offset = (bfd_vma) -1;
> > > 
> > >    stub_entry->id_sec = link_sec;
> > >    
> > >    return stub_entry;
> > > 
> > > @@ -4525,6 +4533,46 @@ arm_dedicated_stub_section_padding (enum
> > > elf32_arm_stub_type stub_type)
> > > 
> > >    abort ();  /* Should be unreachable.  */
> > >  
> > >  }
> > > 
> > > +/* If veneers of type STUB_TYPE should go in a dedicated output
> > > section,
> > > +   returns the address of the hash table field in HTAB holding the
> > > offset
> > > at +   which new veneers should be layed out in the stub section.  */ +
> > > +static bfd_vma*
> > > +arm_new_stubs_start_offset_ptr (struct elf32_arm_link_hash_table *htab,
> > > +				enum elf32_arm_stub_type stub_type)
> > > +{
> > > +  switch (stub_type)
> > > +    {
> > > +    case arm_stub_a8_veneer_b_cond:
> > > +    case arm_stub_a8_veneer_b:
> > > +    case arm_stub_a8_veneer_bl:
> > > +    case arm_stub_long_branch_any_any:
> > > +    case arm_stub_long_branch_v4t_arm_thumb:
> > > +    case arm_stub_long_branch_thumb_only:
> > > +    case arm_stub_long_branch_v4t_thumb_thumb:
> > > +    case arm_stub_long_branch_v4t_thumb_arm:
> > > +    case arm_stub_short_branch_v4t_thumb_arm:
> > > +    case arm_stub_long_branch_any_arm_pic:
> > > +    case arm_stub_long_branch_any_thumb_pic:
> > > +    case arm_stub_long_branch_v4t_thumb_thumb_pic:
> > > +    case arm_stub_long_branch_v4t_arm_thumb_pic:
> > > +    case arm_stub_long_branch_v4t_thumb_arm_pic:
> > > +    case arm_stub_long_branch_thumb_only_pic:
> > > +    case arm_stub_long_branch_any_tls_pic:
> > > +    case arm_stub_long_branch_v4t_thumb_tls_pic:
> > > +    case arm_stub_a8_veneer_blx:
> > > +    case arm_stub_long_branch_arm_nacl:
> > > +    case arm_stub_long_branch_arm_nacl_pic:
> > > +      return NULL;
> > > +
> > > +    case arm_stub_cmse_branch_thumb_only:
> > > +      return &htab->new_cmse_stub_offset;
> > > +
> > > +    default:
> > > +      abort ();  /* Should be unreachable.  */
> > > +    }
> > > +}
> > > +
> > > 
> > >  static bfd_boolean
> > >  arm_build_one_stub (struct bfd_hash_entry *gen_entry,
> > >  
> > >  		    void * in_arg)
> > > 
> > > @@ -4544,6 +4592,7 @@ arm_build_one_stub (struct bfd_hash_entry
> > > *gen_entry,
> > > 
> > >    int stub_reloc_idx[MAXRELOCS] = {-1, -1};
> > >    int stub_reloc_offset[MAXRELOCS] = {0, 0};
> > >    int nrelocs = 0;
> > > 
> > > +  int just_allocated = 0;
> > > 
> > >    /* Massage our args to the form they really have.  */
> > >    stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
> > > 
> > > @@ -4560,8 +4609,12 @@ arm_build_one_stub (struct bfd_hash_entry
> > > *gen_entry,>
> > > 
> > >      /* We have to do less-strictly-aligned fixes last.  */
> > >      return TRUE;
> > > 
> > > -  /* Make a note of the offset within the stubs for this entry.  */
> > > -  stub_entry->stub_offset = stub_sec->size;
> > > +  /* Assign a slot at the end of section if none assigned yet.  */
> > > +  if (stub_entry->stub_offset == (bfd_vma) -1)
> > > +    {
> > > +      stub_entry->stub_offset = stub_sec->size;
> > > +      just_allocated = 1;
> > > +    }
> > > 
> > >    loc = stub_sec->contents + stub_entry->stub_offset;
> > >    
> > >    stub_bfd = stub_sec->owner;
> > > 
> > > @@ -4635,7 +4688,8 @@ arm_build_one_stub (struct bfd_hash_entry
> > > *gen_entry,
> > > 
> > >  	}
> > >  	
> > >      }
> > > 
> > > -  stub_sec->size += size;
> > > +  if (just_allocated)
> > > +    stub_sec->size += size;
> > > 
> > >    /* Stub size has already been computed in arm_size_one_stub. Check
> > >    
> > >       consistency.  */
> > > 
> > > @@ -4647,7 +4701,7 @@ arm_build_one_stub (struct bfd_hash_entry
> > > *gen_entry,
> > > 
> > >    /* Assume there is at least one and at most MAXRELOCS entries to
> > >    relocate
> > >    
> > >       in each stub.  */
> > > 
> > > -  BFD_ASSERT (nrelocs != 0 && nrelocs <= MAXRELOCS);
> > > +  BFD_ASSERT (size == 0 || (nrelocs != 0 && nrelocs <= MAXRELOCS));
> > 
> > The comment no-longer matches the assert.  Direct use of size is also
> > confusing.  It might be clearer if you create a new bool variable which
> > is set to true iff size is zero and makes the code that follows easier
> > to comprehend.
> > 
> > >    for (i = 0; i < nrelocs; i++)
> > >    
> > >      {
> > > 
> > > @@ -4749,9 +4803,17 @@ arm_size_one_stub (struct bfd_hash_entry
> > > *gen_entry,
> > > 
> > >    size = find_stub_size_and_template (stub_entry->stub_type,
> > > 
> > > &template_sequence,
> > > 
> > >  				      &template_size);
> > > 
> > > -  stub_entry->stub_size = size;
> > > -  stub_entry->stub_template = template_sequence;
> > > -  stub_entry->stub_template_size = template_size;
> > > +  /* Initialized to -1.  Null size indicates a zeroed out veneer.  */
> > 
> > Err, what's a zeroed out veneer?
> > 
> > > +  if (stub_entry->stub_template_size)
> > > +    {
> > > +      stub_entry->stub_size = size;
> > > +      stub_entry->stub_template = template_sequence;
> > > +      stub_entry->stub_template_size = template_size;
> > > +    }
> > > +
> > > +  /* Already accounted for.  */
> > > +  if (stub_entry->stub_offset != (bfd_vma) -1)
> > > +    return TRUE;
> > > 
> > >    size = (size + 7) & ~7;
> > >    stub_entry->stub_sec->size += size;
> > > 
> > > @@ -5316,10 +5378,10 @@ cortex_a8_erratum_scan (bfd *input_bfd,
> > > 
> > >     and *NEW_STUB is set to FALSE.  Otherwise, *NEW_STUB is set to
> > >     TRUE and the stub entry is initialized.
> > > 
> > > -   Returns whether the stub could be successfully created or updated,
> > > or
> > > FALSE
> > > -   if an error occured.  */
> > > +   Returns the stub that was created or updated, or NULL if an error
> > > +   occured.  */
> > 
> > s/occured/occurred/  (at least according to my dictionary).
> > 
> > > -static bfd_boolean
> > > +static struct elf32_arm_stub_hash_entry *
> > > 
> > >  elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
> > >  
> > >  		       enum elf32_arm_stub_type stub_type, asection *section,
> > >  		       Elf_Internal_Rela *irela, asection *sym_sec,
> > > 
> > > @@ -5350,7 +5412,7 @@ elf32_arm_create_stub (struct
> > > elf32_arm_link_hash_table *htab,
> > > 
> > >        stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash, irela,
> > >        
> > >  				       stub_type);
> > >        
> > >        if (!stub_name)
> > > 
> > > -	return FALSE;
> > > +	return NULL;
> > > 
> > >      }
> > >    
> > >    stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, stub_name,
> > > 
> > > FALSE,
> > > @@ -5361,7 +5423,7 @@ elf32_arm_create_stub (struct
> > > elf32_arm_link_hash_table *htab,
> > > 
> > >        if (!sym_claimed)
> > >  	
> > >  	free (stub_name);
> > >  	
> > >        stub_entry->target_value = sym_value;
> > > 
> > > -      return TRUE;
> > > +      return stub_entry;
> > > 
> > >      }
> > >    
> > >    stub_entry = elf32_arm_add_stub (stub_name, section, htab,
> > >    stub_type);
> > > 
> > > @@ -5369,7 +5431,7 @@ elf32_arm_create_stub (struct
> > > elf32_arm_link_hash_table *htab,
> > > 
> > >      {
> > >      
> > >        if (!sym_claimed)
> > >  	
> > >  	free (stub_name);
> > > 
> > > -      return FALSE;
> > > +      return NULL;
> > > 
> > >      }
> > >    
> > >    stub_entry->target_value = sym_value;
> > > 
> > > @@ -5390,7 +5452,7 @@ elf32_arm_create_stub (struct
> > > elf32_arm_link_hash_table *htab,
> > > 
> > >        if (stub_entry->output_name == NULL)
> > >  	
> > >  	{
> > >  	
> > >  	  free (stub_name);
> > > 
> > > -	  return FALSE;
> > > +	  return NULL;
> > > 
> > >  	}
> > >  	
> > >        /* For historical reasons, use the existing names for
> > >        ARM-to-Thumb
> > >        and
> > > 
> > > @@ -5410,7 +5472,7 @@ elf32_arm_create_stub (struct
> > > elf32_arm_link_hash_table *htab,
> > > 
> > >      }
> > >    
> > >    *new_stub = TRUE;
> > > 
> > > -  return TRUE;
> > > +  return stub_entry;
> > > 
> > >  }
> > >  
> > >  /* Scan symbols in INPUT_BFD to identify secure entry functions needing
> > >  a
> > > 
> > > @@ -5427,14 +5489,15 @@ elf32_arm_create_stub (struct
> > > elf32_arm_link_hash_table *htab,
> > > 
> > >     OUT_ATTR gives the output attributes, SYM_HASHES the symbol index to
> > >     hash
> > >     entry mapping while HTAB gives the name to hash entry mapping.
> > > 
> > > +   *CMSE_STUB_CREATED is increased by the number of secure gateway
> > > veneer
> > > +   created.
> > > 
> > > -   If any secure gateway veneer is created, *STUB_CHANGED is set to
> > > TRUE.
> > > The
> > > -   return value gives whether a stub failed to be allocated.  */
> > > +   The return value gives whether a stub failed to be allocated.  */
> > > 
> > >  static bfd_boolean
> > >  cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
> > >  
> > >  	   obj_attribute *out_attr, struct elf_link_hash_entry **sym_hashes,
> > > 
> > > -	   bfd_boolean *stub_changed)
> > > +	   int *cmse_stub_created)
> > > 
> > >  {
> > >  
> > >    const struct elf_backend_data *bed;
> > >    Elf_Internal_Shdr *symtab_hdr;
> > > 
> > > @@ -5445,7 +5508,8 @@ cmse_scan (bfd *input_bfd, struct
> > > elf32_arm_link_hash_table *htab,
> > > 
> > >    char *sym_name, *lsym_name;
> > >    bfd_vma sym_value;
> > >    asection *section;
> > > 
> > > -  bfd_boolean is_v8m, new_stub, created_stub, cmse_invalid, ret = TRUE;
> > > +  struct elf32_arm_stub_hash_entry *stub_entry;
> > > +  bfd_boolean is_v8m, new_stub, cmse_invalid, ret = TRUE;
> > > 
> > >    bed = get_elf_backend_data (input_bfd);
> > >    symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
> > > 
> > > @@ -5586,17 +5650,17 @@ cmse_scan (bfd *input_bfd, struct
> > > elf32_arm_link_hash_table *htab,
> > > 
> > >        if (!ret)
> > >  	
> > >  	continue;
> > >  	
> > >        branch_type = ARM_GET_SYM_BRANCH_TYPE
> > >        (hash->root.target_internal);
> > > 
> > > -      created_stub
> > > +      stub_entry
> > > 
> > >  	= elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
> > >  	
> > >  				 NULL, NULL, section, hash, sym_name,
> > >  				 sym_value, branch_type, &new_stub);
> > > 
> > > -      if (!created_stub)
> > > +      if (stub_entry == NULL)
> > > 
> > >  	 ret = FALSE;
> > >  	 
> > >        else
> > >  	
> > >  	{
> > >  	
> > >  	  BFD_ASSERT (new_stub);
> > > 
> > > -	  *stub_changed = TRUE;
> > > +	  (*cmse_stub_created)++;
> > > 
> > >  	}
> > >  	
> > >      }
> > > 
> > > @@ -5605,6 +5669,273 @@ cmse_scan (bfd *input_bfd, struct
> > > elf32_arm_link_hash_table *htab,
> > > 
> > >    return ret;
> > >  
> > >  }
> > > 
> > > +/* Return whether a symbol identified by its linker HASH entry is an
> > > entry
> > 
> > s/an entry/a secure code entry/
> > 
> > Entry function is ambiguous.
> > 
> > As a style point it's probably better to start with
> > 
> > Return TRUE iff a symbol ...
> > 
> > > +   function, ie can be called from non secure code without using a
> > > veneer.
> > > */
> > > +
> > > +static bfd_boolean
> > > +cmse_entry_fct_p (struct elf32_arm_link_hash_entry *hash)
> > > +{
> > > +  uint32_t first_insn;
> > > +  asection *section;
> > > +  file_ptr offset;
> > > +  bfd *abfd;
> > > +
> > > +  /* Defined symbol of function type.  */
> > > +  if (hash->root.root.type != bfd_link_hash_defined
> > > +      && hash->root.root.type != bfd_link_hash_defweak)
> > > +    return FALSE;
> > > +  if (hash->root.type != STT_FUNC)
> > > +    return FALSE;
> > > +
> > > +  /* Read first instruction.  */
> > > +  section = hash->root.root.u.def.section;
> > > +  abfd = section->owner;
> > > +  offset = hash->root.root.u.def.value - section->vma;
> > > +  if (!bfd_get_section_contents (abfd, section, &first_insn, offset,
> > > +				 sizeof (first_insn)))
> > > +    return FALSE;
> > > +
> > > +  /* Start by SG instruction.  */
> > > +  return first_insn == 0xe97fe97f;
> > > +}
> > > +
> > > +/* Output the name (in symbol table) of the veneer GEN_ENTRY if it is a
> > > new +   secure gateway veneers (ie. the veneers was not in the input
> > > import library)
> > > +   and there is no output import library (GEN_INFO->out_implib_bfd is
> > > NULL. */
> > > +
> > > +static bfd_boolean
> > > +arm_list_new_cmse_stub (struct bfd_hash_entry *gen_entry, void
> > > *gen_info)
> > > +{
> > > +  struct elf32_arm_stub_hash_entry *stub_entry;
> > > +  struct bfd_link_info *info;
> > > +
> > > +  /* Massage our args to the form they really have.  */
> > > +  stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
> > > +  info = (struct bfd_link_info *) gen_info;
> > > +
> > > +  if (info->out_implib_bfd)
> > > +    return TRUE;
> > > +
> > > +  if (stub_entry->stub_type != arm_stub_cmse_branch_thumb_only)
> > > +    return TRUE;
> > > +
> > > +  if (stub_entry->stub_offset == (bfd_vma) -1)
> > > +    (*_bfd_error_handler) ("  %s", stub_entry->output_name);
> > > +
> > > +  return TRUE;
> > > +}
> > > +
> > > +/* Set offset of secure gateway veneers so that their address remain
> > > identical
> > 
> > Set the offset of each s g v so that *its* address remains...
> > 
> > > +   to the one in the input import library referred by
> > > HTAB->in_implib_bfd.  A +   warning is issued for veneers that
> > > disappeared (present in input import +   library but absent from the
> > > executable being linked) or if new veneers +   appeared and there is no
> > > output import library (INFO->out_implib_bfd is NULL
> > > +   and *CMSE_STUB_CREATED is bigger than the number of secure gateway
> > > veneers +   found in the input import library.
> > > +
> > > +   The function returns whether an error occured.  If no error occured,
> > > +   *CMSE_STUB_CREATED gives the number of SG veneers created by both
> > > cmse_scan
> > > +   and this function and HTAB->new_cmse_stub_offset is set to the
> > > biggest
> > > +   veneer observed set for new veneers to be layed out after.  */
> > > +
> > > +static bfd_boolean
> > > +set_cmse_veneer_addr_from_implib (struct bfd_link_info *info,
> > > +				  struct elf32_arm_link_hash_table *htab,
> > > +				  int *cmse_stub_created)
> > > +{
> > > +  long symsize;
> > > +  char *sym_name;
> > > +  flagword flags;
> > > +  long i, symcount;
> > > +  bfd *in_implib_bfd;
> > > +  asection *stub_out_sec;
> > > +  bfd_boolean ret = TRUE;
> > > +  Elf_Internal_Sym *intsym;
> > > +  const char *out_sec_name;
> > > +  bfd_size_type cmse_stub_size;
> > > +  asymbol **sympp = NULL, *sym;
> > > +  struct elf32_arm_link_hash_entry *hash;
> > > +  const insn_sequence *cmse_stub_template;
> > > +  struct elf32_arm_stub_hash_entry *stub_entry;
> > > +  int cmse_stub_template_size, new_cmse_stubs_created =
> > > *cmse_stub_created; +  bfd_vma veneer_value, stub_offset,
> > > next_cmse_stub_offset;
> > > +  bfd_vma cmse_stub_array_start = (bfd_vma) -1, cmse_stub_sec_vma = 0;
> > > +
> > > +  /* No input secure gateway import library.  */
> > > +  if (!htab->in_implib_bfd)
> > > +    return TRUE;
> > > +  else if (!htab->cmse_implib)
> > > +    return FALSE;
> > > +
> > > +  /* Get symbol table size.  */
> > > +  in_implib_bfd = htab->in_implib_bfd;
> > > +  symsize = bfd_get_symtab_upper_bound (in_implib_bfd);
> > > +  if (symsize < 0)
> > > +    return FALSE;
> > > +
> > > +  /* Read in the input secure gateway import library's symbol table. 
> > > */
> > > +  sympp = (asymbol **) xmalloc (symsize);
> > > +  symcount = bfd_canonicalize_symtab (in_implib_bfd, sympp);
> > > +  if (symcount < 0)
> > > +    {
> > > +      ret = FALSE;
> > > +      goto free_sym_buf;
> > > +    }
> > > +
> > > +  htab->new_cmse_stub_offset = 0;
> > > +  cmse_stub_size =
> > > +    find_stub_size_and_template (arm_stub_cmse_branch_thumb_only,
> > > +				 &cmse_stub_template,
> > > +				 &cmse_stub_template_size);
> > > +  out_sec_name =
> > > +    arm_dedicated_stub_output_section_name
> > > (arm_stub_cmse_branch_thumb_only); +  stub_out_sec =
> > > +    bfd_get_section_by_name (htab->obfd, out_sec_name);
> > > +  if (stub_out_sec != NULL)
> > > +    cmse_stub_sec_vma = stub_out_sec->vma;
> > > +
> > > +  /* Set addresses of veneers mentionned in input secure gateway import
> > > +     library's symbol table.  */
> > > +  for (i = 0; i < symcount; i++)
> > > +    {
> > > +      sym = sympp[i];
> > > +      flags = sym->flags;
> > > +      sym_name = (char *) bfd_asymbol_name (sym);
> > > +      intsym = &((elf_symbol_type *) sym)->internal_elf_sym;
> > > +
> > > +      if (sym->section != bfd_abs_section_ptr
> > > +	  || !(flags & (BSF_GLOBAL | BSF_WEAK))
> > > +	  || (flags & BSF_FUNCTION) != BSF_FUNCTION
> > > +	  || (ARM_GET_SYM_BRANCH_TYPE (intsym->st_target_internal)
> > > +	      != ST_BRANCH_TO_THUMB))
> > > +	{
> 
> > > +	  (*_bfd_error_handler) (_("%B: invalid import library entry:
> `%s'."),
> 
> > > +				 in_implib_bfd, sym_name);
> > > +	  (*_bfd_error_handler) (_("Symbol should be absolute, global and "
> > > +				   "refer to Thumb functions."));
> > > +	  ret = FALSE;
> > > +	  continue;
> > > +	}
> > > +
> > > +      veneer_value = bfd_asymbol_value (sym);
> > > +      stub_offset = veneer_value - cmse_stub_sec_vma;
> > > +      stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table,
> > > sym_name,
> > > +					 FALSE, FALSE);
> > > +      hash = (struct elf32_arm_link_hash_entry *)
> > > +	elf_link_hash_lookup (&(htab)->root, sym_name, FALSE, FALSE, TRUE);
> > > +
> > > +      /* Stub entry should have been created by cmse_scan or the symbol
> > > be of +	 a secure function callable from non secure code.  */
> > > +      if (!stub_entry && !hash)
> > > +	{
> > > +	  bfd_boolean new_stub;
> > > +
> > > +	  (*_bfd_error_handler)
> > > +	    (_("Entry function `%s' disappeared from secure code."),
> 
> sym_name);
> 
> > > +	  hash = (struct elf32_arm_link_hash_entry *)
> > > +	    elf_link_hash_lookup (&(htab)->root, sym_name, TRUE, TRUE, TRUE);
> > > +	  stub_entry
> > > +	    = elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
> > > +				     NULL, NULL, bfd_abs_section_ptr, hash,
> > > +				     sym_name, veneer_value,
> > > +				     ST_BRANCH_TO_THUMB, &new_stub);
> > > +	  if (stub_entry == NULL)
> > > +	    ret = FALSE;
> > > +	  else
> > > +	  {
> > > +	    BFD_ASSERT (new_stub);
> > > +	    new_cmse_stubs_created++;
> > > +	    (*cmse_stub_created)++;
> > > +	  }
> > > +	  stub_entry->stub_template_size = stub_entry->stub_size = 0;
> > > +	  stub_entry->stub_offset = stub_offset;
> > > +	}
> > > +      /* Symbol found is not callable from non secure code.  */
> > > +      else if (!stub_entry)
> > > +	{
> > > +	  if (!cmse_entry_fct_p (hash))
> > > +	    {
> > > +	      (*_bfd_error_handler) (_("`%s' refers to a non entry
> 
> function."),
> 
> > > +				     sym_name);
> > > +	      ret = FALSE;
> > > +	    }
> > > +	  continue;
> > > +	}
> > > +      else
> > > +	{
> > > +	  /* Only stub for SG veneers should have been created.  */
> > 
> > stubs
> > 
> > > +	  BFD_ASSERT (stub_entry->stub_type ==
> 
> arm_stub_cmse_branch_thumb_only);
> 
> > > +
> > > +	  /* Check visibility hasn't changed.  */
> > > +	  if (!!(flags & BSF_GLOBAL)
> > > +	      != (hash->root.root.type == bfd_link_hash_defined))
> > > +	    (*_bfd_error_handler)
> > > +	      (_("%B: visibility of symbol `%s' has changed."),
> 
> in_implib_bfd,
> 
> > > +	       sym_name);
> > > +
> > > +	  stub_entry->stub_offset = stub_offset;
> > > +	}
> > > +
> > > +      /* Size should match that of a SG veneer.  */
> > > +      if (intsym->st_size != cmse_stub_size)
> > > +	{
> > > +	  (*_bfd_error_handler) (_("%B: incorrect size for symbol `%s'."),
> > > +				 in_implib_bfd, sym_name);
> > > +	  ret = FALSE;
> > > +	}
> > > +
> > > +      /* Previous veneer address is before current SG veneer section. 
> > > */
> > > +      if (veneer_value < cmse_stub_sec_vma)
> > > +	{
> > > +	  /* Avoid offset underflow.  */
> > > +	  if (stub_entry)
> > > +	    stub_entry->stub_offset = 0;
> > > +	  stub_offset = 0;
> > > +	  ret = FALSE;
> > > +	}
> > > +
> > > +      /* Complain if stub offset not a multiple of stub size.  */
> > > +      if (stub_offset % cmse_stub_size)
> > > +	{
> > > +	  (*_bfd_error_handler)
> > > +	    (_("Offset of veneer for entry function `%s' not a multiple of "
> > > +	       "its size."), sym_name);
> > > +	  ret = FALSE;
> > > +	}
> > > +
> > > +      if (!ret)
> > > +	continue;
> > > +
> > > +      new_cmse_stubs_created--;
> > > +      if (veneer_value < cmse_stub_array_start)
> > > +	cmse_stub_array_start = veneer_value;
> > > +      next_cmse_stub_offset = stub_offset + ((cmse_stub_size + 7) &
> > > ~7);
> > > +      if (next_cmse_stub_offset > htab->new_cmse_stub_offset)
> > > +	htab->new_cmse_stub_offset = next_cmse_stub_offset;
> > > +    }
> > > +
> > > +  if (!info->out_implib_bfd && new_cmse_stubs_created != 0)
> > > +    {
> > > +      BFD_ASSERT (new_cmse_stubs_created > 0);
> > > +      (*_bfd_error_handler)
> > > +	(_("new entry function(s) introduced but no output import library "
> > > +	   "specified:"));
> > > +      bfd_hash_traverse (&htab->stub_hash_table,
> > > arm_list_new_cmse_stub,
> > > info);
> > > +    }
> > > +
> > > +  if (cmse_stub_array_start != cmse_stub_sec_vma)
> > > +    {
> > > +      (*_bfd_error_handler)
> > > +	(_("Start address of `%s' is different from previous link."),
> > > +	 out_sec_name);
> > > +      ret = FALSE;
> > > +    }
> > > +
> > > +free_sym_buf:
> > > +  free (sympp);
> > > +  return ret;
> > > +}
> > > +
> > > 
> > >  /* Determine and set the size of the stub section for a final link.
> > >  
> > >     The basic idea here is to examine all the relocations looking for
> > > 
> > > @@ -5621,7 +5952,9 @@ elf32_arm_size_stubs (bfd *output_bfd,
> > > 
> > >  						      unsigned int),
> > >  		      
> > >  		      void (*layout_sections_again) (void))
> > >  
> > >  {
> > > 
> > > +  bfd_boolean ret = TRUE;
> > > 
> > >    obj_attribute *out_attr;
> > > 
> > > +  int cmse_stub_created = 0;
> > > 
> > >    bfd_size_type stub_group_size;
> > >    bfd_boolean m_profile, stubs_always_after_branch, first_veneer_scan =
> > >    TRUE;
> > >    struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
> > > 
> > > @@ -5654,6 +5987,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
> > > 
> > >    out_attr = elf_known_obj_attributes_proc (output_bfd);
> > >    m_profile = out_attr[Tag_CPU_arch_profile].i == 'M';
> > > 
> > > +
> > > 
> > >    /* The Cortex-A8 erratum fix depends on stubs not being in the same
> > >    4K
> > >    page
> > >    
> > >       as the first half of a 32-bit branch straddling two 4K pages. 
> > >       This
> > >       is a
> > >       crude way of enforcing that.  */
> > > 
> > > @@ -5727,8 +6061,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
> > > 
> > >  	      sym_hashes = elf_sym_hashes (input_bfd);
> > >  	      if (!cmse_scan (input_bfd, htab, out_attr, sym_hashes,
> > > 
> > > -			      &stub_changed))
> > > +			      &cmse_stub_created))
> > > 
> > >  		goto error_ret_free_local;
> > > 
> > > +
> > > +	      if (cmse_stub_created != 0)
> > > +		stub_changed = TRUE;
> > > 
> > >  	    }
> > >  	  
> > >  	  /* Walk over each section attached to the input bfd.  */
> > > 
> > > @@ -5954,6 +6291,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
> > > 
> > >  		  do
> > >  		  
> > >  		    {
> > >  		    
> > >  		      bfd_boolean new_stub;
> > > 
> > > +		      struct elf32_arm_stub_hash_entry *stub_entry;
> > > 
> > >  		      /* Determine what (if any) linker stub is needed.  */
> > >  		      stub_type = arm_type_of_stub (info, section, irela,
> > > 
> > > @@ -5965,12 +6303,13 @@ elf32_arm_size_stubs (bfd *output_bfd,
> > > 
> > >  		      /* We've either created a stub for this reloc already,
> > >  			 
> > >  			 or we are about to.  */
> > > 
> > > -		      created_stub =
> > > +		      stub_entry =
> > > 
> > >  			elf32_arm_create_stub (htab, stub_type, section, irela,
> > >  			
> > >  					       sym_sec, hash,
> > >  					       (char *) sym_name, sym_value,
> > >  					       branch_type, &new_stub);
> > > 
> > > +		      created_stub = stub_entry != NULL;
> > > 
> > >  		      if (!created_stub || !new_stub)
> > >  			
> > >  			{
> > >  			
> > >  			  if (!created_stub)
> > > 
> > > @@ -6044,6 +6383,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
> > > 
> > >  	    }
> > >  	
> > >  	}
> > > 
> > > +      if (first_veneer_scan
> > > +	  && !set_cmse_veneer_addr_from_implib (info, htab,
> > > +						&cmse_stub_created))
> > > +	ret = FALSE;
> > > +
> > > 
> > >        if (prev_num_a8_fixes != num_a8_fixes)
> > >  	
> > >  	stub_changed = TRUE;
> > > 
> > > @@ -6063,6 +6407,23 @@ elf32_arm_size_stubs (bfd *output_bfd,
> > > 
> > >  	  stub_sec->size = 0;
> > >  	
> > >  	}
> > > 
> > > +      /* Append new SG veneers after those in input import library.  */
> > 
> > ...after those already in the input...
> > 
> > > +      for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
> > > +	   stub_type++)
> > > +	{
> > > +	  bfd_vma *start_offset_p;
> > > +	  asection **stub_sec_p;
> > > +
> > > +	  start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type);
> > > +	  stub_sec_p = arm_dedicated_stub_input_section_ptr (htab,
> 
> stub_type);
> 
> > > +	  if (start_offset_p == NULL)
> > > +	    continue;
> > > +
> > > +	  BFD_ASSERT (stub_sec_p != NULL);
> > > +	  if (*stub_sec_p != NULL)
> > > +	    (*stub_sec_p)->size = *start_offset_p;
> > > +	}
> > > +
> > > 
> > >        /* Compute stub section size, considering padding.  */
> > >        bfd_hash_traverse (&htab->stub_hash_table, arm_size_one_stub,
> > >        htab);
> > >        for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
> > > 
> > > @@ -6131,7 +6492,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
> > > 
> > >  	    }
> > >  	  
> > >  	  stub_entry->stub_sec = stub_sec;
> > > 
> > > -	  stub_entry->stub_offset = 0;
> > > +	  stub_entry->stub_offset = (bfd_vma) -1;
> > > 
> > >  	  stub_entry->id_sec = link_sec;
> > >  	  stub_entry->stub_type = a8_fixes[i].stub_type;
> > >  	  stub_entry->source_value = a8_fixes[i].offset;
> > > 
> > > @@ -6159,7 +6520,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
> > > 
> > >        htab->a8_erratum_fixes = NULL;
> > >        htab->num_a8_erratum_fixes = 0;
> > >      
> > >      }
> > > 
> > > -  return TRUE;
> > > +  return ret;
> > > 
> > >   error_ret_free_local:
> > >    return FALSE;
> > > 
> > > @@ -6176,6 +6537,7 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
> > > 
> > >  {
> > >  
> > >    asection *stub_sec;
> > >    struct bfd_hash_table *table;
> > > 
> > > +  enum elf32_arm_stub_type stub_type;
> > > 
> > >    struct elf32_arm_link_hash_table *htab;
> > >    
> > >    htab = elf32_arm_hash_table (info);
> > > 
> > > @@ -6193,14 +6555,33 @@ elf32_arm_build_stubs (struct bfd_link_info
> > > *info)
> > > 
> > >  	continue;
> > >  	
> > >        /* Allocate memory to hold the linker stubs.  Zeroing the stub
> > >        sections
> > > 
> > > -	 must at least be done for stub section requiring padding.  */
> > > +	 must at least be done for stub section requiring padding and for SG
> > > +	 veneers to ensure that a non secure code branching to a removed SG
> > > +	 veneer causes an error.  */
> > > 
> > >        size = stub_sec->size;
> > >        stub_sec->contents = (unsigned char *) bfd_zalloc
> > >        (htab->stub_bfd,
> > > 
> > > size);
> > > 
> > >        if (stub_sec->contents == NULL && size != 0)
> > >  	
> > >  	return FALSE;
> > > 
> > > +
> > > 
> > >        stub_sec->size = 0;
> > >      
> > >      }
> > > 
> > > +  /* Append new SG veneers after those in input import library.  */
> > 
> > As above.
> > 
> > > +  for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
> > > stub_type++) +    {
> > > +      bfd_vma *start_offset_p;
> > > +      asection **stub_sec_p;
> > > +
> > > +      start_offset_p = arm_new_stubs_start_offset_ptr (htab,
> > > stub_type);
> > > +      stub_sec_p = arm_dedicated_stub_input_section_ptr (htab,
> > > stub_type);
> > > +      if (start_offset_p == NULL)
> > > +	continue;
> > > +
> > > +      BFD_ASSERT (stub_sec_p != NULL);
> > > +      if (*stub_sec_p != NULL)
> > > +	(*stub_sec_p)->size = *start_offset_p;
> > > +    }
> > > +
> > > 
> > >    /* Build the stubs as directed by the stub hash table.  */
> > >    table = &htab->stub_hash_table;
> > >    bfd_hash_traverse (table, arm_build_one_stub, info);
> > > 
> > > @@ -8183,7 +8564,8 @@ bfd_elf32_arm_set_target_relocs (struct bfd
> > > *output_bfd,>
> > > 
> > >  				 bfd_arm_stm32l4xx_fix stm32l4xx_fix,
> > >  				 int no_enum_warn, int no_wchar_warn,
> > >  				 int pic_veneer, int fix_cortex_a8,
> > > 
> > > -				 int fix_arm1176, int cmse_implib)
> > > +				 int fix_arm1176, int cmse_implib,
> > > +				 bfd *in_implib_bfd)
> > > 
> > >  {
> > >  
> > >    struct elf32_arm_link_hash_table *globals;
> > > 
> > > @@ -8211,6 +8593,7 @@ bfd_elf32_arm_set_target_relocs (struct bfd
> > > *output_bfd,>
> > > 
> > >    globals->fix_cortex_a8 = fix_cortex_a8;
> > >    globals->fix_arm1176 = fix_arm1176;
> > >    globals->cmse_implib = cmse_implib;
> > > 
> > > +  globals->in_implib_bfd = in_implib_bfd;
> > > 
> > >    BFD_ASSERT (is_arm_elf (output_bfd));
> > >    elf_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
> > > 
> > > diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
> > > index
> > > c21f6a82335a58a0ab37f3719c73c95e73e6211c..2346bb42444895605d10b7b7e21cca
> > > 2d
> > > caa38700 100644
> > > --- a/ld/emultempl/armelf.em
> > > +++ b/ld/emultempl/armelf.em
> > > @@ -43,6 +43,7 @@ static int pic_veneer = 0;
> > > 
> > >  static int merge_exidx_entries = -1;
> > >  static int fix_arm1176 = 1;
> > >  static int cmse_implib = 0;
> > > 
> > > +static char *in_implib_filename = NULL;
> > > 
> > >  static void
> > >  gld${EMULATION_NAME}_before_parse (void)
> > > 
> > > @@ -498,6 +499,8 @@ gld${EMULATION_NAME}_finish (void)
> > > 
> > >  static void
> > >  arm_elf_create_output_section_statements (void)
> > >  {
> > > 
> > > +  bfd *in_implib_bfd;
> > > +
> > > 
> > >    if (strstr (bfd_get_target (link_info.output_bfd), "arm") == NULL)
> > >    
> > >      {
> > >      
> > >        /* The arm backend needs special fields in the output hash
> > >        structure.
> > > 
> > > @@ -508,6 +511,20 @@ arm_elf_create_output_section_statements (void)
> > > 
> > >        return;
> > >      
> > >      }
> > > 
> > > +  if (in_implib_filename)
> > > +    {
> > > +      in_implib_bfd = bfd_openr (in_implib_filename,
> > > +				 bfd_get_target (link_info.output_bfd));
> > > +
> > > +      if (in_implib_bfd == NULL)
> > > +	einfo ("%F%s: Can't open: %E\n", in_implib_filename);
> > > +
> > > +      if (!bfd_check_format (in_implib_bfd, bfd_object))
> > > +	einfo ("%F%s: Not a relocatable file: %E\n", in_implib_filename);
> > > +    }
> > > +  else
> > > +    in_implib_bfd = NULL;
> > > +
> > > 
> > >    bfd_elf32_arm_set_target_relocs (link_info.output_bfd, &link_info,
> > >    
> > >  				   target1_is_rel,
> > >  				   target2_type, fix_v4bx, use_blx,
> > > 
> > > @@ -515,7 +532,7 @@ arm_elf_create_output_section_statements (void)
> > > 
> > >  				   no_enum_size_warning,
> > >  				   no_wchar_size_warning,
> > >  				   pic_veneer, fix_cortex_a8,
> > > 
> > > -				   fix_arm1176, cmse_implib);
> > > +				   fix_arm1176, cmse_implib, in_implib_bfd);
> > > 
> > >    stub_file = lang_add_input_file ("linker stubs",
> > >    
> > >   				   lang_input_file_is_fake_enum,
> > > 
> > > @@ -585,6 +602,7 @@ PARSE_AND_LIST_PROLOGUE='
> > > 
> > >  #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
> > > 
> > > @@ -612,6 +630,7 @@ PARSE_AND_LIST_LONGOPTS='
> > > 
> > >    { "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='
> > > 
> > > @@ -634,6 +653,8 @@ PARSE_AND_LIST_OPTIONS='
> > > 
> > >             "                              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\
> > > @@ -758,6 +779,10 @@ PARSE_AND_LIST_ARGS_CASES='
> > > 
> > >     case OPTION_CMSE_IMPLIB:
> > >        cmse_implib = 1;
> > >        break;
> > > 
> > > +
> > > +   case OPTION_IN_IMPLIB:
> > > +      in_implib_filename = optarg;
> > > +      break;
> > > 
> > >  '
> > >  
> > >  # We have our own before_allocation etc. functions, but they call
> > > 
> > > diff --git a/ld/ld.texinfo b/ld/ld.texinfo
> > > index
> > > 82b40355a698958d84b566c09901960370139b27..eda43065f42e28bc4793bd5df78e45
> > > bd
> > > 21cc1817 100644
> > > --- a/ld/ld.texinfo
> > > +++ b/ld/ld.texinfo
> > > @@ -6817,6 +6817,18 @@ specified by the @samp{--out-implib} and
> > > @samp{--in-
> > > implib} options are
> > > 
> > >  secure gateway import libraries, suitable for linking a non-secure
> > >  executable against secure code as per ARMv8-M Security Extensions.
> > > 
> > > +@kindex --in-implib=@var{file}
> > > +@cindex Input import library
> > > +The @samp{--in-implib=file} specifies an input import library whose
> > > symbols +must keep the same address in the executable being produced.  A
> > > warning is +given if no @samp{--out-implib} is given but new symbols
> > > have
> > > been introduced +in the executable that should be listed in its import
> > > library.  Otherwise, if +@samp{--out-implib} is specified, the symbols
> > > are silently added to the output
> > 
> > I think 'silently' is unnecessary here.
> > 
> > > +import library.  A warning is also given if some symbols present in the
> > > input +import library have disappeared from the executable.  This option
> > > is only +effective for Secure Gateway import libraries, ie. when
> > > @samp{--cmse-implib} is
> > > +specified.
> > > +
> > > 
> > >  @ifclear GENERIC
> > >  @lowersections
> > >  @end ifclear
> > > 
> > > diff --git a/ld/testsuite/ld-arm/arm-elf.exp
> > > b/ld/testsuite/ld-arm/arm-elf.exp index
> > > da4bf7e0302de9f1c76bbacf8b64a9318d44c46a..f15a8d42f3d5a4f87f21df2b229e30
> > > a1
> > > 143fe7ac 100644
> > > --- a/ld/testsuite/ld-arm/arm-elf.exp
> > > +++ b/ld/testsuite/ld-arm/arm-elf.exp
> > > @@ -663,16 +663,53 @@ set armeabitests_nonacl {
> > > 
> > >       "cmse-veneers-mainline"}
> > >      
> > >      {"Secure gateway import library generation: errors"
> > >      
> > >       "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-
> > > 
> > > implib.lib --cmse-implib" ""
> > > -     "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1"
> > > +     "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1 --defsym
> > > VER=1"
> > > 
> > >       {cmse-implib.s}
> > >       {{ld cmse-implib-errors.out}}
> > >       "cmse-implib"}
> > >      
> > >      {"Secure gateway import library generation"
> > >      
> > >       "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-
> > > 
> > > implib.lib --cmse-implib" ""
> > > -     "-march=armv8-m.base -mthumb"
> > > +     "-march=armv8-m.base -mthumb --defsym VER=1"
> > > 
> > >       {cmse-implib.s}
> > >       {{readelf {-s tmpdir/cmse-implib.lib} cmse-implib.rd}}
> > >       "cmse-implib"}
> > > 
> > > +    {"Input secure gateway import library"
> > > +     "--section-start .gnu.sgstubs=0x20000
> > > --out-implib=tmpdir/cmse-new-
> > > implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> > > +     "-march=armv8-m.base -mthumb --defsym VER=2"
> > > +     {cmse-implib.s}
> > > +     {{ld cmse-new-implib.out}
> > > +      {readelf {-s tmpdir/cmse-new-implib.lib} cmse-new-implib.rd}}
> > > +     "cmse-new-implib"}
> > > +    {"Input secure gateway import library: no output import library"
> > > +     "--section-start .gnu.sgstubs=0x20000
> > > --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> > > +     "-march=armv8-m.base -mthumb --defsym VER=2"
> > > +     {cmse-implib.s}
> > > +     {{ld cmse-new-implib-no-output.out}}
> > > +     "cmse-new-implib-no-output"}
> > > +    {"Input secure gateway import library: earlier stub section base"
> > > +     "--section-start .gnu.sgstubs=0x19000
> > > --out-implib=tmpdir/cmse-new-
> > > earlier-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> > > +     "-march=armv8-m.base -mthumb --defsym VER=2"
> > > +     {cmse-implib.s}
> > > +     {{ld cmse-new-earlier-later-implib.out}}
> > > +     "cmse-new-earlier-implib"}
> > > +    {"Input secure gateway import library: later stub section base"
> > > +     "--section-start .gnu.sgstubs=0x30000
> > > --out-implib=tmpdir/cmse-new-
> > > later-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> > > +     "-march=armv8-m.base -mthumb --defsym VER=2"
> > > +     {cmse-implib.s}
> > > +     {{ld cmse-new-earlier-later-implib.out}}
> > > +     "cmse-new-later-implib"}
> > > +    {"Input secure gateway import library: veneer comeback"
> > > +     "--section-start .gnu.sgstubs=0x20000
> > > --out-implib=tmpdir/cmse-new-
> > > comeback-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> > > +     "-march=armv8-m.base -mthumb --defsym VER=3"
> > > +     {cmse-implib.s}
> > > +     {{readelf {-s tmpdir/cmse-new-comeback-implib.lib}
> > > cmse-new-comeback-
> > > implib.rd}}
> > > +     "cmse-new-comeback-implib"}
> > > +    {"Input secure gateway import library: entry function change"
> > > +     "--section-start .gnu.sgstubs=0x20000
> > > --out-implib=tmpdir/cmse-new-
> > > wrong-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> > > +     "-march=armv8-m.base -mthumb --defsym VER=4"
> > > +     {cmse-implib.s}
> > > +     {{ld cmse-new-wrong-implib.out}}
> > > +     "cmse-new-wrong-implib"}
> > > 
> > >      {"R_ARM_THM_JUMP19 Relocation veneers: Short"
> > >      
> > >       "--section-start destsect=0x000108002 --section-start
> > >       .text=0x8000"
> > >       ""
> > > 
> > > diff --git a/ld/testsuite/ld-arm/cmse-implib.s
> > > b/ld/testsuite/ld-arm/cmse-
> > > implib.s
> > > index
> > > a42da63fffebe5322be83f278931754262b0f7ae..9dd783939891478351a5f7ccb14809
> > > 80
> > > a77dca68 100644
> > > --- a/ld/testsuite/ld-arm/cmse-implib.s
> > > +++ b/ld/testsuite/ld-arm/cmse-implib.s
> > > 
> > > @@ -20,12 +20,29 @@ __acle_se_\name:
> > >  .endm
> > >  
> > >  	@ Valid setups for veneer generation
> > > 
> > > +.if (VER >= 2)
> > > +	entry exported_entry_veneer1, global
> > > +.endif
> > > +.if (VER != 4)
> > > 
> > >  	entry exported_entry_veneer2, global
> > > 
> > > +.else
> > > +	entry exported_entry_veneer2, weak
> > > +.endif
> > > +.if (VER != 2)
> > > 
> > >  	entry exported_entry_veneer3, global
> > > 
> > > +.endif
> > > +.if (VER > 1)
> > > +	entry exported_entry_veneer4, global
> > > +.endif
> > > 
> > >  	@ Valid setup for entry function without veneer generation
> > >  	entry exported_entry_fct1, global, sg
> > > 
> > > +.if (VER != 4)
> > > 
> > >  	entry exported_entry_fct2, global, sg
> > > 
> > > +.else
> > > +	@ Invalid setup for entry function without veneer generation
> > > +	entry exported_entry_fct2, global, nop
> > > +.endif
> > > 
> > >  	@ Normal symbol not exported to SG import library
> > >  	.align	2
> > > 
> > > diff --git a/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd
> > > b/ld/testsuite/ld- arm/cmse-new-comeback-implib.rd
> > > new file mode 100644
> > > index
> > > 0000000000000000000000000000000000000000..c88d9d5104244abc8ceba4d552e1ef
> > > 0e
> > > 400c37d1 --- /dev/null
> > > +++ b/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd
> > > @@ -0,0 +1,15 @@
> > > +File: tmpdir/cmse-new-.*implib.lib
> > > +
> > > +Symbol table '.symtab' contains 7 entries:
> > > +   Num:    Value  Size Type    Bind   Vis      Ndx Name
> > > +     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
> > > +     1: 00020001     8 FUNC    GLOBAL DEFAULT  ABS
> > > exported_entry_veneer3
> > > +     2: 00020011     8 FUNC    GLOBAL DEFAULT  ABS
> > > exported_entry_veneer4
> > > +     3: 00020019     8 FUNC    GLOBAL DEFAULT  ABS
> > > exported_entry_veneer1
> > > +     4: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
> > > +     5: 00020009     8 FUNC    GLOBAL DEFAULT  ABS
> > > exported_entry_veneer2
> > > +     6: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
> > > +
> > > +File: tmpdir/cmse-new-.*implib
> > > +
> > > +#...
> > > diff --git a/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
> > > b/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
> > > new file mode 100644
> > > index
> > > 0000000000000000000000000000000000000000..b49ad0ac0770a17c39c2d119d1f0c5
> > > 85
> > > 4a5bd8cc --- /dev/null
> > > +++ b/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
> > > @@ -0,0 +1,3 @@
> > > +.*: Entry function `exported_entry_veneer3' disappeared from secure
> > > code.
> > > +.*: Start address of `.gnu.sgstubs' is different from previous link.
> > > +.*: cannot size stub section: Invalid operation
> > > diff --git a/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
> > > b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
> > > new file mode 100644
> > > index
> > > 0000000000000000000000000000000000000000..0590b71c844da3687b29b93797abda
> > > 51
> > > 72ab8d99 --- /dev/null
> > > +++ b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
> > > @@ -0,0 +1,4 @@
> > > +.*: Entry function `exported_entry_veneer3' disappeared from secure
> > > code.
> > > +.*: new entry function\(s\) introduced but no output import library
> > > specified: +.*:   exported_entry_veneer4
> > > +.*:   exported_entry_veneer1
> > > diff --git a/ld/testsuite/ld-arm/cmse-new-implib.out b/ld/testsuite/ld-
> > > arm/cmse-new-implib.out
> > > new file mode 100644
> > > index
> > > 0000000000000000000000000000000000000000..c8af2807e7c1a7eeb1fc156fbf4508
> > > cf
> > > 7a7e932d --- /dev/null
> > > +++ b/ld/testsuite/ld-arm/cmse-new-implib.out
> > > @@ -0,0 +1 @@
> > > +.*: Entry function `exported_entry_veneer3' disappeared from secure
> > > code.
> > > diff --git a/ld/testsuite/ld-arm/cmse-new-implib.rd
> > > b/ld/testsuite/ld-arm/cmse- new-implib.rd
> > > new file mode 100644
> > > index
> > > 0000000000000000000000000000000000000000..9ff0fd87937571f86f99ee940a91a3
> > > f6
> > > 7352242a --- /dev/null
> > > +++ b/ld/testsuite/ld-arm/cmse-new-implib.rd
> > > @@ -0,0 +1,14 @@
> > > +File: tmpdir/cmse-new-.*implib.lib
> > > +
> > > +Symbol table '.symtab' contains 6 entries:
> > > +   Num:    Value  Size Type    Bind   Vis      Ndx Name
> > > +     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
> > > +     1: 00020011     8 FUNC    GLOBAL DEFAULT  ABS
> > > exported_entry_veneer4
> > > +     2: 00020019     8 FUNC    GLOBAL DEFAULT  ABS
> > > exported_entry_veneer1
> > > +     3: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
> > > +     4: 00020009     8 FUNC    GLOBAL DEFAULT  ABS
> > > exported_entry_veneer2
> > > +     5: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
> > > +
> > > +File: tmpdir/cmse-new-.*implib
> > > +
> > > +#...
> > > diff --git a/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
> > > b/ld/testsuite/ld- arm/cmse-new-wrong-implib.out
> > > new file mode 100644
> > > index
> > > 0000000000000000000000000000000000000000..2afe4078e78606d24f05dda6ff1c5e
> > > 6a
> > > 54d42512 --- /dev/null
> > > +++ b/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
> > > @@ -0,0 +1,3 @@
> > > +.*: .*: visibility of symbol `exported_entry_veneer2' has changed.
> > > +.*: `exported_entry_fct2' refers to a non entry function.
> > > +.*: cannot size stub section: Invalid operation
> > > 
> > > 
> > > Is this ok for master branch?
> > > 
> > > Best regards,
> > > 
> > > Thomas

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ARM 11/11, ping] Add support for stable secure gateway veneers addresses
       [not found]       ` <f4e62f04-bebc-135d-372a-d29bdb4efcf0@foss.arm.com>
@ 2016-08-17 15:23         ` Thomas Preudhomme
  2016-08-25 16:14           ` Richard Earnshaw (lists)
  0 siblings, 1 reply; 15+ messages in thread
From: Thomas Preudhomme @ 2016-08-17 15:23 UTC (permalink / raw)
  To: Richard Earnshaw (lists), binutils

[Trying again with inline patch since previous attempt got flagged as spam]

diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index 
d33bb8267b12d9cd2c942d3c502e3e563e63d09f..f9bce9fd3ef778429ea9c1416ca2ffcab3f4e374 
100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.h
@@ -894,7 +894,7 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation

  void bfd_elf32_arm_set_target_relocs
    (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix,
-   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
+   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);

  extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
    (bfd *, struct bfd_link_info *);
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 
cc8428a21d8ce3267420c76a4328fb6d433cd597..8b1d8a01adf529ee42ad6673c82a5028aed5774c 
100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -901,7 +901,7 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation

  void bfd_elf32_arm_set_target_relocs
    (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix,
-   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
+   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);

  extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
    (bfd *, struct bfd_link_info *);
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 
1eba21b42ddfaf3704860107e4fff36dbbc24d8d..539c2aacbd6b47b25288d3b3e691b90806863856 
100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -3148,6 +3148,10 @@ struct elf32_arm_link_hash_table
       as per ARMv8-M Security Extensions.  */
    int cmse_implib;

+  /* The import library whose symbols' address must remain stable in
+     the import library generated.  */
+  bfd *in_implib_bfd;
+
    /* The index of the next unused R_ARM_TLS_DESC slot in .rel.plt.  */
    bfd_vma next_tls_desc_index;

@@ -3209,6 +3213,10 @@ struct elf32_arm_link_hash_table
    /* Input stub section holding secure gateway veneers.  */
    asection *cmse_stub_sec;

+  /* Offset in cmse_stub_sec where new SG veneers (not in input import library)
+     start to be allocated.  */
+  bfd_vma new_cmse_stub_offset;
+
    /* Number of elements in stub_group.  */
    unsigned int top_id;

@@ -3460,7 +3468,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
        /* Initialize the local fields.  */
        eh = (struct elf32_arm_stub_hash_entry *) entry;
        eh->stub_sec = NULL;
-      eh->stub_offset = 0;
+      eh->stub_offset = (bfd_vma) -1;
        eh->source_value = 0;
        eh->target_value = 0;
        eh->target_section = NULL;
@@ -3468,7 +3476,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
        eh->stub_type = arm_stub_none;
        eh->stub_size = 0;
        eh->stub_template = NULL;
-      eh->stub_template_size = 0;
+      eh->stub_template_size = -1;
        eh->h = NULL;
        eh->id_sec = NULL;
        eh->output_name = NULL;
@@ -4467,7 +4475,7 @@ elf32_arm_add_stub (const char *stub_name, asection *section,
      }

    stub_entry->stub_sec = stub_sec;
-  stub_entry->stub_offset = 0;
+  stub_entry->stub_offset = (bfd_vma) -1;
    stub_entry->id_sec = link_sec;

    return stub_entry;
@@ -4633,11 +4641,31 @@ arm_dedicated_stub_section_padding (enum 
elf32_arm_stub_type stub_type)
    abort ();  /* Should be unreachable.  */
  }

+/* If veneers of type STUB_TYPE should go in a dedicated output section,
+   returns the address of the hash table field in HTAB holding the offset at
+   which new veneers should be layed out in the stub section.  */
+
+static bfd_vma*
+arm_new_stubs_start_offset_ptr (struct elf32_arm_link_hash_table *htab,
+				enum elf32_arm_stub_type stub_type)
+{
+  switch (stub_type)
+    {
+    case arm_stub_cmse_branch_thumb_only:
+      return &htab->new_cmse_stub_offset;
+
+    default:
+      BFD_ASSERT (!arm_dedicated_stub_output_section_required (stub_type));
+      return NULL;
+    }
+}
+
  static bfd_boolean
  arm_build_one_stub (struct bfd_hash_entry *gen_entry,
  		    void * in_arg)
  {
  #define MAXRELOCS 3
+  bfd_boolean removed_sg_veneer;
    struct elf32_arm_stub_hash_entry *stub_entry;
    struct elf32_arm_link_hash_table *globals;
    struct bfd_link_info *info;
@@ -4652,6 +4680,7 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
    int stub_reloc_idx[MAXRELOCS] = {-1, -1};
    int stub_reloc_offset[MAXRELOCS] = {0, 0};
    int nrelocs = 0;
+  int just_allocated = 0;

    /* Massage our args to the form they really have.  */
    stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
@@ -4668,8 +4697,12 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
      /* We have to do less-strictly-aligned fixes last.  */
      return TRUE;

-  /* Make a note of the offset within the stubs for this entry.  */
-  stub_entry->stub_offset = stub_sec->size;
+  /* Assign a slot at the end of section if none assigned yet.  */
+  if (stub_entry->stub_offset == (bfd_vma) -1)
+    {
+      stub_entry->stub_offset = stub_sec->size;
+      just_allocated = 1;
+    }
    loc = stub_sec->contents + stub_entry->stub_offset;

    stub_bfd = stub_sec->owner;
@@ -4743,7 +4776,8 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
  	}
      }

-  stub_sec->size += size;
+  if (just_allocated)
+    stub_sec->size += size;

    /* Stub size has already been computed in arm_size_one_stub. Check
       consistency.  */
@@ -4753,9 +4787,11 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
    if (stub_entry->branch_type == ST_BRANCH_TO_THUMB)
      sym_value |= 1;

-  /* Assume there is at least one and at most MAXRELOCS entries to relocate
-     in each stub.  */
-  BFD_ASSERT (nrelocs != 0 && nrelocs <= MAXRELOCS);
+  /* Assume non empty slots have at least one and at most MAXRELOCS entries
+     to relocate in each stub.  */
+  removed_sg_veneer =
+    (size == 0 && stub_entry->stub_type == arm_stub_cmse_branch_thumb_only);
+  BFD_ASSERT (removed_sg_veneer || (nrelocs != 0 && nrelocs <= MAXRELOCS));

    for (i = 0; i < nrelocs; i++)
      {
@@ -4857,9 +4893,17 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry,
    size = find_stub_size_and_template (stub_entry->stub_type, &template_sequence,
  				      &template_size);

-  stub_entry->stub_size = size;
-  stub_entry->stub_template = template_sequence;
-  stub_entry->stub_template_size = template_size;
+  /* Initialized to -1.  Null size indicates an empty slot full of zeros.  */
+  if (stub_entry->stub_template_size)
+    {
+      stub_entry->stub_size = size;
+      stub_entry->stub_template = template_sequence;
+      stub_entry->stub_template_size = template_size;
+    }
+
+  /* Already accounted for.  */
+  if (stub_entry->stub_offset != (bfd_vma) -1)
+    return TRUE;

    size = (size + 7) & ~7;
    stub_entry->stub_sec->size += size;
@@ -5424,10 +5468,10 @@ cortex_a8_erratum_scan (bfd *input_bfd,
     and *NEW_STUB is set to FALSE.  Otherwise, *NEW_STUB is set to
     TRUE and the stub entry is initialized.

-   Returns whether the stub could be successfully created or updated, or FALSE
-   if an error occured.  */
+   Returns the stub that was created or updated, or NULL if an error
+   occurred.  */

-static bfd_boolean
+static struct elf32_arm_stub_hash_entry *
  elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
  		       enum elf32_arm_stub_type stub_type, asection *section,
  		       Elf_Internal_Rela *irela, asection *sym_sec,
@@ -5458,7 +5502,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
        stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash, irela,
  				       stub_type);
        if (!stub_name)
-	return FALSE;
+	return NULL;
      }

    stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, stub_name, FALSE,
@@ -5469,7 +5513,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
        if (!sym_claimed)
  	free (stub_name);
        stub_entry->target_value = sym_value;
-      return TRUE;
+      return stub_entry;
      }

    stub_entry = elf32_arm_add_stub (stub_name, section, htab, stub_type);
@@ -5477,7 +5521,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
      {
        if (!sym_claimed)
  	free (stub_name);
-      return FALSE;
+      return NULL;
      }

    stub_entry->target_value = sym_value;
@@ -5498,7 +5542,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
        if (stub_entry->output_name == NULL)
  	{
  	  free (stub_name);
-	  return FALSE;
+	  return NULL;
  	}

        /* For historical reasons, use the existing names for ARM-to-Thumb and
@@ -5518,7 +5562,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
      }

    *new_stub = TRUE;
-  return TRUE;
+  return stub_entry;
  }

  /* Scan symbols in INPUT_BFD to identify secure entry functions needing a
@@ -5537,14 +5581,15 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table 
*htab,

     OUT_ATTR gives the output attributes, SYM_HASHES the symbol index to hash
     entry mapping while HTAB gives the name to hash entry mapping.
+   *CMSE_STUB_CREATED is increased by the number of secure gateway veneer
+   created.

-   If any secure gateway veneer is created, *STUB_CHANGED is set to TRUE.  The
-   return value gives whether a stub failed to be allocated.  */
+   The return value gives whether a stub failed to be allocated.  */

  static bfd_boolean
  cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
  	   obj_attribute *out_attr, struct elf_link_hash_entry **sym_hashes,
-	   bfd_boolean *stub_changed)
+	   int *cmse_stub_created)
  {
    const struct elf_backend_data *bed;
    Elf_Internal_Shdr *symtab_hdr;
@@ -5555,7 +5600,8 @@ cmse_scan (bfd *input_bfd, struct 
elf32_arm_link_hash_table *htab,
    char *sym_name, *lsym_name;
    bfd_vma sym_value;
    asection *section;
-  bfd_boolean is_v8m, new_stub, created_stub, cmse_invalid, ret = TRUE;
+  struct elf32_arm_stub_hash_entry *stub_entry;
+  bfd_boolean is_v8m, new_stub, cmse_invalid, ret = TRUE;

    bed = get_elf_backend_data (input_bfd);
    symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
@@ -5700,17 +5746,17 @@ cmse_scan (bfd *input_bfd, struct 
elf32_arm_link_hash_table *htab,
        if (!ret)
  	continue;
        branch_type = ARM_GET_SYM_BRANCH_TYPE (hash->root.target_internal);
-      created_stub
+      stub_entry
  	= elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
  				 NULL, NULL, section, hash, sym_name,
  				 sym_value, branch_type, &new_stub);

-      if (!created_stub)
+      if (stub_entry == NULL)
  	 ret = FALSE;
        else
  	{
  	  BFD_ASSERT (new_stub);
-	  *stub_changed = TRUE;
+	  (*cmse_stub_created)++;
  	}
      }

@@ -5719,6 +5765,279 @@ cmse_scan (bfd *input_bfd, struct 
elf32_arm_link_hash_table *htab,
    return ret;
  }

+/* Return TRUE iff a symbol identified by its linker HASH entry is a secure
+   code entry function, ie can be called from non secure code without using a
+   veneer.  */
+
+static bfd_boolean
+cmse_entry_fct_p (struct elf32_arm_link_hash_entry *hash)
+{
+  uint32_t first_insn;
+  asection *section;
+  file_ptr offset;
+  bfd *abfd;
+
+  /* Defined symbol of function type.  */
+  if (hash->root.root.type != bfd_link_hash_defined
+      && hash->root.root.type != bfd_link_hash_defweak)
+    return FALSE;
+  if (hash->root.type != STT_FUNC)
+    return FALSE;
+
+  /* Read first instruction.  */
+  section = hash->root.root.u.def.section;
+  abfd = section->owner;
+  offset = hash->root.root.u.def.value - section->vma;
+  if (!bfd_get_section_contents (abfd, section, &first_insn, offset,
+				 sizeof (first_insn)))
+    return FALSE;
+
+  /* Start by SG instruction.  */
+  return first_insn == 0xe97fe97f;
+}
+
+/* Output the name (in symbol table) of the veneer GEN_ENTRY if it is a new
+   secure gateway veneers (ie. the veneers was not in the input import library)
+   and there is no output import library (GEN_INFO->out_implib_bfd is NULL.  */
+
+static bfd_boolean
+arm_list_new_cmse_stub (struct bfd_hash_entry *gen_entry, void *gen_info)
+{
+  struct elf32_arm_stub_hash_entry *stub_entry;
+  struct bfd_link_info *info;
+
+  /* Massage our args to the form they really have.  */
+  stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
+  info = (struct bfd_link_info *) gen_info;
+
+  if (info->out_implib_bfd)
+    return TRUE;
+
+  if (stub_entry->stub_type != arm_stub_cmse_branch_thumb_only)
+    return TRUE;
+
+  if (stub_entry->stub_offset == (bfd_vma) -1)
+    (*_bfd_error_handler) ("  %s", stub_entry->output_name);
+
+  return TRUE;
+}
+
+/* Set offset of each secure gateway veneers so that its address remain
+   identical to the one in the input import library referred by
+   HTAB->in_implib_bfd.  A warning is issued for veneers that disappeared
+   (present in input import library but absent from the executable being
+   linked) or if new veneers appeared and there is no output import library
+   (INFO->out_implib_bfd is NULL and *CMSE_STUB_CREATED is bigger than the
+   number of secure gateway veneers found in the input import library.
+
+   The function returns whether an error occurred.  If no error occurred,
+   *CMSE_STUB_CREATED gives the number of SG veneers created by both cmse_scan
+   and this function and HTAB->new_cmse_stub_offset is set to the biggest
+   veneer observed set for new veneers to be layed out after.  */
+
+static bfd_boolean
+set_cmse_veneer_addr_from_implib (struct bfd_link_info *info,
+				  struct elf32_arm_link_hash_table *htab,
+				  int *cmse_stub_created)
+{
+  long symsize;
+  char *sym_name;
+  flagword flags;
+  long i, symcount;
+  bfd *in_implib_bfd;
+  asection *stub_out_sec;
+  bfd_boolean ret = TRUE;
+  Elf_Internal_Sym *intsym;
+  const char *out_sec_name;
+  bfd_size_type cmse_stub_size;
+  asymbol **sympp = NULL, *sym;
+  struct elf32_arm_link_hash_entry *hash;
+  const insn_sequence *cmse_stub_template;
+  struct elf32_arm_stub_hash_entry *stub_entry;
+  int cmse_stub_template_size, new_cmse_stubs_created = *cmse_stub_created;
+  bfd_vma veneer_value, stub_offset, next_cmse_stub_offset;
+  bfd_vma cmse_stub_array_start = (bfd_vma) -1, cmse_stub_sec_vma = 0;
+
+  /* No input secure gateway import library.  */
+  if (!htab->in_implib_bfd)
+    return TRUE;
+
+  in_implib_bfd = htab->in_implib_bfd;
+  if (!htab->cmse_implib)
+    {
+      (*_bfd_error_handler) (_("%B: --in-implib only supported for Secure "
+			       "Gateway import libraries."), in_implib_bfd);
+      return FALSE;
+    }
+
+  /* Get symbol table size.  */
+  symsize = bfd_get_symtab_upper_bound (in_implib_bfd);
+  if (symsize < 0)
+    return FALSE;
+
+  /* Read in the input secure gateway import library's symbol table.  */
+  sympp = (asymbol **) xmalloc (symsize);
+  symcount = bfd_canonicalize_symtab (in_implib_bfd, sympp);
+  if (symcount < 0)
+    {
+      ret = FALSE;
+      goto free_sym_buf;
+    }
+
+  htab->new_cmse_stub_offset = 0;
+  cmse_stub_size =
+    find_stub_size_and_template (arm_stub_cmse_branch_thumb_only,
+				 &cmse_stub_template,
+				 &cmse_stub_template_size);
+  out_sec_name =
+    arm_dedicated_stub_output_section_name (arm_stub_cmse_branch_thumb_only);
+  stub_out_sec =
+    bfd_get_section_by_name (htab->obfd, out_sec_name);
+  if (stub_out_sec != NULL)
+    cmse_stub_sec_vma = stub_out_sec->vma;
+
+  /* Set addresses of veneers mentionned in input secure gateway import
+     library's symbol table.  */
+  for (i = 0; i < symcount; i++)
+    {
+      sym = sympp[i];
+      flags = sym->flags;
+      sym_name = (char *) bfd_asymbol_name (sym);
+      intsym = &((elf_symbol_type *) sym)->internal_elf_sym;
+
+      if (sym->section != bfd_abs_section_ptr
+	  || !(flags & (BSF_GLOBAL | BSF_WEAK))
+	  || (flags & BSF_FUNCTION) != BSF_FUNCTION
+	  || (ARM_GET_SYM_BRANCH_TYPE (intsym->st_target_internal)
+	      != ST_BRANCH_TO_THUMB))
+	{
+	  (*_bfd_error_handler) (_("%B: invalid import library entry: `%s'."),
+				 in_implib_bfd, sym_name);
+	  (*_bfd_error_handler) (_("Symbol should be absolute, global and "
+				   "refer to Thumb functions."));
+	  ret = FALSE;
+	  continue;
+	}
+
+      veneer_value = bfd_asymbol_value (sym);
+      stub_offset = veneer_value - cmse_stub_sec_vma;
+      stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, sym_name,
+					 FALSE, FALSE);
+      hash = (struct elf32_arm_link_hash_entry *)
+	elf_link_hash_lookup (&(htab)->root, sym_name, FALSE, FALSE, TRUE);
+
+      /* Stub entry should have been created by cmse_scan or the symbol be of
+	 a secure function callable from non secure code.  */
+      if (!stub_entry && !hash)
+	{
+	  bfd_boolean new_stub;
+
+	  (*_bfd_error_handler)
+	    (_("Entry function `%s' disappeared from secure code."), sym_name);
+	  hash = (struct elf32_arm_link_hash_entry *)
+	    elf_link_hash_lookup (&(htab)->root, sym_name, TRUE, TRUE, TRUE);
+	  stub_entry
+	    = elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
+				     NULL, NULL, bfd_abs_section_ptr, hash,
+				     sym_name, veneer_value,
+				     ST_BRANCH_TO_THUMB, &new_stub);
+	  if (stub_entry == NULL)
+	    ret = FALSE;
+	  else
+	  {
+	    BFD_ASSERT (new_stub);
+	    new_cmse_stubs_created++;
+	    (*cmse_stub_created)++;
+	  }
+	  stub_entry->stub_template_size = stub_entry->stub_size = 0;
+	  stub_entry->stub_offset = stub_offset;
+	}
+      /* Symbol found is not callable from non secure code.  */
+      else if (!stub_entry)
+	{
+	  if (!cmse_entry_fct_p (hash))
+	    {
+	      (*_bfd_error_handler) (_("`%s' refers to a non entry function."),
+				     sym_name);
+	      ret = FALSE;
+	    }
+	  continue;
+	}
+      else
+	{
+	  /* Only stubs for SG veneers should have been created.  */
+	  BFD_ASSERT (stub_entry->stub_type == arm_stub_cmse_branch_thumb_only);
+
+	  /* Check visibility hasn't changed.  */
+	  if (!!(flags & BSF_GLOBAL)
+	      != (hash->root.root.type == bfd_link_hash_defined))
+	    (*_bfd_error_handler)
+	      (_("%B: visibility of symbol `%s' has changed."), in_implib_bfd,
+	       sym_name);
+
+	  stub_entry->stub_offset = stub_offset;
+	}
+
+      /* Size should match that of a SG veneer.  */
+      if (intsym->st_size != cmse_stub_size)
+	{
+	  (*_bfd_error_handler) (_("%B: incorrect size for symbol `%s'."),
+				 in_implib_bfd, sym_name);
+	  ret = FALSE;
+	}
+
+      /* Previous veneer address is before current SG veneer section.  */
+      if (veneer_value < cmse_stub_sec_vma)
+	{
+	  /* Avoid offset underflow.  */
+	  if (stub_entry)
+	    stub_entry->stub_offset = 0;
+	  stub_offset = 0;
+	  ret = FALSE;
+	}
+
+      /* Complain if stub offset not a multiple of stub size.  */
+      if (stub_offset % cmse_stub_size)
+	{
+	  (*_bfd_error_handler)
+	    (_("Offset of veneer for entry function `%s' not a multiple of "
+	       "its size."), sym_name);
+	  ret = FALSE;
+	}
+
+      if (!ret)
+	continue;
+
+      new_cmse_stubs_created--;
+      if (veneer_value < cmse_stub_array_start)
+	cmse_stub_array_start = veneer_value;
+      next_cmse_stub_offset = stub_offset + ((cmse_stub_size + 7) & ~7);
+      if (next_cmse_stub_offset > htab->new_cmse_stub_offset)
+	htab->new_cmse_stub_offset = next_cmse_stub_offset;
+    }
+
+  if (!info->out_implib_bfd && new_cmse_stubs_created != 0)
+    {
+      BFD_ASSERT (new_cmse_stubs_created > 0);
+      (*_bfd_error_handler)
+	(_("new entry function(s) introduced but no output import library "
+	   "specified:"));
+      bfd_hash_traverse (&htab->stub_hash_table, arm_list_new_cmse_stub, info);
+    }
+
+  if (cmse_stub_array_start != cmse_stub_sec_vma)
+    {
+      (*_bfd_error_handler)
+	(_("Start address of `%s' is different from previous link."),
+	 out_sec_name);
+      ret = FALSE;
+    }
+
+free_sym_buf:
+  free (sympp);
+  return ret;
+}
+
  /* Determine and set the size of the stub section for a final link.

     The basic idea here is to examine all the relocations looking for
@@ -5735,7 +6054,9 @@ elf32_arm_size_stubs (bfd *output_bfd,
  						      unsigned int),
  		      void (*layout_sections_again) (void))
  {
+  bfd_boolean ret = TRUE;
    obj_attribute *out_attr;
+  int cmse_stub_created = 0;
    bfd_size_type stub_group_size;
    bfd_boolean m_profile, stubs_always_after_branch, first_veneer_scan = TRUE;
    struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
@@ -5768,6 +6089,7 @@ elf32_arm_size_stubs (bfd *output_bfd,

    out_attr = elf_known_obj_attributes_proc (output_bfd);
    m_profile = out_attr[Tag_CPU_arch_profile].i == 'M';
+
    /* The Cortex-A8 erratum fix depends on stubs not being in the same 4K page
       as the first half of a 32-bit branch straddling two 4K pages.  This is a
       crude way of enforcing that.  */
@@ -5841,8 +6163,11 @@ elf32_arm_size_stubs (bfd *output_bfd,

  	      sym_hashes = elf_sym_hashes (input_bfd);
  	      if (!cmse_scan (input_bfd, htab, out_attr, sym_hashes,
-			      &stub_changed))
+			      &cmse_stub_created))
  		goto error_ret_free_local;
+
+	      if (cmse_stub_created != 0)
+		stub_changed = TRUE;
  	    }

  	  /* Walk over each section attached to the input bfd.  */
@@ -6074,6 +6399,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
  		  do
  		    {
  		      bfd_boolean new_stub;
+		      struct elf32_arm_stub_hash_entry *stub_entry;

  		      /* Determine what (if any) linker stub is needed.  */
  		      stub_type = arm_type_of_stub (info, section, irela,
@@ -6085,12 +6411,13 @@ elf32_arm_size_stubs (bfd *output_bfd,

  		      /* We've either created a stub for this reloc already,
  			 or we are about to.  */
-		      created_stub =
+		      stub_entry =
  			elf32_arm_create_stub (htab, stub_type, section, irela,
  					       sym_sec, hash,
  					       (char *) sym_name, sym_value,
  					       branch_type, &new_stub);

+		      created_stub = stub_entry != NULL;
  		      if (!created_stub)
  			goto error_ret_free_internal;
  		      else if (!new_stub)
@@ -6172,6 +6499,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
  	    }
  	}

+      if (first_veneer_scan
+	  && !set_cmse_veneer_addr_from_implib (info, htab,
+						&cmse_stub_created))
+	ret = FALSE;
+
        if (prev_num_a8_fixes != num_a8_fixes)
  	stub_changed = TRUE;

@@ -6191,6 +6523,24 @@ elf32_arm_size_stubs (bfd *output_bfd,
  	  stub_sec->size = 0;
  	}

+      /* Add new SG veneers after those already in the input import
+	 library.  */
+      for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
+	   stub_type++)
+	{
+	  bfd_vma *start_offset_p;
+	  asection **stub_sec_p;
+
+	  start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type);
+	  stub_sec_p = arm_dedicated_stub_input_section_ptr (htab, stub_type);
+	  if (start_offset_p == NULL)
+	    continue;
+
+	  BFD_ASSERT (stub_sec_p != NULL);
+	  if (*stub_sec_p != NULL)
+	    (*stub_sec_p)->size = *start_offset_p;
+	}
+
        /* Compute stub section size, considering padding.  */
        bfd_hash_traverse (&htab->stub_hash_table, arm_size_one_stub, htab);
        for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
@@ -6259,7 +6609,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
  	    }

  	  stub_entry->stub_sec = stub_sec;
-	  stub_entry->stub_offset = 0;
+	  stub_entry->stub_offset = (bfd_vma) -1;
  	  stub_entry->id_sec = link_sec;
  	  stub_entry->stub_type = a8_fixes[i].stub_type;
  	  stub_entry->source_value = a8_fixes[i].offset;
@@ -6287,7 +6637,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
        htab->a8_erratum_fixes = NULL;
        htab->num_a8_erratum_fixes = 0;
      }
-  return TRUE;
+  return ret;
  }

  /* Build all the stubs associated with the current output file.  The
@@ -6301,6 +6651,7 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
  {
    asection *stub_sec;
    struct bfd_hash_table *table;
+  enum elf32_arm_stub_type stub_type;
    struct elf32_arm_link_hash_table *htab;

    htab = elf32_arm_hash_table (info);
@@ -6318,14 +6669,33 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
  	continue;

        /* Allocate memory to hold the linker stubs.  Zeroing the stub sections
-	 must at least be done for stub section requiring padding.  */
+	 must at least be done for stub section requiring padding and for SG
+	 veneers to ensure that a non secure code branching to a removed SG
+	 veneer causes an error.  */
        size = stub_sec->size;
        stub_sec->contents = (unsigned char *) bfd_zalloc (htab->stub_bfd, size);
        if (stub_sec->contents == NULL && size != 0)
  	return FALSE;
+
        stub_sec->size = 0;
      }

+  /* Add new SG veneers after those already in the input import library.  */
+  for (stub_type = arm_stub_none + 1; stub_type < max_stub_type; stub_type++)
+    {
+      bfd_vma *start_offset_p;
+      asection **stub_sec_p;
+
+      start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type);
+      stub_sec_p = arm_dedicated_stub_input_section_ptr (htab, stub_type);
+      if (start_offset_p == NULL)
+	continue;
+
+      BFD_ASSERT (stub_sec_p != NULL);
+      if (*stub_sec_p != NULL)
+	(*stub_sec_p)->size = *start_offset_p;
+    }
+
    /* Build the stubs as directed by the stub hash table.  */
    table = &htab->stub_hash_table;
    bfd_hash_traverse (table, arm_build_one_stub, info);
@@ -8311,7 +8681,8 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd,
  				 bfd_arm_stm32l4xx_fix stm32l4xx_fix,
  				 int no_enum_warn, int no_wchar_warn,
  				 int pic_veneer, int fix_cortex_a8,
-				 int fix_arm1176, int cmse_implib)
+				 int fix_arm1176, int cmse_implib,
+				 bfd *in_implib_bfd)
  {
    struct elf32_arm_link_hash_table *globals;

@@ -8339,6 +8710,7 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd,
    globals->fix_cortex_a8 = fix_cortex_a8;
    globals->fix_arm1176 = fix_arm1176;
    globals->cmse_implib = cmse_implib;
+  globals->in_implib_bfd = in_implib_bfd;

    BFD_ASSERT (is_arm_elf (output_bfd));
    elf_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
diff --git a/ld/NEWS b/ld/NEWS
index 
2a0b4ac704a088a24cfc1633785a50477513c4db..0f316bfcc248341200af14e5cb1a5c50787e9b1a 
100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -2,6 +2,11 @@

  Changes in 2.28:

+* Add --in-implib=<infile> to the ARM linker to enable specifying a set of
+  Secure Gateway veneers that must exist in the output import library specified
+  by --out-implib=<outfile> and the address they must have.  As such,
+  --in-implib is only supported in combination with --cmse-implib.
+
  * Extended the --out-implib=<file> option, previously restricted to x86 PE
    targets, to any ELF based target.  This allows the generation of an import
    library for an ELF executable, which can then be used by another application
diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
index 
c21f6a82335a58a0ab37f3719c73c95e73e6211c..2346bb42444895605d10b7b7e21cca2dcaa38700 
100644
--- a/ld/emultempl/armelf.em
+++ b/ld/emultempl/armelf.em
@@ -43,6 +43,7 @@ static int pic_veneer = 0;
  static int merge_exidx_entries = -1;
  static int fix_arm1176 = 1;
  static int cmse_implib = 0;
+static char *in_implib_filename = NULL;

  static void
  gld${EMULATION_NAME}_before_parse (void)
@@ -498,6 +499,8 @@ gld${EMULATION_NAME}_finish (void)
  static void
  arm_elf_create_output_section_statements (void)
  {
+  bfd *in_implib_bfd;
+
    if (strstr (bfd_get_target (link_info.output_bfd), "arm") == NULL)
      {
        /* The arm backend needs special fields in the output hash structure.
@@ -508,6 +511,20 @@ arm_elf_create_output_section_statements (void)
        return;
      }

+  if (in_implib_filename)
+    {
+      in_implib_bfd = bfd_openr (in_implib_filename,
+				 bfd_get_target (link_info.output_bfd));
+
+      if (in_implib_bfd == NULL)
+	einfo ("%F%s: Can't open: %E\n", in_implib_filename);
+
+      if (!bfd_check_format (in_implib_bfd, bfd_object))
+	einfo ("%F%s: Not a relocatable file: %E\n", in_implib_filename);
+    }
+  else
+    in_implib_bfd = NULL;
+
    bfd_elf32_arm_set_target_relocs (link_info.output_bfd, &link_info,
  				   target1_is_rel,
  				   target2_type, fix_v4bx, use_blx,
@@ -515,7 +532,7 @@ arm_elf_create_output_section_statements (void)
  				   no_enum_size_warning,
  				   no_wchar_size_warning,
  				   pic_veneer, fix_cortex_a8,
-				   fix_arm1176, cmse_implib);
+				   fix_arm1176, cmse_implib, in_implib_bfd);

    stub_file = lang_add_input_file ("linker stubs",
   				   lang_input_file_is_fake_enum,
@@ -585,6 +602,7 @@ PARSE_AND_LIST_PROLOGUE='
  #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
@@ -612,6 +630,7 @@ PARSE_AND_LIST_LONGOPTS='
    { "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='
@@ -634,6 +653,8 @@ PARSE_AND_LIST_OPTIONS='
             "                              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\
@@ -758,6 +779,10 @@ PARSE_AND_LIST_ARGS_CASES='
     case OPTION_CMSE_IMPLIB:
        cmse_implib = 1;
        break;
+
+   case OPTION_IN_IMPLIB:
+      in_implib_filename = optarg;
+      break;
  '

  # We have our own before_allocation etc. functions, but they call
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 
e6813f287fe5ce4c916bf93f48b2e9edbc336570..021385166887a2d2bd49bdba379e833b9c67d906 
100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -6866,6 +6866,18 @@ specified by the @samp{--out-implib} and 
@samp{--in-implib} options are
  secure gateway import libraries, suitable for linking a non-secure
  executable against secure code as per ARMv8-M Security Extensions.

+@kindex --in-implib=@var{file}
+@cindex Input import library
+The @samp{--in-implib=file} specifies an input import library whose symbols
+must keep the same address in the executable being produced.  A warning is
+given if no @samp{--out-implib} is given but new symbols have been introduced
+in the executable that should be listed in its import library.  Otherwise, if
+@samp{--out-implib} is specified, the symbols are added to the output import
+library.  A warning is also given if some symbols present in the input import
+library have disappeared from the executable.  This option is only effective
+for Secure Gateway import libraries, ie. when @samp{--cmse-implib} is
+specified.
+
  @ifclear GENERIC
  @lowersections
  @end ifclear
diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
index 
55240854a24951194c8150581b8a40dd2910b5cb..24d0b4c72a91550bfa936cdbe4ab7fabbeecb6c5 
100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -670,16 +670,59 @@ set armeabitests_nonacl {
       "cmse-veneers-mainline"}
      {"Secure gateway import library generation: errors"
       "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-implib.lib 
--cmse-implib" ""
-     "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1"
+     "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1 --defsym VER=1"
       {cmse-implib.s}
       {{ld cmse-implib-errors.out}}
       "cmse-implib"}
      {"Secure gateway import library generation"
       "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-implib.lib 
--cmse-implib" ""
-     "-march=armv8-m.base -mthumb"
+     "-march=armv8-m.base -mthumb --defsym VER=1"
       {cmse-implib.s}
       {{readelf {-s tmpdir/cmse-implib.lib} cmse-implib.rd}}
       "cmse-implib"}
+    {"Input secure gateway import library"
+     "--section-start .gnu.sgstubs=0x20000 
--out-implib=tmpdir/cmse-new-implib.lib --in-implib=tmpdir/cmse-implib.lib 
--cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=2"
+     {cmse-implib.s}
+     {{ld cmse-new-implib.out}
+      {readelf {-s tmpdir/cmse-new-implib.lib} cmse-new-implib.rd}}
+     "cmse-new-implib"}
+    {"Input secure gateway import library: no output import library"
+     "--section-start .gnu.sgstubs=0x20000 --in-implib=tmpdir/cmse-implib.lib 
--cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=2"
+     {cmse-implib.s}
+     {{ld cmse-new-implib-no-output.out}}
+     "cmse-new-implib-no-output"}
+    {"Input secure gateway import library: not an SG input import library"
+     "--section-start .gnu.sgstubs=0x20000 --in-implib=tmpdir/cmse-implib.lib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=2"
+     {cmse-implib.s}
+     {{ld cmse-new-implib-not-sg-in-implib.out}}
+     "cmse-new-implib-not-sg-in-implib"}
+    {"Input secure gateway import library: earlier stub section base"
+     "--section-start .gnu.sgstubs=0x19000 
--out-implib=tmpdir/cmse-new-earlier-implib.lib 
--in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=2"
+     {cmse-implib.s}
+     {{ld cmse-new-earlier-later-implib.out}}
+     "cmse-new-earlier-implib"}
+    {"Input secure gateway import library: later stub section base"
+     "--section-start .gnu.sgstubs=0x30000 
--out-implib=tmpdir/cmse-new-later-implib.lib --in-implib=tmpdir/cmse-implib.lib 
--cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=2"
+     {cmse-implib.s}
+     {{ld cmse-new-earlier-later-implib.out}}
+     "cmse-new-later-implib"}
+    {"Input secure gateway import library: veneer comeback"
+     "--section-start .gnu.sgstubs=0x20000 
--out-implib=tmpdir/cmse-new-comeback-implib.lib 
--in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=3"
+     {cmse-implib.s}
+     {{readelf {-s tmpdir/cmse-new-comeback-implib.lib} 
cmse-new-comeback-implib.rd}}
+     "cmse-new-comeback-implib"}
+    {"Input secure gateway import library: entry function change"
+     "--section-start .gnu.sgstubs=0x20000 
--out-implib=tmpdir/cmse-new-wrong-implib.lib --in-implib=tmpdir/cmse-implib.lib 
--cmse-implib" ""
+     "-march=armv8-m.base -mthumb --defsym VER=4"
+     {cmse-implib.s}
+     {{ld cmse-new-wrong-implib.out}}
+     "cmse-new-wrong-implib"}

      {"R_ARM_THM_JUMP19 Relocation veneers: Short"
       "--section-start destsect=0x000108002 --section-start .text=0x8000" ""
diff --git a/ld/testsuite/ld-arm/cmse-implib.s b/ld/testsuite/ld-arm/cmse-implib.s
index 
a42da63fffebe5322be83f278931754262b0f7ae..9dd783939891478351a5f7ccb1480980a77dca68 
100644
--- a/ld/testsuite/ld-arm/cmse-implib.s
+++ b/ld/testsuite/ld-arm/cmse-implib.s
@@ -20,12 +20,29 @@ __acle_se_\name:
  .endm

  	@ Valid setups for veneer generation
+.if (VER >= 2)
+	entry exported_entry_veneer1, global
+.endif
+.if (VER != 4)
  	entry exported_entry_veneer2, global
+.else
+	entry exported_entry_veneer2, weak
+.endif
+.if (VER != 2)
  	entry exported_entry_veneer3, global
+.endif
+.if (VER > 1)
+	entry exported_entry_veneer4, global
+.endif

  	@ Valid setup for entry function without veneer generation
  	entry exported_entry_fct1, global, sg
+.if (VER != 4)
  	entry exported_entry_fct2, global, sg
+.else
+	@ Invalid setup for entry function without veneer generation
+	entry exported_entry_fct2, global, nop
+.endif

  	@ Normal symbol not exported to SG import library
  	.align	2
diff --git a/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd 
b/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd
new file mode 100644
index 
0000000000000000000000000000000000000000..c88d9d5104244abc8ceba4d552e1ef0e400c37d1
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd
@@ -0,0 +1,15 @@
+File: tmpdir/cmse-new-.*implib.lib
+
+Symbol table '.symtab' contains 7 entries:
+   Num:    Value  Size Type    Bind   Vis      Ndx Name
+     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
+     1: 00020001     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer3
+     2: 00020011     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer4
+     3: 00020019     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer1
+     4: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
+     5: 00020009     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer2
+     6: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
+
+File: tmpdir/cmse-new-.*implib
+
+#...
diff --git a/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out 
b/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
new file mode 100644
index 
0000000000000000000000000000000000000000..b49ad0ac0770a17c39c2d119d1f0c5854a5bd8cc
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
@@ -0,0 +1,3 @@
+.*: Entry function `exported_entry_veneer3' disappeared from secure code.
+.*: Start address of `.gnu.sgstubs' is different from previous link.
+.*: cannot size stub section: Invalid operation
diff --git a/ld/testsuite/ld-arm/cmse-new-implib-no-output.out 
b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
new file mode 100644
index 
0000000000000000000000000000000000000000..0590b71c844da3687b29b93797abda5172ab8d99
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
@@ -0,0 +1,4 @@
+.*: Entry function `exported_entry_veneer3' disappeared from secure code.
+.*: new entry function\(s\) introduced but no output import library specified:
+.*:   exported_entry_veneer4
+.*:   exported_entry_veneer1
diff --git a/ld/testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out 
b/ld/testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out
new file mode 100644
index 
0000000000000000000000000000000000000000..c93c3fb97895286e05026b6eac696fa9de6c89f9
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out
@@ -0,0 +1,2 @@
+.*: --in-implib only supported for Secure Gateway import libraries.
+.*: cannot size stub section: Invalid operation
diff --git a/ld/testsuite/ld-arm/cmse-new-implib.out 
b/ld/testsuite/ld-arm/cmse-new-implib.out
new file mode 100644
index 
0000000000000000000000000000000000000000..c8af2807e7c1a7eeb1fc156fbf4508cf7a7e932d
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-implib.out
@@ -0,0 +1 @@
+.*: Entry function `exported_entry_veneer3' disappeared from secure code.
diff --git a/ld/testsuite/ld-arm/cmse-new-implib.rd 
b/ld/testsuite/ld-arm/cmse-new-implib.rd
new file mode 100644
index 
0000000000000000000000000000000000000000..9ff0fd87937571f86f99ee940a91a3f67352242a
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-implib.rd
@@ -0,0 +1,14 @@
+File: tmpdir/cmse-new-.*implib.lib
+
+Symbol table '.symtab' contains 6 entries:
+   Num:    Value  Size Type    Bind   Vis      Ndx Name
+     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
+     1: 00020011     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer4
+     2: 00020019     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer1
+     3: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
+     4: 00020009     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer2
+     5: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
+
+File: tmpdir/cmse-new-.*implib
+
+#...
diff --git a/ld/testsuite/ld-arm/cmse-new-wrong-implib.out 
b/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
new file mode 100644
index 
0000000000000000000000000000000000000000..2afe4078e78606d24f05dda6ff1c5e6a54d42512
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
@@ -0,0 +1,3 @@
+.*: .*: visibility of symbol `exported_entry_veneer2' has changed.
+.*: `exported_entry_fct2' refers to a non entry function.
+.*: cannot size stub section: Invalid operation


On 17/08/16 16:12, Thomas Preudhomme wrote:
> Ping?
>
> Best regards,
>
> Thomas
>
> On 05/08/16 09:47, Thomas Preudhomme wrote:
>> Hi Richard,
>>
>> Sorry for the delay, got caught on other things. Please find an updated patch
>> in attachment. All but one of your comments have been addressed, comment below
>> on that one.
>>
>> Updated ChangeLog entries are as follow:
>>
>> *** bfd/ChangeLog ***
>>
>> 2016-07-08  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>
>>         * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new parameter for
>>         the input import library bfd.
>>         * bfd-in2.h: Regenerate.
>>         * elf32-arm.c (struct elf32_arm_link_hash_table): New in_implib_bfd
>>         and new_cmse_stub_offset fields.
>>         (stub_hash_newfunc): Initialize stub_offset and stub_template_size to
>>         -1.
>>         (elf32_arm_add_stub): Likewise for stub_offset.
>>         (arm_new_stubs_start_offset_ptr): New function.
>>         (arm_build_one_stub): Only allocate a stub_offset if it is -1.  Allow
>>         empty SG veneers to have zero relocations.
>>         (arm_size_one_stub): Only initialize stub size and template
>>         information for non empty veneers.  Do not update veneer section size
>>         if veneer already has an offset.
>>         (elf32_arm_create_stub): Return the stub entry pointer or NULL instead
>>         of a boolean indicating success or failure.
>>         (cmse_scan): Change stub_changed parameter into an integer pointer
>>         parameter cmse_stub_created to count the number of stub created and
>>         adapt to change of return value in elf32_arm_create_stub.
>>         (cmse_entry_fct_p): New function.
>>         (arm_list_new_cmse_stub): Likewise.
>>         (set_cmse_veneer_addr_from_implib): Likewise.
>>         (elf32_arm_size_stubs): Define cmse_stub_created, pass its address to
>>         cmse_scan instead of that of cmse_stub_changed to compute the number
>>         of stub created and use it to initialize stub_changed.  Call
>>         set_cmse_veneer_addr_from_implib after all cmse_scan.  Adapt to change
>>         of return value in elf32_arm_create_stub.  Use
>>         arm_stub_section_start_offset () if not NULL to initialize size of
>>         secure gateway veneers section.  Initialize stub_offset of Cortex-A8
>>         erratum fix to -1.  Use ret to hold return value.
>>         (elf32_arm_build_stubs): Use arm_stub_section_start_offset () if not
>>         NULL to initialize size of secure gateway veneers section.  Adapt
>>         comment to stress the importance of zeroing veneer section content.
>>         (bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd parameter to
>>         initialize eponymous field in struct elf32_arm_link_hash_table.
>>
>>
>> *** ld/ChangeLog ***
>>
>> 2016-07-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>
>>         * emultempl/armelf.em (in_implib_filename): Declare and initialize new
>>         variable.
>>         (arm_elf_create_output_section_statements): Open import input library
>>         file for writing and pass resulting in_implib_bfd to
>>         bfd_elf32_arm_set_target_relocs.
>>         (PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option.
>>         (PARSE_AND_LIST_LONGOPTS): Define --in-implib option.
>>         (PARSE_AND_LIST_OPTIONS): Add help message for --in-implib option.
>>         (PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case.
>>         * ld.texinfo (--cmse-implib): Update to mention --in-implib.
>>         (--in-implib): Document new option.
>>         * NEWS: Likewise.
>>         * testsuite/ld-arm/arm-elf.exp
>>         (Secure gateway import library generation): add --defsym VER=1 to gas
>>         CLI.
>>         (Secure gateway import library generation: errors): Likewise.
>>         (Input secure gateway import library): New test.
>>         (Input secure gateway import library: no output import library):
>>         Likewise.
>>         (Input secure gateway import library: not an SG input import library):
>>         Likewise.
>>         (Input secure gateway import library: earlier stub section base):
>>         Likewise.
>>         (Input secure gateway import library: later stub section base):
>>         Likewise.
>>         (Input secure gateway import library: veneer comeback): Likewise.
>>         (Input secure gateway import library: entry function change):
>>         Likewise.
>>         * testsuite/ld-arm/cmse-implib.s: Add input import library testing.
>>         * testsuite/ld-arm/cmse-implib.rd: Update accordingly.
>>         * testsuite/ld-arm/cmse-new-implib.out: New file.
>>         * testsuite/ld-arm/cmse-new-implib.rd: Likewise.
>>         * testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise.
>>         * testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out: Likewise.
>>         * testsuite/ld-arm/cmse-new-earlier-later-implib.out: Likewise.
>>         * testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise.
>>         * testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise.
>>
>> On Thursday 07 July 2016 13:52:00 you wrote:
>>> On 04/04/16 15:22, Thomas Preudhomme wrote:
>>>> On Wednesday 23 December 2015 16:02:48 Thomas Preud'homme wrote:
>>>>> Hi,
>>>>>
>>>>> [Posting patch series as RFC]
>>>>>
>>>>> This patch is part of a patch series to add support for ARMv8-M security
>>>>> extension[1] to GNU ld. This specific patch adds support for allowing
>>>>> Secure Gateway veneers to have stable addresses when relinking a secure
>>>>> executable.
>>>>>
>>>>> ARM v8-M security extensions allow code running in a device to be divided
>>>>> into secure and non-secure code expected to be developed by independent
>>>>> (teams of) people. To allow updating the secure code without the need to
>>>>> relink the non-secure code against it, it is necessary for the toolchain
>>>>> to
>>>>> provide a way to fix the addresses of the secure gateway veneers that
>>>>> serve
>>>>> as entry points for non-secure code to call secure code. This is also a
>>>>> requirement [2] to claim support for ARM v8-M security extensions.
>>>>>
>>>>> This patch adds a --in-implib=<in_implib_filename> option which, when
>>>>> used
>>>>> in conjunction of --cmse-implib will ensure that the veneers whose
>>>>> symbols
>>>>> are defined in the import library $in_implib_filename will remain at the
>>>>> same address in the executable. In the absence of a --out-implib option,
>>>>> the code will warn about new secure gateway veneers being created,
>>>>> otherwise these are allowed.
>>>>>
>>>>>
>>>>> [1] Software requirements for ARMv8-M security extension are described in
>>>>> document ARM-ECM-0359818 [2] [2] Available on http://infocenter.arm.com
>>>>> in
>>>>> Developer guides and articles > Software development > ARM®v8-M Security
>>>>> Extensions: Requirements on Development Tools [3] See requirement 15 of
>>>>> ARM-ECM-0359818 [2]
>>>>
>>>> Please find an updated patch below.
>>>
>>> Comments inline.
>>>
>>>> *** bfd/ChangeLog ***
>>>>
>>>> 2016-02-18  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>>
>>>>         * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new parameter
>>>>         for
>>>>         the input import library bfd.
>>>>         * bfd-in2.h: Regenerate.
>>>>         * elf32-arm.c (struct elf32_arm_link_hash_table): New
>>>>         in_implib_bfd
>>>>         and new_cmse_stub_offset fields.
>>>>         (stub_hash_newfunc): Initialize stub_offset and stub_template_size
>>>>         to
>>>>         -1.
>>>>         (elf32_arm_add_stub): Likewise for stub_offset.
>>>>         (arm_new_stubs_start_offset_ptr): New function.
>>>>         (arm_build_one_stub): Only allocate a stub_offset if it is -1.
>>>>         Allow
>>>>         empty veneers to have zero relocations.
>>>>         (arm_size_one_stub): Only initialize stub size and template
>>>>         information for non empty veneers.  Do not update veneer section
>>>>         size
>>>>         if veneer already has an offset.
>>>>         (elf32_arm_create_stub): Return the stub entry pointer or NULL
>>>>         instead
>>>>         of a boolean indicating success or failure.
>>>>         (cmse_scan): Change stub_changed parameter into an integer pointer
>>>>         parameter cmse_stub_created to count the number of stub created
>>>>         and
>>>>         adapt to change of return value in elf32_arm_create_stub.
>>>>         (cmse_entry_fct_p): New function.
>>>>         (arm_list_new_cmse_stub): Likewise.
>>>>         (set_cmse_veneer_addr_from_implib): Likewise.
>>>>         (elf32_arm_size_stubs): Define cmse_stub_created, pass its address
>>>>         to
>>>>         cmse_scan instead of that of cmse_stub_changed to compute the
>>>>         number
>>>>         of stub created and use it to initialize stub_changed.  Call
>>>>         set_cmse_veneer_addr_from_implib after all cmse_scan.  Adapt to
>>>>         change
>>>>         of return value in elf32_arm_create_stub.  Use
>>>>         arm_stub_section_start_offset () if not NULL to initialize size of
>>>>         secure gateway veneers section.  Initialize stub_offset of
>>>>         Cortex-A8
>>>>         erratum fix to -1.  Use ret to hold return value.
>>>>         (elf32_arm_build_stubs): Use arm_stub_section_start_offset () if
>>>>         not
>>>>         NULL to initialize size of secure gateway veneers section.  Adapt
>>>>         comment to stress the importance of zeroing veneer section
>>>>         content.
>>>>         (bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd parameter
>>>>         to
>>>>         initialize eponymous field in struct elf32_arm_link_hash_table.
>>>>
>>>> *** ld/ChangeLog ***
>>>>
>>>> 2016-02-18  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>>
>>>>         * emultempl/armelf.em (in_implib_filename): Declare and initialize
>>>>         new
>>>>         variable.
>>>>         (arm_elf_create_output_section_statements): Open import input
>>>>         library
>>>>         file for writing and pass resulting in_implib_bfd to
>>>>         bfd_elf32_arm_set_target_relocs.
>>>>         (PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option.
>>>>         (PARSE_AND_LIST_LONGOPTS): Define --in-implib option.
>>>>         (PARSE_AND_LIST_OPTIONS): Add help message for --in-implib option.
>>>>         (PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case.
>>>>         * ld.texinfo (--cmse-implib): Update to mention --in-implib.
>>>>         (--in-implib): Document new option.
>>>>         * testsuite/ld-arm/arm-elf.exp
>>>>         (Secure gateway import library generation): add --defsym VER=1 to
>>>>         gas
>>>>         CLI.
>>>>         (Secure gateway import library generation: errors): Likewise.
>>>>         (Input secure gateway import library): New test.
>>>>         (Input secure gateway import library: no output import library):
>>>>         Likewise.
>>>>         (Input secure gateway import library: earlier stub section base):
>>>>         Likewise.
>>>>         (Input secure gateway import library: later stub section base):
>>>>         Likewise.
>>>>         (Input secure gateway import library: veneer comeback): Likewise.
>>>>         (Input secure gateway import library: entry function change):
>>>>         Likewise.
>>>>         * testsuite/ld-arm/cmse-implib.s: Add input import library
>>>>         testing.
>>>>         * testsuite/ld-arm/cmse-implib.rd: Update accordingly.
>>>>         * testsuite/ld-arm/cmse-new-implib.out: New file.
>>>>         * testsuite/ld-arm/cmse-new-implib.rd: Likewise.
>>>>         * testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise.
>>>>         * testsuite/ld-arm/cmse-new-earlier-later-implib.out: Likewise.
>>>>         * testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise.
>>>>         * testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise.
>>>>
>>>> diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
>>>> index
>>>> 7e3483b9984b04c534e53f2f9026abf26d37592a..423c534a954c541e227e731e9256f08f
>>>> 9fa62014 100644
>>>> --- a/bfd/bfd-in.h
>>>> +++ b/bfd/bfd-in.h
>>>> @@ -895,7 +895,7 @@ extern bfd_boolean
>>>> bfd_elf32_arm_process_before_allocation>
>>>>  void bfd_elf32_arm_set_target_relocs
>>>>
>>>>    (bfd *, struct bfd_link_info *, int, char *, int, int,
>>>>    bfd_arm_vfp11_fix,
>>>>
>>>> -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
>>>> +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
>>>>
>>>>  extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
>>>>
>>>>    (bfd *, struct bfd_link_info *);
>>>>
>>>> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
>>>> index
>>>> 55e1cdde2d0a899238a224c6915d20197b72f085..3a67fa637f5c709cddf3767496e4ac87
>>>> 96287765 100644
>>>> --- a/bfd/bfd-in2.h
>>>> +++ b/bfd/bfd-in2.h
>>>> @@ -902,7 +902,7 @@ extern bfd_boolean
>>>> bfd_elf32_arm_process_before_allocation>
>>>>  void bfd_elf32_arm_set_target_relocs
>>>>
>>>>    (bfd *, struct bfd_link_info *, int, char *, int, int,
>>>>    bfd_arm_vfp11_fix,
>>>>
>>>> -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
>>>> +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
>>>
>>> This is *only* one more parameter to this function, but it now takes 15,
>>> which seems excessive.
>>>
>>> Some redesign may be in order here...
>>
>> Ok. I did a separate patch for this as I felt this was an independent change
>> and would have made the patch even bigger. I'll post it soon.
>>
>> Best regards,
>>
>> Thomas
>>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ARM 11/11, ping] Add support for stable secure gateway veneers addresses
  2016-08-17 15:23         ` [RFC PATCH, binutils, ARM 11/11, ping] " Thomas Preudhomme
@ 2016-08-25 16:14           ` Richard Earnshaw (lists)
  2016-08-25 16:35             ` Thomas Preudhomme
  0 siblings, 1 reply; 15+ messages in thread
From: Richard Earnshaw (lists) @ 2016-08-25 16:14 UTC (permalink / raw)
  To: Thomas Preudhomme, binutils

On 17/08/16 16:23, Thomas Preudhomme wrote:
> [Trying again with inline patch since previous attempt got flagged as spam]
> 

You're missing the ChangeLog entry, but I'll take it that it's still the
same as last time.

OK.

R.

> diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
> index
> d33bb8267b12d9cd2c942d3c502e3e563e63d09f..f9bce9fd3ef778429ea9c1416ca2ffcab3f4e374
> 100644
> --- a/bfd/bfd-in.h
> +++ b/bfd/bfd-in.h
> @@ -894,7 +894,7 @@ extern bfd_boolean
> bfd_elf32_arm_process_before_allocation
> 
>  void bfd_elf32_arm_set_target_relocs
>    (bfd *, struct bfd_link_info *, int, char *, int, int,
> bfd_arm_vfp11_fix,
> -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
> +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
> 
>  extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
>    (bfd *, struct bfd_link_info *);
> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
> index
> cc8428a21d8ce3267420c76a4328fb6d433cd597..8b1d8a01adf529ee42ad6673c82a5028aed5774c
> 100644
> --- a/bfd/bfd-in2.h
> +++ b/bfd/bfd-in2.h
> @@ -901,7 +901,7 @@ extern bfd_boolean
> bfd_elf32_arm_process_before_allocation
> 
>  void bfd_elf32_arm_set_target_relocs
>    (bfd *, struct bfd_link_info *, int, char *, int, int,
> bfd_arm_vfp11_fix,
> -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
> +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
> 
>  extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
>    (bfd *, struct bfd_link_info *);
> diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
> index
> 1eba21b42ddfaf3704860107e4fff36dbbc24d8d..539c2aacbd6b47b25288d3b3e691b90806863856
> 100644
> --- a/bfd/elf32-arm.c
> +++ b/bfd/elf32-arm.c
> @@ -3148,6 +3148,10 @@ struct elf32_arm_link_hash_table
>       as per ARMv8-M Security Extensions.  */
>    int cmse_implib;
> 
> +  /* The import library whose symbols' address must remain stable in
> +     the import library generated.  */
> +  bfd *in_implib_bfd;
> +
>    /* The index of the next unused R_ARM_TLS_DESC slot in .rel.plt.  */
>    bfd_vma next_tls_desc_index;
> 
> @@ -3209,6 +3213,10 @@ struct elf32_arm_link_hash_table
>    /* Input stub section holding secure gateway veneers.  */
>    asection *cmse_stub_sec;
> 
> +  /* Offset in cmse_stub_sec where new SG veneers (not in input import
> library)
> +     start to be allocated.  */
> +  bfd_vma new_cmse_stub_offset;
> +
>    /* Number of elements in stub_group.  */
>    unsigned int top_id;
> 
> @@ -3460,7 +3468,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
>        /* Initialize the local fields.  */
>        eh = (struct elf32_arm_stub_hash_entry *) entry;
>        eh->stub_sec = NULL;
> -      eh->stub_offset = 0;
> +      eh->stub_offset = (bfd_vma) -1;
>        eh->source_value = 0;
>        eh->target_value = 0;
>        eh->target_section = NULL;
> @@ -3468,7 +3476,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
>        eh->stub_type = arm_stub_none;
>        eh->stub_size = 0;
>        eh->stub_template = NULL;
> -      eh->stub_template_size = 0;
> +      eh->stub_template_size = -1;
>        eh->h = NULL;
>        eh->id_sec = NULL;
>        eh->output_name = NULL;
> @@ -4467,7 +4475,7 @@ elf32_arm_add_stub (const char *stub_name,
> asection *section,
>      }
> 
>    stub_entry->stub_sec = stub_sec;
> -  stub_entry->stub_offset = 0;
> +  stub_entry->stub_offset = (bfd_vma) -1;
>    stub_entry->id_sec = link_sec;
> 
>    return stub_entry;
> @@ -4633,11 +4641,31 @@ arm_dedicated_stub_section_padding (enum
> elf32_arm_stub_type stub_type)
>    abort ();  /* Should be unreachable.  */
>  }
> 
> +/* If veneers of type STUB_TYPE should go in a dedicated output section,
> +   returns the address of the hash table field in HTAB holding the
> offset at
> +   which new veneers should be layed out in the stub section.  */
> +
> +static bfd_vma*
> +arm_new_stubs_start_offset_ptr (struct elf32_arm_link_hash_table *htab,
> +                enum elf32_arm_stub_type stub_type)
> +{
> +  switch (stub_type)
> +    {
> +    case arm_stub_cmse_branch_thumb_only:
> +      return &htab->new_cmse_stub_offset;
> +
> +    default:
> +      BFD_ASSERT (!arm_dedicated_stub_output_section_required
> (stub_type));
> +      return NULL;
> +    }
> +}
> +
>  static bfd_boolean
>  arm_build_one_stub (struct bfd_hash_entry *gen_entry,
>              void * in_arg)
>  {
>  #define MAXRELOCS 3
> +  bfd_boolean removed_sg_veneer;
>    struct elf32_arm_stub_hash_entry *stub_entry;
>    struct elf32_arm_link_hash_table *globals;
>    struct bfd_link_info *info;
> @@ -4652,6 +4680,7 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
>    int stub_reloc_idx[MAXRELOCS] = {-1, -1};
>    int stub_reloc_offset[MAXRELOCS] = {0, 0};
>    int nrelocs = 0;
> +  int just_allocated = 0;
> 
>    /* Massage our args to the form they really have.  */
>    stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
> @@ -4668,8 +4697,12 @@ arm_build_one_stub (struct bfd_hash_entry
> *gen_entry,
>      /* We have to do less-strictly-aligned fixes last.  */
>      return TRUE;
> 
> -  /* Make a note of the offset within the stubs for this entry.  */
> -  stub_entry->stub_offset = stub_sec->size;
> +  /* Assign a slot at the end of section if none assigned yet.  */
> +  if (stub_entry->stub_offset == (bfd_vma) -1)
> +    {
> +      stub_entry->stub_offset = stub_sec->size;
> +      just_allocated = 1;
> +    }
>    loc = stub_sec->contents + stub_entry->stub_offset;
> 
>    stub_bfd = stub_sec->owner;
> @@ -4743,7 +4776,8 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
>      }
>      }
> 
> -  stub_sec->size += size;
> +  if (just_allocated)
> +    stub_sec->size += size;
> 
>    /* Stub size has already been computed in arm_size_one_stub. Check
>       consistency.  */
> @@ -4753,9 +4787,11 @@ arm_build_one_stub (struct bfd_hash_entry
> *gen_entry,
>    if (stub_entry->branch_type == ST_BRANCH_TO_THUMB)
>      sym_value |= 1;
> 
> -  /* Assume there is at least one and at most MAXRELOCS entries to
> relocate
> -     in each stub.  */
> -  BFD_ASSERT (nrelocs != 0 && nrelocs <= MAXRELOCS);
> +  /* Assume non empty slots have at least one and at most MAXRELOCS
> entries
> +     to relocate in each stub.  */
> +  removed_sg_veneer =
> +    (size == 0 && stub_entry->stub_type ==
> arm_stub_cmse_branch_thumb_only);
> +  BFD_ASSERT (removed_sg_veneer || (nrelocs != 0 && nrelocs <=
> MAXRELOCS));
> 
>    for (i = 0; i < nrelocs; i++)
>      {
> @@ -4857,9 +4893,17 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry,
>    size = find_stub_size_and_template (stub_entry->stub_type,
> &template_sequence,
>                        &template_size);
> 
> -  stub_entry->stub_size = size;
> -  stub_entry->stub_template = template_sequence;
> -  stub_entry->stub_template_size = template_size;
> +  /* Initialized to -1.  Null size indicates an empty slot full of
> zeros.  */
> +  if (stub_entry->stub_template_size)
> +    {
> +      stub_entry->stub_size = size;
> +      stub_entry->stub_template = template_sequence;
> +      stub_entry->stub_template_size = template_size;
> +    }
> +
> +  /* Already accounted for.  */
> +  if (stub_entry->stub_offset != (bfd_vma) -1)
> +    return TRUE;
> 
>    size = (size + 7) & ~7;
>    stub_entry->stub_sec->size += size;
> @@ -5424,10 +5468,10 @@ cortex_a8_erratum_scan (bfd *input_bfd,
>     and *NEW_STUB is set to FALSE.  Otherwise, *NEW_STUB is set to
>     TRUE and the stub entry is initialized.
> 
> -   Returns whether the stub could be successfully created or updated,
> or FALSE
> -   if an error occured.  */
> +   Returns the stub that was created or updated, or NULL if an error
> +   occurred.  */
> 
> -static bfd_boolean
> +static struct elf32_arm_stub_hash_entry *
>  elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
>                 enum elf32_arm_stub_type stub_type, asection *section,
>                 Elf_Internal_Rela *irela, asection *sym_sec,
> @@ -5458,7 +5502,7 @@ elf32_arm_create_stub (struct
> elf32_arm_link_hash_table *htab,
>        stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash, irela,
>                         stub_type);
>        if (!stub_name)
> -    return FALSE;
> +    return NULL;
>      }
> 
>    stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, stub_name,
> FALSE,
> @@ -5469,7 +5513,7 @@ elf32_arm_create_stub (struct
> elf32_arm_link_hash_table *htab,
>        if (!sym_claimed)
>      free (stub_name);
>        stub_entry->target_value = sym_value;
> -      return TRUE;
> +      return stub_entry;
>      }
> 
>    stub_entry = elf32_arm_add_stub (stub_name, section, htab, stub_type);
> @@ -5477,7 +5521,7 @@ elf32_arm_create_stub (struct
> elf32_arm_link_hash_table *htab,
>      {
>        if (!sym_claimed)
>      free (stub_name);
> -      return FALSE;
> +      return NULL;
>      }
> 
>    stub_entry->target_value = sym_value;
> @@ -5498,7 +5542,7 @@ elf32_arm_create_stub (struct
> elf32_arm_link_hash_table *htab,
>        if (stub_entry->output_name == NULL)
>      {
>        free (stub_name);
> -      return FALSE;
> +      return NULL;
>      }
> 
>        /* For historical reasons, use the existing names for
> ARM-to-Thumb and
> @@ -5518,7 +5562,7 @@ elf32_arm_create_stub (struct
> elf32_arm_link_hash_table *htab,
>      }
> 
>    *new_stub = TRUE;
> -  return TRUE;
> +  return stub_entry;
>  }
> 
>  /* Scan symbols in INPUT_BFD to identify secure entry functions needing a
> @@ -5537,14 +5581,15 @@ elf32_arm_create_stub (struct
> elf32_arm_link_hash_table *htab,
> 
>     OUT_ATTR gives the output attributes, SYM_HASHES the symbol index to
> hash
>     entry mapping while HTAB gives the name to hash entry mapping.
> +   *CMSE_STUB_CREATED is increased by the number of secure gateway veneer
> +   created.
> 
> -   If any secure gateway veneer is created, *STUB_CHANGED is set to
> TRUE.  The
> -   return value gives whether a stub failed to be allocated.  */
> +   The return value gives whether a stub failed to be allocated.  */
> 
>  static bfd_boolean
>  cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
>         obj_attribute *out_attr, struct elf_link_hash_entry **sym_hashes,
> -       bfd_boolean *stub_changed)
> +       int *cmse_stub_created)
>  {
>    const struct elf_backend_data *bed;
>    Elf_Internal_Shdr *symtab_hdr;
> @@ -5555,7 +5600,8 @@ cmse_scan (bfd *input_bfd, struct
> elf32_arm_link_hash_table *htab,
>    char *sym_name, *lsym_name;
>    bfd_vma sym_value;
>    asection *section;
> -  bfd_boolean is_v8m, new_stub, created_stub, cmse_invalid, ret = TRUE;
> +  struct elf32_arm_stub_hash_entry *stub_entry;
> +  bfd_boolean is_v8m, new_stub, cmse_invalid, ret = TRUE;
> 
>    bed = get_elf_backend_data (input_bfd);
>    symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
> @@ -5700,17 +5746,17 @@ cmse_scan (bfd *input_bfd, struct
> elf32_arm_link_hash_table *htab,
>        if (!ret)
>      continue;
>        branch_type = ARM_GET_SYM_BRANCH_TYPE (hash->root.target_internal);
> -      created_stub
> +      stub_entry
>      = elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
>                   NULL, NULL, section, hash, sym_name,
>                   sym_value, branch_type, &new_stub);
> 
> -      if (!created_stub)
> +      if (stub_entry == NULL)
>       ret = FALSE;
>        else
>      {
>        BFD_ASSERT (new_stub);
> -      *stub_changed = TRUE;
> +      (*cmse_stub_created)++;
>      }
>      }
> 
> @@ -5719,6 +5765,279 @@ cmse_scan (bfd *input_bfd, struct
> elf32_arm_link_hash_table *htab,
>    return ret;
>  }
> 
> +/* Return TRUE iff a symbol identified by its linker HASH entry is a
> secure
> +   code entry function, ie can be called from non secure code without
> using a
> +   veneer.  */
> +
> +static bfd_boolean
> +cmse_entry_fct_p (struct elf32_arm_link_hash_entry *hash)
> +{
> +  uint32_t first_insn;
> +  asection *section;
> +  file_ptr offset;
> +  bfd *abfd;
> +
> +  /* Defined symbol of function type.  */
> +  if (hash->root.root.type != bfd_link_hash_defined
> +      && hash->root.root.type != bfd_link_hash_defweak)
> +    return FALSE;
> +  if (hash->root.type != STT_FUNC)
> +    return FALSE;
> +
> +  /* Read first instruction.  */
> +  section = hash->root.root.u.def.section;
> +  abfd = section->owner;
> +  offset = hash->root.root.u.def.value - section->vma;
> +  if (!bfd_get_section_contents (abfd, section, &first_insn, offset,
> +                 sizeof (first_insn)))
> +    return FALSE;
> +
> +  /* Start by SG instruction.  */
> +  return first_insn == 0xe97fe97f;
> +}
> +
> +/* Output the name (in symbol table) of the veneer GEN_ENTRY if it is a
> new
> +   secure gateway veneers (ie. the veneers was not in the input import
> library)
> +   and there is no output import library (GEN_INFO->out_implib_bfd is
> NULL.  */
> +
> +static bfd_boolean
> +arm_list_new_cmse_stub (struct bfd_hash_entry *gen_entry, void *gen_info)
> +{
> +  struct elf32_arm_stub_hash_entry *stub_entry;
> +  struct bfd_link_info *info;
> +
> +  /* Massage our args to the form they really have.  */
> +  stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
> +  info = (struct bfd_link_info *) gen_info;
> +
> +  if (info->out_implib_bfd)
> +    return TRUE;
> +
> +  if (stub_entry->stub_type != arm_stub_cmse_branch_thumb_only)
> +    return TRUE;
> +
> +  if (stub_entry->stub_offset == (bfd_vma) -1)
> +    (*_bfd_error_handler) ("  %s", stub_entry->output_name);
> +
> +  return TRUE;
> +}
> +
> +/* Set offset of each secure gateway veneers so that its address remain
> +   identical to the one in the input import library referred by
> +   HTAB->in_implib_bfd.  A warning is issued for veneers that disappeared
> +   (present in input import library but absent from the executable being
> +   linked) or if new veneers appeared and there is no output import
> library
> +   (INFO->out_implib_bfd is NULL and *CMSE_STUB_CREATED is bigger than the
> +   number of secure gateway veneers found in the input import library.
> +
> +   The function returns whether an error occurred.  If no error occurred,
> +   *CMSE_STUB_CREATED gives the number of SG veneers created by both
> cmse_scan
> +   and this function and HTAB->new_cmse_stub_offset is set to the biggest
> +   veneer observed set for new veneers to be layed out after.  */
> +
> +static bfd_boolean
> +set_cmse_veneer_addr_from_implib (struct bfd_link_info *info,
> +                  struct elf32_arm_link_hash_table *htab,
> +                  int *cmse_stub_created)
> +{
> +  long symsize;
> +  char *sym_name;
> +  flagword flags;
> +  long i, symcount;
> +  bfd *in_implib_bfd;
> +  asection *stub_out_sec;
> +  bfd_boolean ret = TRUE;
> +  Elf_Internal_Sym *intsym;
> +  const char *out_sec_name;
> +  bfd_size_type cmse_stub_size;
> +  asymbol **sympp = NULL, *sym;
> +  struct elf32_arm_link_hash_entry *hash;
> +  const insn_sequence *cmse_stub_template;
> +  struct elf32_arm_stub_hash_entry *stub_entry;
> +  int cmse_stub_template_size, new_cmse_stubs_created =
> *cmse_stub_created;
> +  bfd_vma veneer_value, stub_offset, next_cmse_stub_offset;
> +  bfd_vma cmse_stub_array_start = (bfd_vma) -1, cmse_stub_sec_vma = 0;
> +
> +  /* No input secure gateway import library.  */
> +  if (!htab->in_implib_bfd)
> +    return TRUE;
> +
> +  in_implib_bfd = htab->in_implib_bfd;
> +  if (!htab->cmse_implib)
> +    {
> +      (*_bfd_error_handler) (_("%B: --in-implib only supported for
> Secure "
> +                   "Gateway import libraries."), in_implib_bfd);
> +      return FALSE;
> +    }
> +
> +  /* Get symbol table size.  */
> +  symsize = bfd_get_symtab_upper_bound (in_implib_bfd);
> +  if (symsize < 0)
> +    return FALSE;
> +
> +  /* Read in the input secure gateway import library's symbol table.  */
> +  sympp = (asymbol **) xmalloc (symsize);
> +  symcount = bfd_canonicalize_symtab (in_implib_bfd, sympp);
> +  if (symcount < 0)
> +    {
> +      ret = FALSE;
> +      goto free_sym_buf;
> +    }
> +
> +  htab->new_cmse_stub_offset = 0;
> +  cmse_stub_size =
> +    find_stub_size_and_template (arm_stub_cmse_branch_thumb_only,
> +                 &cmse_stub_template,
> +                 &cmse_stub_template_size);
> +  out_sec_name =
> +    arm_dedicated_stub_output_section_name
> (arm_stub_cmse_branch_thumb_only);
> +  stub_out_sec =
> +    bfd_get_section_by_name (htab->obfd, out_sec_name);
> +  if (stub_out_sec != NULL)
> +    cmse_stub_sec_vma = stub_out_sec->vma;
> +
> +  /* Set addresses of veneers mentionned in input secure gateway import
> +     library's symbol table.  */
> +  for (i = 0; i < symcount; i++)
> +    {
> +      sym = sympp[i];
> +      flags = sym->flags;
> +      sym_name = (char *) bfd_asymbol_name (sym);
> +      intsym = &((elf_symbol_type *) sym)->internal_elf_sym;
> +
> +      if (sym->section != bfd_abs_section_ptr
> +      || !(flags & (BSF_GLOBAL | BSF_WEAK))
> +      || (flags & BSF_FUNCTION) != BSF_FUNCTION
> +      || (ARM_GET_SYM_BRANCH_TYPE (intsym->st_target_internal)
> +          != ST_BRANCH_TO_THUMB))
> +    {
> +      (*_bfd_error_handler) (_("%B: invalid import library entry: `%s'."),
> +                 in_implib_bfd, sym_name);
> +      (*_bfd_error_handler) (_("Symbol should be absolute, global and "
> +                   "refer to Thumb functions."));
> +      ret = FALSE;
> +      continue;
> +    }
> +
> +      veneer_value = bfd_asymbol_value (sym);
> +      stub_offset = veneer_value - cmse_stub_sec_vma;
> +      stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, sym_name,
> +                     FALSE, FALSE);
> +      hash = (struct elf32_arm_link_hash_entry *)
> +    elf_link_hash_lookup (&(htab)->root, sym_name, FALSE, FALSE, TRUE);
> +
> +      /* Stub entry should have been created by cmse_scan or the symbol
> be of
> +     a secure function callable from non secure code.  */
> +      if (!stub_entry && !hash)
> +    {
> +      bfd_boolean new_stub;
> +
> +      (*_bfd_error_handler)
> +        (_("Entry function `%s' disappeared from secure code."),
> sym_name);
> +      hash = (struct elf32_arm_link_hash_entry *)
> +        elf_link_hash_lookup (&(htab)->root, sym_name, TRUE, TRUE, TRUE);
> +      stub_entry
> +        = elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
> +                     NULL, NULL, bfd_abs_section_ptr, hash,
> +                     sym_name, veneer_value,
> +                     ST_BRANCH_TO_THUMB, &new_stub);
> +      if (stub_entry == NULL)
> +        ret = FALSE;
> +      else
> +      {
> +        BFD_ASSERT (new_stub);
> +        new_cmse_stubs_created++;
> +        (*cmse_stub_created)++;
> +      }
> +      stub_entry->stub_template_size = stub_entry->stub_size = 0;
> +      stub_entry->stub_offset = stub_offset;
> +    }
> +      /* Symbol found is not callable from non secure code.  */
> +      else if (!stub_entry)
> +    {
> +      if (!cmse_entry_fct_p (hash))
> +        {
> +          (*_bfd_error_handler) (_("`%s' refers to a non entry
> function."),
> +                     sym_name);
> +          ret = FALSE;
> +        }
> +      continue;
> +    }
> +      else
> +    {
> +      /* Only stubs for SG veneers should have been created.  */
> +      BFD_ASSERT (stub_entry->stub_type ==
> arm_stub_cmse_branch_thumb_only);
> +
> +      /* Check visibility hasn't changed.  */
> +      if (!!(flags & BSF_GLOBAL)
> +          != (hash->root.root.type == bfd_link_hash_defined))
> +        (*_bfd_error_handler)
> +          (_("%B: visibility of symbol `%s' has changed."), in_implib_bfd,
> +           sym_name);
> +
> +      stub_entry->stub_offset = stub_offset;
> +    }
> +
> +      /* Size should match that of a SG veneer.  */
> +      if (intsym->st_size != cmse_stub_size)
> +    {
> +      (*_bfd_error_handler) (_("%B: incorrect size for symbol `%s'."),
> +                 in_implib_bfd, sym_name);
> +      ret = FALSE;
> +    }
> +
> +      /* Previous veneer address is before current SG veneer section.  */
> +      if (veneer_value < cmse_stub_sec_vma)
> +    {
> +      /* Avoid offset underflow.  */
> +      if (stub_entry)
> +        stub_entry->stub_offset = 0;
> +      stub_offset = 0;
> +      ret = FALSE;
> +    }
> +
> +      /* Complain if stub offset not a multiple of stub size.  */
> +      if (stub_offset % cmse_stub_size)
> +    {
> +      (*_bfd_error_handler)
> +        (_("Offset of veneer for entry function `%s' not a multiple of "
> +           "its size."), sym_name);
> +      ret = FALSE;
> +    }
> +
> +      if (!ret)
> +    continue;
> +
> +      new_cmse_stubs_created--;
> +      if (veneer_value < cmse_stub_array_start)
> +    cmse_stub_array_start = veneer_value;
> +      next_cmse_stub_offset = stub_offset + ((cmse_stub_size + 7) & ~7);
> +      if (next_cmse_stub_offset > htab->new_cmse_stub_offset)
> +    htab->new_cmse_stub_offset = next_cmse_stub_offset;
> +    }
> +
> +  if (!info->out_implib_bfd && new_cmse_stubs_created != 0)
> +    {
> +      BFD_ASSERT (new_cmse_stubs_created > 0);
> +      (*_bfd_error_handler)
> +    (_("new entry function(s) introduced but no output import library "
> +       "specified:"));
> +      bfd_hash_traverse (&htab->stub_hash_table,
> arm_list_new_cmse_stub, info);
> +    }
> +
> +  if (cmse_stub_array_start != cmse_stub_sec_vma)
> +    {
> +      (*_bfd_error_handler)
> +    (_("Start address of `%s' is different from previous link."),
> +     out_sec_name);
> +      ret = FALSE;
> +    }
> +
> +free_sym_buf:
> +  free (sympp);
> +  return ret;
> +}
> +
>  /* Determine and set the size of the stub section for a final link.
> 
>     The basic idea here is to examine all the relocations looking for
> @@ -5735,7 +6054,9 @@ elf32_arm_size_stubs (bfd *output_bfd,
>                                unsigned int),
>                void (*layout_sections_again) (void))
>  {
> +  bfd_boolean ret = TRUE;
>    obj_attribute *out_attr;
> +  int cmse_stub_created = 0;
>    bfd_size_type stub_group_size;
>    bfd_boolean m_profile, stubs_always_after_branch, first_veneer_scan =
> TRUE;
>    struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
> @@ -5768,6 +6089,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
> 
>    out_attr = elf_known_obj_attributes_proc (output_bfd);
>    m_profile = out_attr[Tag_CPU_arch_profile].i == 'M';
> +
>    /* The Cortex-A8 erratum fix depends on stubs not being in the same
> 4K page
>       as the first half of a 32-bit branch straddling two 4K pages. 
> This is a
>       crude way of enforcing that.  */
> @@ -5841,8 +6163,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
> 
>            sym_hashes = elf_sym_hashes (input_bfd);
>            if (!cmse_scan (input_bfd, htab, out_attr, sym_hashes,
> -                  &stub_changed))
> +                  &cmse_stub_created))
>          goto error_ret_free_local;
> +
> +          if (cmse_stub_created != 0)
> +        stub_changed = TRUE;
>          }
> 
>        /* Walk over each section attached to the input bfd.  */
> @@ -6074,6 +6399,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
>            do
>              {
>                bfd_boolean new_stub;
> +              struct elf32_arm_stub_hash_entry *stub_entry;
> 
>                /* Determine what (if any) linker stub is needed.  */
>                stub_type = arm_type_of_stub (info, section, irela,
> @@ -6085,12 +6411,13 @@ elf32_arm_size_stubs (bfd *output_bfd,
> 
>                /* We've either created a stub for this reloc already,
>               or we are about to.  */
> -              created_stub =
> +              stub_entry =
>              elf32_arm_create_stub (htab, stub_type, section, irela,
>                             sym_sec, hash,
>                             (char *) sym_name, sym_value,
>                             branch_type, &new_stub);
> 
> +              created_stub = stub_entry != NULL;
>                if (!created_stub)
>              goto error_ret_free_internal;
>                else if (!new_stub)
> @@ -6172,6 +6499,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
>          }
>      }
> 
> +      if (first_veneer_scan
> +      && !set_cmse_veneer_addr_from_implib (info, htab,
> +                        &cmse_stub_created))
> +    ret = FALSE;
> +
>        if (prev_num_a8_fixes != num_a8_fixes)
>      stub_changed = TRUE;
> 
> @@ -6191,6 +6523,24 @@ elf32_arm_size_stubs (bfd *output_bfd,
>        stub_sec->size = 0;
>      }
> 
> +      /* Add new SG veneers after those already in the input import
> +     library.  */
> +      for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
> +       stub_type++)
> +    {
> +      bfd_vma *start_offset_p;
> +      asection **stub_sec_p;
> +
> +      start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type);
> +      stub_sec_p = arm_dedicated_stub_input_section_ptr (htab, stub_type);
> +      if (start_offset_p == NULL)
> +        continue;
> +
> +      BFD_ASSERT (stub_sec_p != NULL);
> +      if (*stub_sec_p != NULL)
> +        (*stub_sec_p)->size = *start_offset_p;
> +    }
> +
>        /* Compute stub section size, considering padding.  */
>        bfd_hash_traverse (&htab->stub_hash_table, arm_size_one_stub, htab);
>        for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
> @@ -6259,7 +6609,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
>          }
> 
>        stub_entry->stub_sec = stub_sec;
> -      stub_entry->stub_offset = 0;
> +      stub_entry->stub_offset = (bfd_vma) -1;
>        stub_entry->id_sec = link_sec;
>        stub_entry->stub_type = a8_fixes[i].stub_type;
>        stub_entry->source_value = a8_fixes[i].offset;
> @@ -6287,7 +6637,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
>        htab->a8_erratum_fixes = NULL;
>        htab->num_a8_erratum_fixes = 0;
>      }
> -  return TRUE;
> +  return ret;
>  }
> 
>  /* Build all the stubs associated with the current output file.  The
> @@ -6301,6 +6651,7 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
>  {
>    asection *stub_sec;
>    struct bfd_hash_table *table;
> +  enum elf32_arm_stub_type stub_type;
>    struct elf32_arm_link_hash_table *htab;
> 
>    htab = elf32_arm_hash_table (info);
> @@ -6318,14 +6669,33 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
>      continue;
> 
>        /* Allocate memory to hold the linker stubs.  Zeroing the stub
> sections
> -     must at least be done for stub section requiring padding.  */
> +     must at least be done for stub section requiring padding and for SG
> +     veneers to ensure that a non secure code branching to a removed SG
> +     veneer causes an error.  */
>        size = stub_sec->size;
>        stub_sec->contents = (unsigned char *) bfd_zalloc
> (htab->stub_bfd, size);
>        if (stub_sec->contents == NULL && size != 0)
>      return FALSE;
> +
>        stub_sec->size = 0;
>      }
> 
> +  /* Add new SG veneers after those already in the input import
> library.  */
> +  for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
> stub_type++)
> +    {
> +      bfd_vma *start_offset_p;
> +      asection **stub_sec_p;
> +
> +      start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type);
> +      stub_sec_p = arm_dedicated_stub_input_section_ptr (htab, stub_type);
> +      if (start_offset_p == NULL)
> +    continue;
> +
> +      BFD_ASSERT (stub_sec_p != NULL);
> +      if (*stub_sec_p != NULL)
> +    (*stub_sec_p)->size = *start_offset_p;
> +    }
> +
>    /* Build the stubs as directed by the stub hash table.  */
>    table = &htab->stub_hash_table;
>    bfd_hash_traverse (table, arm_build_one_stub, info);
> @@ -8311,7 +8681,8 @@ bfd_elf32_arm_set_target_relocs (struct bfd
> *output_bfd,
>                   bfd_arm_stm32l4xx_fix stm32l4xx_fix,
>                   int no_enum_warn, int no_wchar_warn,
>                   int pic_veneer, int fix_cortex_a8,
> -                 int fix_arm1176, int cmse_implib)
> +                 int fix_arm1176, int cmse_implib,
> +                 bfd *in_implib_bfd)
>  {
>    struct elf32_arm_link_hash_table *globals;
> 
> @@ -8339,6 +8710,7 @@ bfd_elf32_arm_set_target_relocs (struct bfd
> *output_bfd,
>    globals->fix_cortex_a8 = fix_cortex_a8;
>    globals->fix_arm1176 = fix_arm1176;
>    globals->cmse_implib = cmse_implib;
> +  globals->in_implib_bfd = in_implib_bfd;
> 
>    BFD_ASSERT (is_arm_elf (output_bfd));
>    elf_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
> diff --git a/ld/NEWS b/ld/NEWS
> index
> 2a0b4ac704a088a24cfc1633785a50477513c4db..0f316bfcc248341200af14e5cb1a5c50787e9b1a
> 100644
> --- a/ld/NEWS
> +++ b/ld/NEWS
> @@ -2,6 +2,11 @@
> 
>  Changes in 2.28:
> 
> +* Add --in-implib=<infile> to the ARM linker to enable specifying a set of
> +  Secure Gateway veneers that must exist in the output import library
> specified
> +  by --out-implib=<outfile> and the address they must have.  As such,
> +  --in-implib is only supported in combination with --cmse-implib.
> +
>  * Extended the --out-implib=<file> option, previously restricted to x86 PE
>    targets, to any ELF based target.  This allows the generation of an
> import
>    library for an ELF executable, which can then be used by another
> application
> diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
> index
> c21f6a82335a58a0ab37f3719c73c95e73e6211c..2346bb42444895605d10b7b7e21cca2dcaa38700
> 100644
> --- a/ld/emultempl/armelf.em
> +++ b/ld/emultempl/armelf.em
> @@ -43,6 +43,7 @@ static int pic_veneer = 0;
>  static int merge_exidx_entries = -1;
>  static int fix_arm1176 = 1;
>  static int cmse_implib = 0;
> +static char *in_implib_filename = NULL;
> 
>  static void
>  gld${EMULATION_NAME}_before_parse (void)
> @@ -498,6 +499,8 @@ gld${EMULATION_NAME}_finish (void)
>  static void
>  arm_elf_create_output_section_statements (void)
>  {
> +  bfd *in_implib_bfd;
> +
>    if (strstr (bfd_get_target (link_info.output_bfd), "arm") == NULL)
>      {
>        /* The arm backend needs special fields in the output hash
> structure.
> @@ -508,6 +511,20 @@ arm_elf_create_output_section_statements (void)
>        return;
>      }
> 
> +  if (in_implib_filename)
> +    {
> +      in_implib_bfd = bfd_openr (in_implib_filename,
> +                 bfd_get_target (link_info.output_bfd));
> +
> +      if (in_implib_bfd == NULL)
> +    einfo ("%F%s: Can't open: %E\n", in_implib_filename);
> +
> +      if (!bfd_check_format (in_implib_bfd, bfd_object))
> +    einfo ("%F%s: Not a relocatable file: %E\n", in_implib_filename);
> +    }
> +  else
> +    in_implib_bfd = NULL;
> +
>    bfd_elf32_arm_set_target_relocs (link_info.output_bfd, &link_info,
>                     target1_is_rel,
>                     target2_type, fix_v4bx, use_blx,
> @@ -515,7 +532,7 @@ arm_elf_create_output_section_statements (void)
>                     no_enum_size_warning,
>                     no_wchar_size_warning,
>                     pic_veneer, fix_cortex_a8,
> -                   fix_arm1176, cmse_implib);
> +                   fix_arm1176, cmse_implib, in_implib_bfd);
> 
>    stub_file = lang_add_input_file ("linker stubs",
>                      lang_input_file_is_fake_enum,
> @@ -585,6 +602,7 @@ PARSE_AND_LIST_PROLOGUE='
>  #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
> @@ -612,6 +630,7 @@ PARSE_AND_LIST_LONGOPTS='
>    { "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='
> @@ -634,6 +653,8 @@ PARSE_AND_LIST_OPTIONS='
>             "                              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\
> @@ -758,6 +779,10 @@ PARSE_AND_LIST_ARGS_CASES='
>     case OPTION_CMSE_IMPLIB:
>        cmse_implib = 1;
>        break;
> +
> +   case OPTION_IN_IMPLIB:
> +      in_implib_filename = optarg;
> +      break;
>  '
> 
>  # We have our own before_allocation etc. functions, but they call
> diff --git a/ld/ld.texinfo b/ld/ld.texinfo
> index
> e6813f287fe5ce4c916bf93f48b2e9edbc336570..021385166887a2d2bd49bdba379e833b9c67d906
> 100644
> --- a/ld/ld.texinfo
> +++ b/ld/ld.texinfo
> @@ -6866,6 +6866,18 @@ specified by the @samp{--out-implib} and
> @samp{--in-implib} options are
>  secure gateway import libraries, suitable for linking a non-secure
>  executable against secure code as per ARMv8-M Security Extensions.
> 
> +@kindex --in-implib=@var{file}
> +@cindex Input import library
> +The @samp{--in-implib=file} specifies an input import library whose
> symbols
> +must keep the same address in the executable being produced.  A warning is
> +given if no @samp{--out-implib} is given but new symbols have been
> introduced
> +in the executable that should be listed in its import library. 
> Otherwise, if
> +@samp{--out-implib} is specified, the symbols are added to the output
> import
> +library.  A warning is also given if some symbols present in the input
> import
> +library have disappeared from the executable.  This option is only
> effective
> +for Secure Gateway import libraries, ie. when @samp{--cmse-implib} is
> +specified.
> +
>  @ifclear GENERIC
>  @lowersections
>  @end ifclear
> diff --git a/ld/testsuite/ld-arm/arm-elf.exp
> b/ld/testsuite/ld-arm/arm-elf.exp
> index
> 55240854a24951194c8150581b8a40dd2910b5cb..24d0b4c72a91550bfa936cdbe4ab7fabbeecb6c5
> 100644
> --- a/ld/testsuite/ld-arm/arm-elf.exp
> +++ b/ld/testsuite/ld-arm/arm-elf.exp
> @@ -670,16 +670,59 @@ set armeabitests_nonacl {
>       "cmse-veneers-mainline"}
>      {"Secure gateway import library generation: errors"
>       "--section-start .gnu.sgstubs=0x20000
> --out-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> -     "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1"
> +     "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1 --defsym VER=1"
>       {cmse-implib.s}
>       {{ld cmse-implib-errors.out}}
>       "cmse-implib"}
>      {"Secure gateway import library generation"
>       "--section-start .gnu.sgstubs=0x20000
> --out-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> -     "-march=armv8-m.base -mthumb"
> +     "-march=armv8-m.base -mthumb --defsym VER=1"
>       {cmse-implib.s}
>       {{readelf {-s tmpdir/cmse-implib.lib} cmse-implib.rd}}
>       "cmse-implib"}
> +    {"Input secure gateway import library"
> +     "--section-start .gnu.sgstubs=0x20000
> --out-implib=tmpdir/cmse-new-implib.lib
> --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> +     "-march=armv8-m.base -mthumb --defsym VER=2"
> +     {cmse-implib.s}
> +     {{ld cmse-new-implib.out}
> +      {readelf {-s tmpdir/cmse-new-implib.lib} cmse-new-implib.rd}}
> +     "cmse-new-implib"}
> +    {"Input secure gateway import library: no output import library"
> +     "--section-start .gnu.sgstubs=0x20000
> --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> +     "-march=armv8-m.base -mthumb --defsym VER=2"
> +     {cmse-implib.s}
> +     {{ld cmse-new-implib-no-output.out}}
> +     "cmse-new-implib-no-output"}
> +    {"Input secure gateway import library: not an SG input import library"
> +     "--section-start .gnu.sgstubs=0x20000
> --in-implib=tmpdir/cmse-implib.lib" ""
> +     "-march=armv8-m.base -mthumb --defsym VER=2"
> +     {cmse-implib.s}
> +     {{ld cmse-new-implib-not-sg-in-implib.out}}
> +     "cmse-new-implib-not-sg-in-implib"}
> +    {"Input secure gateway import library: earlier stub section base"
> +     "--section-start .gnu.sgstubs=0x19000
> --out-implib=tmpdir/cmse-new-earlier-implib.lib
> --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> +     "-march=armv8-m.base -mthumb --defsym VER=2"
> +     {cmse-implib.s}
> +     {{ld cmse-new-earlier-later-implib.out}}
> +     "cmse-new-earlier-implib"}
> +    {"Input secure gateway import library: later stub section base"
> +     "--section-start .gnu.sgstubs=0x30000
> --out-implib=tmpdir/cmse-new-later-implib.lib
> --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> +     "-march=armv8-m.base -mthumb --defsym VER=2"
> +     {cmse-implib.s}
> +     {{ld cmse-new-earlier-later-implib.out}}
> +     "cmse-new-later-implib"}
> +    {"Input secure gateway import library: veneer comeback"
> +     "--section-start .gnu.sgstubs=0x20000
> --out-implib=tmpdir/cmse-new-comeback-implib.lib
> --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> +     "-march=armv8-m.base -mthumb --defsym VER=3"
> +     {cmse-implib.s}
> +     {{readelf {-s tmpdir/cmse-new-comeback-implib.lib}
> cmse-new-comeback-implib.rd}}
> +     "cmse-new-comeback-implib"}
> +    {"Input secure gateway import library: entry function change"
> +     "--section-start .gnu.sgstubs=0x20000
> --out-implib=tmpdir/cmse-new-wrong-implib.lib
> --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
> +     "-march=armv8-m.base -mthumb --defsym VER=4"
> +     {cmse-implib.s}
> +     {{ld cmse-new-wrong-implib.out}}
> +     "cmse-new-wrong-implib"}
> 
>      {"R_ARM_THM_JUMP19 Relocation veneers: Short"
>       "--section-start destsect=0x000108002 --section-start
> .text=0x8000" ""
> diff --git a/ld/testsuite/ld-arm/cmse-implib.s
> b/ld/testsuite/ld-arm/cmse-implib.s
> index
> a42da63fffebe5322be83f278931754262b0f7ae..9dd783939891478351a5f7ccb1480980a77dca68
> 100644
> --- a/ld/testsuite/ld-arm/cmse-implib.s
> +++ b/ld/testsuite/ld-arm/cmse-implib.s
> @@ -20,12 +20,29 @@ __acle_se_\name:
>  .endm
> 
>      @ Valid setups for veneer generation
> +.if (VER >= 2)
> +    entry exported_entry_veneer1, global
> +.endif
> +.if (VER != 4)
>      entry exported_entry_veneer2, global
> +.else
> +    entry exported_entry_veneer2, weak
> +.endif
> +.if (VER != 2)
>      entry exported_entry_veneer3, global
> +.endif
> +.if (VER > 1)
> +    entry exported_entry_veneer4, global
> +.endif
> 
>      @ Valid setup for entry function without veneer generation
>      entry exported_entry_fct1, global, sg
> +.if (VER != 4)
>      entry exported_entry_fct2, global, sg
> +.else
> +    @ Invalid setup for entry function without veneer generation
> +    entry exported_entry_fct2, global, nop
> +.endif
> 
>      @ Normal symbol not exported to SG import library
>      .align    2
> diff --git a/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd
> b/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..c88d9d5104244abc8ceba4d552e1ef0e400c37d1
> 
> --- /dev/null
> +++ b/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd
> @@ -0,0 +1,15 @@
> +File: tmpdir/cmse-new-.*implib.lib
> +
> +Symbol table '.symtab' contains 7 entries:
> +   Num:    Value  Size Type    Bind   Vis      Ndx Name
> +     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
> +     1: 00020001     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer3
> +     2: 00020011     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer4
> +     3: 00020019     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer1
> +     4: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
> +     5: 00020009     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer2
> +     6: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
> +
> +File: tmpdir/cmse-new-.*implib
> +
> +#...
> diff --git a/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
> b/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..b49ad0ac0770a17c39c2d119d1f0c5854a5bd8cc
> 
> --- /dev/null
> +++ b/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
> @@ -0,0 +1,3 @@
> +.*: Entry function `exported_entry_veneer3' disappeared from secure code.
> +.*: Start address of `.gnu.sgstubs' is different from previous link.
> +.*: cannot size stub section: Invalid operation
> diff --git a/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
> b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..0590b71c844da3687b29b93797abda5172ab8d99
> 
> --- /dev/null
> +++ b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
> @@ -0,0 +1,4 @@
> +.*: Entry function `exported_entry_veneer3' disappeared from secure code.
> +.*: new entry function\(s\) introduced but no output import library
> specified:
> +.*:   exported_entry_veneer4
> +.*:   exported_entry_veneer1
> diff --git a/ld/testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out
> b/ld/testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..c93c3fb97895286e05026b6eac696fa9de6c89f9
> 
> --- /dev/null
> +++ b/ld/testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out
> @@ -0,0 +1,2 @@
> +.*: --in-implib only supported for Secure Gateway import libraries.
> +.*: cannot size stub section: Invalid operation
> diff --git a/ld/testsuite/ld-arm/cmse-new-implib.out
> b/ld/testsuite/ld-arm/cmse-new-implib.out
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..c8af2807e7c1a7eeb1fc156fbf4508cf7a7e932d
> 
> --- /dev/null
> +++ b/ld/testsuite/ld-arm/cmse-new-implib.out
> @@ -0,0 +1 @@
> +.*: Entry function `exported_entry_veneer3' disappeared from secure code.
> diff --git a/ld/testsuite/ld-arm/cmse-new-implib.rd
> b/ld/testsuite/ld-arm/cmse-new-implib.rd
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..9ff0fd87937571f86f99ee940a91a3f67352242a
> 
> --- /dev/null
> +++ b/ld/testsuite/ld-arm/cmse-new-implib.rd
> @@ -0,0 +1,14 @@
> +File: tmpdir/cmse-new-.*implib.lib
> +
> +Symbol table '.symtab' contains 6 entries:
> +   Num:    Value  Size Type    Bind   Vis      Ndx Name
> +     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
> +     1: 00020011     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer4
> +     2: 00020019     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer1
> +     3: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
> +     4: 00020009     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer2
> +     5: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
> +
> +File: tmpdir/cmse-new-.*implib
> +
> +#...
> diff --git a/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
> b/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..2afe4078e78606d24f05dda6ff1c5e6a54d42512
> 
> --- /dev/null
> +++ b/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
> @@ -0,0 +1,3 @@
> +.*: .*: visibility of symbol `exported_entry_veneer2' has changed.
> +.*: `exported_entry_fct2' refers to a non entry function.
> +.*: cannot size stub section: Invalid operation
> 
> 
> On 17/08/16 16:12, Thomas Preudhomme wrote:
>> Ping?
>>
>> Best regards,
>>
>> Thomas
>>
>> On 05/08/16 09:47, Thomas Preudhomme wrote:
>>> Hi Richard,
>>>
>>> Sorry for the delay, got caught on other things. Please find an
>>> updated patch
>>> in attachment. All but one of your comments have been addressed,
>>> comment below
>>> on that one.
>>>
>>> Updated ChangeLog entries are as follow:
>>>
>>> *** bfd/ChangeLog ***
>>>
>>> 2016-07-08  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>
>>>         * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new
>>> parameter for
>>>         the input import library bfd.
>>>         * bfd-in2.h: Regenerate.
>>>         * elf32-arm.c (struct elf32_arm_link_hash_table): New
>>> in_implib_bfd
>>>         and new_cmse_stub_offset fields.
>>>         (stub_hash_newfunc): Initialize stub_offset and
>>> stub_template_size to
>>>         -1.
>>>         (elf32_arm_add_stub): Likewise for stub_offset.
>>>         (arm_new_stubs_start_offset_ptr): New function.
>>>         (arm_build_one_stub): Only allocate a stub_offset if it is
>>> -1.  Allow
>>>         empty SG veneers to have zero relocations.
>>>         (arm_size_one_stub): Only initialize stub size and template
>>>         information for non empty veneers.  Do not update veneer
>>> section size
>>>         if veneer already has an offset.
>>>         (elf32_arm_create_stub): Return the stub entry pointer or
>>> NULL instead
>>>         of a boolean indicating success or failure.
>>>         (cmse_scan): Change stub_changed parameter into an integer
>>> pointer
>>>         parameter cmse_stub_created to count the number of stub
>>> created and
>>>         adapt to change of return value in elf32_arm_create_stub.
>>>         (cmse_entry_fct_p): New function.
>>>         (arm_list_new_cmse_stub): Likewise.
>>>         (set_cmse_veneer_addr_from_implib): Likewise.
>>>         (elf32_arm_size_stubs): Define cmse_stub_created, pass its
>>> address to
>>>         cmse_scan instead of that of cmse_stub_changed to compute the
>>> number
>>>         of stub created and use it to initialize stub_changed.  Call
>>>         set_cmse_veneer_addr_from_implib after all cmse_scan.  Adapt
>>> to change
>>>         of return value in elf32_arm_create_stub.  Use
>>>         arm_stub_section_start_offset () if not NULL to initialize
>>> size of
>>>         secure gateway veneers section.  Initialize stub_offset of
>>> Cortex-A8
>>>         erratum fix to -1.  Use ret to hold return value.
>>>         (elf32_arm_build_stubs): Use arm_stub_section_start_offset ()
>>> if not
>>>         NULL to initialize size of secure gateway veneers section. 
>>> Adapt
>>>         comment to stress the importance of zeroing veneer section
>>> content.
>>>         (bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd
>>> parameter to
>>>         initialize eponymous field in struct elf32_arm_link_hash_table.
>>>
>>>
>>> *** ld/ChangeLog ***
>>>
>>> 2016-07-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>
>>>         * emultempl/armelf.em (in_implib_filename): Declare and
>>> initialize new
>>>         variable.
>>>         (arm_elf_create_output_section_statements): Open import input
>>> library
>>>         file for writing and pass resulting in_implib_bfd to
>>>         bfd_elf32_arm_set_target_relocs.
>>>         (PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option.
>>>         (PARSE_AND_LIST_LONGOPTS): Define --in-implib option.
>>>         (PARSE_AND_LIST_OPTIONS): Add help message for --in-implib
>>> option.
>>>         (PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case.
>>>         * ld.texinfo (--cmse-implib): Update to mention --in-implib.
>>>         (--in-implib): Document new option.
>>>         * NEWS: Likewise.
>>>         * testsuite/ld-arm/arm-elf.exp
>>>         (Secure gateway import library generation): add --defsym
>>> VER=1 to gas
>>>         CLI.
>>>         (Secure gateway import library generation: errors): Likewise.
>>>         (Input secure gateway import library): New test.
>>>         (Input secure gateway import library: no output import library):
>>>         Likewise.
>>>         (Input secure gateway import library: not an SG input import
>>> library):
>>>         Likewise.
>>>         (Input secure gateway import library: earlier stub section
>>> base):
>>>         Likewise.
>>>         (Input secure gateway import library: later stub section base):
>>>         Likewise.
>>>         (Input secure gateway import library: veneer comeback):
>>> Likewise.
>>>         (Input secure gateway import library: entry function change):
>>>         Likewise.
>>>         * testsuite/ld-arm/cmse-implib.s: Add input import library
>>> testing.
>>>         * testsuite/ld-arm/cmse-implib.rd: Update accordingly.
>>>         * testsuite/ld-arm/cmse-new-implib.out: New file.
>>>         * testsuite/ld-arm/cmse-new-implib.rd: Likewise.
>>>         * testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise.
>>>         * testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out:
>>> Likewise.
>>>         * testsuite/ld-arm/cmse-new-earlier-later-implib.out: Likewise.
>>>         * testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise.
>>>         * testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise.
>>>
>>> On Thursday 07 July 2016 13:52:00 you wrote:
>>>> On 04/04/16 15:22, Thomas Preudhomme wrote:
>>>>> On Wednesday 23 December 2015 16:02:48 Thomas Preud'homme wrote:
>>>>>> Hi,
>>>>>>
>>>>>> [Posting patch series as RFC]
>>>>>>
>>>>>> This patch is part of a patch series to add support for ARMv8-M
>>>>>> security
>>>>>> extension[1] to GNU ld. This specific patch adds support for allowing
>>>>>> Secure Gateway veneers to have stable addresses when relinking a
>>>>>> secure
>>>>>> executable.
>>>>>>
>>>>>> ARM v8-M security extensions allow code running in a device to be
>>>>>> divided
>>>>>> into secure and non-secure code expected to be developed by
>>>>>> independent
>>>>>> (teams of) people. To allow updating the secure code without the
>>>>>> need to
>>>>>> relink the non-secure code against it, it is necessary for the
>>>>>> toolchain
>>>>>> to
>>>>>> provide a way to fix the addresses of the secure gateway veneers that
>>>>>> serve
>>>>>> as entry points for non-secure code to call secure code. This is
>>>>>> also a
>>>>>> requirement [2] to claim support for ARM v8-M security extensions.
>>>>>>
>>>>>> This patch adds a --in-implib=<in_implib_filename> option which, when
>>>>>> used
>>>>>> in conjunction of --cmse-implib will ensure that the veneers whose
>>>>>> symbols
>>>>>> are defined in the import library $in_implib_filename will remain
>>>>>> at the
>>>>>> same address in the executable. In the absence of a --out-implib
>>>>>> option,
>>>>>> the code will warn about new secure gateway veneers being created,
>>>>>> otherwise these are allowed.
>>>>>>
>>>>>>
>>>>>> [1] Software requirements for ARMv8-M security extension are
>>>>>> described in
>>>>>> document ARM-ECM-0359818 [2] [2] Available on
>>>>>> http://infocenter.arm.com
>>>>>> in
>>>>>> Developer guides and articles > Software development > ARM®v8-M
>>>>>> Security
>>>>>> Extensions: Requirements on Development Tools [3] See requirement
>>>>>> 15 of
>>>>>> ARM-ECM-0359818 [2]
>>>>>
>>>>> Please find an updated patch below.
>>>>
>>>> Comments inline.
>>>>
>>>>> *** bfd/ChangeLog ***
>>>>>
>>>>> 2016-02-18  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>>>
>>>>>         * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new
>>>>> parameter
>>>>>         for
>>>>>         the input import library bfd.
>>>>>         * bfd-in2.h: Regenerate.
>>>>>         * elf32-arm.c (struct elf32_arm_link_hash_table): New
>>>>>         in_implib_bfd
>>>>>         and new_cmse_stub_offset fields.
>>>>>         (stub_hash_newfunc): Initialize stub_offset and
>>>>> stub_template_size
>>>>>         to
>>>>>         -1.
>>>>>         (elf32_arm_add_stub): Likewise for stub_offset.
>>>>>         (arm_new_stubs_start_offset_ptr): New function.
>>>>>         (arm_build_one_stub): Only allocate a stub_offset if it is -1.
>>>>>         Allow
>>>>>         empty veneers to have zero relocations.
>>>>>         (arm_size_one_stub): Only initialize stub size and template
>>>>>         information for non empty veneers.  Do not update veneer
>>>>> section
>>>>>         size
>>>>>         if veneer already has an offset.
>>>>>         (elf32_arm_create_stub): Return the stub entry pointer or NULL
>>>>>         instead
>>>>>         of a boolean indicating success or failure.
>>>>>         (cmse_scan): Change stub_changed parameter into an integer
>>>>> pointer
>>>>>         parameter cmse_stub_created to count the number of stub
>>>>> created
>>>>>         and
>>>>>         adapt to change of return value in elf32_arm_create_stub.
>>>>>         (cmse_entry_fct_p): New function.
>>>>>         (arm_list_new_cmse_stub): Likewise.
>>>>>         (set_cmse_veneer_addr_from_implib): Likewise.
>>>>>         (elf32_arm_size_stubs): Define cmse_stub_created, pass its
>>>>> address
>>>>>         to
>>>>>         cmse_scan instead of that of cmse_stub_changed to compute the
>>>>>         number
>>>>>         of stub created and use it to initialize stub_changed.  Call
>>>>>         set_cmse_veneer_addr_from_implib after all cmse_scan. 
>>>>> Adapt to
>>>>>         change
>>>>>         of return value in elf32_arm_create_stub.  Use
>>>>>         arm_stub_section_start_offset () if not NULL to initialize
>>>>> size of
>>>>>         secure gateway veneers section.  Initialize stub_offset of
>>>>>         Cortex-A8
>>>>>         erratum fix to -1.  Use ret to hold return value.
>>>>>         (elf32_arm_build_stubs): Use arm_stub_section_start_offset
>>>>> () if
>>>>>         not
>>>>>         NULL to initialize size of secure gateway veneers section. 
>>>>> Adapt
>>>>>         comment to stress the importance of zeroing veneer section
>>>>>         content.
>>>>>         (bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd
>>>>> parameter
>>>>>         to
>>>>>         initialize eponymous field in struct
>>>>> elf32_arm_link_hash_table.
>>>>>
>>>>> *** ld/ChangeLog ***
>>>>>
>>>>> 2016-02-18  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>>>
>>>>>         * emultempl/armelf.em (in_implib_filename): Declare and
>>>>> initialize
>>>>>         new
>>>>>         variable.
>>>>>         (arm_elf_create_output_section_statements): Open import input
>>>>>         library
>>>>>         file for writing and pass resulting in_implib_bfd to
>>>>>         bfd_elf32_arm_set_target_relocs.
>>>>>         (PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option.
>>>>>         (PARSE_AND_LIST_LONGOPTS): Define --in-implib option.
>>>>>         (PARSE_AND_LIST_OPTIONS): Add help message for --in-implib
>>>>> option.
>>>>>         (PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case.
>>>>>         * ld.texinfo (--cmse-implib): Update to mention --in-implib.
>>>>>         (--in-implib): Document new option.
>>>>>         * testsuite/ld-arm/arm-elf.exp
>>>>>         (Secure gateway import library generation): add --defsym
>>>>> VER=1 to
>>>>>         gas
>>>>>         CLI.
>>>>>         (Secure gateway import library generation: errors): Likewise.
>>>>>         (Input secure gateway import library): New test.
>>>>>         (Input secure gateway import library: no output import
>>>>> library):
>>>>>         Likewise.
>>>>>         (Input secure gateway import library: earlier stub section
>>>>> base):
>>>>>         Likewise.
>>>>>         (Input secure gateway import library: later stub section
>>>>> base):
>>>>>         Likewise.
>>>>>         (Input secure gateway import library: veneer comeback):
>>>>> Likewise.
>>>>>         (Input secure gateway import library: entry function change):
>>>>>         Likewise.
>>>>>         * testsuite/ld-arm/cmse-implib.s: Add input import library
>>>>>         testing.
>>>>>         * testsuite/ld-arm/cmse-implib.rd: Update accordingly.
>>>>>         * testsuite/ld-arm/cmse-new-implib.out: New file.
>>>>>         * testsuite/ld-arm/cmse-new-implib.rd: Likewise.
>>>>>         * testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise.
>>>>>         * testsuite/ld-arm/cmse-new-earlier-later-implib.out:
>>>>> Likewise.
>>>>>         * testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise.
>>>>>         * testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise.
>>>>>
>>>>> diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
>>>>> index
>>>>> 7e3483b9984b04c534e53f2f9026abf26d37592a..423c534a954c541e227e731e9256f08f
>>>>>
>>>>> 9fa62014 100644
>>>>> --- a/bfd/bfd-in.h
>>>>> +++ b/bfd/bfd-in.h
>>>>> @@ -895,7 +895,7 @@ extern bfd_boolean
>>>>> bfd_elf32_arm_process_before_allocation>
>>>>>  void bfd_elf32_arm_set_target_relocs
>>>>>
>>>>>    (bfd *, struct bfd_link_info *, int, char *, int, int,
>>>>>    bfd_arm_vfp11_fix,
>>>>>
>>>>> -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
>>>>> +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
>>>>>
>>>>>  extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
>>>>>
>>>>>    (bfd *, struct bfd_link_info *);
>>>>>
>>>>> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
>>>>> index
>>>>> 55e1cdde2d0a899238a224c6915d20197b72f085..3a67fa637f5c709cddf3767496e4ac87
>>>>>
>>>>> 96287765 100644
>>>>> --- a/bfd/bfd-in2.h
>>>>> +++ b/bfd/bfd-in2.h
>>>>> @@ -902,7 +902,7 @@ extern bfd_boolean
>>>>> bfd_elf32_arm_process_before_allocation>
>>>>>  void bfd_elf32_arm_set_target_relocs
>>>>>
>>>>>    (bfd *, struct bfd_link_info *, int, char *, int, int,
>>>>>    bfd_arm_vfp11_fix,
>>>>>
>>>>> -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
>>>>> +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
>>>>
>>>> This is *only* one more parameter to this function, but it now takes
>>>> 15,
>>>> which seems excessive.
>>>>
>>>> Some redesign may be in order here...
>>>
>>> Ok. I did a separate patch for this as I felt this was an independent
>>> change
>>> and would have made the patch even bigger. I'll post it soon.
>>>
>>> Best regards,
>>>
>>> Thomas
>>>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ARM 11/11, ping] Add support for stable secure gateway veneers addresses
  2016-08-25 16:14           ` Richard Earnshaw (lists)
@ 2016-08-25 16:35             ` Thomas Preudhomme
  2016-08-26  9:21               ` Richard Earnshaw (lists)
  0 siblings, 1 reply; 15+ messages in thread
From: Thomas Preudhomme @ 2016-08-25 16:35 UTC (permalink / raw)
  To: Richard Earnshaw (lists), binutils

Hi Richard,

On 25/08/16 17:14, Richard Earnshaw (lists) wrote:
> On 17/08/16 16:23, Thomas Preudhomme wrote:
>> [Trying again with inline patch since previous attempt got flagged as spam]
>>
>
> You're missing the ChangeLog entry, but I'll take it that it's still the
> same as last time.

Sorry, I forgot to copy the message I sent with the patch in my first attempt. I 
paste it below and will wait that you confirm you are happy with the updated 
ChangeLog entries.


Sorry for the delay, got caught on other things. Please find an updated patch
in attachment. All but one of your comments have been addressed, comment below
on that one.

Updated ChangeLog entries are as follow:

*** bfd/ChangeLog ***

2016-07-08  Thomas Preud'homme  <thomas.preudhomme@arm.com>

         * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new parameter for
         the input import library bfd.
         * bfd-in2.h: Regenerate.
         * elf32-arm.c (struct elf32_arm_link_hash_table): New in_implib_bfd
         and new_cmse_stub_offset fields.
         (stub_hash_newfunc): Initialize stub_offset and stub_template_size to
         -1.
         (elf32_arm_add_stub): Likewise for stub_offset.
         (arm_new_stubs_start_offset_ptr): New function.
         (arm_build_one_stub): Only allocate a stub_offset if it is -1.  Allow
         empty SG veneers to have zero relocations.
         (arm_size_one_stub): Only initialize stub size and template
         information for non empty veneers.  Do not update veneer section size
         if veneer already has an offset.
         (elf32_arm_create_stub): Return the stub entry pointer or NULL instead
         of a boolean indicating success or failure.
         (cmse_scan): Change stub_changed parameter into an integer pointer
         parameter cmse_stub_created to count the number of stub created and
         adapt to change of return value in elf32_arm_create_stub.
         (cmse_entry_fct_p): New function.
         (arm_list_new_cmse_stub): Likewise.
         (set_cmse_veneer_addr_from_implib): Likewise.
         (elf32_arm_size_stubs): Define cmse_stub_created, pass its address to
         cmse_scan instead of that of cmse_stub_changed to compute the number
         of stub created and use it to initialize stub_changed.  Call
         set_cmse_veneer_addr_from_implib after all cmse_scan.  Adapt to change
         of return value in elf32_arm_create_stub.  Use
         arm_stub_section_start_offset () if not NULL to initialize size of
         secure gateway veneers section.  Initialize stub_offset of Cortex-A8
         erratum fix to -1.  Use ret to hold return value.
         (elf32_arm_build_stubs): Use arm_stub_section_start_offset () if not
         NULL to initialize size of secure gateway veneers section.  Adapt
         comment to stress the importance of zeroing veneer section content.
         (bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd parameter to
         initialize eponymous field in struct elf32_arm_link_hash_table.


*** ld/ChangeLog ***

2016-07-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>

         * emultempl/armelf.em (in_implib_filename): Declare and initialize new
         variable.
         (arm_elf_create_output_section_statements): Open import input library
         file for writing and pass resulting in_implib_bfd to
         bfd_elf32_arm_set_target_relocs.
         (PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option.
         (PARSE_AND_LIST_LONGOPTS): Define --in-implib option.
         (PARSE_AND_LIST_OPTIONS): Add help message for --in-implib option.
         (PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case.
         * ld.texinfo (--cmse-implib): Update to mention --in-implib.
         (--in-implib): Document new option.
         * NEWS: Likewise.
         * testsuite/ld-arm/arm-elf.exp
         (Secure gateway import library generation): add --defsym VER=1 to gas
         CLI.
         (Secure gateway import library generation: errors): Likewise.
         (Input secure gateway import library): New test.
         (Input secure gateway import library: no output import library):
         Likewise.
         (Input secure gateway import library: not an SG input import library):
         Likewise.
         (Input secure gateway import library: earlier stub section base):
         Likewise.
         (Input secure gateway import library: later stub section base):
         Likewise.
         (Input secure gateway import library: veneer comeback): Likewise.
         (Input secure gateway import library: entry function change):
         Likewise.
         * testsuite/ld-arm/cmse-implib.s: Add input import library testing.
         * testsuite/ld-arm/cmse-implib.rd: Update accordingly.
         * testsuite/ld-arm/cmse-new-implib.out: New file.
         * testsuite/ld-arm/cmse-new-implib.rd: Likewise.
         * testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise.
         * testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out: Likewise.
         * testsuite/ld-arm/cmse-new-earlier-later-implib.out: Likewise.
         * testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise.
         * testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise.

>
> OK.
>
> R.
>
>> diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
>> index
>> d33bb8267b12d9cd2c942d3c502e3e563e63d09f..f9bce9fd3ef778429ea9c1416ca2ffcab3f4e374
>> 100644
>> --- a/bfd/bfd-in.h
>> +++ b/bfd/bfd-in.h
>> @@ -894,7 +894,7 @@ extern bfd_boolean
>> bfd_elf32_arm_process_before_allocation
>>
>>  void bfd_elf32_arm_set_target_relocs
>>    (bfd *, struct bfd_link_info *, int, char *, int, int,
>> bfd_arm_vfp11_fix,
>> -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
>> +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
>>
>>  extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
>>    (bfd *, struct bfd_link_info *);
>> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
>> index
>> cc8428a21d8ce3267420c76a4328fb6d433cd597..8b1d8a01adf529ee42ad6673c82a5028aed5774c
>> 100644
>> --- a/bfd/bfd-in2.h
>> +++ b/bfd/bfd-in2.h
>> @@ -901,7 +901,7 @@ extern bfd_boolean
>> bfd_elf32_arm_process_before_allocation
>>
>>  void bfd_elf32_arm_set_target_relocs
>>    (bfd *, struct bfd_link_info *, int, char *, int, int,
>> bfd_arm_vfp11_fix,
>> -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
>> +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
>>
>>  extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
>>    (bfd *, struct bfd_link_info *);
>> diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
>> index
>> 1eba21b42ddfaf3704860107e4fff36dbbc24d8d..539c2aacbd6b47b25288d3b3e691b90806863856
>> 100644
>> --- a/bfd/elf32-arm.c
>> +++ b/bfd/elf32-arm.c
>> @@ -3148,6 +3148,10 @@ struct elf32_arm_link_hash_table
>>       as per ARMv8-M Security Extensions.  */
>>    int cmse_implib;
>>
>> +  /* The import library whose symbols' address must remain stable in
>> +     the import library generated.  */
>> +  bfd *in_implib_bfd;
>> +
>>    /* The index of the next unused R_ARM_TLS_DESC slot in .rel.plt.  */
>>    bfd_vma next_tls_desc_index;
>>
>> @@ -3209,6 +3213,10 @@ struct elf32_arm_link_hash_table
>>    /* Input stub section holding secure gateway veneers.  */
>>    asection *cmse_stub_sec;
>>
>> +  /* Offset in cmse_stub_sec where new SG veneers (not in input import
>> library)
>> +     start to be allocated.  */
>> +  bfd_vma new_cmse_stub_offset;
>> +
>>    /* Number of elements in stub_group.  */
>>    unsigned int top_id;
>>
>> @@ -3460,7 +3468,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
>>        /* Initialize the local fields.  */
>>        eh = (struct elf32_arm_stub_hash_entry *) entry;
>>        eh->stub_sec = NULL;
>> -      eh->stub_offset = 0;
>> +      eh->stub_offset = (bfd_vma) -1;
>>        eh->source_value = 0;
>>        eh->target_value = 0;
>>        eh->target_section = NULL;
>> @@ -3468,7 +3476,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
>>        eh->stub_type = arm_stub_none;
>>        eh->stub_size = 0;
>>        eh->stub_template = NULL;
>> -      eh->stub_template_size = 0;
>> +      eh->stub_template_size = -1;
>>        eh->h = NULL;
>>        eh->id_sec = NULL;
>>        eh->output_name = NULL;
>> @@ -4467,7 +4475,7 @@ elf32_arm_add_stub (const char *stub_name,
>> asection *section,
>>      }
>>
>>    stub_entry->stub_sec = stub_sec;
>> -  stub_entry->stub_offset = 0;
>> +  stub_entry->stub_offset = (bfd_vma) -1;
>>    stub_entry->id_sec = link_sec;
>>
>>    return stub_entry;
>> @@ -4633,11 +4641,31 @@ arm_dedicated_stub_section_padding (enum
>> elf32_arm_stub_type stub_type)
>>    abort ();  /* Should be unreachable.  */
>>  }
>>
>> +/* If veneers of type STUB_TYPE should go in a dedicated output section,
>> +   returns the address of the hash table field in HTAB holding the
>> offset at
>> +   which new veneers should be layed out in the stub section.  */
>> +
>> +static bfd_vma*
>> +arm_new_stubs_start_offset_ptr (struct elf32_arm_link_hash_table *htab,
>> +                enum elf32_arm_stub_type stub_type)
>> +{
>> +  switch (stub_type)
>> +    {
>> +    case arm_stub_cmse_branch_thumb_only:
>> +      return &htab->new_cmse_stub_offset;
>> +
>> +    default:
>> +      BFD_ASSERT (!arm_dedicated_stub_output_section_required
>> (stub_type));
>> +      return NULL;
>> +    }
>> +}
>> +
>>  static bfd_boolean
>>  arm_build_one_stub (struct bfd_hash_entry *gen_entry,
>>              void * in_arg)
>>  {
>>  #define MAXRELOCS 3
>> +  bfd_boolean removed_sg_veneer;
>>    struct elf32_arm_stub_hash_entry *stub_entry;
>>    struct elf32_arm_link_hash_table *globals;
>>    struct bfd_link_info *info;
>> @@ -4652,6 +4680,7 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
>>    int stub_reloc_idx[MAXRELOCS] = {-1, -1};
>>    int stub_reloc_offset[MAXRELOCS] = {0, 0};
>>    int nrelocs = 0;
>> +  int just_allocated = 0;
>>
>>    /* Massage our args to the form they really have.  */
>>    stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
>> @@ -4668,8 +4697,12 @@ arm_build_one_stub (struct bfd_hash_entry
>> *gen_entry,
>>      /* We have to do less-strictly-aligned fixes last.  */
>>      return TRUE;
>>
>> -  /* Make a note of the offset within the stubs for this entry.  */
>> -  stub_entry->stub_offset = stub_sec->size;
>> +  /* Assign a slot at the end of section if none assigned yet.  */
>> +  if (stub_entry->stub_offset == (bfd_vma) -1)
>> +    {
>> +      stub_entry->stub_offset = stub_sec->size;
>> +      just_allocated = 1;
>> +    }
>>    loc = stub_sec->contents + stub_entry->stub_offset;
>>
>>    stub_bfd = stub_sec->owner;
>> @@ -4743,7 +4776,8 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
>>      }
>>      }
>>
>> -  stub_sec->size += size;
>> +  if (just_allocated)
>> +    stub_sec->size += size;
>>
>>    /* Stub size has already been computed in arm_size_one_stub. Check
>>       consistency.  */
>> @@ -4753,9 +4787,11 @@ arm_build_one_stub (struct bfd_hash_entry
>> *gen_entry,
>>    if (stub_entry->branch_type == ST_BRANCH_TO_THUMB)
>>      sym_value |= 1;
>>
>> -  /* Assume there is at least one and at most MAXRELOCS entries to
>> relocate
>> -     in each stub.  */
>> -  BFD_ASSERT (nrelocs != 0 && nrelocs <= MAXRELOCS);
>> +  /* Assume non empty slots have at least one and at most MAXRELOCS
>> entries
>> +     to relocate in each stub.  */
>> +  removed_sg_veneer =
>> +    (size == 0 && stub_entry->stub_type ==
>> arm_stub_cmse_branch_thumb_only);
>> +  BFD_ASSERT (removed_sg_veneer || (nrelocs != 0 && nrelocs <=
>> MAXRELOCS));
>>
>>    for (i = 0; i < nrelocs; i++)
>>      {
>> @@ -4857,9 +4893,17 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry,
>>    size = find_stub_size_and_template (stub_entry->stub_type,
>> &template_sequence,
>>                        &template_size);
>>
>> -  stub_entry->stub_size = size;
>> -  stub_entry->stub_template = template_sequence;
>> -  stub_entry->stub_template_size = template_size;
>> +  /* Initialized to -1.  Null size indicates an empty slot full of
>> zeros.  */
>> +  if (stub_entry->stub_template_size)
>> +    {
>> +      stub_entry->stub_size = size;
>> +      stub_entry->stub_template = template_sequence;
>> +      stub_entry->stub_template_size = template_size;
>> +    }
>> +
>> +  /* Already accounted for.  */
>> +  if (stub_entry->stub_offset != (bfd_vma) -1)
>> +    return TRUE;
>>
>>    size = (size + 7) & ~7;
>>    stub_entry->stub_sec->size += size;
>> @@ -5424,10 +5468,10 @@ cortex_a8_erratum_scan (bfd *input_bfd,
>>     and *NEW_STUB is set to FALSE.  Otherwise, *NEW_STUB is set to
>>     TRUE and the stub entry is initialized.
>>
>> -   Returns whether the stub could be successfully created or updated,
>> or FALSE
>> -   if an error occured.  */
>> +   Returns the stub that was created or updated, or NULL if an error
>> +   occurred.  */
>>
>> -static bfd_boolean
>> +static struct elf32_arm_stub_hash_entry *
>>  elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
>>                 enum elf32_arm_stub_type stub_type, asection *section,
>>                 Elf_Internal_Rela *irela, asection *sym_sec,
>> @@ -5458,7 +5502,7 @@ elf32_arm_create_stub (struct
>> elf32_arm_link_hash_table *htab,
>>        stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash, irela,
>>                         stub_type);
>>        if (!stub_name)
>> -    return FALSE;
>> +    return NULL;
>>      }
>>
>>    stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, stub_name,
>> FALSE,
>> @@ -5469,7 +5513,7 @@ elf32_arm_create_stub (struct
>> elf32_arm_link_hash_table *htab,
>>        if (!sym_claimed)
>>      free (stub_name);
>>        stub_entry->target_value = sym_value;
>> -      return TRUE;
>> +      return stub_entry;
>>      }
>>
>>    stub_entry = elf32_arm_add_stub (stub_name, section, htab, stub_type);
>> @@ -5477,7 +5521,7 @@ elf32_arm_create_stub (struct
>> elf32_arm_link_hash_table *htab,
>>      {
>>        if (!sym_claimed)
>>      free (stub_name);
>> -      return FALSE;
>> +      return NULL;
>>      }
>>
>>    stub_entry->target_value = sym_value;
>> @@ -5498,7 +5542,7 @@ elf32_arm_create_stub (struct
>> elf32_arm_link_hash_table *htab,
>>        if (stub_entry->output_name == NULL)
>>      {
>>        free (stub_name);
>> -      return FALSE;
>> +      return NULL;
>>      }
>>
>>        /* For historical reasons, use the existing names for
>> ARM-to-Thumb and
>> @@ -5518,7 +5562,7 @@ elf32_arm_create_stub (struct
>> elf32_arm_link_hash_table *htab,
>>      }
>>
>>    *new_stub = TRUE;
>> -  return TRUE;
>> +  return stub_entry;
>>  }
>>
>>  /* Scan symbols in INPUT_BFD to identify secure entry functions needing a
>> @@ -5537,14 +5581,15 @@ elf32_arm_create_stub (struct
>> elf32_arm_link_hash_table *htab,
>>
>>     OUT_ATTR gives the output attributes, SYM_HASHES the symbol index to
>> hash
>>     entry mapping while HTAB gives the name to hash entry mapping.
>> +   *CMSE_STUB_CREATED is increased by the number of secure gateway veneer
>> +   created.
>>
>> -   If any secure gateway veneer is created, *STUB_CHANGED is set to
>> TRUE.  The
>> -   return value gives whether a stub failed to be allocated.  */
>> +   The return value gives whether a stub failed to be allocated.  */
>>
>>  static bfd_boolean
>>  cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
>>         obj_attribute *out_attr, struct elf_link_hash_entry **sym_hashes,
>> -       bfd_boolean *stub_changed)
>> +       int *cmse_stub_created)
>>  {
>>    const struct elf_backend_data *bed;
>>    Elf_Internal_Shdr *symtab_hdr;
>> @@ -5555,7 +5600,8 @@ cmse_scan (bfd *input_bfd, struct
>> elf32_arm_link_hash_table *htab,
>>    char *sym_name, *lsym_name;
>>    bfd_vma sym_value;
>>    asection *section;
>> -  bfd_boolean is_v8m, new_stub, created_stub, cmse_invalid, ret = TRUE;
>> +  struct elf32_arm_stub_hash_entry *stub_entry;
>> +  bfd_boolean is_v8m, new_stub, cmse_invalid, ret = TRUE;
>>
>>    bed = get_elf_backend_data (input_bfd);
>>    symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
>> @@ -5700,17 +5746,17 @@ cmse_scan (bfd *input_bfd, struct
>> elf32_arm_link_hash_table *htab,
>>        if (!ret)
>>      continue;
>>        branch_type = ARM_GET_SYM_BRANCH_TYPE (hash->root.target_internal);
>> -      created_stub
>> +      stub_entry
>>      = elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
>>                   NULL, NULL, section, hash, sym_name,
>>                   sym_value, branch_type, &new_stub);
>>
>> -      if (!created_stub)
>> +      if (stub_entry == NULL)
>>       ret = FALSE;
>>        else
>>      {
>>        BFD_ASSERT (new_stub);
>> -      *stub_changed = TRUE;
>> +      (*cmse_stub_created)++;
>>      }
>>      }
>>
>> @@ -5719,6 +5765,279 @@ cmse_scan (bfd *input_bfd, struct
>> elf32_arm_link_hash_table *htab,
>>    return ret;
>>  }
>>
>> +/* Return TRUE iff a symbol identified by its linker HASH entry is a
>> secure
>> +   code entry function, ie can be called from non secure code without
>> using a
>> +   veneer.  */
>> +
>> +static bfd_boolean
>> +cmse_entry_fct_p (struct elf32_arm_link_hash_entry *hash)
>> +{
>> +  uint32_t first_insn;
>> +  asection *section;
>> +  file_ptr offset;
>> +  bfd *abfd;
>> +
>> +  /* Defined symbol of function type.  */
>> +  if (hash->root.root.type != bfd_link_hash_defined
>> +      && hash->root.root.type != bfd_link_hash_defweak)
>> +    return FALSE;
>> +  if (hash->root.type != STT_FUNC)
>> +    return FALSE;
>> +
>> +  /* Read first instruction.  */
>> +  section = hash->root.root.u.def.section;
>> +  abfd = section->owner;
>> +  offset = hash->root.root.u.def.value - section->vma;
>> +  if (!bfd_get_section_contents (abfd, section, &first_insn, offset,
>> +                 sizeof (first_insn)))
>> +    return FALSE;
>> +
>> +  /* Start by SG instruction.  */
>> +  return first_insn == 0xe97fe97f;
>> +}
>> +
>> +/* Output the name (in symbol table) of the veneer GEN_ENTRY if it is a
>> new
>> +   secure gateway veneers (ie. the veneers was not in the input import
>> library)
>> +   and there is no output import library (GEN_INFO->out_implib_bfd is
>> NULL.  */
>> +
>> +static bfd_boolean
>> +arm_list_new_cmse_stub (struct bfd_hash_entry *gen_entry, void *gen_info)
>> +{
>> +  struct elf32_arm_stub_hash_entry *stub_entry;
>> +  struct bfd_link_info *info;
>> +
>> +  /* Massage our args to the form they really have.  */
>> +  stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
>> +  info = (struct bfd_link_info *) gen_info;
>> +
>> +  if (info->out_implib_bfd)
>> +    return TRUE;
>> +
>> +  if (stub_entry->stub_type != arm_stub_cmse_branch_thumb_only)
>> +    return TRUE;
>> +
>> +  if (stub_entry->stub_offset == (bfd_vma) -1)
>> +    (*_bfd_error_handler) ("  %s", stub_entry->output_name);
>> +
>> +  return TRUE;
>> +}
>> +
>> +/* Set offset of each secure gateway veneers so that its address remain
>> +   identical to the one in the input import library referred by
>> +   HTAB->in_implib_bfd.  A warning is issued for veneers that disappeared
>> +   (present in input import library but absent from the executable being
>> +   linked) or if new veneers appeared and there is no output import
>> library
>> +   (INFO->out_implib_bfd is NULL and *CMSE_STUB_CREATED is bigger than the
>> +   number of secure gateway veneers found in the input import library.
>> +
>> +   The function returns whether an error occurred.  If no error occurred,
>> +   *CMSE_STUB_CREATED gives the number of SG veneers created by both
>> cmse_scan
>> +   and this function and HTAB->new_cmse_stub_offset is set to the biggest
>> +   veneer observed set for new veneers to be layed out after.  */
>> +
>> +static bfd_boolean
>> +set_cmse_veneer_addr_from_implib (struct bfd_link_info *info,
>> +                  struct elf32_arm_link_hash_table *htab,
>> +                  int *cmse_stub_created)
>> +{
>> +  long symsize;
>> +  char *sym_name;
>> +  flagword flags;
>> +  long i, symcount;
>> +  bfd *in_implib_bfd;
>> +  asection *stub_out_sec;
>> +  bfd_boolean ret = TRUE;
>> +  Elf_Internal_Sym *intsym;
>> +  const char *out_sec_name;
>> +  bfd_size_type cmse_stub_size;
>> +  asymbol **sympp = NULL, *sym;
>> +  struct elf32_arm_link_hash_entry *hash;
>> +  const insn_sequence *cmse_stub_template;
>> +  struct elf32_arm_stub_hash_entry *stub_entry;
>> +  int cmse_stub_template_size, new_cmse_stubs_created =
>> *cmse_stub_created;
>> +  bfd_vma veneer_value, stub_offset, next_cmse_stub_offset;
>> +  bfd_vma cmse_stub_array_start = (bfd_vma) -1, cmse_stub_sec_vma = 0;
>> +
>> +  /* No input secure gateway import library.  */
>> +  if (!htab->in_implib_bfd)
>> +    return TRUE;
>> +
>> +  in_implib_bfd = htab->in_implib_bfd;
>> +  if (!htab->cmse_implib)
>> +    {
>> +      (*_bfd_error_handler) (_("%B: --in-implib only supported for
>> Secure "
>> +                   "Gateway import libraries."), in_implib_bfd);
>> +      return FALSE;
>> +    }
>> +
>> +  /* Get symbol table size.  */
>> +  symsize = bfd_get_symtab_upper_bound (in_implib_bfd);
>> +  if (symsize < 0)
>> +    return FALSE;
>> +
>> +  /* Read in the input secure gateway import library's symbol table.  */
>> +  sympp = (asymbol **) xmalloc (symsize);
>> +  symcount = bfd_canonicalize_symtab (in_implib_bfd, sympp);
>> +  if (symcount < 0)
>> +    {
>> +      ret = FALSE;
>> +      goto free_sym_buf;
>> +    }
>> +
>> +  htab->new_cmse_stub_offset = 0;
>> +  cmse_stub_size =
>> +    find_stub_size_and_template (arm_stub_cmse_branch_thumb_only,
>> +                 &cmse_stub_template,
>> +                 &cmse_stub_template_size);
>> +  out_sec_name =
>> +    arm_dedicated_stub_output_section_name
>> (arm_stub_cmse_branch_thumb_only);
>> +  stub_out_sec =
>> +    bfd_get_section_by_name (htab->obfd, out_sec_name);
>> +  if (stub_out_sec != NULL)
>> +    cmse_stub_sec_vma = stub_out_sec->vma;
>> +
>> +  /* Set addresses of veneers mentionned in input secure gateway import
>> +     library's symbol table.  */
>> +  for (i = 0; i < symcount; i++)
>> +    {
>> +      sym = sympp[i];
>> +      flags = sym->flags;
>> +      sym_name = (char *) bfd_asymbol_name (sym);
>> +      intsym = &((elf_symbol_type *) sym)->internal_elf_sym;
>> +
>> +      if (sym->section != bfd_abs_section_ptr
>> +      || !(flags & (BSF_GLOBAL | BSF_WEAK))
>> +      || (flags & BSF_FUNCTION) != BSF_FUNCTION
>> +      || (ARM_GET_SYM_BRANCH_TYPE (intsym->st_target_internal)
>> +          != ST_BRANCH_TO_THUMB))
>> +    {
>> +      (*_bfd_error_handler) (_("%B: invalid import library entry: `%s'."),
>> +                 in_implib_bfd, sym_name);
>> +      (*_bfd_error_handler) (_("Symbol should be absolute, global and "
>> +                   "refer to Thumb functions."));
>> +      ret = FALSE;
>> +      continue;
>> +    }
>> +
>> +      veneer_value = bfd_asymbol_value (sym);
>> +      stub_offset = veneer_value - cmse_stub_sec_vma;
>> +      stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, sym_name,
>> +                     FALSE, FALSE);
>> +      hash = (struct elf32_arm_link_hash_entry *)
>> +    elf_link_hash_lookup (&(htab)->root, sym_name, FALSE, FALSE, TRUE);
>> +
>> +      /* Stub entry should have been created by cmse_scan or the symbol
>> be of
>> +     a secure function callable from non secure code.  */
>> +      if (!stub_entry && !hash)
>> +    {
>> +      bfd_boolean new_stub;
>> +
>> +      (*_bfd_error_handler)
>> +        (_("Entry function `%s' disappeared from secure code."),
>> sym_name);
>> +      hash = (struct elf32_arm_link_hash_entry *)
>> +        elf_link_hash_lookup (&(htab)->root, sym_name, TRUE, TRUE, TRUE);
>> +      stub_entry
>> +        = elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
>> +                     NULL, NULL, bfd_abs_section_ptr, hash,
>> +                     sym_name, veneer_value,
>> +                     ST_BRANCH_TO_THUMB, &new_stub);
>> +      if (stub_entry == NULL)
>> +        ret = FALSE;
>> +      else
>> +      {
>> +        BFD_ASSERT (new_stub);
>> +        new_cmse_stubs_created++;
>> +        (*cmse_stub_created)++;
>> +      }
>> +      stub_entry->stub_template_size = stub_entry->stub_size = 0;
>> +      stub_entry->stub_offset = stub_offset;
>> +    }
>> +      /* Symbol found is not callable from non secure code.  */
>> +      else if (!stub_entry)
>> +    {
>> +      if (!cmse_entry_fct_p (hash))
>> +        {
>> +          (*_bfd_error_handler) (_("`%s' refers to a non entry
>> function."),
>> +                     sym_name);
>> +          ret = FALSE;
>> +        }
>> +      continue;
>> +    }
>> +      else
>> +    {
>> +      /* Only stubs for SG veneers should have been created.  */
>> +      BFD_ASSERT (stub_entry->stub_type ==
>> arm_stub_cmse_branch_thumb_only);
>> +
>> +      /* Check visibility hasn't changed.  */
>> +      if (!!(flags & BSF_GLOBAL)
>> +          != (hash->root.root.type == bfd_link_hash_defined))
>> +        (*_bfd_error_handler)
>> +          (_("%B: visibility of symbol `%s' has changed."), in_implib_bfd,
>> +           sym_name);
>> +
>> +      stub_entry->stub_offset = stub_offset;
>> +    }
>> +
>> +      /* Size should match that of a SG veneer.  */
>> +      if (intsym->st_size != cmse_stub_size)
>> +    {
>> +      (*_bfd_error_handler) (_("%B: incorrect size for symbol `%s'."),
>> +                 in_implib_bfd, sym_name);
>> +      ret = FALSE;
>> +    }
>> +
>> +      /* Previous veneer address is before current SG veneer section.  */
>> +      if (veneer_value < cmse_stub_sec_vma)
>> +    {
>> +      /* Avoid offset underflow.  */
>> +      if (stub_entry)
>> +        stub_entry->stub_offset = 0;
>> +      stub_offset = 0;
>> +      ret = FALSE;
>> +    }
>> +
>> +      /* Complain if stub offset not a multiple of stub size.  */
>> +      if (stub_offset % cmse_stub_size)
>> +    {
>> +      (*_bfd_error_handler)
>> +        (_("Offset of veneer for entry function `%s' not a multiple of "
>> +           "its size."), sym_name);
>> +      ret = FALSE;
>> +    }
>> +
>> +      if (!ret)
>> +    continue;
>> +
>> +      new_cmse_stubs_created--;
>> +      if (veneer_value < cmse_stub_array_start)
>> +    cmse_stub_array_start = veneer_value;
>> +      next_cmse_stub_offset = stub_offset + ((cmse_stub_size + 7) & ~7);
>> +      if (next_cmse_stub_offset > htab->new_cmse_stub_offset)
>> +    htab->new_cmse_stub_offset = next_cmse_stub_offset;
>> +    }
>> +
>> +  if (!info->out_implib_bfd && new_cmse_stubs_created != 0)
>> +    {
>> +      BFD_ASSERT (new_cmse_stubs_created > 0);
>> +      (*_bfd_error_handler)
>> +    (_("new entry function(s) introduced but no output import library "
>> +       "specified:"));
>> +      bfd_hash_traverse (&htab->stub_hash_table,
>> arm_list_new_cmse_stub, info);
>> +    }
>> +
>> +  if (cmse_stub_array_start != cmse_stub_sec_vma)
>> +    {
>> +      (*_bfd_error_handler)
>> +    (_("Start address of `%s' is different from previous link."),
>> +     out_sec_name);
>> +      ret = FALSE;
>> +    }
>> +
>> +free_sym_buf:
>> +  free (sympp);
>> +  return ret;
>> +}
>> +
>>  /* Determine and set the size of the stub section for a final link.
>>
>>     The basic idea here is to examine all the relocations looking for
>> @@ -5735,7 +6054,9 @@ elf32_arm_size_stubs (bfd *output_bfd,
>>                                unsigned int),
>>                void (*layout_sections_again) (void))
>>  {
>> +  bfd_boolean ret = TRUE;
>>    obj_attribute *out_attr;
>> +  int cmse_stub_created = 0;
>>    bfd_size_type stub_group_size;
>>    bfd_boolean m_profile, stubs_always_after_branch, first_veneer_scan =
>> TRUE;
>>    struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
>> @@ -5768,6 +6089,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
>>
>>    out_attr = elf_known_obj_attributes_proc (output_bfd);
>>    m_profile = out_attr[Tag_CPU_arch_profile].i == 'M';
>> +
>>    /* The Cortex-A8 erratum fix depends on stubs not being in the same
>> 4K page
>>       as the first half of a 32-bit branch straddling two 4K pages.
>> This is a
>>       crude way of enforcing that.  */
>> @@ -5841,8 +6163,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
>>
>>            sym_hashes = elf_sym_hashes (input_bfd);
>>            if (!cmse_scan (input_bfd, htab, out_attr, sym_hashes,
>> -                  &stub_changed))
>> +                  &cmse_stub_created))
>>          goto error_ret_free_local;
>> +
>> +          if (cmse_stub_created != 0)
>> +        stub_changed = TRUE;
>>          }
>>
>>        /* Walk over each section attached to the input bfd.  */
>> @@ -6074,6 +6399,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
>>            do
>>              {
>>                bfd_boolean new_stub;
>> +              struct elf32_arm_stub_hash_entry *stub_entry;
>>
>>                /* Determine what (if any) linker stub is needed.  */
>>                stub_type = arm_type_of_stub (info, section, irela,
>> @@ -6085,12 +6411,13 @@ elf32_arm_size_stubs (bfd *output_bfd,
>>
>>                /* We've either created a stub for this reloc already,
>>               or we are about to.  */
>> -              created_stub =
>> +              stub_entry =
>>              elf32_arm_create_stub (htab, stub_type, section, irela,
>>                             sym_sec, hash,
>>                             (char *) sym_name, sym_value,
>>                             branch_type, &new_stub);
>>
>> +              created_stub = stub_entry != NULL;
>>                if (!created_stub)
>>              goto error_ret_free_internal;
>>                else if (!new_stub)
>> @@ -6172,6 +6499,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
>>          }
>>      }
>>
>> +      if (first_veneer_scan
>> +      && !set_cmse_veneer_addr_from_implib (info, htab,
>> +                        &cmse_stub_created))
>> +    ret = FALSE;
>> +
>>        if (prev_num_a8_fixes != num_a8_fixes)
>>      stub_changed = TRUE;
>>
>> @@ -6191,6 +6523,24 @@ elf32_arm_size_stubs (bfd *output_bfd,
>>        stub_sec->size = 0;
>>      }
>>
>> +      /* Add new SG veneers after those already in the input import
>> +     library.  */
>> +      for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
>> +       stub_type++)
>> +    {
>> +      bfd_vma *start_offset_p;
>> +      asection **stub_sec_p;
>> +
>> +      start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type);
>> +      stub_sec_p = arm_dedicated_stub_input_section_ptr (htab, stub_type);
>> +      if (start_offset_p == NULL)
>> +        continue;
>> +
>> +      BFD_ASSERT (stub_sec_p != NULL);
>> +      if (*stub_sec_p != NULL)
>> +        (*stub_sec_p)->size = *start_offset_p;
>> +    }
>> +
>>        /* Compute stub section size, considering padding.  */
>>        bfd_hash_traverse (&htab->stub_hash_table, arm_size_one_stub, htab);
>>        for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
>> @@ -6259,7 +6609,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
>>          }
>>
>>        stub_entry->stub_sec = stub_sec;
>> -      stub_entry->stub_offset = 0;
>> +      stub_entry->stub_offset = (bfd_vma) -1;
>>        stub_entry->id_sec = link_sec;
>>        stub_entry->stub_type = a8_fixes[i].stub_type;
>>        stub_entry->source_value = a8_fixes[i].offset;
>> @@ -6287,7 +6637,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
>>        htab->a8_erratum_fixes = NULL;
>>        htab->num_a8_erratum_fixes = 0;
>>      }
>> -  return TRUE;
>> +  return ret;
>>  }
>>
>>  /* Build all the stubs associated with the current output file.  The
>> @@ -6301,6 +6651,7 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
>>  {
>>    asection *stub_sec;
>>    struct bfd_hash_table *table;
>> +  enum elf32_arm_stub_type stub_type;
>>    struct elf32_arm_link_hash_table *htab;
>>
>>    htab = elf32_arm_hash_table (info);
>> @@ -6318,14 +6669,33 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
>>      continue;
>>
>>        /* Allocate memory to hold the linker stubs.  Zeroing the stub
>> sections
>> -     must at least be done for stub section requiring padding.  */
>> +     must at least be done for stub section requiring padding and for SG
>> +     veneers to ensure that a non secure code branching to a removed SG
>> +     veneer causes an error.  */
>>        size = stub_sec->size;
>>        stub_sec->contents = (unsigned char *) bfd_zalloc
>> (htab->stub_bfd, size);
>>        if (stub_sec->contents == NULL && size != 0)
>>      return FALSE;
>> +
>>        stub_sec->size = 0;
>>      }
>>
>> +  /* Add new SG veneers after those already in the input import
>> library.  */
>> +  for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
>> stub_type++)
>> +    {
>> +      bfd_vma *start_offset_p;
>> +      asection **stub_sec_p;
>> +
>> +      start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type);
>> +      stub_sec_p = arm_dedicated_stub_input_section_ptr (htab, stub_type);
>> +      if (start_offset_p == NULL)
>> +    continue;
>> +
>> +      BFD_ASSERT (stub_sec_p != NULL);
>> +      if (*stub_sec_p != NULL)
>> +    (*stub_sec_p)->size = *start_offset_p;
>> +    }
>> +
>>    /* Build the stubs as directed by the stub hash table.  */
>>    table = &htab->stub_hash_table;
>>    bfd_hash_traverse (table, arm_build_one_stub, info);
>> @@ -8311,7 +8681,8 @@ bfd_elf32_arm_set_target_relocs (struct bfd
>> *output_bfd,
>>                   bfd_arm_stm32l4xx_fix stm32l4xx_fix,
>>                   int no_enum_warn, int no_wchar_warn,
>>                   int pic_veneer, int fix_cortex_a8,
>> -                 int fix_arm1176, int cmse_implib)
>> +                 int fix_arm1176, int cmse_implib,
>> +                 bfd *in_implib_bfd)
>>  {
>>    struct elf32_arm_link_hash_table *globals;
>>
>> @@ -8339,6 +8710,7 @@ bfd_elf32_arm_set_target_relocs (struct bfd
>> *output_bfd,
>>    globals->fix_cortex_a8 = fix_cortex_a8;
>>    globals->fix_arm1176 = fix_arm1176;
>>    globals->cmse_implib = cmse_implib;
>> +  globals->in_implib_bfd = in_implib_bfd;
>>
>>    BFD_ASSERT (is_arm_elf (output_bfd));
>>    elf_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
>> diff --git a/ld/NEWS b/ld/NEWS
>> index
>> 2a0b4ac704a088a24cfc1633785a50477513c4db..0f316bfcc248341200af14e5cb1a5c50787e9b1a
>> 100644
>> --- a/ld/NEWS
>> +++ b/ld/NEWS
>> @@ -2,6 +2,11 @@
>>
>>  Changes in 2.28:
>>
>> +* Add --in-implib=<infile> to the ARM linker to enable specifying a set of
>> +  Secure Gateway veneers that must exist in the output import library
>> specified
>> +  by --out-implib=<outfile> and the address they must have.  As such,
>> +  --in-implib is only supported in combination with --cmse-implib.
>> +
>>  * Extended the --out-implib=<file> option, previously restricted to x86 PE
>>    targets, to any ELF based target.  This allows the generation of an
>> import
>>    library for an ELF executable, which can then be used by another
>> application
>> diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
>> index
>> c21f6a82335a58a0ab37f3719c73c95e73e6211c..2346bb42444895605d10b7b7e21cca2dcaa38700
>> 100644
>> --- a/ld/emultempl/armelf.em
>> +++ b/ld/emultempl/armelf.em
>> @@ -43,6 +43,7 @@ static int pic_veneer = 0;
>>  static int merge_exidx_entries = -1;
>>  static int fix_arm1176 = 1;
>>  static int cmse_implib = 0;
>> +static char *in_implib_filename = NULL;
>>
>>  static void
>>  gld${EMULATION_NAME}_before_parse (void)
>> @@ -498,6 +499,8 @@ gld${EMULATION_NAME}_finish (void)
>>  static void
>>  arm_elf_create_output_section_statements (void)
>>  {
>> +  bfd *in_implib_bfd;
>> +
>>    if (strstr (bfd_get_target (link_info.output_bfd), "arm") == NULL)
>>      {
>>        /* The arm backend needs special fields in the output hash
>> structure.
>> @@ -508,6 +511,20 @@ arm_elf_create_output_section_statements (void)
>>        return;
>>      }
>>
>> +  if (in_implib_filename)
>> +    {
>> +      in_implib_bfd = bfd_openr (in_implib_filename,
>> +                 bfd_get_target (link_info.output_bfd));
>> +
>> +      if (in_implib_bfd == NULL)
>> +    einfo ("%F%s: Can't open: %E\n", in_implib_filename);
>> +
>> +      if (!bfd_check_format (in_implib_bfd, bfd_object))
>> +    einfo ("%F%s: Not a relocatable file: %E\n", in_implib_filename);
>> +    }
>> +  else
>> +    in_implib_bfd = NULL;
>> +
>>    bfd_elf32_arm_set_target_relocs (link_info.output_bfd, &link_info,
>>                     target1_is_rel,
>>                     target2_type, fix_v4bx, use_blx,
>> @@ -515,7 +532,7 @@ arm_elf_create_output_section_statements (void)
>>                     no_enum_size_warning,
>>                     no_wchar_size_warning,
>>                     pic_veneer, fix_cortex_a8,
>> -                   fix_arm1176, cmse_implib);
>> +                   fix_arm1176, cmse_implib, in_implib_bfd);
>>
>>    stub_file = lang_add_input_file ("linker stubs",
>>                      lang_input_file_is_fake_enum,
>> @@ -585,6 +602,7 @@ PARSE_AND_LIST_PROLOGUE='
>>  #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
>> @@ -612,6 +630,7 @@ PARSE_AND_LIST_LONGOPTS='
>>    { "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='
>> @@ -634,6 +653,8 @@ PARSE_AND_LIST_OPTIONS='
>>             "                              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\
>> @@ -758,6 +779,10 @@ PARSE_AND_LIST_ARGS_CASES='
>>     case OPTION_CMSE_IMPLIB:
>>        cmse_implib = 1;
>>        break;
>> +
>> +   case OPTION_IN_IMPLIB:
>> +      in_implib_filename = optarg;
>> +      break;
>>  '
>>
>>  # We have our own before_allocation etc. functions, but they call
>> diff --git a/ld/ld.texinfo b/ld/ld.texinfo
>> index
>> e6813f287fe5ce4c916bf93f48b2e9edbc336570..021385166887a2d2bd49bdba379e833b9c67d906
>> 100644
>> --- a/ld/ld.texinfo
>> +++ b/ld/ld.texinfo
>> @@ -6866,6 +6866,18 @@ specified by the @samp{--out-implib} and
>> @samp{--in-implib} options are
>>  secure gateway import libraries, suitable for linking a non-secure
>>  executable against secure code as per ARMv8-M Security Extensions.
>>
>> +@kindex --in-implib=@var{file}
>> +@cindex Input import library
>> +The @samp{--in-implib=file} specifies an input import library whose
>> symbols
>> +must keep the same address in the executable being produced.  A warning is
>> +given if no @samp{--out-implib} is given but new symbols have been
>> introduced
>> +in the executable that should be listed in its import library.
>> Otherwise, if
>> +@samp{--out-implib} is specified, the symbols are added to the output
>> import
>> +library.  A warning is also given if some symbols present in the input
>> import
>> +library have disappeared from the executable.  This option is only
>> effective
>> +for Secure Gateway import libraries, ie. when @samp{--cmse-implib} is
>> +specified.
>> +
>>  @ifclear GENERIC
>>  @lowersections
>>  @end ifclear
>> diff --git a/ld/testsuite/ld-arm/arm-elf.exp
>> b/ld/testsuite/ld-arm/arm-elf.exp
>> index
>> 55240854a24951194c8150581b8a40dd2910b5cb..24d0b4c72a91550bfa936cdbe4ab7fabbeecb6c5
>> 100644
>> --- a/ld/testsuite/ld-arm/arm-elf.exp
>> +++ b/ld/testsuite/ld-arm/arm-elf.exp
>> @@ -670,16 +670,59 @@ set armeabitests_nonacl {
>>       "cmse-veneers-mainline"}
>>      {"Secure gateway import library generation: errors"
>>       "--section-start .gnu.sgstubs=0x20000
>> --out-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
>> -     "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1"
>> +     "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1 --defsym VER=1"
>>       {cmse-implib.s}
>>       {{ld cmse-implib-errors.out}}
>>       "cmse-implib"}
>>      {"Secure gateway import library generation"
>>       "--section-start .gnu.sgstubs=0x20000
>> --out-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
>> -     "-march=armv8-m.base -mthumb"
>> +     "-march=armv8-m.base -mthumb --defsym VER=1"
>>       {cmse-implib.s}
>>       {{readelf {-s tmpdir/cmse-implib.lib} cmse-implib.rd}}
>>       "cmse-implib"}
>> +    {"Input secure gateway import library"
>> +     "--section-start .gnu.sgstubs=0x20000
>> --out-implib=tmpdir/cmse-new-implib.lib
>> --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
>> +     "-march=armv8-m.base -mthumb --defsym VER=2"
>> +     {cmse-implib.s}
>> +     {{ld cmse-new-implib.out}
>> +      {readelf {-s tmpdir/cmse-new-implib.lib} cmse-new-implib.rd}}
>> +     "cmse-new-implib"}
>> +    {"Input secure gateway import library: no output import library"
>> +     "--section-start .gnu.sgstubs=0x20000
>> --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
>> +     "-march=armv8-m.base -mthumb --defsym VER=2"
>> +     {cmse-implib.s}
>> +     {{ld cmse-new-implib-no-output.out}}
>> +     "cmse-new-implib-no-output"}
>> +    {"Input secure gateway import library: not an SG input import library"
>> +     "--section-start .gnu.sgstubs=0x20000
>> --in-implib=tmpdir/cmse-implib.lib" ""
>> +     "-march=armv8-m.base -mthumb --defsym VER=2"
>> +     {cmse-implib.s}
>> +     {{ld cmse-new-implib-not-sg-in-implib.out}}
>> +     "cmse-new-implib-not-sg-in-implib"}
>> +    {"Input secure gateway import library: earlier stub section base"
>> +     "--section-start .gnu.sgstubs=0x19000
>> --out-implib=tmpdir/cmse-new-earlier-implib.lib
>> --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
>> +     "-march=armv8-m.base -mthumb --defsym VER=2"
>> +     {cmse-implib.s}
>> +     {{ld cmse-new-earlier-later-implib.out}}
>> +     "cmse-new-earlier-implib"}
>> +    {"Input secure gateway import library: later stub section base"
>> +     "--section-start .gnu.sgstubs=0x30000
>> --out-implib=tmpdir/cmse-new-later-implib.lib
>> --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
>> +     "-march=armv8-m.base -mthumb --defsym VER=2"
>> +     {cmse-implib.s}
>> +     {{ld cmse-new-earlier-later-implib.out}}
>> +     "cmse-new-later-implib"}
>> +    {"Input secure gateway import library: veneer comeback"
>> +     "--section-start .gnu.sgstubs=0x20000
>> --out-implib=tmpdir/cmse-new-comeback-implib.lib
>> --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
>> +     "-march=armv8-m.base -mthumb --defsym VER=3"
>> +     {cmse-implib.s}
>> +     {{readelf {-s tmpdir/cmse-new-comeback-implib.lib}
>> cmse-new-comeback-implib.rd}}
>> +     "cmse-new-comeback-implib"}
>> +    {"Input secure gateway import library: entry function change"
>> +     "--section-start .gnu.sgstubs=0x20000
>> --out-implib=tmpdir/cmse-new-wrong-implib.lib
>> --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
>> +     "-march=armv8-m.base -mthumb --defsym VER=4"
>> +     {cmse-implib.s}
>> +     {{ld cmse-new-wrong-implib.out}}
>> +     "cmse-new-wrong-implib"}
>>
>>      {"R_ARM_THM_JUMP19 Relocation veneers: Short"
>>       "--section-start destsect=0x000108002 --section-start
>> .text=0x8000" ""
>> diff --git a/ld/testsuite/ld-arm/cmse-implib.s
>> b/ld/testsuite/ld-arm/cmse-implib.s
>> index
>> a42da63fffebe5322be83f278931754262b0f7ae..9dd783939891478351a5f7ccb1480980a77dca68
>> 100644
>> --- a/ld/testsuite/ld-arm/cmse-implib.s
>> +++ b/ld/testsuite/ld-arm/cmse-implib.s
>> @@ -20,12 +20,29 @@ __acle_se_\name:
>>  .endm
>>
>>      @ Valid setups for veneer generation
>> +.if (VER >= 2)
>> +    entry exported_entry_veneer1, global
>> +.endif
>> +.if (VER != 4)
>>      entry exported_entry_veneer2, global
>> +.else
>> +    entry exported_entry_veneer2, weak
>> +.endif
>> +.if (VER != 2)
>>      entry exported_entry_veneer3, global
>> +.endif
>> +.if (VER > 1)
>> +    entry exported_entry_veneer4, global
>> +.endif
>>
>>      @ Valid setup for entry function without veneer generation
>>      entry exported_entry_fct1, global, sg
>> +.if (VER != 4)
>>      entry exported_entry_fct2, global, sg
>> +.else
>> +    @ Invalid setup for entry function without veneer generation
>> +    entry exported_entry_fct2, global, nop
>> +.endif
>>
>>      @ Normal symbol not exported to SG import library
>>      .align    2
>> diff --git a/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd
>> b/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd
>> new file mode 100644
>> index
>> 0000000000000000000000000000000000000000..c88d9d5104244abc8ceba4d552e1ef0e400c37d1
>>
>> --- /dev/null
>> +++ b/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd
>> @@ -0,0 +1,15 @@
>> +File: tmpdir/cmse-new-.*implib.lib
>> +
>> +Symbol table '.symtab' contains 7 entries:
>> +   Num:    Value  Size Type    Bind   Vis      Ndx Name
>> +     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
>> +     1: 00020001     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer3
>> +     2: 00020011     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer4
>> +     3: 00020019     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer1
>> +     4: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
>> +     5: 00020009     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer2
>> +     6: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
>> +
>> +File: tmpdir/cmse-new-.*implib
>> +
>> +#...
>> diff --git a/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
>> b/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
>> new file mode 100644
>> index
>> 0000000000000000000000000000000000000000..b49ad0ac0770a17c39c2d119d1f0c5854a5bd8cc
>>
>> --- /dev/null
>> +++ b/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
>> @@ -0,0 +1,3 @@
>> +.*: Entry function `exported_entry_veneer3' disappeared from secure code.
>> +.*: Start address of `.gnu.sgstubs' is different from previous link.
>> +.*: cannot size stub section: Invalid operation
>> diff --git a/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
>> b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
>> new file mode 100644
>> index
>> 0000000000000000000000000000000000000000..0590b71c844da3687b29b93797abda5172ab8d99
>>
>> --- /dev/null
>> +++ b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
>> @@ -0,0 +1,4 @@
>> +.*: Entry function `exported_entry_veneer3' disappeared from secure code.
>> +.*: new entry function\(s\) introduced but no output import library
>> specified:
>> +.*:   exported_entry_veneer4
>> +.*:   exported_entry_veneer1
>> diff --git a/ld/testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out
>> b/ld/testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out
>> new file mode 100644
>> index
>> 0000000000000000000000000000000000000000..c93c3fb97895286e05026b6eac696fa9de6c89f9
>>
>> --- /dev/null
>> +++ b/ld/testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out
>> @@ -0,0 +1,2 @@
>> +.*: --in-implib only supported for Secure Gateway import libraries.
>> +.*: cannot size stub section: Invalid operation
>> diff --git a/ld/testsuite/ld-arm/cmse-new-implib.out
>> b/ld/testsuite/ld-arm/cmse-new-implib.out
>> new file mode 100644
>> index
>> 0000000000000000000000000000000000000000..c8af2807e7c1a7eeb1fc156fbf4508cf7a7e932d
>>
>> --- /dev/null
>> +++ b/ld/testsuite/ld-arm/cmse-new-implib.out
>> @@ -0,0 +1 @@
>> +.*: Entry function `exported_entry_veneer3' disappeared from secure code.
>> diff --git a/ld/testsuite/ld-arm/cmse-new-implib.rd
>> b/ld/testsuite/ld-arm/cmse-new-implib.rd
>> new file mode 100644
>> index
>> 0000000000000000000000000000000000000000..9ff0fd87937571f86f99ee940a91a3f67352242a
>>
>> --- /dev/null
>> +++ b/ld/testsuite/ld-arm/cmse-new-implib.rd
>> @@ -0,0 +1,14 @@
>> +File: tmpdir/cmse-new-.*implib.lib
>> +
>> +Symbol table '.symtab' contains 6 entries:
>> +   Num:    Value  Size Type    Bind   Vis      Ndx Name
>> +     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
>> +     1: 00020011     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer4
>> +     2: 00020019     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer1
>> +     3: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
>> +     4: 00020009     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer2
>> +     5: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
>> +
>> +File: tmpdir/cmse-new-.*implib
>> +
>> +#...
>> diff --git a/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
>> b/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
>> new file mode 100644
>> index
>> 0000000000000000000000000000000000000000..2afe4078e78606d24f05dda6ff1c5e6a54d42512
>>
>> --- /dev/null
>> +++ b/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
>> @@ -0,0 +1,3 @@
>> +.*: .*: visibility of symbol `exported_entry_veneer2' has changed.
>> +.*: `exported_entry_fct2' refers to a non entry function.
>> +.*: cannot size stub section: Invalid operation
>>
>>
>> On 17/08/16 16:12, Thomas Preudhomme wrote:
>>> Ping?
>>>
>>> Best regards,
>>>
>>> Thomas
>>>
>>> On 05/08/16 09:47, Thomas Preudhomme wrote:
>>>> Hi Richard,
>>>>
>>>> Sorry for the delay, got caught on other things. Please find an
>>>> updated patch
>>>> in attachment. All but one of your comments have been addressed,
>>>> comment below
>>>> on that one.
>>>>
>>>> Updated ChangeLog entries are as follow:
>>>>
>>>> *** bfd/ChangeLog ***
>>>>
>>>> 2016-07-08  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>>
>>>>         * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new
>>>> parameter for
>>>>         the input import library bfd.
>>>>         * bfd-in2.h: Regenerate.
>>>>         * elf32-arm.c (struct elf32_arm_link_hash_table): New
>>>> in_implib_bfd
>>>>         and new_cmse_stub_offset fields.
>>>>         (stub_hash_newfunc): Initialize stub_offset and
>>>> stub_template_size to
>>>>         -1.
>>>>         (elf32_arm_add_stub): Likewise for stub_offset.
>>>>         (arm_new_stubs_start_offset_ptr): New function.
>>>>         (arm_build_one_stub): Only allocate a stub_offset if it is
>>>> -1.  Allow
>>>>         empty SG veneers to have zero relocations.
>>>>         (arm_size_one_stub): Only initialize stub size and template
>>>>         information for non empty veneers.  Do not update veneer
>>>> section size
>>>>         if veneer already has an offset.
>>>>         (elf32_arm_create_stub): Return the stub entry pointer or
>>>> NULL instead
>>>>         of a boolean indicating success or failure.
>>>>         (cmse_scan): Change stub_changed parameter into an integer
>>>> pointer
>>>>         parameter cmse_stub_created to count the number of stub
>>>> created and
>>>>         adapt to change of return value in elf32_arm_create_stub.
>>>>         (cmse_entry_fct_p): New function.
>>>>         (arm_list_new_cmse_stub): Likewise.
>>>>         (set_cmse_veneer_addr_from_implib): Likewise.
>>>>         (elf32_arm_size_stubs): Define cmse_stub_created, pass its
>>>> address to
>>>>         cmse_scan instead of that of cmse_stub_changed to compute the
>>>> number
>>>>         of stub created and use it to initialize stub_changed.  Call
>>>>         set_cmse_veneer_addr_from_implib after all cmse_scan.  Adapt
>>>> to change
>>>>         of return value in elf32_arm_create_stub.  Use
>>>>         arm_stub_section_start_offset () if not NULL to initialize
>>>> size of
>>>>         secure gateway veneers section.  Initialize stub_offset of
>>>> Cortex-A8
>>>>         erratum fix to -1.  Use ret to hold return value.
>>>>         (elf32_arm_build_stubs): Use arm_stub_section_start_offset ()
>>>> if not
>>>>         NULL to initialize size of secure gateway veneers section.
>>>> Adapt
>>>>         comment to stress the importance of zeroing veneer section
>>>> content.
>>>>         (bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd
>>>> parameter to
>>>>         initialize eponymous field in struct elf32_arm_link_hash_table.
>>>>
>>>>
>>>> *** ld/ChangeLog ***
>>>>
>>>> 2016-07-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>>
>>>>         * emultempl/armelf.em (in_implib_filename): Declare and
>>>> initialize new
>>>>         variable.
>>>>         (arm_elf_create_output_section_statements): Open import input
>>>> library
>>>>         file for writing and pass resulting in_implib_bfd to
>>>>         bfd_elf32_arm_set_target_relocs.
>>>>         (PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option.
>>>>         (PARSE_AND_LIST_LONGOPTS): Define --in-implib option.
>>>>         (PARSE_AND_LIST_OPTIONS): Add help message for --in-implib
>>>> option.
>>>>         (PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case.
>>>>         * ld.texinfo (--cmse-implib): Update to mention --in-implib.
>>>>         (--in-implib): Document new option.
>>>>         * NEWS: Likewise.
>>>>         * testsuite/ld-arm/arm-elf.exp
>>>>         (Secure gateway import library generation): add --defsym
>>>> VER=1 to gas
>>>>         CLI.
>>>>         (Secure gateway import library generation: errors): Likewise.
>>>>         (Input secure gateway import library): New test.
>>>>         (Input secure gateway import library: no output import library):
>>>>         Likewise.
>>>>         (Input secure gateway import library: not an SG input import
>>>> library):
>>>>         Likewise.
>>>>         (Input secure gateway import library: earlier stub section
>>>> base):
>>>>         Likewise.
>>>>         (Input secure gateway import library: later stub section base):
>>>>         Likewise.
>>>>         (Input secure gateway import library: veneer comeback):
>>>> Likewise.
>>>>         (Input secure gateway import library: entry function change):
>>>>         Likewise.
>>>>         * testsuite/ld-arm/cmse-implib.s: Add input import library
>>>> testing.
>>>>         * testsuite/ld-arm/cmse-implib.rd: Update accordingly.
>>>>         * testsuite/ld-arm/cmse-new-implib.out: New file.
>>>>         * testsuite/ld-arm/cmse-new-implib.rd: Likewise.
>>>>         * testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise.
>>>>         * testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out:
>>>> Likewise.
>>>>         * testsuite/ld-arm/cmse-new-earlier-later-implib.out: Likewise.
>>>>         * testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise.
>>>>         * testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise.
>>>>
>>>> On Thursday 07 July 2016 13:52:00 you wrote:
>>>>> On 04/04/16 15:22, Thomas Preudhomme wrote:
>>>>>> On Wednesday 23 December 2015 16:02:48 Thomas Preud'homme wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> [Posting patch series as RFC]
>>>>>>>
>>>>>>> This patch is part of a patch series to add support for ARMv8-M
>>>>>>> security
>>>>>>> extension[1] to GNU ld. This specific patch adds support for allowing
>>>>>>> Secure Gateway veneers to have stable addresses when relinking a
>>>>>>> secure
>>>>>>> executable.
>>>>>>>
>>>>>>> ARM v8-M security extensions allow code running in a device to be
>>>>>>> divided
>>>>>>> into secure and non-secure code expected to be developed by
>>>>>>> independent
>>>>>>> (teams of) people. To allow updating the secure code without the
>>>>>>> need to
>>>>>>> relink the non-secure code against it, it is necessary for the
>>>>>>> toolchain
>>>>>>> to
>>>>>>> provide a way to fix the addresses of the secure gateway veneers that
>>>>>>> serve
>>>>>>> as entry points for non-secure code to call secure code. This is
>>>>>>> also a
>>>>>>> requirement [2] to claim support for ARM v8-M security extensions.
>>>>>>>
>>>>>>> This patch adds a --in-implib=<in_implib_filename> option which, when
>>>>>>> used
>>>>>>> in conjunction of --cmse-implib will ensure that the veneers whose
>>>>>>> symbols
>>>>>>> are defined in the import library $in_implib_filename will remain
>>>>>>> at the
>>>>>>> same address in the executable. In the absence of a --out-implib
>>>>>>> option,
>>>>>>> the code will warn about new secure gateway veneers being created,
>>>>>>> otherwise these are allowed.
>>>>>>>
>>>>>>>
>>>>>>> [1] Software requirements for ARMv8-M security extension are
>>>>>>> described in
>>>>>>> document ARM-ECM-0359818 [2] [2] Available on
>>>>>>> http://infocenter.arm.com
>>>>>>> in
>>>>>>> Developer guides and articles > Software development > ARM®v8-M
>>>>>>> Security
>>>>>>> Extensions: Requirements on Development Tools [3] See requirement
>>>>>>> 15 of
>>>>>>> ARM-ECM-0359818 [2]
>>>>>>
>>>>>> Please find an updated patch below.
>>>>>
>>>>> Comments inline.
>>>>>
>>>>>> *** bfd/ChangeLog ***
>>>>>>
>>>>>> 2016-02-18  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>>>>
>>>>>>         * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new
>>>>>> parameter
>>>>>>         for
>>>>>>         the input import library bfd.
>>>>>>         * bfd-in2.h: Regenerate.
>>>>>>         * elf32-arm.c (struct elf32_arm_link_hash_table): New
>>>>>>         in_implib_bfd
>>>>>>         and new_cmse_stub_offset fields.
>>>>>>         (stub_hash_newfunc): Initialize stub_offset and
>>>>>> stub_template_size
>>>>>>         to
>>>>>>         -1.
>>>>>>         (elf32_arm_add_stub): Likewise for stub_offset.
>>>>>>         (arm_new_stubs_start_offset_ptr): New function.
>>>>>>         (arm_build_one_stub): Only allocate a stub_offset if it is -1.
>>>>>>         Allow
>>>>>>         empty veneers to have zero relocations.
>>>>>>         (arm_size_one_stub): Only initialize stub size and template
>>>>>>         information for non empty veneers.  Do not update veneer
>>>>>> section
>>>>>>         size
>>>>>>         if veneer already has an offset.
>>>>>>         (elf32_arm_create_stub): Return the stub entry pointer or NULL
>>>>>>         instead
>>>>>>         of a boolean indicating success or failure.
>>>>>>         (cmse_scan): Change stub_changed parameter into an integer
>>>>>> pointer
>>>>>>         parameter cmse_stub_created to count the number of stub
>>>>>> created
>>>>>>         and
>>>>>>         adapt to change of return value in elf32_arm_create_stub.
>>>>>>         (cmse_entry_fct_p): New function.
>>>>>>         (arm_list_new_cmse_stub): Likewise.
>>>>>>         (set_cmse_veneer_addr_from_implib): Likewise.
>>>>>>         (elf32_arm_size_stubs): Define cmse_stub_created, pass its
>>>>>> address
>>>>>>         to
>>>>>>         cmse_scan instead of that of cmse_stub_changed to compute the
>>>>>>         number
>>>>>>         of stub created and use it to initialize stub_changed.  Call
>>>>>>         set_cmse_veneer_addr_from_implib after all cmse_scan.
>>>>>> Adapt to
>>>>>>         change
>>>>>>         of return value in elf32_arm_create_stub.  Use
>>>>>>         arm_stub_section_start_offset () if not NULL to initialize
>>>>>> size of
>>>>>>         secure gateway veneers section.  Initialize stub_offset of
>>>>>>         Cortex-A8
>>>>>>         erratum fix to -1.  Use ret to hold return value.
>>>>>>         (elf32_arm_build_stubs): Use arm_stub_section_start_offset
>>>>>> () if
>>>>>>         not
>>>>>>         NULL to initialize size of secure gateway veneers section.
>>>>>> Adapt
>>>>>>         comment to stress the importance of zeroing veneer section
>>>>>>         content.
>>>>>>         (bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd
>>>>>> parameter
>>>>>>         to
>>>>>>         initialize eponymous field in struct
>>>>>> elf32_arm_link_hash_table.
>>>>>>
>>>>>> *** ld/ChangeLog ***
>>>>>>
>>>>>> 2016-02-18  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>>>>
>>>>>>         * emultempl/armelf.em (in_implib_filename): Declare and
>>>>>> initialize
>>>>>>         new
>>>>>>         variable.
>>>>>>         (arm_elf_create_output_section_statements): Open import input
>>>>>>         library
>>>>>>         file for writing and pass resulting in_implib_bfd to
>>>>>>         bfd_elf32_arm_set_target_relocs.
>>>>>>         (PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option.
>>>>>>         (PARSE_AND_LIST_LONGOPTS): Define --in-implib option.
>>>>>>         (PARSE_AND_LIST_OPTIONS): Add help message for --in-implib
>>>>>> option.
>>>>>>         (PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case.
>>>>>>         * ld.texinfo (--cmse-implib): Update to mention --in-implib.
>>>>>>         (--in-implib): Document new option.
>>>>>>         * testsuite/ld-arm/arm-elf.exp
>>>>>>         (Secure gateway import library generation): add --defsym
>>>>>> VER=1 to
>>>>>>         gas
>>>>>>         CLI.
>>>>>>         (Secure gateway import library generation: errors): Likewise.
>>>>>>         (Input secure gateway import library): New test.
>>>>>>         (Input secure gateway import library: no output import
>>>>>> library):
>>>>>>         Likewise.
>>>>>>         (Input secure gateway import library: earlier stub section
>>>>>> base):
>>>>>>         Likewise.
>>>>>>         (Input secure gateway import library: later stub section
>>>>>> base):
>>>>>>         Likewise.
>>>>>>         (Input secure gateway import library: veneer comeback):
>>>>>> Likewise.
>>>>>>         (Input secure gateway import library: entry function change):
>>>>>>         Likewise.
>>>>>>         * testsuite/ld-arm/cmse-implib.s: Add input import library
>>>>>>         testing.
>>>>>>         * testsuite/ld-arm/cmse-implib.rd: Update accordingly.
>>>>>>         * testsuite/ld-arm/cmse-new-implib.out: New file.
>>>>>>         * testsuite/ld-arm/cmse-new-implib.rd: Likewise.
>>>>>>         * testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise.
>>>>>>         * testsuite/ld-arm/cmse-new-earlier-later-implib.out:
>>>>>> Likewise.
>>>>>>         * testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise.
>>>>>>         * testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise.
>>>>>>
>>>>>> diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
>>>>>> index
>>>>>> 7e3483b9984b04c534e53f2f9026abf26d37592a..423c534a954c541e227e731e9256f08f
>>>>>>
>>>>>> 9fa62014 100644
>>>>>> --- a/bfd/bfd-in.h
>>>>>> +++ b/bfd/bfd-in.h
>>>>>> @@ -895,7 +895,7 @@ extern bfd_boolean
>>>>>> bfd_elf32_arm_process_before_allocation>
>>>>>>  void bfd_elf32_arm_set_target_relocs
>>>>>>
>>>>>>    (bfd *, struct bfd_link_info *, int, char *, int, int,
>>>>>>    bfd_arm_vfp11_fix,
>>>>>>
>>>>>> -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
>>>>>> +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
>>>>>>
>>>>>>  extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
>>>>>>
>>>>>>    (bfd *, struct bfd_link_info *);
>>>>>>
>>>>>> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
>>>>>> index
>>>>>> 55e1cdde2d0a899238a224c6915d20197b72f085..3a67fa637f5c709cddf3767496e4ac87
>>>>>>
>>>>>> 96287765 100644
>>>>>> --- a/bfd/bfd-in2.h
>>>>>> +++ b/bfd/bfd-in2.h
>>>>>> @@ -902,7 +902,7 @@ extern bfd_boolean
>>>>>> bfd_elf32_arm_process_before_allocation>
>>>>>>  void bfd_elf32_arm_set_target_relocs
>>>>>>
>>>>>>    (bfd *, struct bfd_link_info *, int, char *, int, int,
>>>>>>    bfd_arm_vfp11_fix,
>>>>>>
>>>>>> -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
>>>>>> +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
>>>>>
>>>>> This is *only* one more parameter to this function, but it now takes
>>>>> 15,
>>>>> which seems excessive.
>>>>>
>>>>> Some redesign may be in order here...
>>>>
>>>> Ok. I did a separate patch for this as I felt this was an independent
>>>> change
>>>> and would have made the patch even bigger. I'll post it soon.
>>>>
>>>> Best regards,
>>>>
>>>> Thomas
>>>>
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ARM 11/11, ping] Add support for stable secure gateway veneers addresses
  2016-08-25 16:35             ` Thomas Preudhomme
@ 2016-08-26  9:21               ` Richard Earnshaw (lists)
       [not found]                 ` <CAKdteOZ4uC=dOKO5WoysePRT1is9rvX4etjgj1iK5Hj23TSdLw@mail.gmail.com>
  0 siblings, 1 reply; 15+ messages in thread
From: Richard Earnshaw (lists) @ 2016-08-26  9:21 UTC (permalink / raw)
  To: Thomas Preudhomme, binutils

On 25/08/16 17:35, Thomas Preudhomme wrote:
> Hi Richard,
> 
> On 25/08/16 17:14, Richard Earnshaw (lists) wrote:
>> On 17/08/16 16:23, Thomas Preudhomme wrote:
>>> [Trying again with inline patch since previous attempt got flagged as
>>> spam]
>>>
>>
>> You're missing the ChangeLog entry, but I'll take it that it's still the
>> same as last time.
> 
> Sorry, I forgot to copy the message I sent with the patch in my first
> attempt. I paste it below and will wait that you confirm you are happy
> with the updated ChangeLog entries.
> 
> 

This is fine.

R.

> Sorry for the delay, got caught on other things. Please find an updated
> patch
> in attachment. All but one of your comments have been addressed, comment
> below
> on that one.
> 
> Updated ChangeLog entries are as follow:
> 
> *** bfd/ChangeLog ***
> 
> 2016-07-08  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> 
>         * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new
> parameter for
>         the input import library bfd.
>         * bfd-in2.h: Regenerate.
>         * elf32-arm.c (struct elf32_arm_link_hash_table): New in_implib_bfd
>         and new_cmse_stub_offset fields.
>         (stub_hash_newfunc): Initialize stub_offset and
> stub_template_size to
>         -1.
>         (elf32_arm_add_stub): Likewise for stub_offset.
>         (arm_new_stubs_start_offset_ptr): New function.
>         (arm_build_one_stub): Only allocate a stub_offset if it is -1. 
> Allow
>         empty SG veneers to have zero relocations.
>         (arm_size_one_stub): Only initialize stub size and template
>         information for non empty veneers.  Do not update veneer section
> size
>         if veneer already has an offset.
>         (elf32_arm_create_stub): Return the stub entry pointer or NULL
> instead
>         of a boolean indicating success or failure.
>         (cmse_scan): Change stub_changed parameter into an integer pointer
>         parameter cmse_stub_created to count the number of stub created and
>         adapt to change of return value in elf32_arm_create_stub.
>         (cmse_entry_fct_p): New function.
>         (arm_list_new_cmse_stub): Likewise.
>         (set_cmse_veneer_addr_from_implib): Likewise.
>         (elf32_arm_size_stubs): Define cmse_stub_created, pass its
> address to
>         cmse_scan instead of that of cmse_stub_changed to compute the
> number
>         of stub created and use it to initialize stub_changed.  Call
>         set_cmse_veneer_addr_from_implib after all cmse_scan.  Adapt to
> change
>         of return value in elf32_arm_create_stub.  Use
>         arm_stub_section_start_offset () if not NULL to initialize size of
>         secure gateway veneers section.  Initialize stub_offset of
> Cortex-A8
>         erratum fix to -1.  Use ret to hold return value.
>         (elf32_arm_build_stubs): Use arm_stub_section_start_offset () if
> not
>         NULL to initialize size of secure gateway veneers section.  Adapt
>         comment to stress the importance of zeroing veneer section content.
>         (bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd
> parameter to
>         initialize eponymous field in struct elf32_arm_link_hash_table.
> 
> 
> *** ld/ChangeLog ***
> 
> 2016-07-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> 
>         * emultempl/armelf.em (in_implib_filename): Declare and
> initialize new
>         variable.
>         (arm_elf_create_output_section_statements): Open import input
> library
>         file for writing and pass resulting in_implib_bfd to
>         bfd_elf32_arm_set_target_relocs.
>         (PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option.
>         (PARSE_AND_LIST_LONGOPTS): Define --in-implib option.
>         (PARSE_AND_LIST_OPTIONS): Add help message for --in-implib option.
>         (PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case.
>         * ld.texinfo (--cmse-implib): Update to mention --in-implib.
>         (--in-implib): Document new option.
>         * NEWS: Likewise.
>         * testsuite/ld-arm/arm-elf.exp
>         (Secure gateway import library generation): add --defsym VER=1
> to gas
>         CLI.
>         (Secure gateway import library generation: errors): Likewise.
>         (Input secure gateway import library): New test.
>         (Input secure gateway import library: no output import library):
>         Likewise.
>         (Input secure gateway import library: not an SG input import
> library):
>         Likewise.
>         (Input secure gateway import library: earlier stub section base):
>         Likewise.
>         (Input secure gateway import library: later stub section base):
>         Likewise.
>         (Input secure gateway import library: veneer comeback): Likewise.
>         (Input secure gateway import library: entry function change):
>         Likewise.
>         * testsuite/ld-arm/cmse-implib.s: Add input import library testing.
>         * testsuite/ld-arm/cmse-implib.rd: Update accordingly.
>         * testsuite/ld-arm/cmse-new-implib.out: New file.
>         * testsuite/ld-arm/cmse-new-implib.rd: Likewise.
>         * testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise.
>         * testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out: Likewise.
>         * testsuite/ld-arm/cmse-new-earlier-later-implib.out: Likewise.
>         * testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise.
>         * testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise.
> 
>>
>> OK.
>>
>> R.
>>
>>> diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
>>> index
>>> d33bb8267b12d9cd2c942d3c502e3e563e63d09f..f9bce9fd3ef778429ea9c1416ca2ffcab3f4e374
>>>
>>> 100644
>>> --- a/bfd/bfd-in.h
>>> +++ b/bfd/bfd-in.h
>>> @@ -894,7 +894,7 @@ extern bfd_boolean
>>> bfd_elf32_arm_process_before_allocation
>>>
>>>  void bfd_elf32_arm_set_target_relocs
>>>    (bfd *, struct bfd_link_info *, int, char *, int, int,
>>> bfd_arm_vfp11_fix,
>>> -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
>>> +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
>>>
>>>  extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
>>>    (bfd *, struct bfd_link_info *);
>>> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
>>> index
>>> cc8428a21d8ce3267420c76a4328fb6d433cd597..8b1d8a01adf529ee42ad6673c82a5028aed5774c
>>>
>>> 100644
>>> --- a/bfd/bfd-in2.h
>>> +++ b/bfd/bfd-in2.h
>>> @@ -901,7 +901,7 @@ extern bfd_boolean
>>> bfd_elf32_arm_process_before_allocation
>>>
>>>  void bfd_elf32_arm_set_target_relocs
>>>    (bfd *, struct bfd_link_info *, int, char *, int, int,
>>> bfd_arm_vfp11_fix,
>>> -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
>>> +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
>>>
>>>  extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
>>>    (bfd *, struct bfd_link_info *);
>>> diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
>>> index
>>> 1eba21b42ddfaf3704860107e4fff36dbbc24d8d..539c2aacbd6b47b25288d3b3e691b90806863856
>>>
>>> 100644
>>> --- a/bfd/elf32-arm.c
>>> +++ b/bfd/elf32-arm.c
>>> @@ -3148,6 +3148,10 @@ struct elf32_arm_link_hash_table
>>>       as per ARMv8-M Security Extensions.  */
>>>    int cmse_implib;
>>>
>>> +  /* The import library whose symbols' address must remain stable in
>>> +     the import library generated.  */
>>> +  bfd *in_implib_bfd;
>>> +
>>>    /* The index of the next unused R_ARM_TLS_DESC slot in .rel.plt.  */
>>>    bfd_vma next_tls_desc_index;
>>>
>>> @@ -3209,6 +3213,10 @@ struct elf32_arm_link_hash_table
>>>    /* Input stub section holding secure gateway veneers.  */
>>>    asection *cmse_stub_sec;
>>>
>>> +  /* Offset in cmse_stub_sec where new SG veneers (not in input import
>>> library)
>>> +     start to be allocated.  */
>>> +  bfd_vma new_cmse_stub_offset;
>>> +
>>>    /* Number of elements in stub_group.  */
>>>    unsigned int top_id;
>>>
>>> @@ -3460,7 +3468,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
>>>        /* Initialize the local fields.  */
>>>        eh = (struct elf32_arm_stub_hash_entry *) entry;
>>>        eh->stub_sec = NULL;
>>> -      eh->stub_offset = 0;
>>> +      eh->stub_offset = (bfd_vma) -1;
>>>        eh->source_value = 0;
>>>        eh->target_value = 0;
>>>        eh->target_section = NULL;
>>> @@ -3468,7 +3476,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
>>>        eh->stub_type = arm_stub_none;
>>>        eh->stub_size = 0;
>>>        eh->stub_template = NULL;
>>> -      eh->stub_template_size = 0;
>>> +      eh->stub_template_size = -1;
>>>        eh->h = NULL;
>>>        eh->id_sec = NULL;
>>>        eh->output_name = NULL;
>>> @@ -4467,7 +4475,7 @@ elf32_arm_add_stub (const char *stub_name,
>>> asection *section,
>>>      }
>>>
>>>    stub_entry->stub_sec = stub_sec;
>>> -  stub_entry->stub_offset = 0;
>>> +  stub_entry->stub_offset = (bfd_vma) -1;
>>>    stub_entry->id_sec = link_sec;
>>>
>>>    return stub_entry;
>>> @@ -4633,11 +4641,31 @@ arm_dedicated_stub_section_padding (enum
>>> elf32_arm_stub_type stub_type)
>>>    abort ();  /* Should be unreachable.  */
>>>  }
>>>
>>> +/* If veneers of type STUB_TYPE should go in a dedicated output
>>> section,
>>> +   returns the address of the hash table field in HTAB holding the
>>> offset at
>>> +   which new veneers should be layed out in the stub section.  */
>>> +
>>> +static bfd_vma*
>>> +arm_new_stubs_start_offset_ptr (struct elf32_arm_link_hash_table *htab,
>>> +                enum elf32_arm_stub_type stub_type)
>>> +{
>>> +  switch (stub_type)
>>> +    {
>>> +    case arm_stub_cmse_branch_thumb_only:
>>> +      return &htab->new_cmse_stub_offset;
>>> +
>>> +    default:
>>> +      BFD_ASSERT (!arm_dedicated_stub_output_section_required
>>> (stub_type));
>>> +      return NULL;
>>> +    }
>>> +}
>>> +
>>>  static bfd_boolean
>>>  arm_build_one_stub (struct bfd_hash_entry *gen_entry,
>>>              void * in_arg)
>>>  {
>>>  #define MAXRELOCS 3
>>> +  bfd_boolean removed_sg_veneer;
>>>    struct elf32_arm_stub_hash_entry *stub_entry;
>>>    struct elf32_arm_link_hash_table *globals;
>>>    struct bfd_link_info *info;
>>> @@ -4652,6 +4680,7 @@ arm_build_one_stub (struct bfd_hash_entry
>>> *gen_entry,
>>>    int stub_reloc_idx[MAXRELOCS] = {-1, -1};
>>>    int stub_reloc_offset[MAXRELOCS] = {0, 0};
>>>    int nrelocs = 0;
>>> +  int just_allocated = 0;
>>>
>>>    /* Massage our args to the form they really have.  */
>>>    stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
>>> @@ -4668,8 +4697,12 @@ arm_build_one_stub (struct bfd_hash_entry
>>> *gen_entry,
>>>      /* We have to do less-strictly-aligned fixes last.  */
>>>      return TRUE;
>>>
>>> -  /* Make a note of the offset within the stubs for this entry.  */
>>> -  stub_entry->stub_offset = stub_sec->size;
>>> +  /* Assign a slot at the end of section if none assigned yet.  */
>>> +  if (stub_entry->stub_offset == (bfd_vma) -1)
>>> +    {
>>> +      stub_entry->stub_offset = stub_sec->size;
>>> +      just_allocated = 1;
>>> +    }
>>>    loc = stub_sec->contents + stub_entry->stub_offset;
>>>
>>>    stub_bfd = stub_sec->owner;
>>> @@ -4743,7 +4776,8 @@ arm_build_one_stub (struct bfd_hash_entry
>>> *gen_entry,
>>>      }
>>>      }
>>>
>>> -  stub_sec->size += size;
>>> +  if (just_allocated)
>>> +    stub_sec->size += size;
>>>
>>>    /* Stub size has already been computed in arm_size_one_stub. Check
>>>       consistency.  */
>>> @@ -4753,9 +4787,11 @@ arm_build_one_stub (struct bfd_hash_entry
>>> *gen_entry,
>>>    if (stub_entry->branch_type == ST_BRANCH_TO_THUMB)
>>>      sym_value |= 1;
>>>
>>> -  /* Assume there is at least one and at most MAXRELOCS entries to
>>> relocate
>>> -     in each stub.  */
>>> -  BFD_ASSERT (nrelocs != 0 && nrelocs <= MAXRELOCS);
>>> +  /* Assume non empty slots have at least one and at most MAXRELOCS
>>> entries
>>> +     to relocate in each stub.  */
>>> +  removed_sg_veneer =
>>> +    (size == 0 && stub_entry->stub_type ==
>>> arm_stub_cmse_branch_thumb_only);
>>> +  BFD_ASSERT (removed_sg_veneer || (nrelocs != 0 && nrelocs <=
>>> MAXRELOCS));
>>>
>>>    for (i = 0; i < nrelocs; i++)
>>>      {
>>> @@ -4857,9 +4893,17 @@ arm_size_one_stub (struct bfd_hash_entry
>>> *gen_entry,
>>>    size = find_stub_size_and_template (stub_entry->stub_type,
>>> &template_sequence,
>>>                        &template_size);
>>>
>>> -  stub_entry->stub_size = size;
>>> -  stub_entry->stub_template = template_sequence;
>>> -  stub_entry->stub_template_size = template_size;
>>> +  /* Initialized to -1.  Null size indicates an empty slot full of
>>> zeros.  */
>>> +  if (stub_entry->stub_template_size)
>>> +    {
>>> +      stub_entry->stub_size = size;
>>> +      stub_entry->stub_template = template_sequence;
>>> +      stub_entry->stub_template_size = template_size;
>>> +    }
>>> +
>>> +  /* Already accounted for.  */
>>> +  if (stub_entry->stub_offset != (bfd_vma) -1)
>>> +    return TRUE;
>>>
>>>    size = (size + 7) & ~7;
>>>    stub_entry->stub_sec->size += size;
>>> @@ -5424,10 +5468,10 @@ cortex_a8_erratum_scan (bfd *input_bfd,
>>>     and *NEW_STUB is set to FALSE.  Otherwise, *NEW_STUB is set to
>>>     TRUE and the stub entry is initialized.
>>>
>>> -   Returns whether the stub could be successfully created or updated,
>>> or FALSE
>>> -   if an error occured.  */
>>> +   Returns the stub that was created or updated, or NULL if an error
>>> +   occurred.  */
>>>
>>> -static bfd_boolean
>>> +static struct elf32_arm_stub_hash_entry *
>>>  elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
>>>                 enum elf32_arm_stub_type stub_type, asection *section,
>>>                 Elf_Internal_Rela *irela, asection *sym_sec,
>>> @@ -5458,7 +5502,7 @@ elf32_arm_create_stub (struct
>>> elf32_arm_link_hash_table *htab,
>>>        stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash, irela,
>>>                         stub_type);
>>>        if (!stub_name)
>>> -    return FALSE;
>>> +    return NULL;
>>>      }
>>>
>>>    stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, stub_name,
>>> FALSE,
>>> @@ -5469,7 +5513,7 @@ elf32_arm_create_stub (struct
>>> elf32_arm_link_hash_table *htab,
>>>        if (!sym_claimed)
>>>      free (stub_name);
>>>        stub_entry->target_value = sym_value;
>>> -      return TRUE;
>>> +      return stub_entry;
>>>      }
>>>
>>>    stub_entry = elf32_arm_add_stub (stub_name, section, htab,
>>> stub_type);
>>> @@ -5477,7 +5521,7 @@ elf32_arm_create_stub (struct
>>> elf32_arm_link_hash_table *htab,
>>>      {
>>>        if (!sym_claimed)
>>>      free (stub_name);
>>> -      return FALSE;
>>> +      return NULL;
>>>      }
>>>
>>>    stub_entry->target_value = sym_value;
>>> @@ -5498,7 +5542,7 @@ elf32_arm_create_stub (struct
>>> elf32_arm_link_hash_table *htab,
>>>        if (stub_entry->output_name == NULL)
>>>      {
>>>        free (stub_name);
>>> -      return FALSE;
>>> +      return NULL;
>>>      }
>>>
>>>        /* For historical reasons, use the existing names for
>>> ARM-to-Thumb and
>>> @@ -5518,7 +5562,7 @@ elf32_arm_create_stub (struct
>>> elf32_arm_link_hash_table *htab,
>>>      }
>>>
>>>    *new_stub = TRUE;
>>> -  return TRUE;
>>> +  return stub_entry;
>>>  }
>>>
>>>  /* Scan symbols in INPUT_BFD to identify secure entry functions
>>> needing a
>>> @@ -5537,14 +5581,15 @@ elf32_arm_create_stub (struct
>>> elf32_arm_link_hash_table *htab,
>>>
>>>     OUT_ATTR gives the output attributes, SYM_HASHES the symbol index to
>>> hash
>>>     entry mapping while HTAB gives the name to hash entry mapping.
>>> +   *CMSE_STUB_CREATED is increased by the number of secure gateway
>>> veneer
>>> +   created.
>>>
>>> -   If any secure gateway veneer is created, *STUB_CHANGED is set to
>>> TRUE.  The
>>> -   return value gives whether a stub failed to be allocated.  */
>>> +   The return value gives whether a stub failed to be allocated.  */
>>>
>>>  static bfd_boolean
>>>  cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
>>>         obj_attribute *out_attr, struct elf_link_hash_entry
>>> **sym_hashes,
>>> -       bfd_boolean *stub_changed)
>>> +       int *cmse_stub_created)
>>>  {
>>>    const struct elf_backend_data *bed;
>>>    Elf_Internal_Shdr *symtab_hdr;
>>> @@ -5555,7 +5600,8 @@ cmse_scan (bfd *input_bfd, struct
>>> elf32_arm_link_hash_table *htab,
>>>    char *sym_name, *lsym_name;
>>>    bfd_vma sym_value;
>>>    asection *section;
>>> -  bfd_boolean is_v8m, new_stub, created_stub, cmse_invalid, ret = TRUE;
>>> +  struct elf32_arm_stub_hash_entry *stub_entry;
>>> +  bfd_boolean is_v8m, new_stub, cmse_invalid, ret = TRUE;
>>>
>>>    bed = get_elf_backend_data (input_bfd);
>>>    symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
>>> @@ -5700,17 +5746,17 @@ cmse_scan (bfd *input_bfd, struct
>>> elf32_arm_link_hash_table *htab,
>>>        if (!ret)
>>>      continue;
>>>        branch_type = ARM_GET_SYM_BRANCH_TYPE
>>> (hash->root.target_internal);
>>> -      created_stub
>>> +      stub_entry
>>>      = elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
>>>                   NULL, NULL, section, hash, sym_name,
>>>                   sym_value, branch_type, &new_stub);
>>>
>>> -      if (!created_stub)
>>> +      if (stub_entry == NULL)
>>>       ret = FALSE;
>>>        else
>>>      {
>>>        BFD_ASSERT (new_stub);
>>> -      *stub_changed = TRUE;
>>> +      (*cmse_stub_created)++;
>>>      }
>>>      }
>>>
>>> @@ -5719,6 +5765,279 @@ cmse_scan (bfd *input_bfd, struct
>>> elf32_arm_link_hash_table *htab,
>>>    return ret;
>>>  }
>>>
>>> +/* Return TRUE iff a symbol identified by its linker HASH entry is a
>>> secure
>>> +   code entry function, ie can be called from non secure code without
>>> using a
>>> +   veneer.  */
>>> +
>>> +static bfd_boolean
>>> +cmse_entry_fct_p (struct elf32_arm_link_hash_entry *hash)
>>> +{
>>> +  uint32_t first_insn;
>>> +  asection *section;
>>> +  file_ptr offset;
>>> +  bfd *abfd;
>>> +
>>> +  /* Defined symbol of function type.  */
>>> +  if (hash->root.root.type != bfd_link_hash_defined
>>> +      && hash->root.root.type != bfd_link_hash_defweak)
>>> +    return FALSE;
>>> +  if (hash->root.type != STT_FUNC)
>>> +    return FALSE;
>>> +
>>> +  /* Read first instruction.  */
>>> +  section = hash->root.root.u.def.section;
>>> +  abfd = section->owner;
>>> +  offset = hash->root.root.u.def.value - section->vma;
>>> +  if (!bfd_get_section_contents (abfd, section, &first_insn, offset,
>>> +                 sizeof (first_insn)))
>>> +    return FALSE;
>>> +
>>> +  /* Start by SG instruction.  */
>>> +  return first_insn == 0xe97fe97f;
>>> +}
>>> +
>>> +/* Output the name (in symbol table) of the veneer GEN_ENTRY if it is a
>>> new
>>> +   secure gateway veneers (ie. the veneers was not in the input import
>>> library)
>>> +   and there is no output import library (GEN_INFO->out_implib_bfd is
>>> NULL.  */
>>> +
>>> +static bfd_boolean
>>> +arm_list_new_cmse_stub (struct bfd_hash_entry *gen_entry, void
>>> *gen_info)
>>> +{
>>> +  struct elf32_arm_stub_hash_entry *stub_entry;
>>> +  struct bfd_link_info *info;
>>> +
>>> +  /* Massage our args to the form they really have.  */
>>> +  stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
>>> +  info = (struct bfd_link_info *) gen_info;
>>> +
>>> +  if (info->out_implib_bfd)
>>> +    return TRUE;
>>> +
>>> +  if (stub_entry->stub_type != arm_stub_cmse_branch_thumb_only)
>>> +    return TRUE;
>>> +
>>> +  if (stub_entry->stub_offset == (bfd_vma) -1)
>>> +    (*_bfd_error_handler) ("  %s", stub_entry->output_name);
>>> +
>>> +  return TRUE;
>>> +}
>>> +
>>> +/* Set offset of each secure gateway veneers so that its address remain
>>> +   identical to the one in the input import library referred by
>>> +   HTAB->in_implib_bfd.  A warning is issued for veneers that
>>> disappeared
>>> +   (present in input import library but absent from the executable
>>> being
>>> +   linked) or if new veneers appeared and there is no output import
>>> library
>>> +   (INFO->out_implib_bfd is NULL and *CMSE_STUB_CREATED is bigger
>>> than the
>>> +   number of secure gateway veneers found in the input import library.
>>> +
>>> +   The function returns whether an error occurred.  If no error
>>> occurred,
>>> +   *CMSE_STUB_CREATED gives the number of SG veneers created by both
>>> cmse_scan
>>> +   and this function and HTAB->new_cmse_stub_offset is set to the
>>> biggest
>>> +   veneer observed set for new veneers to be layed out after.  */
>>> +
>>> +static bfd_boolean
>>> +set_cmse_veneer_addr_from_implib (struct bfd_link_info *info,
>>> +                  struct elf32_arm_link_hash_table *htab,
>>> +                  int *cmse_stub_created)
>>> +{
>>> +  long symsize;
>>> +  char *sym_name;
>>> +  flagword flags;
>>> +  long i, symcount;
>>> +  bfd *in_implib_bfd;
>>> +  asection *stub_out_sec;
>>> +  bfd_boolean ret = TRUE;
>>> +  Elf_Internal_Sym *intsym;
>>> +  const char *out_sec_name;
>>> +  bfd_size_type cmse_stub_size;
>>> +  asymbol **sympp = NULL, *sym;
>>> +  struct elf32_arm_link_hash_entry *hash;
>>> +  const insn_sequence *cmse_stub_template;
>>> +  struct elf32_arm_stub_hash_entry *stub_entry;
>>> +  int cmse_stub_template_size, new_cmse_stubs_created =
>>> *cmse_stub_created;
>>> +  bfd_vma veneer_value, stub_offset, next_cmse_stub_offset;
>>> +  bfd_vma cmse_stub_array_start = (bfd_vma) -1, cmse_stub_sec_vma = 0;
>>> +
>>> +  /* No input secure gateway import library.  */
>>> +  if (!htab->in_implib_bfd)
>>> +    return TRUE;
>>> +
>>> +  in_implib_bfd = htab->in_implib_bfd;
>>> +  if (!htab->cmse_implib)
>>> +    {
>>> +      (*_bfd_error_handler) (_("%B: --in-implib only supported for
>>> Secure "
>>> +                   "Gateway import libraries."), in_implib_bfd);
>>> +      return FALSE;
>>> +    }
>>> +
>>> +  /* Get symbol table size.  */
>>> +  symsize = bfd_get_symtab_upper_bound (in_implib_bfd);
>>> +  if (symsize < 0)
>>> +    return FALSE;
>>> +
>>> +  /* Read in the input secure gateway import library's symbol
>>> table.  */
>>> +  sympp = (asymbol **) xmalloc (symsize);
>>> +  symcount = bfd_canonicalize_symtab (in_implib_bfd, sympp);
>>> +  if (symcount < 0)
>>> +    {
>>> +      ret = FALSE;
>>> +      goto free_sym_buf;
>>> +    }
>>> +
>>> +  htab->new_cmse_stub_offset = 0;
>>> +  cmse_stub_size =
>>> +    find_stub_size_and_template (arm_stub_cmse_branch_thumb_only,
>>> +                 &cmse_stub_template,
>>> +                 &cmse_stub_template_size);
>>> +  out_sec_name =
>>> +    arm_dedicated_stub_output_section_name
>>> (arm_stub_cmse_branch_thumb_only);
>>> +  stub_out_sec =
>>> +    bfd_get_section_by_name (htab->obfd, out_sec_name);
>>> +  if (stub_out_sec != NULL)
>>> +    cmse_stub_sec_vma = stub_out_sec->vma;
>>> +
>>> +  /* Set addresses of veneers mentionned in input secure gateway import
>>> +     library's symbol table.  */
>>> +  for (i = 0; i < symcount; i++)
>>> +    {
>>> +      sym = sympp[i];
>>> +      flags = sym->flags;
>>> +      sym_name = (char *) bfd_asymbol_name (sym);
>>> +      intsym = &((elf_symbol_type *) sym)->internal_elf_sym;
>>> +
>>> +      if (sym->section != bfd_abs_section_ptr
>>> +      || !(flags & (BSF_GLOBAL | BSF_WEAK))
>>> +      || (flags & BSF_FUNCTION) != BSF_FUNCTION
>>> +      || (ARM_GET_SYM_BRANCH_TYPE (intsym->st_target_internal)
>>> +          != ST_BRANCH_TO_THUMB))
>>> +    {
>>> +      (*_bfd_error_handler) (_("%B: invalid import library entry:
>>> `%s'."),
>>> +                 in_implib_bfd, sym_name);
>>> +      (*_bfd_error_handler) (_("Symbol should be absolute, global and "
>>> +                   "refer to Thumb functions."));
>>> +      ret = FALSE;
>>> +      continue;
>>> +    }
>>> +
>>> +      veneer_value = bfd_asymbol_value (sym);
>>> +      stub_offset = veneer_value - cmse_stub_sec_vma;
>>> +      stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table,
>>> sym_name,
>>> +                     FALSE, FALSE);
>>> +      hash = (struct elf32_arm_link_hash_entry *)
>>> +    elf_link_hash_lookup (&(htab)->root, sym_name, FALSE, FALSE, TRUE);
>>> +
>>> +      /* Stub entry should have been created by cmse_scan or the symbol
>>> be of
>>> +     a secure function callable from non secure code.  */
>>> +      if (!stub_entry && !hash)
>>> +    {
>>> +      bfd_boolean new_stub;
>>> +
>>> +      (*_bfd_error_handler)
>>> +        (_("Entry function `%s' disappeared from secure code."),
>>> sym_name);
>>> +      hash = (struct elf32_arm_link_hash_entry *)
>>> +        elf_link_hash_lookup (&(htab)->root, sym_name, TRUE, TRUE,
>>> TRUE);
>>> +      stub_entry
>>> +        = elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
>>> +                     NULL, NULL, bfd_abs_section_ptr, hash,
>>> +                     sym_name, veneer_value,
>>> +                     ST_BRANCH_TO_THUMB, &new_stub);
>>> +      if (stub_entry == NULL)
>>> +        ret = FALSE;
>>> +      else
>>> +      {
>>> +        BFD_ASSERT (new_stub);
>>> +        new_cmse_stubs_created++;
>>> +        (*cmse_stub_created)++;
>>> +      }
>>> +      stub_entry->stub_template_size = stub_entry->stub_size = 0;
>>> +      stub_entry->stub_offset = stub_offset;
>>> +    }
>>> +      /* Symbol found is not callable from non secure code.  */
>>> +      else if (!stub_entry)
>>> +    {
>>> +      if (!cmse_entry_fct_p (hash))
>>> +        {
>>> +          (*_bfd_error_handler) (_("`%s' refers to a non entry
>>> function."),
>>> +                     sym_name);
>>> +          ret = FALSE;
>>> +        }
>>> +      continue;
>>> +    }
>>> +      else
>>> +    {
>>> +      /* Only stubs for SG veneers should have been created.  */
>>> +      BFD_ASSERT (stub_entry->stub_type ==
>>> arm_stub_cmse_branch_thumb_only);
>>> +
>>> +      /* Check visibility hasn't changed.  */
>>> +      if (!!(flags & BSF_GLOBAL)
>>> +          != (hash->root.root.type == bfd_link_hash_defined))
>>> +        (*_bfd_error_handler)
>>> +          (_("%B: visibility of symbol `%s' has changed."),
>>> in_implib_bfd,
>>> +           sym_name);
>>> +
>>> +      stub_entry->stub_offset = stub_offset;
>>> +    }
>>> +
>>> +      /* Size should match that of a SG veneer.  */
>>> +      if (intsym->st_size != cmse_stub_size)
>>> +    {
>>> +      (*_bfd_error_handler) (_("%B: incorrect size for symbol `%s'."),
>>> +                 in_implib_bfd, sym_name);
>>> +      ret = FALSE;
>>> +    }
>>> +
>>> +      /* Previous veneer address is before current SG veneer
>>> section.  */
>>> +      if (veneer_value < cmse_stub_sec_vma)
>>> +    {
>>> +      /* Avoid offset underflow.  */
>>> +      if (stub_entry)
>>> +        stub_entry->stub_offset = 0;
>>> +      stub_offset = 0;
>>> +      ret = FALSE;
>>> +    }
>>> +
>>> +      /* Complain if stub offset not a multiple of stub size.  */
>>> +      if (stub_offset % cmse_stub_size)
>>> +    {
>>> +      (*_bfd_error_handler)
>>> +        (_("Offset of veneer for entry function `%s' not a multiple
>>> of "
>>> +           "its size."), sym_name);
>>> +      ret = FALSE;
>>> +    }
>>> +
>>> +      if (!ret)
>>> +    continue;
>>> +
>>> +      new_cmse_stubs_created--;
>>> +      if (veneer_value < cmse_stub_array_start)
>>> +    cmse_stub_array_start = veneer_value;
>>> +      next_cmse_stub_offset = stub_offset + ((cmse_stub_size + 7) &
>>> ~7);
>>> +      if (next_cmse_stub_offset > htab->new_cmse_stub_offset)
>>> +    htab->new_cmse_stub_offset = next_cmse_stub_offset;
>>> +    }
>>> +
>>> +  if (!info->out_implib_bfd && new_cmse_stubs_created != 0)
>>> +    {
>>> +      BFD_ASSERT (new_cmse_stubs_created > 0);
>>> +      (*_bfd_error_handler)
>>> +    (_("new entry function(s) introduced but no output import library "
>>> +       "specified:"));
>>> +      bfd_hash_traverse (&htab->stub_hash_table,
>>> arm_list_new_cmse_stub, info);
>>> +    }
>>> +
>>> +  if (cmse_stub_array_start != cmse_stub_sec_vma)
>>> +    {
>>> +      (*_bfd_error_handler)
>>> +    (_("Start address of `%s' is different from previous link."),
>>> +     out_sec_name);
>>> +      ret = FALSE;
>>> +    }
>>> +
>>> +free_sym_buf:
>>> +  free (sympp);
>>> +  return ret;
>>> +}
>>> +
>>>  /* Determine and set the size of the stub section for a final link.
>>>
>>>     The basic idea here is to examine all the relocations looking for
>>> @@ -5735,7 +6054,9 @@ elf32_arm_size_stubs (bfd *output_bfd,
>>>                                unsigned int),
>>>                void (*layout_sections_again) (void))
>>>  {
>>> +  bfd_boolean ret = TRUE;
>>>    obj_attribute *out_attr;
>>> +  int cmse_stub_created = 0;
>>>    bfd_size_type stub_group_size;
>>>    bfd_boolean m_profile, stubs_always_after_branch, first_veneer_scan =
>>> TRUE;
>>>    struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
>>> @@ -5768,6 +6089,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
>>>
>>>    out_attr = elf_known_obj_attributes_proc (output_bfd);
>>>    m_profile = out_attr[Tag_CPU_arch_profile].i == 'M';
>>> +
>>>    /* The Cortex-A8 erratum fix depends on stubs not being in the same
>>> 4K page
>>>       as the first half of a 32-bit branch straddling two 4K pages.
>>> This is a
>>>       crude way of enforcing that.  */
>>> @@ -5841,8 +6163,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
>>>
>>>            sym_hashes = elf_sym_hashes (input_bfd);
>>>            if (!cmse_scan (input_bfd, htab, out_attr, sym_hashes,
>>> -                  &stub_changed))
>>> +                  &cmse_stub_created))
>>>          goto error_ret_free_local;
>>> +
>>> +          if (cmse_stub_created != 0)
>>> +        stub_changed = TRUE;
>>>          }
>>>
>>>        /* Walk over each section attached to the input bfd.  */
>>> @@ -6074,6 +6399,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
>>>            do
>>>              {
>>>                bfd_boolean new_stub;
>>> +              struct elf32_arm_stub_hash_entry *stub_entry;
>>>
>>>                /* Determine what (if any) linker stub is needed.  */
>>>                stub_type = arm_type_of_stub (info, section, irela,
>>> @@ -6085,12 +6411,13 @@ elf32_arm_size_stubs (bfd *output_bfd,
>>>
>>>                /* We've either created a stub for this reloc already,
>>>               or we are about to.  */
>>> -              created_stub =
>>> +              stub_entry =
>>>              elf32_arm_create_stub (htab, stub_type, section, irela,
>>>                             sym_sec, hash,
>>>                             (char *) sym_name, sym_value,
>>>                             branch_type, &new_stub);
>>>
>>> +              created_stub = stub_entry != NULL;
>>>                if (!created_stub)
>>>              goto error_ret_free_internal;
>>>                else if (!new_stub)
>>> @@ -6172,6 +6499,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
>>>          }
>>>      }
>>>
>>> +      if (first_veneer_scan
>>> +      && !set_cmse_veneer_addr_from_implib (info, htab,
>>> +                        &cmse_stub_created))
>>> +    ret = FALSE;
>>> +
>>>        if (prev_num_a8_fixes != num_a8_fixes)
>>>      stub_changed = TRUE;
>>>
>>> @@ -6191,6 +6523,24 @@ elf32_arm_size_stubs (bfd *output_bfd,
>>>        stub_sec->size = 0;
>>>      }
>>>
>>> +      /* Add new SG veneers after those already in the input import
>>> +     library.  */
>>> +      for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
>>> +       stub_type++)
>>> +    {
>>> +      bfd_vma *start_offset_p;
>>> +      asection **stub_sec_p;
>>> +
>>> +      start_offset_p = arm_new_stubs_start_offset_ptr (htab,
>>> stub_type);
>>> +      stub_sec_p = arm_dedicated_stub_input_section_ptr (htab,
>>> stub_type);
>>> +      if (start_offset_p == NULL)
>>> +        continue;
>>> +
>>> +      BFD_ASSERT (stub_sec_p != NULL);
>>> +      if (*stub_sec_p != NULL)
>>> +        (*stub_sec_p)->size = *start_offset_p;
>>> +    }
>>> +
>>>        /* Compute stub section size, considering padding.  */
>>>        bfd_hash_traverse (&htab->stub_hash_table, arm_size_one_stub,
>>> htab);
>>>        for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
>>> @@ -6259,7 +6609,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
>>>          }
>>>
>>>        stub_entry->stub_sec = stub_sec;
>>> -      stub_entry->stub_offset = 0;
>>> +      stub_entry->stub_offset = (bfd_vma) -1;
>>>        stub_entry->id_sec = link_sec;
>>>        stub_entry->stub_type = a8_fixes[i].stub_type;
>>>        stub_entry->source_value = a8_fixes[i].offset;
>>> @@ -6287,7 +6637,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
>>>        htab->a8_erratum_fixes = NULL;
>>>        htab->num_a8_erratum_fixes = 0;
>>>      }
>>> -  return TRUE;
>>> +  return ret;
>>>  }
>>>
>>>  /* Build all the stubs associated with the current output file.  The
>>> @@ -6301,6 +6651,7 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
>>>  {
>>>    asection *stub_sec;
>>>    struct bfd_hash_table *table;
>>> +  enum elf32_arm_stub_type stub_type;
>>>    struct elf32_arm_link_hash_table *htab;
>>>
>>>    htab = elf32_arm_hash_table (info);
>>> @@ -6318,14 +6669,33 @@ elf32_arm_build_stubs (struct bfd_link_info
>>> *info)
>>>      continue;
>>>
>>>        /* Allocate memory to hold the linker stubs.  Zeroing the stub
>>> sections
>>> -     must at least be done for stub section requiring padding.  */
>>> +     must at least be done for stub section requiring padding and
>>> for SG
>>> +     veneers to ensure that a non secure code branching to a removed SG
>>> +     veneer causes an error.  */
>>>        size = stub_sec->size;
>>>        stub_sec->contents = (unsigned char *) bfd_zalloc
>>> (htab->stub_bfd, size);
>>>        if (stub_sec->contents == NULL && size != 0)
>>>      return FALSE;
>>> +
>>>        stub_sec->size = 0;
>>>      }
>>>
>>> +  /* Add new SG veneers after those already in the input import
>>> library.  */
>>> +  for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
>>> stub_type++)
>>> +    {
>>> +      bfd_vma *start_offset_p;
>>> +      asection **stub_sec_p;
>>> +
>>> +      start_offset_p = arm_new_stubs_start_offset_ptr (htab,
>>> stub_type);
>>> +      stub_sec_p = arm_dedicated_stub_input_section_ptr (htab,
>>> stub_type);
>>> +      if (start_offset_p == NULL)
>>> +    continue;
>>> +
>>> +      BFD_ASSERT (stub_sec_p != NULL);
>>> +      if (*stub_sec_p != NULL)
>>> +    (*stub_sec_p)->size = *start_offset_p;
>>> +    }
>>> +
>>>    /* Build the stubs as directed by the stub hash table.  */
>>>    table = &htab->stub_hash_table;
>>>    bfd_hash_traverse (table, arm_build_one_stub, info);
>>> @@ -8311,7 +8681,8 @@ bfd_elf32_arm_set_target_relocs (struct bfd
>>> *output_bfd,
>>>                   bfd_arm_stm32l4xx_fix stm32l4xx_fix,
>>>                   int no_enum_warn, int no_wchar_warn,
>>>                   int pic_veneer, int fix_cortex_a8,
>>> -                 int fix_arm1176, int cmse_implib)
>>> +                 int fix_arm1176, int cmse_implib,
>>> +                 bfd *in_implib_bfd)
>>>  {
>>>    struct elf32_arm_link_hash_table *globals;
>>>
>>> @@ -8339,6 +8710,7 @@ bfd_elf32_arm_set_target_relocs (struct bfd
>>> *output_bfd,
>>>    globals->fix_cortex_a8 = fix_cortex_a8;
>>>    globals->fix_arm1176 = fix_arm1176;
>>>    globals->cmse_implib = cmse_implib;
>>> +  globals->in_implib_bfd = in_implib_bfd;
>>>
>>>    BFD_ASSERT (is_arm_elf (output_bfd));
>>>    elf_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
>>> diff --git a/ld/NEWS b/ld/NEWS
>>> index
>>> 2a0b4ac704a088a24cfc1633785a50477513c4db..0f316bfcc248341200af14e5cb1a5c50787e9b1a
>>>
>>> 100644
>>> --- a/ld/NEWS
>>> +++ b/ld/NEWS
>>> @@ -2,6 +2,11 @@
>>>
>>>  Changes in 2.28:
>>>
>>> +* Add --in-implib=<infile> to the ARM linker to enable specifying a
>>> set of
>>> +  Secure Gateway veneers that must exist in the output import library
>>> specified
>>> +  by --out-implib=<outfile> and the address they must have.  As such,
>>> +  --in-implib is only supported in combination with --cmse-implib.
>>> +
>>>  * Extended the --out-implib=<file> option, previously restricted to
>>> x86 PE
>>>    targets, to any ELF based target.  This allows the generation of an
>>> import
>>>    library for an ELF executable, which can then be used by another
>>> application
>>> diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
>>> index
>>> c21f6a82335a58a0ab37f3719c73c95e73e6211c..2346bb42444895605d10b7b7e21cca2dcaa38700
>>>
>>> 100644
>>> --- a/ld/emultempl/armelf.em
>>> +++ b/ld/emultempl/armelf.em
>>> @@ -43,6 +43,7 @@ static int pic_veneer = 0;
>>>  static int merge_exidx_entries = -1;
>>>  static int fix_arm1176 = 1;
>>>  static int cmse_implib = 0;
>>> +static char *in_implib_filename = NULL;
>>>
>>>  static void
>>>  gld${EMULATION_NAME}_before_parse (void)
>>> @@ -498,6 +499,8 @@ gld${EMULATION_NAME}_finish (void)
>>>  static void
>>>  arm_elf_create_output_section_statements (void)
>>>  {
>>> +  bfd *in_implib_bfd;
>>> +
>>>    if (strstr (bfd_get_target (link_info.output_bfd), "arm") == NULL)
>>>      {
>>>        /* The arm backend needs special fields in the output hash
>>> structure.
>>> @@ -508,6 +511,20 @@ arm_elf_create_output_section_statements (void)
>>>        return;
>>>      }
>>>
>>> +  if (in_implib_filename)
>>> +    {
>>> +      in_implib_bfd = bfd_openr (in_implib_filename,
>>> +                 bfd_get_target (link_info.output_bfd));
>>> +
>>> +      if (in_implib_bfd == NULL)
>>> +    einfo ("%F%s: Can't open: %E\n", in_implib_filename);
>>> +
>>> +      if (!bfd_check_format (in_implib_bfd, bfd_object))
>>> +    einfo ("%F%s: Not a relocatable file: %E\n", in_implib_filename);
>>> +    }
>>> +  else
>>> +    in_implib_bfd = NULL;
>>> +
>>>    bfd_elf32_arm_set_target_relocs (link_info.output_bfd, &link_info,
>>>                     target1_is_rel,
>>>                     target2_type, fix_v4bx, use_blx,
>>> @@ -515,7 +532,7 @@ arm_elf_create_output_section_statements (void)
>>>                     no_enum_size_warning,
>>>                     no_wchar_size_warning,
>>>                     pic_veneer, fix_cortex_a8,
>>> -                   fix_arm1176, cmse_implib);
>>> +                   fix_arm1176, cmse_implib, in_implib_bfd);
>>>
>>>    stub_file = lang_add_input_file ("linker stubs",
>>>                      lang_input_file_is_fake_enum,
>>> @@ -585,6 +602,7 @@ PARSE_AND_LIST_PROLOGUE='
>>>  #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
>>> @@ -612,6 +630,7 @@ PARSE_AND_LIST_LONGOPTS='
>>>    { "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='
>>> @@ -634,6 +653,8 @@ PARSE_AND_LIST_OPTIONS='
>>>             "                              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\
>>> @@ -758,6 +779,10 @@ PARSE_AND_LIST_ARGS_CASES='
>>>     case OPTION_CMSE_IMPLIB:
>>>        cmse_implib = 1;
>>>        break;
>>> +
>>> +   case OPTION_IN_IMPLIB:
>>> +      in_implib_filename = optarg;
>>> +      break;
>>>  '
>>>
>>>  # We have our own before_allocation etc. functions, but they call
>>> diff --git a/ld/ld.texinfo b/ld/ld.texinfo
>>> index
>>> e6813f287fe5ce4c916bf93f48b2e9edbc336570..021385166887a2d2bd49bdba379e833b9c67d906
>>>
>>> 100644
>>> --- a/ld/ld.texinfo
>>> +++ b/ld/ld.texinfo
>>> @@ -6866,6 +6866,18 @@ specified by the @samp{--out-implib} and
>>> @samp{--in-implib} options are
>>>  secure gateway import libraries, suitable for linking a non-secure
>>>  executable against secure code as per ARMv8-M Security Extensions.
>>>
>>> +@kindex --in-implib=@var{file}
>>> +@cindex Input import library
>>> +The @samp{--in-implib=file} specifies an input import library whose
>>> symbols
>>> +must keep the same address in the executable being produced.  A
>>> warning is
>>> +given if no @samp{--out-implib} is given but new symbols have been
>>> introduced
>>> +in the executable that should be listed in its import library.
>>> Otherwise, if
>>> +@samp{--out-implib} is specified, the symbols are added to the output
>>> import
>>> +library.  A warning is also given if some symbols present in the input
>>> import
>>> +library have disappeared from the executable.  This option is only
>>> effective
>>> +for Secure Gateway import libraries, ie. when @samp{--cmse-implib} is
>>> +specified.
>>> +
>>>  @ifclear GENERIC
>>>  @lowersections
>>>  @end ifclear
>>> diff --git a/ld/testsuite/ld-arm/arm-elf.exp
>>> b/ld/testsuite/ld-arm/arm-elf.exp
>>> index
>>> 55240854a24951194c8150581b8a40dd2910b5cb..24d0b4c72a91550bfa936cdbe4ab7fabbeecb6c5
>>>
>>> 100644
>>> --- a/ld/testsuite/ld-arm/arm-elf.exp
>>> +++ b/ld/testsuite/ld-arm/arm-elf.exp
>>> @@ -670,16 +670,59 @@ set armeabitests_nonacl {
>>>       "cmse-veneers-mainline"}
>>>      {"Secure gateway import library generation: errors"
>>>       "--section-start .gnu.sgstubs=0x20000
>>> --out-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
>>> -     "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1"
>>> +     "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1 --defsym
>>> VER=1"
>>>       {cmse-implib.s}
>>>       {{ld cmse-implib-errors.out}}
>>>       "cmse-implib"}
>>>      {"Secure gateway import library generation"
>>>       "--section-start .gnu.sgstubs=0x20000
>>> --out-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
>>> -     "-march=armv8-m.base -mthumb"
>>> +     "-march=armv8-m.base -mthumb --defsym VER=1"
>>>       {cmse-implib.s}
>>>       {{readelf {-s tmpdir/cmse-implib.lib} cmse-implib.rd}}
>>>       "cmse-implib"}
>>> +    {"Input secure gateway import library"
>>> +     "--section-start .gnu.sgstubs=0x20000
>>> --out-implib=tmpdir/cmse-new-implib.lib
>>> --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
>>> +     "-march=armv8-m.base -mthumb --defsym VER=2"
>>> +     {cmse-implib.s}
>>> +     {{ld cmse-new-implib.out}
>>> +      {readelf {-s tmpdir/cmse-new-implib.lib} cmse-new-implib.rd}}
>>> +     "cmse-new-implib"}
>>> +    {"Input secure gateway import library: no output import library"
>>> +     "--section-start .gnu.sgstubs=0x20000
>>> --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
>>> +     "-march=armv8-m.base -mthumb --defsym VER=2"
>>> +     {cmse-implib.s}
>>> +     {{ld cmse-new-implib-no-output.out}}
>>> +     "cmse-new-implib-no-output"}
>>> +    {"Input secure gateway import library: not an SG input import
>>> library"
>>> +     "--section-start .gnu.sgstubs=0x20000
>>> --in-implib=tmpdir/cmse-implib.lib" ""
>>> +     "-march=armv8-m.base -mthumb --defsym VER=2"
>>> +     {cmse-implib.s}
>>> +     {{ld cmse-new-implib-not-sg-in-implib.out}}
>>> +     "cmse-new-implib-not-sg-in-implib"}
>>> +    {"Input secure gateway import library: earlier stub section base"
>>> +     "--section-start .gnu.sgstubs=0x19000
>>> --out-implib=tmpdir/cmse-new-earlier-implib.lib
>>> --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
>>> +     "-march=armv8-m.base -mthumb --defsym VER=2"
>>> +     {cmse-implib.s}
>>> +     {{ld cmse-new-earlier-later-implib.out}}
>>> +     "cmse-new-earlier-implib"}
>>> +    {"Input secure gateway import library: later stub section base"
>>> +     "--section-start .gnu.sgstubs=0x30000
>>> --out-implib=tmpdir/cmse-new-later-implib.lib
>>> --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
>>> +     "-march=armv8-m.base -mthumb --defsym VER=2"
>>> +     {cmse-implib.s}
>>> +     {{ld cmse-new-earlier-later-implib.out}}
>>> +     "cmse-new-later-implib"}
>>> +    {"Input secure gateway import library: veneer comeback"
>>> +     "--section-start .gnu.sgstubs=0x20000
>>> --out-implib=tmpdir/cmse-new-comeback-implib.lib
>>> --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
>>> +     "-march=armv8-m.base -mthumb --defsym VER=3"
>>> +     {cmse-implib.s}
>>> +     {{readelf {-s tmpdir/cmse-new-comeback-implib.lib}
>>> cmse-new-comeback-implib.rd}}
>>> +     "cmse-new-comeback-implib"}
>>> +    {"Input secure gateway import library: entry function change"
>>> +     "--section-start .gnu.sgstubs=0x20000
>>> --out-implib=tmpdir/cmse-new-wrong-implib.lib
>>> --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
>>> +     "-march=armv8-m.base -mthumb --defsym VER=4"
>>> +     {cmse-implib.s}
>>> +     {{ld cmse-new-wrong-implib.out}}
>>> +     "cmse-new-wrong-implib"}
>>>
>>>      {"R_ARM_THM_JUMP19 Relocation veneers: Short"
>>>       "--section-start destsect=0x000108002 --section-start
>>> .text=0x8000" ""
>>> diff --git a/ld/testsuite/ld-arm/cmse-implib.s
>>> b/ld/testsuite/ld-arm/cmse-implib.s
>>> index
>>> a42da63fffebe5322be83f278931754262b0f7ae..9dd783939891478351a5f7ccb1480980a77dca68
>>>
>>> 100644
>>> --- a/ld/testsuite/ld-arm/cmse-implib.s
>>> +++ b/ld/testsuite/ld-arm/cmse-implib.s
>>> @@ -20,12 +20,29 @@ __acle_se_\name:
>>>  .endm
>>>
>>>      @ Valid setups for veneer generation
>>> +.if (VER >= 2)
>>> +    entry exported_entry_veneer1, global
>>> +.endif
>>> +.if (VER != 4)
>>>      entry exported_entry_veneer2, global
>>> +.else
>>> +    entry exported_entry_veneer2, weak
>>> +.endif
>>> +.if (VER != 2)
>>>      entry exported_entry_veneer3, global
>>> +.endif
>>> +.if (VER > 1)
>>> +    entry exported_entry_veneer4, global
>>> +.endif
>>>
>>>      @ Valid setup for entry function without veneer generation
>>>      entry exported_entry_fct1, global, sg
>>> +.if (VER != 4)
>>>      entry exported_entry_fct2, global, sg
>>> +.else
>>> +    @ Invalid setup for entry function without veneer generation
>>> +    entry exported_entry_fct2, global, nop
>>> +.endif
>>>
>>>      @ Normal symbol not exported to SG import library
>>>      .align    2
>>> diff --git a/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd
>>> b/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd
>>> new file mode 100644
>>> index
>>> 0000000000000000000000000000000000000000..c88d9d5104244abc8ceba4d552e1ef0e400c37d1
>>>
>>>
>>> --- /dev/null
>>> +++ b/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd
>>> @@ -0,0 +1,15 @@
>>> +File: tmpdir/cmse-new-.*implib.lib
>>> +
>>> +Symbol table '.symtab' contains 7 entries:
>>> +   Num:    Value  Size Type    Bind   Vis      Ndx Name
>>> +     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
>>> +     1: 00020001     8 FUNC    GLOBAL DEFAULT  ABS
>>> exported_entry_veneer3
>>> +     2: 00020011     8 FUNC    GLOBAL DEFAULT  ABS
>>> exported_entry_veneer4
>>> +     3: 00020019     8 FUNC    GLOBAL DEFAULT  ABS
>>> exported_entry_veneer1
>>> +     4: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
>>> +     5: 00020009     8 FUNC    GLOBAL DEFAULT  ABS
>>> exported_entry_veneer2
>>> +     6: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
>>> +
>>> +File: tmpdir/cmse-new-.*implib
>>> +
>>> +#...
>>> diff --git a/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
>>> b/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
>>> new file mode 100644
>>> index
>>> 0000000000000000000000000000000000000000..b49ad0ac0770a17c39c2d119d1f0c5854a5bd8cc
>>>
>>>
>>> --- /dev/null
>>> +++ b/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
>>> @@ -0,0 +1,3 @@
>>> +.*: Entry function `exported_entry_veneer3' disappeared from secure
>>> code.
>>> +.*: Start address of `.gnu.sgstubs' is different from previous link.
>>> +.*: cannot size stub section: Invalid operation
>>> diff --git a/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
>>> b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
>>> new file mode 100644
>>> index
>>> 0000000000000000000000000000000000000000..0590b71c844da3687b29b93797abda5172ab8d99
>>>
>>>
>>> --- /dev/null
>>> +++ b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
>>> @@ -0,0 +1,4 @@
>>> +.*: Entry function `exported_entry_veneer3' disappeared from secure
>>> code.
>>> +.*: new entry function\(s\) introduced but no output import library
>>> specified:
>>> +.*:   exported_entry_veneer4
>>> +.*:   exported_entry_veneer1
>>> diff --git a/ld/testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out
>>> b/ld/testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out
>>> new file mode 100644
>>> index
>>> 0000000000000000000000000000000000000000..c93c3fb97895286e05026b6eac696fa9de6c89f9
>>>
>>>
>>> --- /dev/null
>>> +++ b/ld/testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out
>>> @@ -0,0 +1,2 @@
>>> +.*: --in-implib only supported for Secure Gateway import libraries.
>>> +.*: cannot size stub section: Invalid operation
>>> diff --git a/ld/testsuite/ld-arm/cmse-new-implib.out
>>> b/ld/testsuite/ld-arm/cmse-new-implib.out
>>> new file mode 100644
>>> index
>>> 0000000000000000000000000000000000000000..c8af2807e7c1a7eeb1fc156fbf4508cf7a7e932d
>>>
>>>
>>> --- /dev/null
>>> +++ b/ld/testsuite/ld-arm/cmse-new-implib.out
>>> @@ -0,0 +1 @@
>>> +.*: Entry function `exported_entry_veneer3' disappeared from secure
>>> code.
>>> diff --git a/ld/testsuite/ld-arm/cmse-new-implib.rd
>>> b/ld/testsuite/ld-arm/cmse-new-implib.rd
>>> new file mode 100644
>>> index
>>> 0000000000000000000000000000000000000000..9ff0fd87937571f86f99ee940a91a3f67352242a
>>>
>>>
>>> --- /dev/null
>>> +++ b/ld/testsuite/ld-arm/cmse-new-implib.rd
>>> @@ -0,0 +1,14 @@
>>> +File: tmpdir/cmse-new-.*implib.lib
>>> +
>>> +Symbol table '.symtab' contains 6 entries:
>>> +   Num:    Value  Size Type    Bind   Vis      Ndx Name
>>> +     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
>>> +     1: 00020011     8 FUNC    GLOBAL DEFAULT  ABS
>>> exported_entry_veneer4
>>> +     2: 00020019     8 FUNC    GLOBAL DEFAULT  ABS
>>> exported_entry_veneer1
>>> +     3: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
>>> +     4: 00020009     8 FUNC    GLOBAL DEFAULT  ABS
>>> exported_entry_veneer2
>>> +     5: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
>>> +
>>> +File: tmpdir/cmse-new-.*implib
>>> +
>>> +#...
>>> diff --git a/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
>>> b/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
>>> new file mode 100644
>>> index
>>> 0000000000000000000000000000000000000000..2afe4078e78606d24f05dda6ff1c5e6a54d42512
>>>
>>>
>>> --- /dev/null
>>> +++ b/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
>>> @@ -0,0 +1,3 @@
>>> +.*: .*: visibility of symbol `exported_entry_veneer2' has changed.
>>> +.*: `exported_entry_fct2' refers to a non entry function.
>>> +.*: cannot size stub section: Invalid operation
>>>
>>>
>>> On 17/08/16 16:12, Thomas Preudhomme wrote:
>>>> Ping?
>>>>
>>>> Best regards,
>>>>
>>>> Thomas
>>>>
>>>> On 05/08/16 09:47, Thomas Preudhomme wrote:
>>>>> Hi Richard,
>>>>>
>>>>> Sorry for the delay, got caught on other things. Please find an
>>>>> updated patch
>>>>> in attachment. All but one of your comments have been addressed,
>>>>> comment below
>>>>> on that one.
>>>>>
>>>>> Updated ChangeLog entries are as follow:
>>>>>
>>>>> *** bfd/ChangeLog ***
>>>>>
>>>>> 2016-07-08  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>>>
>>>>>         * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new
>>>>> parameter for
>>>>>         the input import library bfd.
>>>>>         * bfd-in2.h: Regenerate.
>>>>>         * elf32-arm.c (struct elf32_arm_link_hash_table): New
>>>>> in_implib_bfd
>>>>>         and new_cmse_stub_offset fields.
>>>>>         (stub_hash_newfunc): Initialize stub_offset and
>>>>> stub_template_size to
>>>>>         -1.
>>>>>         (elf32_arm_add_stub): Likewise for stub_offset.
>>>>>         (arm_new_stubs_start_offset_ptr): New function.
>>>>>         (arm_build_one_stub): Only allocate a stub_offset if it is
>>>>> -1.  Allow
>>>>>         empty SG veneers to have zero relocations.
>>>>>         (arm_size_one_stub): Only initialize stub size and template
>>>>>         information for non empty veneers.  Do not update veneer
>>>>> section size
>>>>>         if veneer already has an offset.
>>>>>         (elf32_arm_create_stub): Return the stub entry pointer or
>>>>> NULL instead
>>>>>         of a boolean indicating success or failure.
>>>>>         (cmse_scan): Change stub_changed parameter into an integer
>>>>> pointer
>>>>>         parameter cmse_stub_created to count the number of stub
>>>>> created and
>>>>>         adapt to change of return value in elf32_arm_create_stub.
>>>>>         (cmse_entry_fct_p): New function.
>>>>>         (arm_list_new_cmse_stub): Likewise.
>>>>>         (set_cmse_veneer_addr_from_implib): Likewise.
>>>>>         (elf32_arm_size_stubs): Define cmse_stub_created, pass its
>>>>> address to
>>>>>         cmse_scan instead of that of cmse_stub_changed to compute the
>>>>> number
>>>>>         of stub created and use it to initialize stub_changed.  Call
>>>>>         set_cmse_veneer_addr_from_implib after all cmse_scan.  Adapt
>>>>> to change
>>>>>         of return value in elf32_arm_create_stub.  Use
>>>>>         arm_stub_section_start_offset () if not NULL to initialize
>>>>> size of
>>>>>         secure gateway veneers section.  Initialize stub_offset of
>>>>> Cortex-A8
>>>>>         erratum fix to -1.  Use ret to hold return value.
>>>>>         (elf32_arm_build_stubs): Use arm_stub_section_start_offset ()
>>>>> if not
>>>>>         NULL to initialize size of secure gateway veneers section.
>>>>> Adapt
>>>>>         comment to stress the importance of zeroing veneer section
>>>>> content.
>>>>>         (bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd
>>>>> parameter to
>>>>>         initialize eponymous field in struct
>>>>> elf32_arm_link_hash_table.
>>>>>
>>>>>
>>>>> *** ld/ChangeLog ***
>>>>>
>>>>> 2016-07-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>>>
>>>>>         * emultempl/armelf.em (in_implib_filename): Declare and
>>>>> initialize new
>>>>>         variable.
>>>>>         (arm_elf_create_output_section_statements): Open import input
>>>>> library
>>>>>         file for writing and pass resulting in_implib_bfd to
>>>>>         bfd_elf32_arm_set_target_relocs.
>>>>>         (PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option.
>>>>>         (PARSE_AND_LIST_LONGOPTS): Define --in-implib option.
>>>>>         (PARSE_AND_LIST_OPTIONS): Add help message for --in-implib
>>>>> option.
>>>>>         (PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case.
>>>>>         * ld.texinfo (--cmse-implib): Update to mention --in-implib.
>>>>>         (--in-implib): Document new option.
>>>>>         * NEWS: Likewise.
>>>>>         * testsuite/ld-arm/arm-elf.exp
>>>>>         (Secure gateway import library generation): add --defsym
>>>>> VER=1 to gas
>>>>>         CLI.
>>>>>         (Secure gateway import library generation: errors): Likewise.
>>>>>         (Input secure gateway import library): New test.
>>>>>         (Input secure gateway import library: no output import
>>>>> library):
>>>>>         Likewise.
>>>>>         (Input secure gateway import library: not an SG input import
>>>>> library):
>>>>>         Likewise.
>>>>>         (Input secure gateway import library: earlier stub section
>>>>> base):
>>>>>         Likewise.
>>>>>         (Input secure gateway import library: later stub section
>>>>> base):
>>>>>         Likewise.
>>>>>         (Input secure gateway import library: veneer comeback):
>>>>> Likewise.
>>>>>         (Input secure gateway import library: entry function change):
>>>>>         Likewise.
>>>>>         * testsuite/ld-arm/cmse-implib.s: Add input import library
>>>>> testing.
>>>>>         * testsuite/ld-arm/cmse-implib.rd: Update accordingly.
>>>>>         * testsuite/ld-arm/cmse-new-implib.out: New file.
>>>>>         * testsuite/ld-arm/cmse-new-implib.rd: Likewise.
>>>>>         * testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise.
>>>>>         * testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out:
>>>>> Likewise.
>>>>>         * testsuite/ld-arm/cmse-new-earlier-later-implib.out:
>>>>> Likewise.
>>>>>         * testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise.
>>>>>         * testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise.
>>>>>
>>>>> On Thursday 07 July 2016 13:52:00 you wrote:
>>>>>> On 04/04/16 15:22, Thomas Preudhomme wrote:
>>>>>>> On Wednesday 23 December 2015 16:02:48 Thomas Preud'homme wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> [Posting patch series as RFC]
>>>>>>>>
>>>>>>>> This patch is part of a patch series to add support for ARMv8-M
>>>>>>>> security
>>>>>>>> extension[1] to GNU ld. This specific patch adds support for
>>>>>>>> allowing
>>>>>>>> Secure Gateway veneers to have stable addresses when relinking a
>>>>>>>> secure
>>>>>>>> executable.
>>>>>>>>
>>>>>>>> ARM v8-M security extensions allow code running in a device to be
>>>>>>>> divided
>>>>>>>> into secure and non-secure code expected to be developed by
>>>>>>>> independent
>>>>>>>> (teams of) people. To allow updating the secure code without the
>>>>>>>> need to
>>>>>>>> relink the non-secure code against it, it is necessary for the
>>>>>>>> toolchain
>>>>>>>> to
>>>>>>>> provide a way to fix the addresses of the secure gateway veneers
>>>>>>>> that
>>>>>>>> serve
>>>>>>>> as entry points for non-secure code to call secure code. This is
>>>>>>>> also a
>>>>>>>> requirement [2] to claim support for ARM v8-M security extensions.
>>>>>>>>
>>>>>>>> This patch adds a --in-implib=<in_implib_filename> option which,
>>>>>>>> when
>>>>>>>> used
>>>>>>>> in conjunction of --cmse-implib will ensure that the veneers whose
>>>>>>>> symbols
>>>>>>>> are defined in the import library $in_implib_filename will remain
>>>>>>>> at the
>>>>>>>> same address in the executable. In the absence of a --out-implib
>>>>>>>> option,
>>>>>>>> the code will warn about new secure gateway veneers being created,
>>>>>>>> otherwise these are allowed.
>>>>>>>>
>>>>>>>>
>>>>>>>> [1] Software requirements for ARMv8-M security extension are
>>>>>>>> described in
>>>>>>>> document ARM-ECM-0359818 [2] [2] Available on
>>>>>>>> http://infocenter.arm.com
>>>>>>>> in
>>>>>>>> Developer guides and articles > Software development > ARM®v8-M
>>>>>>>> Security
>>>>>>>> Extensions: Requirements on Development Tools [3] See requirement
>>>>>>>> 15 of
>>>>>>>> ARM-ECM-0359818 [2]
>>>>>>>
>>>>>>> Please find an updated patch below.
>>>>>>
>>>>>> Comments inline.
>>>>>>
>>>>>>> *** bfd/ChangeLog ***
>>>>>>>
>>>>>>> 2016-02-18  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>>>>>
>>>>>>>         * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new
>>>>>>> parameter
>>>>>>>         for
>>>>>>>         the input import library bfd.
>>>>>>>         * bfd-in2.h: Regenerate.
>>>>>>>         * elf32-arm.c (struct elf32_arm_link_hash_table): New
>>>>>>>         in_implib_bfd
>>>>>>>         and new_cmse_stub_offset fields.
>>>>>>>         (stub_hash_newfunc): Initialize stub_offset and
>>>>>>> stub_template_size
>>>>>>>         to
>>>>>>>         -1.
>>>>>>>         (elf32_arm_add_stub): Likewise for stub_offset.
>>>>>>>         (arm_new_stubs_start_offset_ptr): New function.
>>>>>>>         (arm_build_one_stub): Only allocate a stub_offset if it
>>>>>>> is -1.
>>>>>>>         Allow
>>>>>>>         empty veneers to have zero relocations.
>>>>>>>         (arm_size_one_stub): Only initialize stub size and template
>>>>>>>         information for non empty veneers.  Do not update veneer
>>>>>>> section
>>>>>>>         size
>>>>>>>         if veneer already has an offset.
>>>>>>>         (elf32_arm_create_stub): Return the stub entry pointer or
>>>>>>> NULL
>>>>>>>         instead
>>>>>>>         of a boolean indicating success or failure.
>>>>>>>         (cmse_scan): Change stub_changed parameter into an integer
>>>>>>> pointer
>>>>>>>         parameter cmse_stub_created to count the number of stub
>>>>>>> created
>>>>>>>         and
>>>>>>>         adapt to change of return value in elf32_arm_create_stub.
>>>>>>>         (cmse_entry_fct_p): New function.
>>>>>>>         (arm_list_new_cmse_stub): Likewise.
>>>>>>>         (set_cmse_veneer_addr_from_implib): Likewise.
>>>>>>>         (elf32_arm_size_stubs): Define cmse_stub_created, pass its
>>>>>>> address
>>>>>>>         to
>>>>>>>         cmse_scan instead of that of cmse_stub_changed to compute
>>>>>>> the
>>>>>>>         number
>>>>>>>         of stub created and use it to initialize stub_changed.  Call
>>>>>>>         set_cmse_veneer_addr_from_implib after all cmse_scan.
>>>>>>> Adapt to
>>>>>>>         change
>>>>>>>         of return value in elf32_arm_create_stub.  Use
>>>>>>>         arm_stub_section_start_offset () if not NULL to initialize
>>>>>>> size of
>>>>>>>         secure gateway veneers section.  Initialize stub_offset of
>>>>>>>         Cortex-A8
>>>>>>>         erratum fix to -1.  Use ret to hold return value.
>>>>>>>         (elf32_arm_build_stubs): Use arm_stub_section_start_offset
>>>>>>> () if
>>>>>>>         not
>>>>>>>         NULL to initialize size of secure gateway veneers section.
>>>>>>> Adapt
>>>>>>>         comment to stress the importance of zeroing veneer section
>>>>>>>         content.
>>>>>>>         (bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd
>>>>>>> parameter
>>>>>>>         to
>>>>>>>         initialize eponymous field in struct
>>>>>>> elf32_arm_link_hash_table.
>>>>>>>
>>>>>>> *** ld/ChangeLog ***
>>>>>>>
>>>>>>> 2016-02-18  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>>>>>
>>>>>>>         * emultempl/armelf.em (in_implib_filename): Declare and
>>>>>>> initialize
>>>>>>>         new
>>>>>>>         variable.
>>>>>>>         (arm_elf_create_output_section_statements): Open import
>>>>>>> input
>>>>>>>         library
>>>>>>>         file for writing and pass resulting in_implib_bfd to
>>>>>>>         bfd_elf32_arm_set_target_relocs.
>>>>>>>         (PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option.
>>>>>>>         (PARSE_AND_LIST_LONGOPTS): Define --in-implib option.
>>>>>>>         (PARSE_AND_LIST_OPTIONS): Add help message for --in-implib
>>>>>>> option.
>>>>>>>         (PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB
>>>>>>> case.
>>>>>>>         * ld.texinfo (--cmse-implib): Update to mention --in-implib.
>>>>>>>         (--in-implib): Document new option.
>>>>>>>         * testsuite/ld-arm/arm-elf.exp
>>>>>>>         (Secure gateway import library generation): add --defsym
>>>>>>> VER=1 to
>>>>>>>         gas
>>>>>>>         CLI.
>>>>>>>         (Secure gateway import library generation: errors):
>>>>>>> Likewise.
>>>>>>>         (Input secure gateway import library): New test.
>>>>>>>         (Input secure gateway import library: no output import
>>>>>>> library):
>>>>>>>         Likewise.
>>>>>>>         (Input secure gateway import library: earlier stub section
>>>>>>> base):
>>>>>>>         Likewise.
>>>>>>>         (Input secure gateway import library: later stub section
>>>>>>> base):
>>>>>>>         Likewise.
>>>>>>>         (Input secure gateway import library: veneer comeback):
>>>>>>> Likewise.
>>>>>>>         (Input secure gateway import library: entry function
>>>>>>> change):
>>>>>>>         Likewise.
>>>>>>>         * testsuite/ld-arm/cmse-implib.s: Add input import library
>>>>>>>         testing.
>>>>>>>         * testsuite/ld-arm/cmse-implib.rd: Update accordingly.
>>>>>>>         * testsuite/ld-arm/cmse-new-implib.out: New file.
>>>>>>>         * testsuite/ld-arm/cmse-new-implib.rd: Likewise.
>>>>>>>         * testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise.
>>>>>>>         * testsuite/ld-arm/cmse-new-earlier-later-implib.out:
>>>>>>> Likewise.
>>>>>>>         * testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise.
>>>>>>>         * testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise.
>>>>>>>
>>>>>>> diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
>>>>>>> index
>>>>>>> 7e3483b9984b04c534e53f2f9026abf26d37592a..423c534a954c541e227e731e9256f08f
>>>>>>>
>>>>>>>
>>>>>>> 9fa62014 100644
>>>>>>> --- a/bfd/bfd-in.h
>>>>>>> +++ b/bfd/bfd-in.h
>>>>>>> @@ -895,7 +895,7 @@ extern bfd_boolean
>>>>>>> bfd_elf32_arm_process_before_allocation>
>>>>>>>  void bfd_elf32_arm_set_target_relocs
>>>>>>>
>>>>>>>    (bfd *, struct bfd_link_info *, int, char *, int, int,
>>>>>>>    bfd_arm_vfp11_fix,
>>>>>>>
>>>>>>> -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
>>>>>>> +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
>>>>>>>
>>>>>>>  extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
>>>>>>>
>>>>>>>    (bfd *, struct bfd_link_info *);
>>>>>>>
>>>>>>> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
>>>>>>> index
>>>>>>> 55e1cdde2d0a899238a224c6915d20197b72f085..3a67fa637f5c709cddf3767496e4ac87
>>>>>>>
>>>>>>>
>>>>>>> 96287765 100644
>>>>>>> --- a/bfd/bfd-in2.h
>>>>>>> +++ b/bfd/bfd-in2.h
>>>>>>> @@ -902,7 +902,7 @@ extern bfd_boolean
>>>>>>> bfd_elf32_arm_process_before_allocation>
>>>>>>>  void bfd_elf32_arm_set_target_relocs
>>>>>>>
>>>>>>>    (bfd *, struct bfd_link_info *, int, char *, int, int,
>>>>>>>    bfd_arm_vfp11_fix,
>>>>>>>
>>>>>>> -   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
>>>>>>> +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
>>>>>>
>>>>>> This is *only* one more parameter to this function, but it now takes
>>>>>> 15,
>>>>>> which seems excessive.
>>>>>>
>>>>>> Some redesign may be in order here...
>>>>>
>>>>> Ok. I did a separate patch for this as I felt this was an independent
>>>>> change
>>>>> and would have made the patch even bigger. I'll post it soon.
>>>>>
>>>>> Best regards,
>>>>>
>>>>> Thomas
>>>>>
>>
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ARM 11/11, ping] Add support for stable secure gateway veneers addresses
       [not found]                 ` <CAKdteOZ4uC=dOKO5WoysePRT1is9rvX4etjgj1iK5Hj23TSdLw@mail.gmail.com>
@ 2016-08-26 12:37                   ` Thomas Preudhomme
  2016-08-26 14:18                     ` Thomas Preudhomme
  0 siblings, 1 reply; 15+ messages in thread
From: Thomas Preudhomme @ 2016-08-26 12:37 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: binutils

Hi Christophe,

On 26/08/16 12:55, Christophe Lyon wrote:
>
> I've noticed that the new tests fail on armeb. I didn't look at the
> detailed logs yet, but I guess you can a look?
>
> ./ld/ld.sum:FAIL: Input secure gateway import library
> ./ld/ld.sum:FAIL: Input secure gateway import library: no output import library
> ./ld/ld.sum:FAIL: Input secure gateway import library: earlier stub section base
> ./ld/ld.sum:FAIL: Input secure gateway import library: later stub section base
> ./ld/ld.sum:FAIL: Input secure gateway import library: veneer comeback
> ./ld/ld.sum:FAIL: Input secure gateway import library: entry function change

I can reproduce indeed. I'll have a look, thanks for the notice. Note that 
Monday is a bank holidays here so might only answer after that if I'm too slow 
to find the root cause.

Best regards,

Thomas

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ARM 11/11, ping] Add support for stable secure gateway veneers addresses
  2016-08-26 12:37                   ` Thomas Preudhomme
@ 2016-08-26 14:18                     ` Thomas Preudhomme
  2016-08-29 14:56                       ` Christophe Lyon
  0 siblings, 1 reply; 15+ messages in thread
From: Thomas Preudhomme @ 2016-08-26 14:18 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: binutils

On 26/08/16 13:36, Thomas Preudhomme wrote:
> Hi Christophe,
>
> On 26/08/16 12:55, Christophe Lyon wrote:
>>
>> I've noticed that the new tests fail on armeb. I didn't look at the
>> detailed logs yet, but I guess you can a look?
>>
>> ./ld/ld.sum:FAIL: Input secure gateway import library
>> ./ld/ld.sum:FAIL: Input secure gateway import library: no output import library
>> ./ld/ld.sum:FAIL: Input secure gateway import library: earlier stub section base
>> ./ld/ld.sum:FAIL: Input secure gateway import library: later stub section base
>> ./ld/ld.sum:FAIL: Input secure gateway import library: veneer comeback
>> ./ld/ld.sum:FAIL: Input secure gateway import library: entry function change
>
> I can reproduce indeed. I'll have a look, thanks for the notice. Note that
> Monday is a bank holidays here so might only answer after that if I'm too slow
> to find the root cause.

Doh, the code checks for a SG instruction by comparing the 4 bytes in the code 
against its litteral value. The problem of course is that the read puts the 4 
bytes of the instruction in memory order but these will then be interpreted 
according to the endianness.

The fix should be easy.

Best regards,

Thomas

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ARM 11/11, ping] Add support for stable secure gateway veneers addresses
  2016-08-26 14:18                     ` Thomas Preudhomme
@ 2016-08-29 14:56                       ` Christophe Lyon
  2016-08-30  8:10                         ` Thomas Preudhomme
  0 siblings, 1 reply; 15+ messages in thread
From: Christophe Lyon @ 2016-08-29 14:56 UTC (permalink / raw)
  To: Thomas Preudhomme; +Cc: binutils

[-- Attachment #1: Type: text/plain, Size: 1469 bytes --]

On 26 August 2016 at 16:18, Thomas Preudhomme
<thomas.preudhomme@foss.arm.com> wrote:
> On 26/08/16 13:36, Thomas Preudhomme wrote:
>>
>> Hi Christophe,
>>
>> On 26/08/16 12:55, Christophe Lyon wrote:
>>>
>>>
>>> I've noticed that the new tests fail on armeb. I didn't look at the
>>> detailed logs yet, but I guess you can a look?
>>>
>>> ./ld/ld.sum:FAIL: Input secure gateway import library
>>> ./ld/ld.sum:FAIL: Input secure gateway import library: no output import
>>> library
>>> ./ld/ld.sum:FAIL: Input secure gateway import library: earlier stub
>>> section base
>>> ./ld/ld.sum:FAIL: Input secure gateway import library: later stub section
>>> base
>>> ./ld/ld.sum:FAIL: Input secure gateway import library: veneer comeback
>>> ./ld/ld.sum:FAIL: Input secure gateway import library: entry function
>>> change
>>
>>
>> I can reproduce indeed. I'll have a look, thanks for the notice. Note that
>> Monday is a bank holidays here so might only answer after that if I'm too
>> slow
>> to find the root cause.
>
>
> Doh, the code checks for a SG instruction by comparing the 4 bytes in the
> code against its litteral value. The problem of course is that the read puts
> the 4 bytes of the instruction in memory order but these will then be
> interpreted according to the endianness.
>
> The fix should be easy.
>

Indeed, thanks to your analysis it was quick enough.

Here is a patch, maybe there is a simpler way?

Thanks,

Christophe

> Best regards,
>
> Thomas

[-- Attachment #2: binutils-SG-BE.log.txt --]
[-- Type: text/plain, Size: 157 bytes --]

2016-08-29  Christophe Lyon  <chritophe.lyon@linaro.org>

	bfd/
	* elf32-arm.c (cmse_entry_fct_p): Read first instruction in an
	endianness independent way.

[-- Attachment #3: binutils-SG-BE.patch.txt --]
[-- Type: text/plain, Size: 909 bytes --]

diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 9ff418a..5c04b9b 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -5791,11 +5791,19 @@ cmse_entry_fct_p (struct elf32_arm_link_hash_entry *hash)
   section = hash->root.root.u.def.section;
   abfd = section->owner;
   offset = hash->root.root.u.def.value - section->vma;
-  if (!bfd_get_section_contents (abfd, section, &first_insn, offset,
-				 sizeof (first_insn)))
-    return FALSE;
 
   /* Start by SG instruction.  */
+  bfd_byte * contents;
+  /* Get cached copy if it exists.  */
+  if (elf_section_data (section)->this_hdr.contents != NULL)
+    contents = elf_section_data (section)->this_hdr.contents;
+  else
+    {
+      /* Go get them off disk.  */
+      if (! bfd_malloc_and_get_section (abfd, section, &contents))
+	return FALSE;
+    }
+  first_insn = bfd_get_32 (abfd, contents + offset);
   return first_insn == 0xe97fe97f;
 }
 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ARM 11/11, ping] Add support for stable secure gateway veneers addresses
  2016-08-29 14:56                       ` Christophe Lyon
@ 2016-08-30  8:10                         ` Thomas Preudhomme
  2016-08-30  8:56                           ` Christophe Lyon
  0 siblings, 1 reply; 15+ messages in thread
From: Thomas Preudhomme @ 2016-08-30  8:10 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: binutils

Hi Christophe,

On 29/08/16 15:56, Christophe Lyon wrote:
> On 26 August 2016 at 16:18, Thomas Preudhomme
> <thomas.preudhomme@foss.arm.com> wrote:
>> On 26/08/16 13:36, Thomas Preudhomme wrote:
>>>
>>> Hi Christophe,
>>>
>>> On 26/08/16 12:55, Christophe Lyon wrote:
>>>>
>>>>
>>>> I've noticed that the new tests fail on armeb. I didn't look at the
>>>> detailed logs yet, but I guess you can a look?
>>>>
>>>> ./ld/ld.sum:FAIL: Input secure gateway import library
>>>> ./ld/ld.sum:FAIL: Input secure gateway import library: no output import
>>>> library
>>>> ./ld/ld.sum:FAIL: Input secure gateway import library: earlier stub
>>>> section base
>>>> ./ld/ld.sum:FAIL: Input secure gateway import library: later stub section
>>>> base
>>>> ./ld/ld.sum:FAIL: Input secure gateway import library: veneer comeback
>>>> ./ld/ld.sum:FAIL: Input secure gateway import library: entry function
>>>> change
>>>
>>>
>>> I can reproduce indeed. I'll have a look, thanks for the notice. Note that
>>> Monday is a bank holidays here so might only answer after that if I'm too
>>> slow
>>> to find the root cause.
>>
>>
>> Doh, the code checks for a SG instruction by comparing the 4 bytes in the
>> code against its litteral value. The problem of course is that the read puts
>> the 4 bytes of the instruction in memory order but these will then be
>> interpreted according to the endianness.
>>
>> The fix should be easy.
>>
>
> Indeed, thanks to your analysis it was quick enough.
>
> Here is a patch, maybe there is a simpler way?

diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 9ff418a..5c04b9b 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -5791,11 +5791,19 @@ cmse_entry_fct_p (struct elf32_arm_link_hash_entry *hash)
    section = hash->root.root.u.def.section;
    abfd = section->owner;
    offset = hash->root.root.u.def.value - section->vma;
-  if (!bfd_get_section_contents (abfd, section, &first_insn, offset,
-				 sizeof (first_insn)))
-    return FALSE;

    /* Start by SG instruction.  */
+  bfd_byte * contents;
+  /* Get cached copy if it exists.  */
+  if (elf_section_data (section)->this_hdr.contents != NULL)
+    contents = elf_section_data (section)->this_hdr.contents;
+  else
+    {
+      /* Go get them off disk.  */
+      if (! bfd_malloc_and_get_section (abfd, section, &contents))
+	return FALSE;
+    }
+  first_insn = bfd_get_32 (abfd, contents + offset);
    return first_insn == 0xe97fe97f;
  }

I have a similar patch but I'm still using bfd_get_section_contents with a 4byte 
buffer named contents. It avoids reading the entire section to just analyze 4 
bytes. I did it on Friday so wanted to test it a bit more today.

Best regards,

Thomas

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ARM 11/11, ping] Add support for stable secure gateway veneers addresses
  2016-08-30  8:10                         ` Thomas Preudhomme
@ 2016-08-30  8:56                           ` Christophe Lyon
  2016-08-30  9:49                             ` Thomas Preudhomme
  0 siblings, 1 reply; 15+ messages in thread
From: Christophe Lyon @ 2016-08-30  8:56 UTC (permalink / raw)
  To: Thomas Preudhomme; +Cc: binutils

On 30 August 2016 at 10:10, Thomas Preudhomme
<thomas.preudhomme@foss.arm.com> wrote:
> Hi Christophe,
>
>
> On 29/08/16 15:56, Christophe Lyon wrote:
>>
>> On 26 August 2016 at 16:18, Thomas Preudhomme
>> <thomas.preudhomme@foss.arm.com> wrote:
>>>
>>> On 26/08/16 13:36, Thomas Preudhomme wrote:
>>>>
>>>>
>>>> Hi Christophe,
>>>>
>>>> On 26/08/16 12:55, Christophe Lyon wrote:
>>>>>
>>>>>
>>>>>
>>>>> I've noticed that the new tests fail on armeb. I didn't look at the
>>>>> detailed logs yet, but I guess you can a look?
>>>>>
>>>>> ./ld/ld.sum:FAIL: Input secure gateway import library
>>>>> ./ld/ld.sum:FAIL: Input secure gateway import library: no output import
>>>>> library
>>>>> ./ld/ld.sum:FAIL: Input secure gateway import library: earlier stub
>>>>> section base
>>>>> ./ld/ld.sum:FAIL: Input secure gateway import library: later stub
>>>>> section
>>>>> base
>>>>> ./ld/ld.sum:FAIL: Input secure gateway import library: veneer comeback
>>>>> ./ld/ld.sum:FAIL: Input secure gateway import library: entry function
>>>>> change
>>>>
>>>>
>>>>
>>>> I can reproduce indeed. I'll have a look, thanks for the notice. Note
>>>> that
>>>> Monday is a bank holidays here so might only answer after that if I'm
>>>> too
>>>> slow
>>>> to find the root cause.
>>>
>>>
>>>
>>> Doh, the code checks for a SG instruction by comparing the 4 bytes in the
>>> code against its litteral value. The problem of course is that the read
>>> puts
>>> the 4 bytes of the instruction in memory order but these will then be
>>> interpreted according to the endianness.
>>>
>>> The fix should be easy.
>>>
>>
>> Indeed, thanks to your analysis it was quick enough.
>>
>> Here is a patch, maybe there is a simpler way?
>
>
> diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
> index 9ff418a..5c04b9b 100644
> --- a/bfd/elf32-arm.c
> +++ b/bfd/elf32-arm.c
> @@ -5791,11 +5791,19 @@ cmse_entry_fct_p (struct elf32_arm_link_hash_entry
> *hash)
>    section = hash->root.root.u.def.section;
>    abfd = section->owner;
>    offset = hash->root.root.u.def.value - section->vma;
> -  if (!bfd_get_section_contents (abfd, section, &first_insn, offset,
> -                                sizeof (first_insn)))
> -    return FALSE;
>
>    /* Start by SG instruction.  */
> +  bfd_byte * contents;
> +  /* Get cached copy if it exists.  */
> +  if (elf_section_data (section)->this_hdr.contents != NULL)
> +    contents = elf_section_data (section)->this_hdr.contents;
> +  else
> +    {
> +      /* Go get them off disk.  */
> +      if (! bfd_malloc_and_get_section (abfd, section, &contents))
> +       return FALSE;
> +    }
> +  first_insn = bfd_get_32 (abfd, contents + offset);
>    return first_insn == 0xe97fe97f;
>  }
>
> I have a similar patch but I'm still using bfd_get_section_contents with a
> 4byte buffer named contents. It avoids reading the entire section to just
> analyze 4 bytes. I did it on Friday so wanted to test it a bit more today.
>

OK that's fine, it sounds better than mine. I posted mine because
I wasn't sure you were actually working on a fix.

Thanks

Christophe

> Best regards,
>
> Thomas

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ARM 11/11, ping] Add support for stable secure gateway veneers addresses
  2016-08-30  8:56                           ` Christophe Lyon
@ 2016-08-30  9:49                             ` Thomas Preudhomme
  0 siblings, 0 replies; 15+ messages in thread
From: Thomas Preudhomme @ 2016-08-30  9:49 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: binutils



On 30/08/16 09:56, Christophe Lyon wrote:
> On 30 August 2016 at 10:10, Thomas Preudhomme
> <thomas.preudhomme@foss.arm.com> wrote:
>> Hi Christophe,
>>
>>
>> On 29/08/16 15:56, Christophe Lyon wrote:
>>>
>>> On 26 August 2016 at 16:18, Thomas Preudhomme
>>> <thomas.preudhomme@foss.arm.com> wrote:
>>>>
>>>> On 26/08/16 13:36, Thomas Preudhomme wrote:
>>>>>
>>>>>
>>>>> Hi Christophe,
>>>>>
>>>>> On 26/08/16 12:55, Christophe Lyon wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> I've noticed that the new tests fail on armeb. I didn't look at the
>>>>>> detailed logs yet, but I guess you can a look?
>>>>>>
>>>>>> ./ld/ld.sum:FAIL: Input secure gateway import library
>>>>>> ./ld/ld.sum:FAIL: Input secure gateway import library: no output import
>>>>>> library
>>>>>> ./ld/ld.sum:FAIL: Input secure gateway import library: earlier stub
>>>>>> section base
>>>>>> ./ld/ld.sum:FAIL: Input secure gateway import library: later stub
>>>>>> section
>>>>>> base
>>>>>> ./ld/ld.sum:FAIL: Input secure gateway import library: veneer comeback
>>>>>> ./ld/ld.sum:FAIL: Input secure gateway import library: entry function
>>>>>> change
>>>>>
>>>>>
>>>>>
>>>>> I can reproduce indeed. I'll have a look, thanks for the notice. Note
>>>>> that
>>>>> Monday is a bank holidays here so might only answer after that if I'm
>>>>> too
>>>>> slow
>>>>> to find the root cause.
>>>>
>>>>
>>>>
>>>> Doh, the code checks for a SG instruction by comparing the 4 bytes in the
>>>> code against its litteral value. The problem of course is that the read
>>>> puts
>>>> the 4 bytes of the instruction in memory order but these will then be
>>>> interpreted according to the endianness.
>>>>
>>>> The fix should be easy.
>>>>
>>>
>>> Indeed, thanks to your analysis it was quick enough.
>>>
>>> Here is a patch, maybe there is a simpler way?
>>
>>
>> diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
>> index 9ff418a..5c04b9b 100644
>> --- a/bfd/elf32-arm.c
>> +++ b/bfd/elf32-arm.c
>> @@ -5791,11 +5791,19 @@ cmse_entry_fct_p (struct elf32_arm_link_hash_entry
>> *hash)
>>    section = hash->root.root.u.def.section;
>>    abfd = section->owner;
>>    offset = hash->root.root.u.def.value - section->vma;
>> -  if (!bfd_get_section_contents (abfd, section, &first_insn, offset,
>> -                                sizeof (first_insn)))
>> -    return FALSE;
>>
>>    /* Start by SG instruction.  */
>> +  bfd_byte * contents;
>> +  /* Get cached copy if it exists.  */
>> +  if (elf_section_data (section)->this_hdr.contents != NULL)
>> +    contents = elf_section_data (section)->this_hdr.contents;
>> +  else
>> +    {
>> +      /* Go get them off disk.  */
>> +      if (! bfd_malloc_and_get_section (abfd, section, &contents))
>> +       return FALSE;
>> +    }
>> +  first_insn = bfd_get_32 (abfd, contents + offset);
>>    return first_insn == 0xe97fe97f;
>>  }
>>
>> I have a similar patch but I'm still using bfd_get_section_contents with a
>> 4byte buffer named contents. It avoids reading the entire section to just
>> analyze 4 bytes. I did it on Friday so wanted to test it a bit more today.
>>
>
> OK that's fine, it sounds better than mine. I posted mine because
> I wasn't sure you were actually working on a fix.

I am, will post the patch later today. Thanks for providing a fix.

Best regards,

Thomas

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2016-08-30  9:49 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-23  8:02 [RFC PATCH, binutils, ARM 9/9] Add support for stable secure gateway veneers addresses Thomas Preud'homme
2016-04-04 14:23 ` [RFC PATCH, binutils, ARM 11/11] " Thomas Preudhomme
2016-05-18 16:41   ` [PATCH, " Thomas Preudhomme
2016-07-07 12:52   ` [RFC PATCH, " Richard Earnshaw (lists)
     [not found]     ` <1735561.4TLJhTojVK@e108577-lin>
2016-07-15  8:43       ` Thomas Preudhomme
     [not found]     ` <4163700.8nzTNaTl0I@e108577-lin>
     [not found]       ` <f4e62f04-bebc-135d-372a-d29bdb4efcf0@foss.arm.com>
2016-08-17 15:23         ` [RFC PATCH, binutils, ARM 11/11, ping] " Thomas Preudhomme
2016-08-25 16:14           ` Richard Earnshaw (lists)
2016-08-25 16:35             ` Thomas Preudhomme
2016-08-26  9:21               ` Richard Earnshaw (lists)
     [not found]                 ` <CAKdteOZ4uC=dOKO5WoysePRT1is9rvX4etjgj1iK5Hj23TSdLw@mail.gmail.com>
2016-08-26 12:37                   ` Thomas Preudhomme
2016-08-26 14:18                     ` Thomas Preudhomme
2016-08-29 14:56                       ` Christophe Lyon
2016-08-30  8:10                         ` Thomas Preudhomme
2016-08-30  8:56                           ` Christophe Lyon
2016-08-30  9:49                             ` Thomas Preudhomme

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).