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