This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC PATCH, binutils, ARM 11/11, ping] Add support for stable secure gateway veneers addresses


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
>>>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]