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