From: Thomas Preud'homme Date: Tue, 29 Mar 2016 19:36:43 +0000 (+0100) Subject: Add support for stable secure gateway veneers addresses X-Git-Tag: users/ARM/embedded-binutils-2_26-branch-2016q1~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c16628bd6c9170e0cebdbef6fcf1e808901429fa;p=thirdparty%2Fbinutils-gdb.git Add support for stable secure gateway veneers addresses 2016-03-29 Thomas Preud'homme bfd/ * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new parameter for the input import library bfd. * bfd-in2.h: Regenerate. * elf32-arm.c (struct elf32_arm_link_hash_table): New in_implib_bfd and new_cmse_stub_offset fields. (stub_hash_newfunc): Initialize stub_offset and stub_template_size to -1. (elf32_arm_add_stub): Likewise for stub_offset. (arm_new_stubs_start_offset_ptr): New function. (arm_build_one_stub): Only allocate a stub_offset if it is -1. Allow empty veneers to have zero relocations. (arm_size_one_stub): Only initialize stub size and template information for non empty veneers. Do not update veneer section size if veneer already has an offset. (elf32_arm_create_stub): Return the stub entry pointer or NULL instead of a boolean indicating success or failure. (cmse_scan): Change stub_changed parameter into an integer pointer parameter cmse_stub_created to count the number of stub created and adapt to change of return value in elf32_arm_create_stub. (cmse_entry_fct_p): New function. (arm_list_new_cmse_stub): Likewise. (set_cmse_veneer_addr_from_implib): Likewise. (elf32_arm_size_stubs): Define cmse_stub_created, pass its address to cmse_scan instead of that of cmse_stub_changed to compute the number of stub created and use it to initialize stub_changed. Call set_cmse_veneer_addr_from_implib after all cmse_scan. Adapt to change of return value in elf32_arm_create_stub. Use arm_stub_section_start_offset () if not NULL to initialize size of secure gateway veneers section. Initialize stub_offset of Cortex-A8 erratum fix to -1. Use ret to hold return value. (elf32_arm_build_stubs): Use arm_stub_section_start_offset () if not NULL to initialize size of secure gateway veneers section. Adapt comment to stress the importance of zeroing veneer section content. (bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd parameter to initialize eponymous field in struct elf32_arm_link_hash_table. ld/ * emultempl/armelf.em (in_implib_filename): Declare and initialize new variable. (arm_elf_create_output_section_statements): Open import input library file for writing and pass resulting in_implib_bfd to bfd_elf32_arm_set_target_relocs. (PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option. (PARSE_AND_LIST_LONGOPTS): Define --in-implib option. (PARSE_AND_LIST_OPTIONS): Add help message for --in-implib option. (PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case. * ld.texinfo (--cmse-implib): Update to mention --in-implib. (--in-implib): Document new option. * testsuite/ld-arm/arm-elf.exp (Secure gateway import library generation): add --defsym VER=1 to gas CLI. (Secure gateway import library generation: errors): Likewise. (Input secure gateway import library): New test. (Input secure gateway import library: no output import library): Likewise. (Input secure gateway import library: earlier stub section base): Likewise. (Input secure gateway import library: later stub section base): Likewise. (Input secure gateway import library: veneer comeback): Likewise. (Input secure gateway import library: entry function change): Likewise. ld/testsuite/ * ld-arm/cmse-implib.s: Add input import library testing. * ld-arm/cmse-implib.rd: Update accordingly. * ld-arm/cmse-new-implib.out: New file. * ld-arm/cmse-new-implib.rd: Likewise. * ld-arm/cmse-new-implib-no-output.out: Likewise. * ld-arm/cmse-new-earlier-later-implib.out: Likewise. * ld-arm/cmse-new-comeback-implib.rd: Likewise. * ld-arm/cmse-new-wrong-implib.out: Likewise. --- diff --git a/bfd/ChangeLog.arm b/bfd/ChangeLog.arm index 1506ecbe202..65e8b446195 100644 --- a/bfd/ChangeLog.arm +++ b/bfd/ChangeLog.arm @@ -1,3 +1,41 @@ +2016-03-29 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. + 2016-03-29 Thomas Preud'homme * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add one parameter. diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h index 4144401d12e..5e6e9805849 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 c7c7fac542a..fe7e11931f5 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -902,7 +902,7 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation void bfd_elf32_arm_set_target_relocs (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix, - bfd_arm_stm32l4xx_fix, int, int, int, int, int, int); + bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *); extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking (bfd *, struct bfd_link_info *); diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index e35bd58207c..1bbcef0f1bc 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -3068,6 +3068,10 @@ struct elf32_arm_link_hash_table as per ARMv8-M Security Extensions. */ int cmse_implib; + /* The import library whose symbols' address must remain stable in + the import library generated. */ + bfd *in_implib_bfd; + /* The index of the next unused R_ARM_TLS_DESC slot in .rel.plt. */ bfd_vma next_tls_desc_index; @@ -3129,6 +3133,10 @@ struct elf32_arm_link_hash_table /* Input stub section holding secure gateway veneers. */ asection *cmse_stub_sec; + /* Offset in cmse_stub_sec where new SG veneers (not in input import library) + start to be allocated. */ + bfd_vma new_cmse_stub_offset; + /* Number of elements in stub_group. */ unsigned int top_id; @@ -3380,7 +3388,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry, /* Initialize the local fields. */ eh = (struct elf32_arm_stub_hash_entry *) entry; eh->stub_sec = NULL; - eh->stub_offset = 0; + eh->stub_offset = (bfd_vma) -1; eh->source_value = 0; eh->target_value = 0; eh->target_section = NULL; @@ -3388,7 +3396,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry, eh->stub_type = arm_stub_none; eh->stub_size = 0; eh->stub_template = NULL; - eh->stub_template_size = 0; + eh->stub_template_size = -1; eh->h = NULL; eh->id_sec = NULL; eh->output_name = NULL; @@ -4299,7 +4307,7 @@ elf32_arm_add_stub (const char *stub_name, asection *section, } stub_entry->stub_sec = stub_sec; - stub_entry->stub_offset = 0; + stub_entry->stub_offset = (bfd_vma) -1; stub_entry->id_sec = link_sec; return stub_entry; @@ -4463,6 +4471,46 @@ arm_dedicated_stub_section_padding (enum elf32_arm_stub_type stub_type) abort (); /* Should be unreachable. */ } +/* If veneers of type STUB_TYPE should go in a dedicated output section, + returns the address of the hash table field in HTAB holding the offset at + which new veneers should be layed out in the stub section. */ + +static bfd_vma* +arm_new_stubs_start_offset_ptr (struct elf32_arm_link_hash_table *htab, + enum elf32_arm_stub_type stub_type) +{ + switch (stub_type) + { + case arm_stub_a8_veneer_b_cond: + case arm_stub_a8_veneer_b: + case arm_stub_a8_veneer_bl: + case arm_stub_long_branch_any_any: + case arm_stub_long_branch_v4t_arm_thumb: + case arm_stub_long_branch_thumb_only: + case arm_stub_long_branch_v4t_thumb_thumb: + case arm_stub_long_branch_v4t_thumb_arm: + case arm_stub_short_branch_v4t_thumb_arm: + case arm_stub_long_branch_any_arm_pic: + case arm_stub_long_branch_any_thumb_pic: + case arm_stub_long_branch_v4t_thumb_thumb_pic: + case arm_stub_long_branch_v4t_arm_thumb_pic: + case arm_stub_long_branch_v4t_thumb_arm_pic: + case arm_stub_long_branch_thumb_only_pic: + case arm_stub_long_branch_any_tls_pic: + case arm_stub_long_branch_v4t_thumb_tls_pic: + case arm_stub_a8_veneer_blx: + case arm_stub_long_branch_arm_nacl: + case arm_stub_long_branch_arm_nacl_pic: + return NULL; + + case arm_stub_cmse_branch_thumb_only: + return &htab->new_cmse_stub_offset; + + default: + abort (); /* Should be unreachable. */ + } +} + static bfd_boolean arm_build_one_stub (struct bfd_hash_entry *gen_entry, void * in_arg) @@ -4482,6 +4530,7 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry, int stub_reloc_idx[MAXRELOCS] = {-1, -1}; int stub_reloc_offset[MAXRELOCS] = {0, 0}; int nrelocs = 0; + int just_allocated = 0; /* Massage our args to the form they really have. */ stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry; @@ -4498,8 +4547,12 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry, /* We have to do less-strictly-aligned fixes last. */ return TRUE; - /* Make a note of the offset within the stubs for this entry. */ - stub_entry->stub_offset = stub_sec->size; + /* Assign a slot at the end of section if none assigned yet. */ + if (stub_entry->stub_offset == (bfd_vma) -1) + { + stub_entry->stub_offset = stub_sec->size; + just_allocated = 1; + } loc = stub_sec->contents + stub_entry->stub_offset; stub_bfd = stub_sec->owner; @@ -4573,7 +4626,8 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry, } } - stub_sec->size += size; + if (just_allocated) + stub_sec->size += size; /* Stub size has already been computed in arm_size_one_stub. Check consistency. */ @@ -4585,7 +4639,7 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry, /* Assume there is at least one and at most MAXRELOCS entries to relocate in each stub. */ - BFD_ASSERT (nrelocs != 0 && nrelocs <= MAXRELOCS); + BFD_ASSERT (size == 0 || (nrelocs != 0 && nrelocs <= MAXRELOCS)); for (i = 0; i < nrelocs; i++) { @@ -4687,9 +4741,17 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry, size = find_stub_size_and_template (stub_entry->stub_type, &template_sequence, &template_size); - stub_entry->stub_size = size; - stub_entry->stub_template = template_sequence; - stub_entry->stub_template_size = template_size; + /* Initialized to -1. Null size indicates a zeroed out veneer. */ + if (stub_entry->stub_template_size) + { + stub_entry->stub_size = size; + stub_entry->stub_template = template_sequence; + stub_entry->stub_template_size = template_size; + } + + /* Already accounted for. */ + if (stub_entry->stub_offset != (bfd_vma) -1) + return TRUE; size = (size + 7) & ~7; stub_entry->stub_sec->size += size; @@ -5254,10 +5316,10 @@ cortex_a8_erratum_scan (bfd *input_bfd, and *NEW_STUB is set to FALSE. Otherwise, *NEW_STUB is set to TRUE and the stub entry is initialized. - Returns whether the stub could be successfully created or updated, or FALSE - if an error occured. */ + Returns the stub that was created or updated, or NULL if an error + occured. */ -static bfd_boolean +static struct elf32_arm_stub_hash_entry * elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab, enum elf32_arm_stub_type stub_type, asection *section, Elf_Internal_Rela *irela, asection *sym_sec, @@ -5288,7 +5350,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab, stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash, irela, stub_type); if (!stub_name) - return FALSE; + return NULL; } stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, stub_name, FALSE, @@ -5299,7 +5361,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab, if (!sym_claimed) free (stub_name); stub_entry->target_value = sym_value; - return TRUE; + return stub_entry; } stub_entry = elf32_arm_add_stub (stub_name, section, htab, stub_type); @@ -5307,7 +5369,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab, { if (!sym_claimed) free (stub_name); - return FALSE; + return NULL; } stub_entry->target_value = sym_value; @@ -5328,7 +5390,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab, if (stub_entry->output_name == NULL) { free (stub_name); - return FALSE; + return NULL; } /* For historical reasons, use the existing names for ARM-to-Thumb and @@ -5348,7 +5410,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab, } *new_stub = TRUE; - return TRUE; + return stub_entry; } /* Scan symbols in INPUT_BFD to identify secure entry functions needing a @@ -5365,14 +5427,15 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab, OUT_ATTR gives the output attributes, SYM_HASHES the symbol index to hash entry mapping while HTAB gives the name to hash entry mapping. + *CMSE_STUB_CREATED is increased by the number of secure gateway veneer + created. - If any secure gateway veneer is created, *STUB_CHANGED is set to TRUE. The - return value gives whether a stub failed to be allocated. */ + The return value gives whether a stub failed to be allocated. */ static bfd_boolean cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab, obj_attribute *out_attr, struct elf_link_hash_entry **sym_hashes, - bfd_boolean *stub_changed) + int *cmse_stub_created) { const struct elf_backend_data *bed; Elf_Internal_Shdr *symtab_hdr; @@ -5383,7 +5446,8 @@ cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab, char *sym_name, *lsym_name; bfd_vma sym_value; asection *section; - bfd_boolean is_v8m, new_stub, created_stub, cmse_invalid, ret = TRUE; + struct elf32_arm_stub_hash_entry *stub_entry; + bfd_boolean is_v8m, new_stub, cmse_invalid, ret = TRUE; bed = get_elf_backend_data (input_bfd); symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; @@ -5524,17 +5588,17 @@ cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab, if (!ret) continue; branch_type = ARM_GET_SYM_BRANCH_TYPE (hash->root.target_internal); - created_stub + stub_entry = elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only, NULL, NULL, section, hash, sym_name, sym_value, branch_type, &new_stub); - if (!created_stub) + if (stub_entry == NULL) ret = FALSE; else { BFD_ASSERT (new_stub); - *stub_changed = TRUE; + (*cmse_stub_created)++; } } @@ -5543,6 +5607,273 @@ cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab, return ret; } +/* Return whether a symbol identified by its linker HASH entry is an entry + function, ie can be called from non secure code without using a veneer. */ + +static bfd_boolean +cmse_entry_fct_p (struct elf32_arm_link_hash_entry *hash) +{ + uint32_t first_insn; + asection *section; + file_ptr offset; + bfd *abfd; + + /* Defined symbol of function type. */ + if (hash->root.root.type != bfd_link_hash_defined + && hash->root.root.type != bfd_link_hash_defweak) + return FALSE; + if (hash->root.type != STT_FUNC) + return FALSE; + + /* Read first instruction. */ + section = hash->root.root.u.def.section; + abfd = section->owner; + offset = hash->root.root.u.def.value - section->vma; + if (!bfd_get_section_contents (abfd, section, &first_insn, offset, + sizeof (first_insn))) + return FALSE; + + /* Start by SG instruction. */ + return first_insn == 0xe97fe97f; +} + +/* Output the name (in symbol table) of the veneer GEN_ENTRY if it is a new + secure gateway veneers (ie. the veneers was not in the input import library) + and there is no output import library (GEN_INFO->out_implib_bfd is NULL. */ + +static bfd_boolean +arm_list_new_cmse_stub (struct bfd_hash_entry *gen_entry, void *gen_info) +{ + struct elf32_arm_stub_hash_entry *stub_entry; + struct bfd_link_info *info; + + /* Massage our args to the form they really have. */ + stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry; + info = (struct bfd_link_info *) gen_info; + + if (info->out_implib_bfd) + return TRUE; + + if (stub_entry->stub_type != arm_stub_cmse_branch_thumb_only) + return TRUE; + + if (stub_entry->stub_offset == (bfd_vma) -1) + (*_bfd_error_handler) (" %s", stub_entry->output_name); + + return TRUE; +} + +/* Set offset of secure gateway veneers so that their address remain identical + to the one in the input import library referred by HTAB->in_implib_bfd. A + warning is issued for veneers that disappeared (present in input import + library but absent from the executable being linked) or if new veneers + appeared and there is no output import library (INFO->out_implib_bfd is NULL + and *CMSE_STUB_CREATED is bigger than the number of secure gateway veneers + found in the input import library. + + The function returns whether an error occured. If no error occured, + *CMSE_STUB_CREATED gives the number of SG veneers created by both cmse_scan + and this function and HTAB->new_cmse_stub_offset is set to the biggest + veneer observed set for new veneers to be layed out after. */ + +static bfd_boolean +set_cmse_veneer_addr_from_implib (struct bfd_link_info *info, + struct elf32_arm_link_hash_table *htab, + int *cmse_stub_created) +{ + long symsize; + char *sym_name; + flagword flags; + long i, symcount; + bfd *in_implib_bfd; + asection *stub_out_sec; + bfd_boolean ret = TRUE; + Elf_Internal_Sym *intsym; + const char *out_sec_name; + bfd_size_type cmse_stub_size; + asymbol **sympp = NULL, *sym; + struct elf32_arm_link_hash_entry *hash; + const insn_sequence *cmse_stub_template; + struct elf32_arm_stub_hash_entry *stub_entry; + int cmse_stub_template_size, new_cmse_stubs_created = *cmse_stub_created; + bfd_vma veneer_value, stub_offset, next_cmse_stub_offset; + bfd_vma cmse_stub_array_start = (bfd_vma) -1, cmse_stub_sec_vma = 0; + + /* No input secure gateway import library. */ + if (!htab->in_implib_bfd) + return TRUE; + else if (!htab->cmse_implib) + return FALSE; + + /* Get symbol table size. */ + in_implib_bfd = htab->in_implib_bfd; + symsize = bfd_get_symtab_upper_bound (in_implib_bfd); + if (symsize < 0) + return FALSE; + + /* Read in the input secure gateway import library's symbol table. */ + sympp = (asymbol **) xmalloc (symsize); + symcount = bfd_canonicalize_symtab (in_implib_bfd, sympp); + if (symcount < 0) + { + ret = FALSE; + goto free_sym_buf; + } + + htab->new_cmse_stub_offset = 0; + cmse_stub_size = + find_stub_size_and_template (arm_stub_cmse_branch_thumb_only, + &cmse_stub_template, + &cmse_stub_template_size); + out_sec_name = + arm_dedicated_stub_output_section_name (arm_stub_cmse_branch_thumb_only); + stub_out_sec = + bfd_get_section_by_name (htab->obfd, out_sec_name); + if (stub_out_sec != NULL) + cmse_stub_sec_vma = stub_out_sec->vma; + + /* Set addresses of veneers mentionned in input secure gateway import + library's symbol table. */ + for (i = 0; i < symcount; i++) + { + sym = sympp[i]; + flags = sym->flags; + sym_name = (char *) bfd_asymbol_name (sym); + intsym = &((elf_symbol_type *) sym)->internal_elf_sym; + + if (sym->section != bfd_abs_section_ptr + || !(flags & (BSF_GLOBAL | BSF_WEAK)) + || (flags & BSF_FUNCTION) != BSF_FUNCTION + || (ARM_GET_SYM_BRANCH_TYPE (intsym->st_target_internal) + != ST_BRANCH_TO_THUMB)) + { + (*_bfd_error_handler) (_("%B: invalid import library entry: `%s'."), + in_implib_bfd, sym_name); + (*_bfd_error_handler) (_("Symbol should be absolute, global and " + "refer to Thumb functions.")); + ret = FALSE; + continue; + } + + veneer_value = bfd_asymbol_value (sym); + stub_offset = veneer_value - cmse_stub_sec_vma; + stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, sym_name, + FALSE, FALSE); + hash = (struct elf32_arm_link_hash_entry *) + elf_link_hash_lookup (&(htab)->root, sym_name, FALSE, FALSE, TRUE); + + /* Stub entry should have been created by cmse_scan or the symbol be of + a secure function callable from non secure code. */ + if (!stub_entry && !hash) + { + bfd_boolean new_stub; + + (*_bfd_error_handler) + (_("Entry function `%s' disappeared from secure code."), sym_name); + hash = (struct elf32_arm_link_hash_entry *) + elf_link_hash_lookup (&(htab)->root, sym_name, TRUE, TRUE, TRUE); + stub_entry + = elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only, + NULL, NULL, bfd_abs_section_ptr, hash, + sym_name, veneer_value, + ST_BRANCH_TO_THUMB, &new_stub); + if (stub_entry == NULL) + ret = FALSE; + else + { + BFD_ASSERT (new_stub); + new_cmse_stubs_created++; + (*cmse_stub_created)++; + } + stub_entry->stub_template_size = stub_entry->stub_size = 0; + stub_entry->stub_offset = stub_offset; + } + /* Symbol found is not callable from non secure code. */ + else if (!stub_entry) + { + if (!cmse_entry_fct_p (hash)) + { + (*_bfd_error_handler) (_("`%s' refers to a non entry function."), + sym_name); + ret = FALSE; + } + continue; + } + else + { + /* Only stub for SG veneers should have been created. */ + BFD_ASSERT (stub_entry->stub_type == arm_stub_cmse_branch_thumb_only); + + /* Check visibility hasn't changed. */ + if (!!(flags & BSF_GLOBAL) + != (hash->root.root.type == bfd_link_hash_defined)) + (*_bfd_error_handler) + (_("%B: visibility of symbol `%s' has changed."), in_implib_bfd, + sym_name); + + stub_entry->stub_offset = stub_offset; + } + + /* Size should match that of a SG veneer. */ + if (intsym->st_size != cmse_stub_size) + { + (*_bfd_error_handler) (_("%B: incorrect size for symbol `%s'."), + in_implib_bfd, sym_name); + ret = FALSE; + } + + /* Previous veneer address is before current SG veneer section. */ + if (veneer_value < cmse_stub_sec_vma) + { + /* Avoid offset underflow. */ + if (stub_entry) + stub_entry->stub_offset = 0; + stub_offset = 0; + ret = FALSE; + } + + /* Complain if stub offset not a multiple of stub size. */ + if (stub_offset % cmse_stub_size) + { + (*_bfd_error_handler) + (_("Offset of veneer for entry function `%s' not a multiple of " + "its size."), sym_name); + ret = FALSE; + } + + if (!ret) + continue; + + new_cmse_stubs_created--; + if (veneer_value < cmse_stub_array_start) + cmse_stub_array_start = veneer_value; + next_cmse_stub_offset = stub_offset + ((cmse_stub_size + 7) & ~7); + if (next_cmse_stub_offset > htab->new_cmse_stub_offset) + htab->new_cmse_stub_offset = next_cmse_stub_offset; + } + + if (!info->out_implib_bfd && new_cmse_stubs_created != 0) + { + BFD_ASSERT (new_cmse_stubs_created > 0); + (*_bfd_error_handler) + (_("new entry function(s) introduced but no output import library " + "specified:")); + bfd_hash_traverse (&htab->stub_hash_table, arm_list_new_cmse_stub, info); + } + + if (cmse_stub_array_start != cmse_stub_sec_vma) + { + (*_bfd_error_handler) + (_("Start address of `%s' is different from previous link."), + out_sec_name); + ret = FALSE; + } + +free_sym_buf: + free (sympp); + return ret; +} + /* Determine and set the size of the stub section for a final link. The basic idea here is to examine all the relocations looking for @@ -5559,7 +5890,9 @@ elf32_arm_size_stubs (bfd *output_bfd, unsigned int), void (*layout_sections_again) (void)) { + bfd_boolean ret = TRUE; obj_attribute *out_attr; + int cmse_stub_created = 0; bfd_size_type stub_group_size; bfd_boolean m_profile, stubs_always_after_branch, first_veneer_scan = TRUE; struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info); @@ -5592,6 +5925,7 @@ elf32_arm_size_stubs (bfd *output_bfd, out_attr = elf_known_obj_attributes_proc (output_bfd); m_profile = out_attr[Tag_CPU_arch_profile].i == 'M'; + /* The Cortex-A8 erratum fix depends on stubs not being in the same 4K page as the first half of a 32-bit branch straddling two 4K pages. This is a crude way of enforcing that. */ @@ -5665,8 +5999,11 @@ elf32_arm_size_stubs (bfd *output_bfd, sym_hashes = elf_sym_hashes (input_bfd); if (!cmse_scan (input_bfd, htab, out_attr, sym_hashes, - &stub_changed)) + &cmse_stub_created)) goto error_ret_free_local; + + if (cmse_stub_created != 0) + stub_changed = TRUE; } /* Walk over each section attached to the input bfd. */ @@ -5892,6 +6229,7 @@ elf32_arm_size_stubs (bfd *output_bfd, do { bfd_boolean new_stub; + struct elf32_arm_stub_hash_entry *stub_entry; /* Determine what (if any) linker stub is needed. */ stub_type = arm_type_of_stub (info, section, irela, @@ -5903,12 +6241,13 @@ elf32_arm_size_stubs (bfd *output_bfd, /* We've either created a stub for this reloc already, or we are about to. */ - created_stub = + stub_entry = elf32_arm_create_stub (htab, stub_type, section, irela, sym_sec, hash, (char *) sym_name, sym_value, branch_type, &new_stub); + created_stub = stub_entry != NULL; if (!created_stub || !new_stub) { if (!created_stub) @@ -5982,6 +6321,11 @@ elf32_arm_size_stubs (bfd *output_bfd, } } + if (first_veneer_scan + && !set_cmse_veneer_addr_from_implib (info, htab, + &cmse_stub_created)) + ret = FALSE; + if (prev_num_a8_fixes != num_a8_fixes) stub_changed = TRUE; @@ -6001,6 +6345,23 @@ elf32_arm_size_stubs (bfd *output_bfd, stub_sec->size = 0; } + /* Append new SG veneers after those in input import library. */ + for (stub_type = arm_stub_none + 1; stub_type < max_stub_type; + stub_type++) + { + bfd_vma *start_offset_p; + asection **stub_sec_p; + + start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type); + stub_sec_p = arm_dedicated_stub_input_section_ptr (htab, stub_type); + if (start_offset_p == NULL) + continue; + + BFD_ASSERT (stub_sec_p != NULL); + if (*stub_sec_p != NULL) + (*stub_sec_p)->size = *start_offset_p; + } + /* Compute stub section size, considering padding. */ bfd_hash_traverse (&htab->stub_hash_table, arm_size_one_stub, htab); for (stub_type = arm_stub_none + 1; stub_type < max_stub_type; @@ -6069,7 +6430,7 @@ elf32_arm_size_stubs (bfd *output_bfd, } stub_entry->stub_sec = stub_sec; - stub_entry->stub_offset = 0; + stub_entry->stub_offset = (bfd_vma) -1; stub_entry->id_sec = link_sec; stub_entry->stub_type = a8_fixes[i].stub_type; stub_entry->source_value = a8_fixes[i].offset; @@ -6097,7 +6458,7 @@ elf32_arm_size_stubs (bfd *output_bfd, htab->a8_erratum_fixes = NULL; htab->num_a8_erratum_fixes = 0; } - return TRUE; + return ret; error_ret_free_local: return FALSE; @@ -6114,6 +6475,7 @@ elf32_arm_build_stubs (struct bfd_link_info *info) { asection *stub_sec; struct bfd_hash_table *table; + enum elf32_arm_stub_type stub_type; struct elf32_arm_link_hash_table *htab; htab = elf32_arm_hash_table (info); @@ -6131,14 +6493,33 @@ elf32_arm_build_stubs (struct bfd_link_info *info) continue; /* Allocate memory to hold the linker stubs. Zeroing the stub sections - must at least be done for stub section requiring padding. */ + must at least be done for stub section requiring padding and for SG + veneers to ensure that a non secure code branching to a removed SG + veneer causes an error. */ size = stub_sec->size; stub_sec->contents = (unsigned char *) bfd_zalloc (htab->stub_bfd, size); if (stub_sec->contents == NULL && size != 0) return FALSE; + stub_sec->size = 0; } + /* Append new SG veneers after those in input import library. */ + for (stub_type = arm_stub_none + 1; stub_type < max_stub_type; stub_type++) + { + bfd_vma *start_offset_p; + asection **stub_sec_p; + + start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type); + stub_sec_p = arm_dedicated_stub_input_section_ptr (htab, stub_type); + if (start_offset_p == NULL) + continue; + + BFD_ASSERT (stub_sec_p != NULL); + if (*stub_sec_p != NULL) + (*stub_sec_p)->size = *start_offset_p; + } + /* Build the stubs as directed by the stub hash table. */ table = &htab->stub_hash_table; bfd_hash_traverse (table, arm_build_one_stub, info); @@ -8121,7 +8502,8 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd, bfd_arm_stm32l4xx_fix stm32l4xx_fix, int no_enum_warn, int no_wchar_warn, int pic_veneer, int fix_cortex_a8, - int fix_arm1176, int cmse_implib) + int fix_arm1176, int cmse_implib, + bfd *in_implib_bfd) { struct elf32_arm_link_hash_table *globals; @@ -8149,6 +8531,7 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd, globals->fix_cortex_a8 = fix_cortex_a8; globals->fix_arm1176 = fix_arm1176; globals->cmse_implib = cmse_implib; + globals->in_implib_bfd = in_implib_bfd; BFD_ASSERT (is_arm_elf (output_bfd)); elf_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn; diff --git a/ld/ChangeLog.arm b/ld/ChangeLog.arm index 4a04ca2e96d..cc662f2d1b4 100644 --- a/ld/ChangeLog.arm +++ b/ld/ChangeLog.arm @@ -1,3 +1,31 @@ +2016-03-29 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. + 2016-03-29 Thomas Preud'homme * emultempl/armelf.em (cmse_implib): Declare and define this new diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em index 6a1984625c8..e6f5757ddf8 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) @@ -488,6 +489,8 @@ gld${EMULATION_NAME}_finish (void) static void arm_elf_create_output_section_statements (void) { + bfd *in_implib_bfd; + if (strstr (bfd_get_target (link_info.output_bfd), "arm") == NULL) { /* The arm backend needs special fields in the output hash structure. @@ -498,6 +501,20 @@ arm_elf_create_output_section_statements (void) return; } + if (in_implib_filename) + { + in_implib_bfd = bfd_openr (in_implib_filename, + bfd_get_target (link_info.output_bfd)); + + if (in_implib_bfd == NULL) + einfo ("%F%s: Can't open: %E\n", in_implib_filename); + + if (!bfd_check_format (in_implib_bfd, bfd_object)) + einfo ("%F%s: Not a relocatable file: %E\n", in_implib_filename); + } + else + in_implib_bfd = NULL; + bfd_elf32_arm_set_target_relocs (link_info.output_bfd, &link_info, target1_is_rel, target2_type, fix_v4bx, use_blx, @@ -505,7 +522,7 @@ arm_elf_create_output_section_statements (void) no_enum_size_warning, no_wchar_size_warning, pic_veneer, fix_cortex_a8, - fix_arm1176, cmse_implib); + fix_arm1176, cmse_implib, in_implib_bfd); stub_file = lang_add_input_file ("linker stubs", lang_input_file_is_fake_enum, @@ -575,6 +592,7 @@ PARSE_AND_LIST_PROLOGUE=' #define OPTION_LONG_PLT 319 #define OPTION_STM32L4XX_FIX 320 #define OPTION_CMSE_IMPLIB 321 +#define OPTION_IN_IMPLIB 322 ' PARSE_AND_LIST_SHORTOPTS=p @@ -602,6 +620,7 @@ PARSE_AND_LIST_LONGOPTS=' { "no-fix-arm1176", no_argument, NULL, OPTION_NO_FIX_ARM1176 }, { "long-plt", no_argument, NULL, OPTION_LONG_PLT }, { "cmse-implib", no_argument, NULL, OPTION_CMSE_IMPLIB }, + { "in-implib", required_argument, NULL, OPTION_IN_IMPLIB }, ' PARSE_AND_LIST_OPTIONS=' @@ -624,6 +643,8 @@ PARSE_AND_LIST_OPTIONS=' " to handle large .plt/.got displacements\n")); fprintf (file, _(" --cmse-implib Make import library to be a secure gateway import\n" " library as per ARMv8-M Security Extensions\n")); + fprintf (file, _(" --in-implib Import library whose symbols address must\n" + " remain stable\n")); fprintf (file, _("\ --stub-group-size=N Maximum size of a group of input sections that\n\ can be handled by one stub section. A negative\n\ @@ -748,6 +769,10 @@ PARSE_AND_LIST_ARGS_CASES=' case OPTION_CMSE_IMPLIB: cmse_implib = 1; break; + + case OPTION_IN_IMPLIB: + in_implib_filename = optarg; + break; ' # We have our own before_allocation etc. functions, but they call diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 5ee4c45aca6..09e8b1ef5d7 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -6823,6 +6823,18 @@ specified by the @samp{--out-implib} and @samp{--in-implib} options are secure gateway import libraries, suitable for linking a non-secure executable against secure code as per ARMv8-M Security Extensions. +@kindex --in-implib=@var{file} +@cindex Input import library +The @samp{--in-implib=file} specifies an input import library whose symbols +must keep the same address in the executable being produced. A warning is +given if no @samp{--out-implib} is given but new symbols have been introduced +in the executable that should be listed in its import library. Otherwise, if +@samp{--out-implib} is specified, the symbols are silently added to the output +import library. A warning is also given if some symbols present in the input +import library have disappeared from the executable. This option is only +effective for Secure Gateway import libraries, ie. when @samp{--cmse-implib} is +specified. + @ifclear GENERIC @lowersections @end ifclear diff --git a/ld/testsuite/ChangeLog.arm b/ld/testsuite/ChangeLog.arm index 929771a9c61..598ee9cdbc1 100644 --- a/ld/testsuite/ChangeLog.arm +++ b/ld/testsuite/ChangeLog.arm @@ -1,3 +1,14 @@ +2016-03-29 Thomas Preud'homme + + * testsuite/ld-arm/cmse-implib.s: Add input import library testing. + * testsuite/ld-arm/cmse-implib.rd: Update accordingly. + * testsuite/ld-arm/cmse-new-implib.out: New file. + * testsuite/ld-arm/cmse-new-implib.rd: Likewise. + * testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise. + * testsuite/ld-arm/cmse-new-earlier-later-implib.out: Likewise. + * testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise. + * testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise. + 2016-03-29 Thomas Preud'homme * testsuite/ld-arm/arm-elf.exp diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp index 100b9645ef1..1fb56690826 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -625,16 +625,53 @@ set armeabitests_nonacl { "cmse-veneers-mainline"} {"Secure gateway import library generation: errors" "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-implib.lib --cmse-implib" "" - "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1" + "-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1 --defsym VER=1" {cmse-implib.s} {{ld cmse-implib-errors.out}} "cmse-implib"} {"Secure gateway import library generation" "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-implib.lib --cmse-implib" "" - "-march=armv8-m.base -mthumb" + "-march=armv8-m.base -mthumb --defsym VER=1" {cmse-implib.s} {{readelf {-s tmpdir/cmse-implib.lib} cmse-implib.rd}} "cmse-implib"} + {"Input secure gateway import library" + "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-new-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" "" + "-march=armv8-m.base -mthumb --defsym VER=2" + {cmse-implib.s} + {{ld cmse-new-implib.out} + {readelf {-s tmpdir/cmse-new-implib.lib} cmse-new-implib.rd}} + "cmse-new-implib"} + {"Input secure gateway import library: no output import library" + "--section-start .gnu.sgstubs=0x20000 --in-implib=tmpdir/cmse-implib.lib --cmse-implib" "" + "-march=armv8-m.base -mthumb --defsym VER=2" + {cmse-implib.s} + {{ld cmse-new-implib-no-output.out}} + "cmse-new-implib-no-output"} + {"Input secure gateway import library: earlier stub section base" + "--section-start .gnu.sgstubs=0x19000 --out-implib=tmpdir/cmse-new-earlier-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" "" + "-march=armv8-m.base -mthumb --defsym VER=2" + {cmse-implib.s} + {{ld cmse-new-earlier-later-implib.out}} + "cmse-new-earlier-implib"} + {"Input secure gateway import library: later stub section base" + "--section-start .gnu.sgstubs=0x30000 --out-implib=tmpdir/cmse-new-later-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" "" + "-march=armv8-m.base -mthumb --defsym VER=2" + {cmse-implib.s} + {{ld cmse-new-earlier-later-implib.out}} + "cmse-new-later-implib"} + {"Input secure gateway import library: veneer comeback" + "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-new-comeback-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" "" + "-march=armv8-m.base -mthumb --defsym VER=3" + {cmse-implib.s} + {{readelf {-s tmpdir/cmse-new-comeback-implib.lib} cmse-new-comeback-implib.rd}} + "cmse-new-comeback-implib"} + {"Input secure gateway import library: entry function change" + "--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-new-wrong-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" "" + "-march=armv8-m.base -mthumb --defsym VER=4" + {cmse-implib.s} + {{ld cmse-new-wrong-implib.out}} + "cmse-new-wrong-implib"} {"R_ARM_THM_JUMP19 Relocation veneers: Short" "--section-start destsect=0x000108002 --section-start .text=0x8000" "" diff --git a/ld/testsuite/ld-arm/cmse-implib.s b/ld/testsuite/ld-arm/cmse-implib.s index a42da63fffe..9dd78393989 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 00000000000..c88d9d51042 --- /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 00000000000..b49ad0ac077 --- /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 00000000000..0590b71c844 --- /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 00000000000..c8af2807e7c --- /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 00000000000..9ff0fd87937 --- /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 00000000000..2afe4078e78 --- /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