This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH, binutils, ARM 11/11] Add support for stable secure gateway veneers addresses
- From: Thomas Preudhomme <thomas dot preudhomme at foss dot arm dot com>
- To: binutils at sourceware dot org
- Cc: richard dot earnshaw at arm dot com, nickc at redhat dot com
- Date: Wed, 18 May 2016 17:41:40 +0100
- Subject: Re: [PATCH, binutils, ARM 11/11] Add support for stable secure gateway veneers addresses
- Authentication-results: sourceware.org; auth=none
- References: <005601d13d58$522afb60$f680f220$ at foss dot arm dot com> <1796369 dot 8BmbsroDJA at e108577-lin>
[CCing Richard Earnshaw and Nick Clifton who reviewed previous ARMv8-M
patches]
On Monday 04 April 2016 15:23 Thomas Preud'homme wrote:
> On Wednesday 23 December 2015 16:02:48 Thomas Preud'homme wrote:
> > Hi,
> >
> > [Posting patch series as RFC]
> >
> > This patch is part of a patch series to add support for ARMv8-M
> > security extension[1] to GNU ld. This specific patch adds support for
> > allowing Secure Gateway veneers to have stable addresses when
> > relinking a secure executable.
> >
> > ARM v8-M security extensions allow code running in a device to be
> > divided into secure and non-secure code expected to be developed by
> > independent (teams of) people. To allow updating the secure code
> > without the need to relink the non-secure code against it, it is
> > necessary for the toolchain to provide a way to fix the addresses of
> > the secure gateway veneers that serve as entry points for non-secure
> > code to call secure code. This is also a requirement [2] to claim support
for
> ARM v8-M security extensions.
> >
> > This patch adds a --in-implib=<in_implib_filename> option which, when
> > used in conjunction of --cmse-implib will ensure that the veneers
> > whose symbols are defined in the import library $in_implib_filename
> > will remain at the same address in the executable. In the absence of a
> > --out-implib option, the code will warn about new secure gateway
> > veneers being created, otherwise these are allowed.
> >
> >
> > [1] Software requirements for ARMv8-M security extension are described
> > in document ARM-ECM-0359818 [2] [2] Available on
> > http://infocenter.arm.com in Developer guides and articles > Software
> > development > ARMÂv8-M Security
> > Extensions: Requirements on Development Tools [3] See requirement 15
> > of
> > ARM-ECM-0359818 [2]
>
> Please find an updated patch below.
Please find an updated patch below, following the fix to the issue hilighted by
Christophe Lyon in patch 2/11 (Factor our stub creation in ARM backend).
ChangeLog entries are unchanged:
*** bfd/ChangeLog ***
2016-02-18 Thomas Preud'homme <thomas.preudhomme@arm.com>
* bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new parameter for
the input import library bfd.
* bfd-in2.h: Regenerate.
* elf32-arm.c (struct elf32_arm_link_hash_table): New in_implib_bfd
and new_cmse_stub_offset fields.
(stub_hash_newfunc): Initialize stub_offset and stub_template_size to
-1.
(elf32_arm_add_stub): Likewise for stub_offset.
(arm_new_stubs_start_offset_ptr): New function.
(arm_build_one_stub): Only allocate a stub_offset if it is -1. Allow
empty veneers to have zero relocations.
(arm_size_one_stub): Only initialize stub size and template
information for non empty veneers. Do not update veneer section size
if veneer already has an offset.
(elf32_arm_create_stub): Return the stub entry pointer or NULL instead
of a boolean indicating success or failure.
(cmse_scan): Change stub_changed parameter into an integer pointer
parameter cmse_stub_created to count the number of stub created and
adapt to change of return value in elf32_arm_create_stub.
(cmse_entry_fct_p): New function.
(arm_list_new_cmse_stub): Likewise.
(set_cmse_veneer_addr_from_implib): Likewise.
(elf32_arm_size_stubs): Define cmse_stub_created, pass its address to
cmse_scan instead of that of cmse_stub_changed to compute the number
of stub created and use it to initialize stub_changed. Call
set_cmse_veneer_addr_from_implib after all cmse_scan. Adapt to change
of return value in elf32_arm_create_stub. Use
arm_stub_section_start_offset () if not NULL to initialize size of
secure gateway veneers section. Initialize stub_offset of Cortex-A8
erratum fix to -1. Use ret to hold return value.
(elf32_arm_build_stubs): Use arm_stub_section_start_offset () if not
NULL to initialize size of secure gateway veneers section. Adapt
comment to stress the importance of zeroing veneer section content.
(bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd parameter to
initialize eponymous field in struct elf32_arm_link_hash_table.
*** ld/ChangeLog ***
2016-02-18 Thomas Preud'homme <thomas.preudhomme@arm.com>
* emultempl/armelf.em (in_implib_filename): Declare and initialize new
variable.
(arm_elf_create_output_section_statements): Open import input library
file for writing and pass resulting in_implib_bfd to
bfd_elf32_arm_set_target_relocs.
(PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option.
(PARSE_AND_LIST_LONGOPTS): Define --in-implib option.
(PARSE_AND_LIST_OPTIONS): Add help message for --in-implib option.
(PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case.
* ld.texinfo (--cmse-implib): Update to mention --in-implib.
(--in-implib): Document new option.
* testsuite/ld-arm/arm-elf.exp
(Secure gateway import library generation): add --defsym VER=1 to gas
CLI.
(Secure gateway import library generation: errors): Likewise.
(Input secure gateway import library): New test.
(Input secure gateway import library: no output import library):
Likewise.
(Input secure gateway import library: earlier stub section base):
Likewise.
(Input secure gateway import library: later stub section base):
Likewise.
(Input secure gateway import library: veneer comeback): Likewise.
(Input secure gateway import library: entry function change):
Likewise.
* testsuite/ld-arm/cmse-implib.s: Add input import library testing.
* testsuite/ld-arm/cmse-implib.rd: Update accordingly.
* testsuite/ld-arm/cmse-new-implib.out: New file.
* testsuite/ld-arm/cmse-new-implib.rd: Likewise.
* testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise.
* testsuite/ld-arm/cmse-new-earlier-later-implib.out: Likewise.
* testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise.
* testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise.
diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index
d7f77d7650b8f4f23f2106c61c72fc238575d35a..140ddf463f6fffb00bace2f96b8365b71c962152
100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.h
@@ -895,7 +895,7 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation
void bfd_elf32_arm_set_target_relocs
(bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix,
- bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
+ bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
(bfd *, struct bfd_link_info *);
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index
c7ba6427a5fd02a53a7bcbc042ac741456ddb213..b3db448d56ba850d998bcd21a4d9adc8aeabdd2e
100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -902,7 +902,7 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation
void bfd_elf32_arm_set_target_relocs
(bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix,
- bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
+ bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
(bfd *, struct bfd_link_info *);
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index
1c9d97c4fa6af07a858d67f541e51fc49c4d40ee..d2a5de46b0819b7f1ad433507bfa86107befc3c1
100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -3128,6 +3128,10 @@ struct elf32_arm_link_hash_table
as per ARMv8-M Security Extensions. */
int cmse_implib;
+ /* The import library whose symbols' address must remain stable in
+ the import library generated. */
+ bfd *in_implib_bfd;
+
/* The index of the next unused R_ARM_TLS_DESC slot in .rel.plt. */
bfd_vma next_tls_desc_index;
@@ -3189,6 +3193,10 @@ struct elf32_arm_link_hash_table
/* Input stub section holding secure gateway veneers. */
asection *cmse_stub_sec;
+ /* Offset in cmse_stub_sec where new SG veneers (not in input import
library)
+ start to be allocated. */
+ bfd_vma new_cmse_stub_offset;
+
/* Number of elements in stub_group. */
unsigned int top_id;
@@ -3440,7 +3448,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
/* Initialize the local fields. */
eh = (struct elf32_arm_stub_hash_entry *) entry;
eh->stub_sec = NULL;
- eh->stub_offset = 0;
+ eh->stub_offset = (bfd_vma) -1;
eh->source_value = 0;
eh->target_value = 0;
eh->target_section = NULL;
@@ -3448,7 +3456,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
eh->stub_type = arm_stub_none;
eh->stub_size = 0;
eh->stub_template = NULL;
- eh->stub_template_size = 0;
+ eh->stub_template_size = -1;
eh->h = NULL;
eh->id_sec = NULL;
eh->output_name = NULL;
@@ -4362,7 +4370,7 @@ elf32_arm_add_stub (const char *stub_name, asection
*section,
}
stub_entry->stub_sec = stub_sec;
- stub_entry->stub_offset = 0;
+ stub_entry->stub_offset = (bfd_vma) -1;
stub_entry->id_sec = link_sec;
return stub_entry;
@@ -4526,6 +4534,46 @@ arm_dedicated_stub_section_padding (enum
elf32_arm_stub_type stub_type)
abort (); /* Should be unreachable. */
}
+/* If veneers of type STUB_TYPE should go in a dedicated output section,
+ returns the address of the hash table field in HTAB holding the offset at
+ which new veneers should be layed out in the stub section. */
+
+static bfd_vma*
+arm_new_stubs_start_offset_ptr (struct elf32_arm_link_hash_table *htab,
+ enum elf32_arm_stub_type stub_type)
+{
+ switch (stub_type)
+ {
+ case arm_stub_a8_veneer_b_cond:
+ case arm_stub_a8_veneer_b:
+ case arm_stub_a8_veneer_bl:
+ case arm_stub_long_branch_any_any:
+ case arm_stub_long_branch_v4t_arm_thumb:
+ case arm_stub_long_branch_thumb_only:
+ case arm_stub_long_branch_v4t_thumb_thumb:
+ case arm_stub_long_branch_v4t_thumb_arm:
+ case arm_stub_short_branch_v4t_thumb_arm:
+ case arm_stub_long_branch_any_arm_pic:
+ case arm_stub_long_branch_any_thumb_pic:
+ case arm_stub_long_branch_v4t_thumb_thumb_pic:
+ case arm_stub_long_branch_v4t_arm_thumb_pic:
+ case arm_stub_long_branch_v4t_thumb_arm_pic:
+ case arm_stub_long_branch_thumb_only_pic:
+ case arm_stub_long_branch_any_tls_pic:
+ case arm_stub_long_branch_v4t_thumb_tls_pic:
+ case arm_stub_a8_veneer_blx:
+ case arm_stub_long_branch_arm_nacl:
+ case arm_stub_long_branch_arm_nacl_pic:
+ return NULL;
+
+ case arm_stub_cmse_branch_thumb_only:
+ return &htab->new_cmse_stub_offset;
+
+ default:
+ abort (); /* Should be unreachable. */
+ }
+}
+
static bfd_boolean
arm_build_one_stub (struct bfd_hash_entry *gen_entry,
void * in_arg)
@@ -4545,6 +4593,7 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
int stub_reloc_idx[MAXRELOCS] = {-1, -1};
int stub_reloc_offset[MAXRELOCS] = {0, 0};
int nrelocs = 0;
+ int just_allocated = 0;
/* Massage our args to the form they really have. */
stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
@@ -4561,8 +4610,12 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
/* We have to do less-strictly-aligned fixes last. */
return TRUE;
- /* Make a note of the offset within the stubs for this entry. */
- stub_entry->stub_offset = stub_sec->size;
+ /* Assign a slot at the end of section if none assigned yet. */
+ if (stub_entry->stub_offset == (bfd_vma) -1)
+ {
+ stub_entry->stub_offset = stub_sec->size;
+ just_allocated = 1;
+ }
loc = stub_sec->contents + stub_entry->stub_offset;
stub_bfd = stub_sec->owner;
@@ -4636,7 +4689,8 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
}
}
- stub_sec->size += size;
+ if (just_allocated)
+ stub_sec->size += size;
/* Stub size has already been computed in arm_size_one_stub. Check
consistency. */
@@ -4648,7 +4702,7 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
/* Assume there is at least one and at most MAXRELOCS entries to relocate
in each stub. */
- BFD_ASSERT (nrelocs != 0 && nrelocs <= MAXRELOCS);
+ BFD_ASSERT (size == 0 || (nrelocs != 0 && nrelocs <= MAXRELOCS));
for (i = 0; i < nrelocs; i++)
{
@@ -4750,9 +4804,17 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry,
size = find_stub_size_and_template (stub_entry->stub_type,
&template_sequence,
&template_size);
- stub_entry->stub_size = size;
- stub_entry->stub_template = template_sequence;
- stub_entry->stub_template_size = template_size;
+ /* Initialized to -1. Null size indicates a zeroed out veneer. */
+ if (stub_entry->stub_template_size)
+ {
+ stub_entry->stub_size = size;
+ stub_entry->stub_template = template_sequence;
+ stub_entry->stub_template_size = template_size;
+ }
+
+ /* Already accounted for. */
+ if (stub_entry->stub_offset != (bfd_vma) -1)
+ return TRUE;
size = (size + 7) & ~7;
stub_entry->stub_sec->size += size;
@@ -5317,10 +5379,10 @@ cortex_a8_erratum_scan (bfd *input_bfd,
and *NEW_STUB is set to FALSE. Otherwise, *NEW_STUB is set to
TRUE and the stub entry is initialized.
- Returns whether the stub could be successfully created or updated, or
FALSE
- if an error occured. */
+ Returns the stub that was created or updated, or NULL if an error
+ occured. */
-static bfd_boolean
+static struct elf32_arm_stub_hash_entry *
elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
enum elf32_arm_stub_type stub_type, asection *section,
Elf_Internal_Rela *irela, asection *sym_sec,
@@ -5351,7 +5413,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table
*htab,
stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash, irela,
stub_type);
if (!stub_name)
- return FALSE;
+ return NULL;
}
stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, stub_name,
FALSE,
@@ -5362,7 +5424,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table
*htab,
if (!sym_claimed)
free (stub_name);
stub_entry->target_value = sym_value;
- return TRUE;
+ return stub_entry;
}
stub_entry = elf32_arm_add_stub (stub_name, section, htab, stub_type);
@@ -5370,7 +5432,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table
*htab,
{
if (!sym_claimed)
free (stub_name);
- return FALSE;
+ return NULL;
}
stub_entry->target_value = sym_value;
@@ -5391,7 +5453,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table
*htab,
if (stub_entry->output_name == NULL)
{
free (stub_name);
- return FALSE;
+ return NULL;
}
/* For historical reasons, use the existing names for ARM-to-Thumb and
@@ -5411,7 +5473,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table
*htab,
}
*new_stub = TRUE;
- return TRUE;
+ return stub_entry;
}
/* Scan symbols in INPUT_BFD to identify secure entry functions needing a
@@ -5428,14 +5490,15 @@ elf32_arm_create_stub (struct
elf32_arm_link_hash_table *htab,
OUT_ATTR gives the output attributes, SYM_HASHES the symbol index to hash
entry mapping while HTAB gives the name to hash entry mapping.
+ *CMSE_STUB_CREATED is increased by the number of secure gateway veneer
+ created.
- If any secure gateway veneer is created, *STUB_CHANGED is set to TRUE.
The
- return value gives whether a stub failed to be allocated. */
+ The return value gives whether a stub failed to be allocated. */
static bfd_boolean
cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
obj_attribute *out_attr, struct elf_link_hash_entry **sym_hashes,
- bfd_boolean *stub_changed)
+ int *cmse_stub_created)
{
const struct elf_backend_data *bed;
Elf_Internal_Shdr *symtab_hdr;
@@ -5446,7 +5509,8 @@ cmse_scan (bfd *input_bfd, struct
elf32_arm_link_hash_table *htab,
char *sym_name, *lsym_name;
bfd_vma sym_value;
asection *section;
- bfd_boolean is_v8m, new_stub, created_stub, cmse_invalid, ret = TRUE;
+ struct elf32_arm_stub_hash_entry *stub_entry;
+ bfd_boolean is_v8m, new_stub, cmse_invalid, ret = TRUE;
bed = get_elf_backend_data (input_bfd);
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
@@ -5587,17 +5651,17 @@ cmse_scan (bfd *input_bfd, struct
elf32_arm_link_hash_table *htab,
if (!ret)
continue;
branch_type = ARM_GET_SYM_BRANCH_TYPE (hash->root.target_internal);
- created_stub
+ stub_entry
= elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
NULL, NULL, section, hash, sym_name,
sym_value, branch_type, &new_stub);
- if (!created_stub)
+ if (stub_entry == NULL)
ret = FALSE;
else
{
BFD_ASSERT (new_stub);
- *stub_changed = TRUE;
+ (*cmse_stub_created)++;
}
}
@@ -5606,6 +5670,273 @@ cmse_scan (bfd *input_bfd, struct
elf32_arm_link_hash_table *htab,
return ret;
}
+/* Return whether a symbol identified by its linker HASH entry is an entry
+ function, ie can be called from non secure code without using a veneer.
*/
+
+static bfd_boolean
+cmse_entry_fct_p (struct elf32_arm_link_hash_entry *hash)
+{
+ uint32_t first_insn;
+ asection *section;
+ file_ptr offset;
+ bfd *abfd;
+
+ /* Defined symbol of function type. */
+ if (hash->root.root.type != bfd_link_hash_defined
+ && hash->root.root.type != bfd_link_hash_defweak)
+ return FALSE;
+ if (hash->root.type != STT_FUNC)
+ return FALSE;
+
+ /* Read first instruction. */
+ section = hash->root.root.u.def.section;
+ abfd = section->owner;
+ offset = hash->root.root.u.def.value - section->vma;
+ if (!bfd_get_section_contents (abfd, section, &first_insn, offset,
+ sizeof (first_insn)))
+ return FALSE;
+
+ /* Start by SG instruction. */
+ return first_insn == 0xe97fe97f;
+}
+
+/* Output the name (in symbol table) of the veneer GEN_ENTRY if it is a new
+ secure gateway veneers (ie. the veneers was not in the input import
library)
+ and there is no output import library (GEN_INFO->out_implib_bfd is NULL.
*/
+
+static bfd_boolean
+arm_list_new_cmse_stub (struct bfd_hash_entry *gen_entry, void *gen_info)
+{
+ struct elf32_arm_stub_hash_entry *stub_entry;
+ struct bfd_link_info *info;
+
+ /* Massage our args to the form they really have. */
+ stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
+ info = (struct bfd_link_info *) gen_info;
+
+ if (info->out_implib_bfd)
+ return TRUE;
+
+ if (stub_entry->stub_type != arm_stub_cmse_branch_thumb_only)
+ return TRUE;
+
+ if (stub_entry->stub_offset == (bfd_vma) -1)
+ (*_bfd_error_handler) (" %s", stub_entry->output_name);
+
+ return TRUE;
+}
+
+/* Set offset of secure gateway veneers so that their address remain identical
+ to the one in the input import library referred by HTAB->in_implib_bfd. A
+ warning is issued for veneers that disappeared (present in input import
+ library but absent from the executable being linked) or if new veneers
+ appeared and there is no output import library (INFO->out_implib_bfd is
NULL
+ and *CMSE_STUB_CREATED is bigger than the number of secure gateway veneers
+ found in the input import library.
+
+ The function returns whether an error occured. If no error occured,
+ *CMSE_STUB_CREATED gives the number of SG veneers created by both
cmse_scan
+ and this function and HTAB->new_cmse_stub_offset is set to the biggest
+ veneer observed set for new veneers to be layed out after. */
+
+static bfd_boolean
+set_cmse_veneer_addr_from_implib (struct bfd_link_info *info,
+ struct elf32_arm_link_hash_table *htab,
+ int *cmse_stub_created)
+{
+ long symsize;
+ char *sym_name;
+ flagword flags;
+ long i, symcount;
+ bfd *in_implib_bfd;
+ asection *stub_out_sec;
+ bfd_boolean ret = TRUE;
+ Elf_Internal_Sym *intsym;
+ const char *out_sec_name;
+ bfd_size_type cmse_stub_size;
+ asymbol **sympp = NULL, *sym;
+ struct elf32_arm_link_hash_entry *hash;
+ const insn_sequence *cmse_stub_template;
+ struct elf32_arm_stub_hash_entry *stub_entry;
+ int cmse_stub_template_size, new_cmse_stubs_created = *cmse_stub_created;
+ bfd_vma veneer_value, stub_offset, next_cmse_stub_offset;
+ bfd_vma cmse_stub_array_start = (bfd_vma) -1, cmse_stub_sec_vma = 0;
+
+ /* No input secure gateway import library. */
+ if (!htab->in_implib_bfd)
+ return TRUE;
+ else if (!htab->cmse_implib)
+ return FALSE;
+
+ /* Get symbol table size. */
+ in_implib_bfd = htab->in_implib_bfd;
+ symsize = bfd_get_symtab_upper_bound (in_implib_bfd);
+ if (symsize < 0)
+ return FALSE;
+
+ /* Read in the input secure gateway import library's symbol table. */
+ sympp = (asymbol **) xmalloc (symsize);
+ symcount = bfd_canonicalize_symtab (in_implib_bfd, sympp);
+ if (symcount < 0)
+ {
+ ret = FALSE;
+ goto free_sym_buf;
+ }
+
+ htab->new_cmse_stub_offset = 0;
+ cmse_stub_size =
+ find_stub_size_and_template (arm_stub_cmse_branch_thumb_only,
+ &cmse_stub_template,
+ &cmse_stub_template_size);
+ out_sec_name =
+ arm_dedicated_stub_output_section_name (arm_stub_cmse_branch_thumb_only);
+ stub_out_sec =
+ bfd_get_section_by_name (htab->obfd, out_sec_name);
+ if (stub_out_sec != NULL)
+ cmse_stub_sec_vma = stub_out_sec->vma;
+
+ /* Set addresses of veneers mentionned in input secure gateway import
+ library's symbol table. */
+ for (i = 0; i < symcount; i++)
+ {
+ sym = sympp[i];
+ flags = sym->flags;
+ sym_name = (char *) bfd_asymbol_name (sym);
+ intsym = &((elf_symbol_type *) sym)->internal_elf_sym;
+
+ if (sym->section != bfd_abs_section_ptr
+ || !(flags & (BSF_GLOBAL | BSF_WEAK))
+ || (flags & BSF_FUNCTION) != BSF_FUNCTION
+ || (ARM_GET_SYM_BRANCH_TYPE (intsym->st_target_internal)
+ != ST_BRANCH_TO_THUMB))
+ {
+ (*_bfd_error_handler) (_("%B: invalid import library entry: `%s'."),
+ in_implib_bfd, sym_name);
+ (*_bfd_error_handler) (_("Symbol should be absolute, global and "
+ "refer to Thumb functions."));
+ ret = FALSE;
+ continue;
+ }
+
+ veneer_value = bfd_asymbol_value (sym);
+ stub_offset = veneer_value - cmse_stub_sec_vma;
+ stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, sym_name,
+ FALSE, FALSE);
+ hash = (struct elf32_arm_link_hash_entry *)
+ elf_link_hash_lookup (&(htab)->root, sym_name, FALSE, FALSE, TRUE);
+
+ /* Stub entry should have been created by cmse_scan or the symbol be of
+ a secure function callable from non secure code. */
+ if (!stub_entry && !hash)
+ {
+ bfd_boolean new_stub;
+
+ (*_bfd_error_handler)
+ (_("Entry function `%s' disappeared from secure code."), sym_name);
+ hash = (struct elf32_arm_link_hash_entry *)
+ elf_link_hash_lookup (&(htab)->root, sym_name, TRUE, TRUE, TRUE);
+ stub_entry
+ = elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
+ NULL, NULL, bfd_abs_section_ptr, hash,
+ sym_name, veneer_value,
+ ST_BRANCH_TO_THUMB, &new_stub);
+ if (stub_entry == NULL)
+ ret = FALSE;
+ else
+ {
+ BFD_ASSERT (new_stub);
+ new_cmse_stubs_created++;
+ (*cmse_stub_created)++;
+ }
+ stub_entry->stub_template_size = stub_entry->stub_size = 0;
+ stub_entry->stub_offset = stub_offset;
+ }
+ /* Symbol found is not callable from non secure code. */
+ else if (!stub_entry)
+ {
+ if (!cmse_entry_fct_p (hash))
+ {
+ (*_bfd_error_handler) (_("`%s' refers to a non entry function."),
+ sym_name);
+ ret = FALSE;
+ }
+ continue;
+ }
+ else
+ {
+ /* Only stub for SG veneers should have been created. */
+ BFD_ASSERT (stub_entry->stub_type == arm_stub_cmse_branch_thumb_only);
+
+ /* Check visibility hasn't changed. */
+ if (!!(flags & BSF_GLOBAL)
+ != (hash->root.root.type == bfd_link_hash_defined))
+ (*_bfd_error_handler)
+ (_("%B: visibility of symbol `%s' has changed."), in_implib_bfd,
+ sym_name);
+
+ stub_entry->stub_offset = stub_offset;
+ }
+
+ /* Size should match that of a SG veneer. */
+ if (intsym->st_size != cmse_stub_size)
+ {
+ (*_bfd_error_handler) (_("%B: incorrect size for symbol `%s'."),
+ in_implib_bfd, sym_name);
+ ret = FALSE;
+ }
+
+ /* Previous veneer address is before current SG veneer section. */
+ if (veneer_value < cmse_stub_sec_vma)
+ {
+ /* Avoid offset underflow. */
+ if (stub_entry)
+ stub_entry->stub_offset = 0;
+ stub_offset = 0;
+ ret = FALSE;
+ }
+
+ /* Complain if stub offset not a multiple of stub size. */
+ if (stub_offset % cmse_stub_size)
+ {
+ (*_bfd_error_handler)
+ (_("Offset of veneer for entry function `%s' not a multiple of "
+ "its size."), sym_name);
+ ret = FALSE;
+ }
+
+ if (!ret)
+ continue;
+
+ new_cmse_stubs_created--;
+ if (veneer_value < cmse_stub_array_start)
+ cmse_stub_array_start = veneer_value;
+ next_cmse_stub_offset = stub_offset + ((cmse_stub_size + 7) & ~7);
+ if (next_cmse_stub_offset > htab->new_cmse_stub_offset)
+ htab->new_cmse_stub_offset = next_cmse_stub_offset;
+ }
+
+ if (!info->out_implib_bfd && new_cmse_stubs_created != 0)
+ {
+ BFD_ASSERT (new_cmse_stubs_created > 0);
+ (*_bfd_error_handler)
+ (_("new entry function(s) introduced but no output import library "
+ "specified:"));
+ bfd_hash_traverse (&htab->stub_hash_table, arm_list_new_cmse_stub,
info);
+ }
+
+ if (cmse_stub_array_start != cmse_stub_sec_vma)
+ {
+ (*_bfd_error_handler)
+ (_("Start address of `%s' is different from previous link."),
+ out_sec_name);
+ ret = FALSE;
+ }
+
+free_sym_buf:
+ free (sympp);
+ return ret;
+}
+
/* Determine and set the size of the stub section for a final link.
The basic idea here is to examine all the relocations looking for
@@ -5622,7 +5953,9 @@ elf32_arm_size_stubs (bfd *output_bfd,
unsigned int),
void (*layout_sections_again) (void))
{
+ bfd_boolean ret = TRUE;
obj_attribute *out_attr;
+ int cmse_stub_created = 0;
bfd_size_type stub_group_size;
bfd_boolean m_profile, stubs_always_after_branch, first_veneer_scan = TRUE;
struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
@@ -5655,6 +5988,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
out_attr = elf_known_obj_attributes_proc (output_bfd);
m_profile = out_attr[Tag_CPU_arch_profile].i == 'M';
+
/* The Cortex-A8 erratum fix depends on stubs not being in the same 4K page
as the first half of a 32-bit branch straddling two 4K pages. This is a
crude way of enforcing that. */
@@ -5728,8 +6062,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
sym_hashes = elf_sym_hashes (input_bfd);
if (!cmse_scan (input_bfd, htab, out_attr, sym_hashes,
- &stub_changed))
+ &cmse_stub_created))
goto error_ret_free_local;
+
+ if (cmse_stub_created != 0)
+ stub_changed = TRUE;
}
/* Walk over each section attached to the input bfd. */
@@ -5961,6 +6298,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
do
{
bfd_boolean new_stub;
+ struct elf32_arm_stub_hash_entry *stub_entry;
/* Determine what (if any) linker stub is needed. */
stub_type = arm_type_of_stub (info, section, irela,
@@ -5972,12 +6310,13 @@ elf32_arm_size_stubs (bfd *output_bfd,
/* We've either created a stub for this reloc already,
or we are about to. */
- created_stub =
+ stub_entry =
elf32_arm_create_stub (htab, stub_type, section, irela,
sym_sec, hash,
(char *) sym_name, sym_value,
branch_type, &new_stub);
+ created_stub = stub_entry != NULL;
if (!created_stub)
goto error_ret_free_internal;
else if (!new_stub)
@@ -6050,6 +6389,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
}
}
+ if (first_veneer_scan
+ && !set_cmse_veneer_addr_from_implib (info, htab,
+ &cmse_stub_created))
+ ret = FALSE;
+
if (prev_num_a8_fixes != num_a8_fixes)
stub_changed = TRUE;
@@ -6069,6 +6413,23 @@ elf32_arm_size_stubs (bfd *output_bfd,
stub_sec->size = 0;
}
+ /* Append new SG veneers after those in input import library. */
+ for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
+ stub_type++)
+ {
+ bfd_vma *start_offset_p;
+ asection **stub_sec_p;
+
+ start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type);
+ stub_sec_p = arm_dedicated_stub_input_section_ptr (htab, stub_type);
+ if (start_offset_p == NULL)
+ continue;
+
+ BFD_ASSERT (stub_sec_p != NULL);
+ if (*stub_sec_p != NULL)
+ (*stub_sec_p)->size = *start_offset_p;
+ }
+
/* Compute stub section size, considering padding. */
bfd_hash_traverse (&htab->stub_hash_table, arm_size_one_stub, htab);
for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
@@ -6137,7 +6498,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
}
stub_entry->stub_sec = stub_sec;
- stub_entry->stub_offset = 0;
+ stub_entry->stub_offset = (bfd_vma) -1;
stub_entry->id_sec = link_sec;
stub_entry->stub_type = a8_fixes[i].stub_type;
stub_entry->source_value = a8_fixes[i].offset;
@@ -6165,7 +6526,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
htab->a8_erratum_fixes = NULL;
htab->num_a8_erratum_fixes = 0;
}
- return TRUE;
+ return ret;
}
/* Build all the stubs associated with the current output file. The
@@ -6179,6 +6540,7 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
{
asection *stub_sec;
struct bfd_hash_table *table;
+ enum elf32_arm_stub_type stub_type;
struct elf32_arm_link_hash_table *htab;
htab = elf32_arm_hash_table (info);
@@ -6196,14 +6558,33 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
continue;
/* Allocate memory to hold the linker stubs. Zeroing the stub sections
- must at least be done for stub section requiring padding. */
+ must at least be done for stub section requiring padding and for SG
+ veneers to ensure that a non secure code branching to a removed SG
+ veneer causes an error. */
size = stub_sec->size;
stub_sec->contents = (unsigned char *) bfd_zalloc (htab->stub_bfd,
size);
if (stub_sec->contents == NULL && size != 0)
return FALSE;
+
stub_sec->size = 0;
}
+ /* Append new SG veneers after those in input import library. */
+ for (stub_type = arm_stub_none + 1; stub_type < max_stub_type; stub_type++)
+ {
+ bfd_vma *start_offset_p;
+ asection **stub_sec_p;
+
+ start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type);
+ stub_sec_p = arm_dedicated_stub_input_section_ptr (htab, stub_type);
+ if (start_offset_p == NULL)
+ continue;
+
+ BFD_ASSERT (stub_sec_p != NULL);
+ if (*stub_sec_p != NULL)
+ (*stub_sec_p)->size = *start_offset_p;
+ }
+
/* Build the stubs as directed by the stub hash table. */
table = &htab->stub_hash_table;
bfd_hash_traverse (table, arm_build_one_stub, info);
@@ -8189,7 +8570,8 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd,
bfd_arm_stm32l4xx_fix stm32l4xx_fix,
int no_enum_warn, int no_wchar_warn,
int pic_veneer, int fix_cortex_a8,
- int fix_arm1176, int cmse_implib)
+ int fix_arm1176, int cmse_implib,
+ bfd *in_implib_bfd)
{
struct elf32_arm_link_hash_table *globals;
@@ -8217,6 +8599,7 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd,
globals->fix_cortex_a8 = fix_cortex_a8;
globals->fix_arm1176 = fix_arm1176;
globals->cmse_implib = cmse_implib;
+ globals->in_implib_bfd = in_implib_bfd;
BFD_ASSERT (is_arm_elf (output_bfd));
elf_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
index
c21f6a82335a58a0ab37f3719c73c95e73e6211c..2346bb42444895605d10b7b7e21cca2dcaa38700
100644
--- a/ld/emultempl/armelf.em
+++ b/ld/emultempl/armelf.em
@@ -43,6 +43,7 @@ static int pic_veneer = 0;
static int merge_exidx_entries = -1;
static int fix_arm1176 = 1;
static int cmse_implib = 0;
+static char *in_implib_filename = NULL;
static void
gld${EMULATION_NAME}_before_parse (void)
@@ -498,6 +499,8 @@ gld${EMULATION_NAME}_finish (void)
static void
arm_elf_create_output_section_statements (void)
{
+ bfd *in_implib_bfd;
+
if (strstr (bfd_get_target (link_info.output_bfd), "arm") == NULL)
{
/* The arm backend needs special fields in the output hash structure.
@@ -508,6 +511,20 @@ arm_elf_create_output_section_statements (void)
return;
}
+ if (in_implib_filename)
+ {
+ in_implib_bfd = bfd_openr (in_implib_filename,
+ bfd_get_target (link_info.output_bfd));
+
+ if (in_implib_bfd == NULL)
+ einfo ("%F%s: Can't open: %E\n", in_implib_filename);
+
+ if (!bfd_check_format (in_implib_bfd, bfd_object))
+ einfo ("%F%s: Not a relocatable file: %E\n", in_implib_filename);
+ }
+ else
+ in_implib_bfd = NULL;
+
bfd_elf32_arm_set_target_relocs (link_info.output_bfd, &link_info,
target1_is_rel,
target2_type, fix_v4bx, use_blx,
@@ -515,7 +532,7 @@ arm_elf_create_output_section_statements (void)
no_enum_size_warning,
no_wchar_size_warning,
pic_veneer, fix_cortex_a8,
- fix_arm1176, cmse_implib);
+ fix_arm1176, cmse_implib, in_implib_bfd);
stub_file = lang_add_input_file ("linker stubs",
lang_input_file_is_fake_enum,
@@ -585,6 +602,7 @@ PARSE_AND_LIST_PROLOGUE='
#define OPTION_LONG_PLT 319
#define OPTION_STM32L4XX_FIX 320
#define OPTION_CMSE_IMPLIB 321
+#define OPTION_IN_IMPLIB 322
'
PARSE_AND_LIST_SHORTOPTS=p
@@ -612,6 +630,7 @@ PARSE_AND_LIST_LONGOPTS='
{ "no-fix-arm1176", no_argument, NULL, OPTION_NO_FIX_ARM1176 },
{ "long-plt", no_argument, NULL, OPTION_LONG_PLT },
{ "cmse-implib", no_argument, NULL, OPTION_CMSE_IMPLIB },
+ { "in-implib", required_argument, NULL, OPTION_IN_IMPLIB },
'
PARSE_AND_LIST_OPTIONS='
@@ -634,6 +653,8 @@ PARSE_AND_LIST_OPTIONS='
" to handle large .plt/.got
displacements\n"));
fprintf (file, _(" --cmse-implib Make import library to be a
secure gateway import\n"
" library as per ARMv8-M
Security Extensions\n"));
+ fprintf (file, _(" --in-implib Import library whose symbols
address must\n"
+ " remain stable\n"));
fprintf (file, _("\
--stub-group-size=N Maximum size of a group of input sections
that\n\
can be handled by one stub section. A
negative\n\
@@ -758,6 +779,10 @@ PARSE_AND_LIST_ARGS_CASES='
case OPTION_CMSE_IMPLIB:
cmse_implib = 1;
break;
+
+ case OPTION_IN_IMPLIB:
+ in_implib_filename = optarg;
+ break;
'
# We have our own before_allocation etc. functions, but they call
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index
e6813f287fe5ce4c916bf93f48b2e9edbc336570..5994d2efc7a2406d0dcddbd2fe7eeefab910534a
100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -6866,6 +6866,18 @@ specified by the @samp{--out-implib} and @samp{--in-
implib} options are
secure gateway import libraries, suitable for linking a non-secure
executable against secure code as per ARMv8-M Security Extensions.
+@kindex --in-implib=@var{file}
+@cindex Input import library
+The @samp{--in-implib=file} specifies an input import library whose symbols
+must keep the same address in the executable being produced. A warning is
+given if no @samp{--out-implib} is given but new symbols have been introduced
+in the executable that should be listed in its import library. Otherwise, if
+@samp{--out-implib} is specified, the symbols are silently added to the output
+import library. A warning is also given if some symbols present in the input
+import library have disappeared from the executable. This option is only
+effective for Secure Gateway import libraries, ie. when @samp{--cmse-implib}
is
+specified.
+
@ifclear GENERIC
@lowersections
@end ifclear
diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
index
2efc047a63d6d5e3250a3259e01633394f102ac0..019f00abf6e43883c052a1b3f5f4d913f2dc0039
100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -661,16 +661,53 @@ set armeabitests_nonacl {
"cmse-veneers-mainline"}
{"Secure gateway import library generation: errors"
"--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-
implib.lib --cmse-implib" ""
- "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1"
+ "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1 --defsym VER=1"
{cmse-implib.s}
{{ld cmse-implib-errors.out}}
"cmse-implib"}
{"Secure gateway import library generation"
"--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-
implib.lib --cmse-implib" ""
- "-march=armv8-m.base -mthumb"
+ "-march=armv8-m.base -mthumb --defsym VER=1"
{cmse-implib.s}
{{readelf {-s tmpdir/cmse-implib.lib} cmse-implib.rd}}
"cmse-implib"}
+ {"Input secure gateway import library"
+ "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-new-
implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+ "-march=armv8-m.base -mthumb --defsym VER=2"
+ {cmse-implib.s}
+ {{ld cmse-new-implib.out}
+ {readelf {-s tmpdir/cmse-new-implib.lib} cmse-new-implib.rd}}
+ "cmse-new-implib"}
+ {"Input secure gateway import library: no output import library"
+ "--section-start .gnu.sgstubs=0x20000 --in-implib=tmpdir/cmse-implib.lib
--cmse-implib" ""
+ "-march=armv8-m.base -mthumb --defsym VER=2"
+ {cmse-implib.s}
+ {{ld cmse-new-implib-no-output.out}}
+ "cmse-new-implib-no-output"}
+ {"Input secure gateway import library: earlier stub section base"
+ "--section-start .gnu.sgstubs=0x19000 --out-implib=tmpdir/cmse-new-
earlier-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+ "-march=armv8-m.base -mthumb --defsym VER=2"
+ {cmse-implib.s}
+ {{ld cmse-new-earlier-later-implib.out}}
+ "cmse-new-earlier-implib"}
+ {"Input secure gateway import library: later stub section base"
+ "--section-start .gnu.sgstubs=0x30000 --out-implib=tmpdir/cmse-new-
later-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+ "-march=armv8-m.base -mthumb --defsym VER=2"
+ {cmse-implib.s}
+ {{ld cmse-new-earlier-later-implib.out}}
+ "cmse-new-later-implib"}
+ {"Input secure gateway import library: veneer comeback"
+ "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-new-
comeback-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+ "-march=armv8-m.base -mthumb --defsym VER=3"
+ {cmse-implib.s}
+ {{readelf {-s tmpdir/cmse-new-comeback-implib.lib} cmse-new-comeback-
implib.rd}}
+ "cmse-new-comeback-implib"}
+ {"Input secure gateway import library: entry function change"
+ "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-new-
wrong-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
+ "-march=armv8-m.base -mthumb --defsym VER=4"
+ {cmse-implib.s}
+ {{ld cmse-new-wrong-implib.out}}
+ "cmse-new-wrong-implib"}
{"R_ARM_THM_JUMP19 Relocation veneers: Short"
"--section-start destsect=0x000108002 --section-start .text=0x8000" ""
diff --git a/ld/testsuite/ld-arm/cmse-implib.s b/ld/testsuite/ld-arm/cmse-
implib.s
index
a42da63fffebe5322be83f278931754262b0f7ae..9dd783939891478351a5f7ccb1480980a77dca68
100644
--- a/ld/testsuite/ld-arm/cmse-implib.s
+++ b/ld/testsuite/ld-arm/cmse-implib.s
@@ -20,12 +20,29 @@ __acle_se_\name:
.endm
@ Valid setups for veneer generation
+.if (VER >= 2)
+ entry exported_entry_veneer1, global
+.endif
+.if (VER != 4)
entry exported_entry_veneer2, global
+.else
+ entry exported_entry_veneer2, weak
+.endif
+.if (VER != 2)
entry exported_entry_veneer3, global
+.endif
+.if (VER > 1)
+ entry exported_entry_veneer4, global
+.endif
@ Valid setup for entry function without veneer generation
entry exported_entry_fct1, global, sg
+.if (VER != 4)
entry exported_entry_fct2, global, sg
+.else
+ @ Invalid setup for entry function without veneer generation
+ entry exported_entry_fct2, global, nop
+.endif
@ Normal symbol not exported to SG import library
.align 2
diff --git a/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd b/ld/testsuite/ld-
arm/cmse-new-comeback-implib.rd
new file mode 100644
index
0000000000000000000000000000000000000000..c88d9d5104244abc8ceba4d552e1ef0e400c37d1
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-comeback-implib.rd
@@ -0,0 +1,15 @@
+File: tmpdir/cmse-new-.*implib.lib
+
+Symbol table '.symtab' contains 7 entries:
+ Num: Value Size Type Bind Vis Ndx Name
+ 0: 00000000 0 NOTYPE LOCAL DEFAULT UND
+ 1: 00020001 8 FUNC GLOBAL DEFAULT ABS exported_entry_veneer3
+ 2: 00020011 8 FUNC GLOBAL DEFAULT ABS exported_entry_veneer4
+ 3: 00020019 8 FUNC GLOBAL DEFAULT ABS exported_entry_veneer1
+ 4: [0-9a-f]+ 6 FUNC GLOBAL DEFAULT ABS exported_entry_fct1
+ 5: 00020009 8 FUNC GLOBAL DEFAULT ABS exported_entry_veneer2
+ 6: [0-9a-f]+ 6 FUNC GLOBAL DEFAULT ABS exported_entry_fct2
+
+File: tmpdir/cmse-new-.*implib
+
+#...
diff --git a/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
b/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
new file mode 100644
index
0000000000000000000000000000000000000000..b49ad0ac0770a17c39c2d119d1f0c5854a5bd8cc
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-earlier-later-implib.out
@@ -0,0 +1,3 @@
+.*: Entry function `exported_entry_veneer3' disappeared from secure code.
+.*: Start address of `.gnu.sgstubs' is different from previous link.
+.*: cannot size stub section: Invalid operation
diff --git a/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
new file mode 100644
index
0000000000000000000000000000000000000000..0590b71c844da3687b29b93797abda5172ab8d99
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-implib-no-output.out
@@ -0,0 +1,4 @@
+.*: Entry function `exported_entry_veneer3' disappeared from secure code.
+.*: new entry function\(s\) introduced but no output import library specified:
+.*: exported_entry_veneer4
+.*: exported_entry_veneer1
diff --git a/ld/testsuite/ld-arm/cmse-new-implib.out b/ld/testsuite/ld-
arm/cmse-new-implib.out
new file mode 100644
index
0000000000000000000000000000000000000000..c8af2807e7c1a7eeb1fc156fbf4508cf7a7e932d
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-implib.out
@@ -0,0 +1 @@
+.*: Entry function `exported_entry_veneer3' disappeared from secure code.
diff --git a/ld/testsuite/ld-arm/cmse-new-implib.rd b/ld/testsuite/ld-arm/cmse-
new-implib.rd
new file mode 100644
index
0000000000000000000000000000000000000000..9ff0fd87937571f86f99ee940a91a3f67352242a
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-implib.rd
@@ -0,0 +1,14 @@
+File: tmpdir/cmse-new-.*implib.lib
+
+Symbol table '.symtab' contains 6 entries:
+ Num: Value Size Type Bind Vis Ndx Name
+ 0: 00000000 0 NOTYPE LOCAL DEFAULT UND
+ 1: 00020011 8 FUNC GLOBAL DEFAULT ABS exported_entry_veneer4
+ 2: 00020019 8 FUNC GLOBAL DEFAULT ABS exported_entry_veneer1
+ 3: [0-9a-f]+ 6 FUNC GLOBAL DEFAULT ABS exported_entry_fct1
+ 4: 00020009 8 FUNC GLOBAL DEFAULT ABS exported_entry_veneer2
+ 5: [0-9a-f]+ 6 FUNC GLOBAL DEFAULT ABS exported_entry_fct2
+
+File: tmpdir/cmse-new-.*implib
+
+#...
diff --git a/ld/testsuite/ld-arm/cmse-new-wrong-implib.out b/ld/testsuite/ld-
arm/cmse-new-wrong-implib.out
new file mode 100644
index
0000000000000000000000000000000000000000..2afe4078e78606d24f05dda6ff1c5e6a54d42512
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-new-wrong-implib.out
@@ -0,0 +1,3 @@
+.*: .*: visibility of symbol `exported_entry_veneer2' has changed.
+.*: `exported_entry_fct2' refers to a non entry function.
+.*: cannot size stub section: Invalid operation
Best regards,
Thomas