From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30393 invoked by alias); 29 Mar 2016 14:42:53 -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 29938 invoked by uid 89); 29 Mar 2016 14:42:52 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=2.6 required=5.0 tests=BAYES_50,KAM_LAZY_DOMAIN_SECURITY,KAM_LOTSOFHASH,KAM_STOCKGEN,RP_MATCHES_RCVD autolearn=no version=3.3.2 spammy=Ask, Secure, 8000, Scan 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; Tue, 29 Mar 2016 14:42:42 +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 18D3E28 for ; Tue, 29 Mar 2016 07:41:34 -0700 (PDT) Received: from e108577-lin.localnet (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 284EC3F21A for ; Tue, 29 Mar 2016 07:42:41 -0700 (PDT) From: Thomas Preudhomme To: binutils@sourceware.org Subject: Re: [RFC PATCH, binutils, ARM 8/11] Add support for ARMv8-M Secure Gateway veneer generation Date: Tue, 29 Mar 2016 14:42:00 -0000 Message-ID: <1490553.SH7fNscOFN@e108577-lin> User-Agent: KMail/4.13.3 (Linux/3.13.0-79-generic; KDE/4.13.3; x86_64; ; ) In-Reply-To: <005001d13d57$e3fb95a0$abf2c0e0$@foss.arm.com> References: <005001d13d57$e3fb95a0$abf2c0e0$@foss.arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" X-IsSubscribed: yes X-SW-Source: 2016-03/txt/msg00379.txt.bz2 On Wednesday 23 December 2015 15:59:44 Thomas Preud'homme wrote: > Hi, >=20 > [Posting patch series as RFC] >=20 > 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 creating > ARMv8-M Secure Gateway veneers. >=20 > ARM v8-M security extensions require [3] secure gateway veneers to be > generated for (secure) entry function in order for code to transition from > non-secure state to secure state when calling these entry function. Unlike > other veneers, these veneers are generated independently of relocations, = ie > a veneer can be generated in the absence of relocation. The condition for > the generation is that the normal symbol (the one whose name is the same = as > in C) of an entry function has the same value as the special symbol (norm= al > symbol prefixed with "__acle_se_"). When that happens, the normal symbol = is > rebound to the veneer generated. When the two symbols have different value > it indicates that the entry function already contains an sg instruction to > do the secure state transition and the normal symbol points to the sg > instruction while the special symbol points after that. >=20 > It is also required [4] that such veneers must be able to keep their addr= ess > when the secure code is relinked in order to avoid relinking the non secu= re > code with the secure code. This patch adds support for generating these > veneers in a dedicated output section and expect the user to specify the > address of that section (either via --section-start parameter or in the > linker script). This ensure that they are placed in a memory area with > sufficient space for more veneers to be added. Ensuring that existing > veneers keep their addresses when the secure executable is relinked is > handled by a subsequent patch of this patch serie. >=20 > Note: this patch needs the Cortex-A8 errata workaround refactoring patch > applied to work (patch 1/9 in the patch serie). >=20 > RFC Note: This patch contains some Secure Gateway specific elements that > could potentially be made into more generic and independent suitable for > separate patch. Namely, these are the padding of stub section and setting= a > specific output section for a given stub section. >=20 >=20 > [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=C2=AEv8-M Secu= rity > Extensions: Requirements on Development Tools [3] See section 3.4.3 and > requirement 44 of ARM-ECM-0359818 [2] > [4] requirement 14 and following comment of ARM-ECM-0359818 [2] Please find an updated patch below, following the split of most of its cont= ent=20 in 6/11 and 7/11. *** bfd/ChangeLog *** 2016-02-17 Thomas Preud'homme * elf32-arm.c (CMSE_PREFIX): Define macro. (elf32_arm_stub_cmse_branch_thumb_only): Define stub sequence. (cmse_branch_thumb_only): Declare stub. (struct elf32_arm_link_hash_table): Define cmse_stub_sec field. (elf32_arm_get_plt_info): Add globals parameter. Use it to return FALSE if there is no PLT. (arm_type_of_stub): Adapt to new elf32_arm_get_plt_info signature. (elf32_arm_final_link_relocate): Likewise. (elf32_arm_gc_sweep_hook): Likewise. (arm_stub_is_thumb): Add case for arm_stub_cmse_branch_thumb_only. (arm_dedicated_stub_output_section_required): Likewise. (arm_dedicated_stub_output_section_required_alignment): Likewise. (arm_stub_dedicated_output_section_name): Likewise. (arm_stub_dedicated_input_section_ptr): Likewise and remove ATTRIBUTE_UNUSED for htab parameter. (arm_stub_required_alignment): Likewise. (arm_stub_sym_claimed): Likewise. (arm_dedicated_stub_section_padding): Likewise. (cmse_scan): New function. (elf32_arm_size_stubs): Call cmse_scan for ARM M profile targets. Set stub_changed to TRUE if such veneers were created. (elf32_arm_swap_symbol_in): Add detection code for CMSE special symbols. *** include/elf/ChangeLog *** 2015-12-16 Thomas Preud'homme * arm.h (ARM_GET_SYM_CMSE_SPCL): Define macro. (ARM_SET_SYM_CMSE_SPCL): Likewise. *** ld/ChangeLog *** 2016-02-17 Thomas Preud'homme * ld.texinfo (Placement of SG veneers): New concept entry. * testsuite/ld-arm/arm-elf.exp (Secure gateway veneers: no .gnu.sgstubs section): New test. (Secure gateway veneers: wrong entry functions): Likewise. (Secure gateway veneers (ARMv8-M Baseline)): Likewise. (Secure gateway veneers (ARMv8-M Mainline)): Likewise. * testsuite/ld-arm/cmse-veneers.s: New file. * testsuite/ld-arm/cmse-veneers.d: Likewise. * testsuite/ld-arm/cmse-veneers.rd: Likewise. * testsuite/ld-arm/cmse-veneers.sd: Likewise. * testsuite/ld-arm/cmse-veneers-no-gnu_sgstubs.out: Likewise. * testsuite/ld-arm/cmse-veneers-wrong-entryfct.out: Likewise. diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index=20 8b3dc8fc2dce2a4dbb1b5dbea6e94ee287111286..126c30df9fbf5ee11020b9fa4efb59c61= bc1c352=20 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -2138,6 +2138,8 @@ typedef unsigned short int insn16; =20 #define STUB_ENTRY_NAME "__%s_veneer" =20 +#define CMSE_PREFIX "__acle_se_" + /* The name of the dynamic interpreter. This is put in the .interp section. */ #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" @@ -2543,6 +2545,13 @@ static const insn_sequence=20 elf32_arm_stub_long_branch_arm_nacl_pic[] =3D DATA_WORD (0, R_ARM_NONE, 0), /* .word 0 */ }; =20 +/* Stub used for transition to secure state (aka SG veneer). */ +static const insn_sequence elf32_arm_stub_cmse_branch_thumb_only[] =3D +{ + THUMB32_INSN (0xe97fe97f), /* sg. */ + THUMB32_B_INSN (0xf000b800, -4), /* b.w original_branch_dest. */ +}; + =20 /* Cortex-A8 erratum-workaround stubs. */ =20 @@ -2622,6 +2631,7 @@ static const insn_sequence=20 elf32_arm_stub_a8_veneer_blx[] =3D DEF_STUB(long_branch_v4t_thumb_tls_pic) \ DEF_STUB(long_branch_arm_nacl) \ DEF_STUB(long_branch_arm_nacl_pic) \ + DEF_STUB(cmse_branch_thumb_only) \ DEF_STUB(a8_veneer_b_cond) \ DEF_STUB(a8_veneer_b) \ DEF_STUB(a8_veneer_bl) \ @@ -3171,6 +3181,9 @@ struct elf32_arm_link_hash_table information on stub grouping. */ struct map_stub *stub_group; =20 + /* Input stub section holding secure gateway veneers. */ + asection *cmse_stub_sec; + /* Number of elements in stub_group. */ unsigned int top_id; =20 @@ -3319,12 +3332,16 @@ elf32_arm_create_local_iplt (bfd *abfd, unsigned lo= ng=20 r_symndx) union and *ARM_PLT at the ARM-specific information. */ =20 static bfd_boolean -elf32_arm_get_plt_info (bfd *abfd, struct elf32_arm_link_hash_entry *h, +elf32_arm_get_plt_info (bfd *abfd, struct elf32_arm_link_hash_table *globa= ls, + struct elf32_arm_link_hash_entry *h, unsigned long r_symndx, union gotplt_union **root_plt, struct arm_plt_info **arm_plt) { struct arm_local_iplt_info *local_iplt; =20 + if (globals->root.splt =3D=3D NULL && globals->root.iplt =3D=3D NULL) + return FALSE; + if (h !=3D NULL) { *root_plt =3D &h->root.plt; @@ -3767,6 +3784,7 @@ arm_stub_is_thumb (enum elf32_arm_stub_type stub_type) case arm_stub_long_branch_v4t_thumb_arm_pic: case arm_stub_long_branch_v4t_thumb_tls_pic: case arm_stub_long_branch_thumb_only_pic: + case arm_stub_cmse_branch_thumb_only: return TRUE; case arm_stub_none: BFD_FAIL (); @@ -3832,8 +3850,9 @@ arm_type_of_stub (struct bfd_link_info *info, the address of the appropriate trampoline. */ if (r_type !=3D R_ARM_TLS_CALL && r_type !=3D R_ARM_THM_TLS_CALL - && elf32_arm_get_plt_info (input_bfd, hash, ELF32_R_SYM (rel->r_info= ), - &root_plt, &arm_plt) + && elf32_arm_get_plt_info (input_bfd, globals, hash, + ELF32_R_SYM (rel->r_info), &root_plt, + &arm_plt) && root_plt->offset !=3D (bfd_vma) -1) { asection *splt; @@ -4146,6 +4165,9 @@ arm_dedicated_stub_output_section_required (enum=20 elf32_arm_stub_type stub_type) =20 switch (stub_type) { + case arm_stub_cmse_branch_thumb_only: + return TRUE; + default: return FALSE; } @@ -4166,6 +4188,11 @@ arm_dedicated_stub_output_section_required_alignment =20 switch (stub_type) { + /* Vectors of Secure Gateway veneers must be aligned on 32byte + boundary. */ + case arm_stub_cmse_branch_thumb_only: + return 5; + default: BFD_ASSERT (!arm_dedicated_stub_output_section_required (stub_type)); return 0; @@ -4185,6 +4212,9 @@ arm_dedicated_stub_output_section_name (enum=20 elf32_arm_stub_type stub_type) =20 switch (stub_type) { + case arm_stub_cmse_branch_thumb_only: + return ".gnu.sgstubs"; + default: BFD_ASSERT (!arm_dedicated_stub_output_section_required (stub_type)); return NULL; @@ -4198,15 +4228,17 @@ arm_dedicated_stub_output_section_name (enum=20 elf32_arm_stub_type stub_type) corresponding input section. Otherwise, returns NULL. */ =20 static asection ** -arm_dedicated_stub_input_section_ptr - (struct elf32_arm_link_hash_table *htab ATTRIBUTE_UNUSED, - enum elf32_arm_stub_type stub_type) +arm_dedicated_stub_input_section_ptr (struct elf32_arm_link_hash_table *ht= ab, + enum elf32_arm_stub_type stub_type) { if (stub_type >=3D max_stub_type) abort (); /* Should be unreachable. */ =20 switch (stub_type) { + case arm_stub_cmse_branch_thumb_only: + return &htab->cmse_stub_sec; + default: BFD_ASSERT (!arm_dedicated_stub_output_section_required (stub_type)); return NULL; @@ -4434,6 +4466,7 @@ arm_stub_required_alignment (enum elf32_arm_stub_type= =20 stub_type) 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_cmse_branch_thumb_only: case arm_stub_a8_veneer_blx: return 4; =20 @@ -4457,6 +4490,9 @@ arm_stub_sym_claimed (enum elf32_arm_stub_type=20 stub_type) =20 switch (stub_type) { + case arm_stub_cmse_branch_thumb_only: + return TRUE; + default: return FALSE; } @@ -4475,6 +4511,9 @@ arm_dedicated_stub_section_padding (enum=20 elf32_arm_stub_type stub_type) =20 switch (stub_type) { + case arm_stub_cmse_branch_thumb_only: + return 32; + default: return 0; } @@ -5370,6 +5409,198 @@ elf32_arm_create_stub (struct=20 elf32_arm_link_hash_table *htab, return TRUE; } =20 +/* Scan symbols in INPUT_BFD to identify secure entry functions needing a + gateway veneer to transition from non secure to secure state and create= =20 them + accordingly. + + As per "ARMv8-M Security Extensions: Requirements on Development Tools" + document, a secure gateway veneer is needed when there exists a non-loc= al + function symbol called "normal" symbol (eg. foo) with the same value as= a + symbol with the same type, binding a name save for a __acle_se_ prefix, + called a "special" symbol (eg. __acle_se_foo). Entry functions handling + with secure state transition by themselves have these symbols with=20 different + values. + + OUT_ATTR gives the output attributes, SYM_HASHES the symbol index to ha= sh + entry mapping while HTAB gives the name to hash entry mapping. + + If any secure gateway veneer is created, *STUB_CHANGED is set to TRUE.= =20=20 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) +{ + const struct elf_backend_data *bed; + Elf_Internal_Shdr *symtab_hdr; + unsigned i, j, sym_count, ext_start; + Elf_Internal_Sym *cmse_sym, *local_syms; + struct elf32_arm_link_hash_entry *hash, *cmse_hash =3D NULL; + enum arm_st_branch_type branch_type; + char *sym_name, *lsym_name; + bfd_vma sym_value; + asection *section; + bfd_boolean is_v8m, new_stub, created_stub, cmse_invalid, ret =3D TRUE; + + bed =3D get_elf_backend_data (input_bfd); + symtab_hdr =3D &elf_tdata (input_bfd)->symtab_hdr; + sym_count =3D symtab_hdr->sh_size / bed->s->sizeof_sym; + ext_start =3D symtab_hdr->sh_info; + is_v8m =3D (out_attr[Tag_CPU_arch].i >=3D TAG_CPU_ARCH_V8M_BASE + && out_attr[Tag_CPU_arch_profile].i =3D=3D 'M'); + + local_syms =3D (Elf_Internal_Sym *) symtab_hdr->contents; + if (local_syms =3D=3D NULL) + local_syms =3D bfd_elf_get_elf_syms (input_bfd, symtab_hdr, + symtab_hdr->sh_info, 0, NULL, NULL, + NULL); + if (symtab_hdr->sh_info && local_syms =3D=3D NULL) + return FALSE; + + /* Scan symbols. */ + for (i =3D 0; i < sym_count; i++) + { + cmse_invalid =3D FALSE; + + if (i < ext_start) + { + cmse_sym =3D &local_syms[i]; + /* Not a special symbol. */ + if (!ARM_GET_SYM_CMSE_SPCL (cmse_sym->st_target_internal)) + continue; + sym_name =3D bfd_elf_string_from_elf_section (input_bfd, + symtab_hdr->sh_link, + cmse_sym->st_name); + /* Special symbol with local binding. */ + cmse_invalid =3D TRUE; + } + else + { + cmse_hash =3D elf32_arm_hash_entry (sym_hashes[i - ext_start]); + sym_name =3D (char *) cmse_hash->root.root.root.string; + + /* Not a special symbol. */ + if (!ARM_GET_SYM_CMSE_SPCL (cmse_hash->root.target_internal)) + continue; + + /* Special symbol has incorrect binding or type. */ + if ((cmse_hash->root.root.type !=3D bfd_link_hash_defined + && cmse_hash->root.root.type !=3D bfd_link_hash_defweak) + || cmse_hash->root.type !=3D STT_FUNC) + cmse_invalid =3D TRUE; + } + + if (!is_v8m) + { + (*_bfd_error_handler) (_("%B: Special symbol `%s' only allowed for " + "ARMv8-M architecture or later."), + input_bfd, sym_name); + is_v8m =3D TRUE; /* Avoid multiple warning. */ + ret =3D FALSE; + } + + if (cmse_invalid) + { + (*_bfd_error_handler) (_("%B: invalid special symbol `%s'."), + input_bfd, sym_name); + (*_bfd_error_handler) (_("It must be a global or weak function " + "symbol.")); + ret =3D FALSE; + if (i < ext_start) + continue; + } + + sym_name +=3D strlen (CMSE_PREFIX); + hash =3D (struct elf32_arm_link_hash_entry *) + elf_link_hash_lookup (&(htab)->root, sym_name, FALSE, FALSE, TRUE); + + /* No associated normal symbol or it is neither global nor weak. */ + if (!hash + || (hash->root.root.type !=3D bfd_link_hash_defined + && hash->root.root.type !=3D bfd_link_hash_defweak) + || hash->root.type !=3D STT_FUNC) + { + if (!hash) + { + /* Searching for a normal symbol with local binding. */ + for (j =3D 0; j < ext_start; j++) + { + lsym_name =3D + bfd_elf_string_from_elf_section (input_bfd, + symtab_hdr->sh_link, + local_syms[j].st_name); + if (!strcmp (sym_name, lsym_name)) + break; + } + } + + if (hash || j < ext_start) + { + (*_bfd_error_handler) + (_("%B: invalid standard symbol `%s'."), input_bfd, sym_name); + (*_bfd_error_handler) + (_("It must be a global or weak function symbol.")); + } + else + (*_bfd_error_handler) + (_("%B: absent standard symbol `%s'."), input_bfd, sym_name); + ret =3D FALSE; + if (!hash) + continue; + } + + sym_value =3D hash->root.root.u.def.value; + section =3D hash->root.root.u.def.section; + + if (cmse_hash->root.root.u.def.section !=3D section) + { + (*_bfd_error_handler) + (_("%B: `%s' and its special symbol are in different sections."), + input_bfd, sym_name); + ret =3D FALSE; + } + if (cmse_hash->root.root.u.def.value !=3D sym_value) + continue; /* Ignore: could be an entry function starting with SG. */ + + /* If this section is a link-once section that will be discarded, then + don't create any stubs. */ + if (section->output_section =3D=3D NULL) + { + (*_bfd_error_handler) + (_("%B: entry function `%s' not output."), input_bfd, sym_name); + continue; + } + + if (hash->root.size =3D=3D 0) + { + (*_bfd_error_handler) + (_("%B: entry function `%s' is empty."), input_bfd, sym_name); + ret =3D FALSE; + } + + if (!ret) + continue; + branch_type =3D ARM_GET_SYM_BRANCH_TYPE (hash->root.target_internal); + created_stub + =3D 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) + ret =3D FALSE; + else + { + BFD_ASSERT (new_stub); + *stub_changed =3D TRUE; + } + } + + if (!symtab_hdr->contents) + free (local_syms); + return ret; +} + /* Determine and set the size of the stub section for a final link. =20 The basic idea here is to examine all the relocations looking for @@ -5386,8 +5617,9 @@ elf32_arm_size_stubs (bfd *output_bfd, unsigned int), void (*layout_sections_again) (void)) { + obj_attribute *out_attr; bfd_size_type stub_group_size; - bfd_boolean stubs_always_after_branch; + bfd_boolean m_profile, stubs_always_after_branch, first_veneer_scan =3D = TRUE; struct elf32_arm_link_hash_table *htab =3D elf32_arm_hash_table (info); struct a8_erratum_fix *a8_fixes =3D NULL; unsigned int num_a8_fixes =3D 0, a8_fix_table_size =3D 10; @@ -5416,6 +5648,8 @@ elf32_arm_size_stubs (bfd *output_bfd, htab->layout_sections_again =3D layout_sections_again; stubs_always_after_branch =3D group_size < 0; =20 + out_attr =3D elf_known_obj_attributes_proc (output_bfd); + m_profile =3D out_attr[Tag_CPU_arch_profile].i =3D=3D 'M'; /* The Cortex-A8 erratum fix depends on stubs not being in the same 4K p= age as the first half of a 32-bit branch straddling two 4K pages. This i= s a crude way of enforcing that. */ @@ -5481,6 +5715,18 @@ elf32_arm_size_stubs (bfd *output_bfd, if (symtab_hdr->sh_info =3D=3D 0) continue; =20 + /* Limit scan of symbols to object file whose profile is + Microcontroller to not hinder performance in the general case. */ + if (m_profile && first_veneer_scan) + { + struct elf_link_hash_entry **sym_hashes; + + sym_hashes =3D elf_sym_hashes (input_bfd); + if (!cmse_scan (input_bfd, htab, out_attr, sym_hashes, + &stub_changed)) + goto error_ret_free_local; + } + /* Walk over each section attached to the input bfd. */ for (section =3D input_bfd->sections; section !=3D NULL; @@ -5853,6 +6099,7 @@ elf32_arm_size_stubs (bfd *output_bfd, =20 /* Ask the linker to do its stuff. */ (*htab->layout_sections_again) (); + first_veneer_scan =3D FALSE; } =20 /* Add stubs for Cortex-A8 erratum fixes now. */ @@ -9194,7 +9441,8 @@ elf32_arm_final_link_relocate (reloc_howto_type *=20= =20=20=20=20=20=20=20=20=20=20 howto, /* Find out whether the symbol has a PLT. Set ST_VALUE, BRANCH_TYPE and VALUE appropriately for relocations that we resolve at link time. */ has_iplt_entry =3D FALSE; - if (elf32_arm_get_plt_info (input_bfd, eh, r_symndx, &root_plt, &arm_plt) + if (elf32_arm_get_plt_info (input_bfd, globals, eh, r_symndx, &root_plt, + &arm_plt) && root_plt->offset !=3D (bfd_vma) -1) { plt_offset =3D root_plt->offset; @@ -13616,7 +13864,8 @@ elf32_arm_gc_sweep_hook (bfd *=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20 abfd, } =20 if (may_need_local_target_p - && elf32_arm_get_plt_info (abfd, eh, r_symndx, &root_plt, &arm_plt)) + && elf32_arm_get_plt_info (abfd, globals, eh, r_symndx, &root_plt, + &arm_plt)) { /* If PLT refcount book-keeping is wrong and too low, we'll see a zero value (going to -1) for the root PLT reference @@ -17769,6 +18018,9 @@ elf32_arm_swap_symbol_in (bfd * abfd, const void *pshn, Elf_Internal_Sym *dst) { + Elf_Internal_Shdr *symtab_hdr; + const char *name =3D NULL; + if (!bfd_elf32_swap_symbol_in (abfd, psrc, pshn, dst)) return FALSE; dst->st_target_internal =3D 0; @@ -17797,6 +18049,13 @@ elf32_arm_swap_symbol_in (bfd * abfd, else ARM_SET_SYM_BRANCH_TYPE (dst->st_target_internal, ST_BRANCH_UNKNOWN); =20 + /* Mark CMSE special symbols. */ + symtab_hdr =3D & elf_symtab_hdr (abfd); + if (symtab_hdr->sh_size) + name =3D bfd_elf_sym_name (abfd, symtab_hdr, dst, NULL); + if (name && CONST_STRNEQ (name, CMSE_PREFIX)) + ARM_SET_SYM_CMSE_SPCL (dst->st_target_internal); + return TRUE; } =20 diff --git a/include/elf/arm.h b/include/elf/arm.h index=20 d98fef3c605deda3d01e4644870c8e7fa783814c..28a437205f09714901e4266f9a46f359a= cde25a2=20 100644 --- a/include/elf/arm.h +++ b/include/elf/arm.h @@ -367,4 +367,11 @@ enum arm_st_branch_type { #define ARM_SET_SYM_BRANCH_TYPE(SYM_TARGET_INTERNAL,TYPE) \ ((SYM_TARGET_INTERNAL) =3D ((SYM_TARGET_INTERNAL) & ~3) | ((TYPE) & 3)) =20 +/* Get or set whether a symbol is a special symbol of an entry function of= =20 CMSE + secure code. */ +#define ARM_GET_SYM_CMSE_SPCL(SYM_TARGET_INTERNAL) \ + (((SYM_TARGET_INTERNAL) >> 2) & 1) +#define ARM_SET_SYM_CMSE_SPCL(SYM_TARGET_INTERNAL) \ + (SYM_TARGET_INTERNAL) |=3D 4 + #endif /* _ELF_ARM_H */ diff --git a/ld/ld.texinfo b/ld/ld.texinfo index=20 8507c3fe677921c0c8fbd5fcb5b5a5799d8cfae0..f339e30a3c4b8a5c4e44cc6cf1bca8fe2= e2ef3d8=20 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -6804,6 +6804,12 @@ The @samp{--long-plt} option enables the use of 16 b= yte=20 PLT entries which support up to 4Gb of code. The default is to use 12 byte PLT entries which only support 512Mb of code. =20 +@cindex Placement of SG veneers +All SG veneers are placed in the special output section @code{.gnu.sgstubs= }. +Its start address must be set, either with the command line option +@samp{--section-start} or in a linker script, to indicate where to place=20 these +veneers in memory. + @ifclear GENERIC @lowersections @end ifclear diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.= exp index=20 e2fa3b054cfe8ccbb3b93c21b7de9fd89bfb241f..d6e20504e45f4210a1af6a814fe48d30f= f91f6fc=20 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -635,6 +635,33 @@ set armeabitests_nonacl { {{objdump -d jump-reloc-veneers-long.d}} "jump-reloc-veneers-long"} =20 + {"Secure gateway veneers: no .gnu.sgstubs section" "" "" + "-march=3Darmv8-m.base -mthumb" + {cmse-veneers.s} + {{ld cmse-veneers-no-gnu_sgstubs.out}} + "cmse-veneers-no-gnu_sgstubs"} + {"Secure gateway veneers: wrong entry functions" "" "" + "-march=3Darmv7-m -mthumb --defsym CHECK_ERRORS=3D1" + {cmse-veneers.s} + {{ld cmse-veneers-wrong-entryfct.out}} + "cmse-veneers-wrong-entryfct"} + {"Secure gateway veneers (ARMv8-M Baseline)" + "-Ttext=3D0x8000 --section-start .gnu.sgstubs=3D0x20000" "" + "-march=3Darmv8-m.base -mthumb" + {cmse-veneers.s} + {{objdump {-d -j .gnu.sgstubs} cmse-veneers.d} + {objdump {-h -j .gnu.sgstubs} cmse-veneers.sd} + {nm {} cmse-veneers.rd}} + "cmse-veneers-baseline"} + {"Secure gateway veneers (ARMv8-M Mainline)" + "-Ttext=3D0x8000 --section-start .gnu.sgstubs=3D0x20000" "" + "-march=3Darmv8-m.main -mthumb" + {cmse-veneers.s} + {{objdump {-d -j .gnu.sgstubs} cmse-veneers.d} + {objdump {-h -j .gnu.sgstubs} cmse-veneers.sd} + {nm {} cmse-veneers.rd}} + "cmse-veneers-mainline"} + {"R_ARM_THM_JUMP19 Relocation veneers: Short" "--section-start destsect=3D0x000108002 --section-start .text=3D0x800= 0" "" "-march=3Darmv7-m -mthumb" diff --git a/ld/testsuite/ld-arm/cmse-veneers-no-gnu_sgstubs.out=20 b/ld/testsuite/ld-arm/cmse-veneers-no-gnu_sgstubs.out new file mode 100644 index=20 0000000000000000000000000000000000000000..9d1e5ba3215ae8a29585fcf04ec1f9431= 4670a29 --- /dev/null +++ b/ld/testsuite/ld-arm/cmse-veneers-no-gnu_sgstubs.out @@ -0,0 +1,3 @@ +.*: No address assigned to the veneers output section .gnu.sgstubs +.*: cannot size stub section: Invalid operation +#... diff --git a/ld/testsuite/ld-arm/cmse-veneers-wrong-entryfct.out=20 b/ld/testsuite/ld-arm/cmse-veneers-wrong-entryfct.out new file mode 100644 index=20 0000000000000000000000000000000000000000..fd4766ab877a4abbeb8b2c4c053ab11d3= f86773c --- /dev/null +++ b/ld/testsuite/ld-arm/cmse-veneers-wrong-entryfct.out @@ -0,0 +1,19 @@ +.*: .*: Special symbol `__acle_se_loc_entry_veneer1' only allowed for ARMv= 8-M=20 architecture or later. +.*: .*: invalid .* symbol `.*loc_entry_veneer1'. +.*: It must be a global or weak function symbol. +.*: .*: invalid special symbol `__acle_se_loc_entry_veneer2'. +.*: It must be a global or weak function symbol. +.*: .*: invalid special symbol `__acle_se_loc_entry_veneer4'. +.*: It must be a global or weak function symbol. +.*: .*: invalid standard symbol `loc_entry_veneer3'. +.*: It must be a global or weak function symbol. +.*: .*: invalid standard symbol `loc_entry_veneer5'. +.*: It must be a global or weak function symbol. +.*: .*: absent standard symbol `fake_entry_veneer1'. +.*: .*: invalid standard symbol `obj_entry_veneer1'. +.*: It must be a global or weak function symbol. +.*: .*: invalid special symbol `__acle_se_obj_entry_veneer2'. +.*: It must be a global or weak function symbol. +.*: .*: `fake_entry_veneer2' and its special symbol are in different secti= ons. +.*: cannot size stub section: Invalid operation +#... diff --git a/ld/testsuite/ld-arm/cmse-veneers.d b/ld/testsuite/ld-arm/cmse- veneers.d new file mode 100644 index=20 0000000000000000000000000000000000000000..6a44a2b5dce9de4f5d64fe644e41f5ab9= 840806e --- /dev/null +++ b/ld/testsuite/ld-arm/cmse-veneers.d @@ -0,0 +1,21 @@ + +.* + + +Disassembly of section \.gnu.sgstubs: + +00020000 : + 20000: e97f e97f sg + 20004: f7e8 b800 b\.w 8008 <__acle_se_glob_entry_veneer2> + +00020008 : + 20008: e97f e97f sg + 2000c: f7e7 bffe b\.w 800c <__acle_se_weak_entry_veneer2> + +00020010 : + 20010: e97f e97f sg + 20014: f7e7 bff4 b\.w 8000 <__acle_se_glob_entry_veneer1> + +00020018 : + 20018: e97f e97f sg + 2001c: f7e7 bff2 b\.w 8004 <__acle_se_weak_entry_veneer1> diff --git a/ld/testsuite/ld-arm/cmse-veneers.rd b/ld/testsuite/ld-arm/cmse- veneers.rd new file mode 100644 index=20 0000000000000000000000000000000000000000..20fad961bd8803109c3cf57ef22e3b36d= a5b1500 --- /dev/null +++ b/ld/testsuite/ld-arm/cmse-veneers.rd @@ -0,0 +1,9 @@ +#... +[0-9a-f]+ T glob_entry_fct +#... +[0-9a-f]+ T glob_entry_veneer1 +[0-9a-f]+ T glob_entry_veneer2 +#... +[0-9a-f]+ W weak_entry_veneer1 +[0-9a-f]+ W weak_entry_veneer2 +#... diff --git a/ld/testsuite/ld-arm/cmse-veneers.s b/ld/testsuite/ld-arm/cmse- veneers.s new file mode 100644 index=20 0000000000000000000000000000000000000000..d5c57f646a78c4736e4f084d8ad6aff7e= fea554f --- /dev/null +++ b/ld/testsuite/ld-arm/cmse-veneers.s @@ -0,0 +1,97 @@ + .syntax unified + .thumb + .file "foo.c" + .text + +.macro decltype name, type +.ifc \type,object + .data +.else + .thumb + .thumb_func +.endif + .type \name, %\type +.endm + + +.macro entry name, type, vis, typespc, visspc, entry_fct + .align 2 +.ifb \visspc + .\vis __acle_se_\name +.else + .\visspc __acle_se_\name +.endif + .\vis \name + .thumb + .thumb_func +.ifb \typespc + decltype __acle_se_\name, \type +.else + decltype __acle_se_\name, \typespc +.endif + decltype \name, \type +__acle_se_\name: + \entry_fct +\name: +.ifc \type,object + .word 42 +.else + nop +.endif + .size \name, .-\name + .size __acle_se_\name, .-__acle_se_\name +.endm + + +.ifndef CHECK_ERRORS + @ Valid setups for veneer generation + entry glob_entry_veneer1, function, global + entry weak_entry_veneer1, function, weak + entry glob_entry_veneer2, function, global, visspc=3Dweak + entry weak_entry_veneer2, function, weak, visspc=3Dglobal + + @ Valid setup for entry function without SG veneer + entry glob_entry_fct, function, global, entry_fct=3Dnop + +.else + @ Invalid setups for veneer generation (visibility) + entry loc_entry_veneer1, function, local + entry loc_entry_veneer2, function, global, visspc=3Dlocal + entry loc_entry_veneer3, function, local, visspc=3Dglobal + entry loc_entry_veneer4, function, weak, visspc=3Dlocal + entry loc_entry_veneer5, function, local, visspc=3Dweak + + @ Invalid setups for veneer generation (absent standard symbol) + .align 2 + .global __acle_se_fake_entry_veneer1 + .thumb + .thumb_func + .type __acle_se_fake_entry_veneer1, %function +__acle_se_fake_entry_veneer1: + nop + .size __acle_se_fake_entry_veneer1, .-__acle_se_fake_entry_veneer1 + + @ Invalid setups for veneer generation (type) + entry obj_entry_veneer1, object, global, typespc=3Dfunction + entry obj_entry_veneer2, function, global, typespc=3Dobject + + @ Invalid setup for veneer generation (sections) + .section .text.sub1 + .align 2 + .thumb + .thumb_func + .global __acle_se_fake_entry_veneer2 + .type __acle_se_fake_entry_veneer2, %function +__acle_se_fake_entry_veneer2: + nop + .size __acle_se_fake_entry_veneer2, .-__acle_se_fake_entry_veneer2 + .section .text.sub2 + .align 2 + .thumb + .thumb_func + .global fake_entry_veneer2 + .type fake_entry_veneer2, %function +fake_entry_veneer2: + nop + .size fake_entry_veneer2, .-fake_entry_veneer2 +.endif diff --git a/ld/testsuite/ld-arm/cmse-veneers.sd b/ld/testsuite/ld-arm/cmse- veneers.sd new file mode 100644 index=20 0000000000000000000000000000000000000000..99bfc8f37c25b7a57122b330b1145e27a= 9b087fd --- /dev/null +++ b/ld/testsuite/ld-arm/cmse-veneers.sd @@ -0,0 +1,7 @@ + +.* + +Sections: +Idx Name Size VMA LMA File off Algn + \d+ \.gnu\.sgstubs 00000020 00020000 00020000 00010000 2\*\*5 + CONTENTS, ALLOC, LOAD, READONLY, CODE Is this ok for master branch? Best regards, Thomas