]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Add support for stable secure gateway veneers addresses
authorThomas Preud'homme <thomas.preudhomme@arm.com>
Tue, 29 Mar 2016 19:36:43 +0000 (20:36 +0100)
committerThomas Preud'homme <thomas.preudhomme@arm.com>
Tue, 29 Mar 2016 19:36:43 +0000 (20:36 +0100)
2016-03-29  Thomas Preud'homme  <thomas.preudhomme@arm.com>

bfd/
* 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/
* 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.

ld/testsuite/
* 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-implib-no-output.out: Likewise.
* ld-arm/cmse-new-earlier-later-implib.out: Likewise.
* ld-arm/cmse-new-comeback-implib.rd: Likewise.
* ld-arm/cmse-new-wrong-implib.out: Likewise.

16 files changed:
bfd/ChangeLog.arm
bfd/bfd-in.h
bfd/bfd-in2.h
bfd/elf32-arm.c
ld/ChangeLog.arm
ld/emultempl/armelf.em
ld/ld.texinfo
ld/testsuite/ChangeLog.arm
ld/testsuite/ld-arm/arm-elf.exp
ld/testsuite/ld-arm/cmse-implib.s
ld/testsuite/ld-arm/cmse-new-comeback-implib.rd [new file with mode: 0644]
ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out [new file with mode: 0644]
ld/testsuite/ld-arm/cmse-new-implib-no-output.out [new file with mode: 0644]
ld/testsuite/ld-arm/cmse-new-implib.out [new file with mode: 0644]
ld/testsuite/ld-arm/cmse-new-implib.rd [new file with mode: 0644]
ld/testsuite/ld-arm/cmse-new-wrong-implib.out [new file with mode: 0644]

index 1506ecbe2025ac37468ba9800d6b88c4d18aacf3..65e8b4461959b292ff65b79e22720d6a47e586ec 100644 (file)
@@ -1,3 +1,41 @@
+2016-03-29  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.
+
 2016-03-29  Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
        * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add one parameter.
index 4144401d12ed1b98c0be3614c0f204bbc11886f8..5e6e980584978042f43e1dc11989ac84f2e15d3f 100644 (file)
@@ -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 *);
index c7c7fac542a6f9fbabf506e30cd11340c8c13d2e..fe7e11931f5ba1ca179cd800f94d5fddd7f47724 100644 (file)
@@ -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 *);
index e35bd58207c746d12d35c9990019c84ba29f8e61..1bbcef0f1bc2f6f3382afb3c35f25d4a8b463546 100644 (file)
@@ -3068,6 +3068,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;
 
@@ -3129,6 +3133,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;
 
@@ -3380,7 +3388,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;
@@ -3388,7 +3396,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;
@@ -4299,7 +4307,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;
@@ -4463,6 +4471,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)
@@ -4482,6 +4530,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;
@@ -4498,8 +4547,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;
@@ -4573,7 +4626,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.  */
@@ -4585,7 +4639,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++)
     {
@@ -4687,9 +4741,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;
@@ -5254,10 +5316,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,
@@ -5288,7 +5350,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,
@@ -5299,7 +5361,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);
@@ -5307,7 +5369,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;
@@ -5328,7 +5390,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
@@ -5348,7 +5410,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
@@ -5365,14 +5427,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;
@@ -5383,7 +5446,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;
@@ -5524,17 +5588,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)++;
        }
     }
 
@@ -5543,6 +5607,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
@@ -5559,7 +5890,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);
@@ -5592,6 +5925,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.  */
@@ -5665,8 +5999,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.  */
@@ -5892,6 +6229,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,
@@ -5903,12 +6241,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)
@@ -5982,6 +6321,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;
 
@@ -6001,6 +6345,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;
@@ -6069,7 +6430,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;
@@ -6097,7 +6458,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;
@@ -6114,6 +6475,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);
@@ -6131,14 +6493,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);
@@ -8121,7 +8502,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;
 
@@ -8149,6 +8531,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;
index 4a04ca2e96de0295d24117d962cb8ae00b6ddcb3..cc662f2d1b46af166ee1c2e8964f8c23c6b7f8f5 100644 (file)
@@ -1,3 +1,31 @@
+2016-03-29  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.
+
 2016-03-29  Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
        * emultempl/armelf.em (cmse_implib): Declare and define this new
index 6a1984625c8db4b82308f845f607bcb810f7d305..e6f5757ddf8807f48e1d4cfb39e8c59bb606b036 100644 (file)
@@ -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)
@@ -488,6 +489,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.
@@ -498,6 +501,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,
@@ -505,7 +522,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,
@@ -575,6 +592,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
@@ -602,6 +620,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='
@@ -624,6 +643,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\
@@ -748,6 +769,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
index 5ee4c45aca6558db017539fc56cc4c30c2d26d0b..09e8b1ef5d74e03ba2ec0e752eb7b354343c93d9 100644 (file)
@@ -6823,6 +6823,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
index 929771a9c6157d9ba5573ab699b2075687ec9491..598ee9cdbc19576cea3e5de69d122c2926139320 100644 (file)
@@ -1,3 +1,14 @@
+2016-03-29  Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
+       * 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.
+
 2016-03-29  Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
        * testsuite/ld-arm/arm-elf.exp
index 100b9645ef134988a68186661e37309f2b0ba8ef..1fb566908269bb3bc05a9a576ed0a58ad92643f3 100644 (file)
@@ -625,16 +625,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" ""
index a42da63fffebe5322be83f278931754262b0f7ae..9dd783939891478351a5f7ccb1480980a77dca68 100644 (file)
@@ -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 (file)
index 0000000..c88d9d5
--- /dev/null
@@ -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 (file)
index 0000000..b49ad0a
--- /dev/null
@@ -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 (file)
index 0000000..0590b71
--- /dev/null
@@ -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 (file)
index 0000000..c8af280
--- /dev/null
@@ -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 (file)
index 0000000..9ff0fd8
--- /dev/null
@@ -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 (file)
index 0000000..2afe407
--- /dev/null
@@ -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