This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC PATCH, binutils, ARM 10/11] Add support for creating ARM v8-M secure extensions import libraries


On 29/03/16 15:46, Thomas Preudhomme wrote:
> On Wednesday 23 December 2015 16:01:50 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 creating
>> *Secure Gateway* import libraries.
>>
>> ARM v8-M security extensions require [3] a secure gateway import library to
>> be generated for non-secure executable to link against entry points in
>> secure executable. Such an import library must contain all global function
>> symbols from the secure executable that have a corresponding special (ie
>> prefixed by "__acle_se_") symbol and these symbol should be made absolute.
>>
>> This patch adds support for generating such an import library. It reuses the
>> code to generate an import library by requiring the user to add an extra
>> --cmse-implib option for him/her to state the intent to create a *secure
>> gateway* import library.
>>
>>
>> [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 9 of
>> ARM-ECM-0359818 [2]
> 
> Please find an updated patch below.

One question: What happens if the user tries to use the new option
--cmse-implib on a target that doesn't support v8-M SE?  We should get
some sensible diagnostic in that case.

Otherwise I think this is OK.

R.

> 
> *** bfd/ChangeLog ***
> 
> 2015-07-16  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> 
>         * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add one parameter.
>         * bfd-in2.h: Regenerate.
>         * elf32-arm.c (struct elf32_arm_link_hash_table): Declare new
>         cmse_implib field.
>         (bfd_elf32_arm_set_target_relocs): Add new parameter to initialize
>         cmse_implib field in struct elf32_arm_link_hash_table.
>         (elf32_arm_filter_cmse_symbols): New function.
>         (elf32_arm_filter_implib_symbols): Likewise.
>         (elf_backend_filter_implib_symbols): Define to
>         elf32_arm_filter_implib_symbols.
> 
> 
> *** ld/ChangeLog ***
> 
> 2016-02-17  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> 
>         * emultempl/armelf.em (cmse_implib): Declare and define this new
>         static variable.
>         (arm_elf_create_output_section_statements): Add new cmse_implib
>         parameter.
>         (OPTION_CMSE_IMPLIB): Define macro.
>         (PARSE_AND_LIST_LONGOPTS): Add entry for new --cmse-implib switch.
>         (PARSE_AND_LIST_OPTIONS): Likewise.
>         (PARSE_AND_LIST_ARGS_CASES): Handle OPTION_CMSE_IMPLIB case.
>         * ld.texinfo (--cmse-implib): Document new option.
>         * testsuite/ld-arm/arm-elf.exp
>         (Secure gateway import library generation): New test.
>         (Secure gateway import library generation: errors): Likewise.
>         * testsuite/ld-arm/cmse-implib.s: New file.
>         * testsuite/ld-arm/cmse-implib-errors.out: Likewise.
>         * testsuite/ld-arm/cmse-implib.rd: Likewise.
> 
> 
> diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
> index 
> c66ce3bba1ad1d1ce670f7404e465834cbf43fb1..7e3483b9984b04c534e53f2f9026abf26d37592a 
> 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);
> +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
>  
>  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 
> afaca4ef19e49cf9899952a84a90c60fcd3fc8dd..55e1cdde2d0a899238a224c6915d20197b72f085 
> 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);
> +   bfd_arm_stm32l4xx_fix, int, int, int, int, int, int);
>  
>  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 
> 126c30df9fbf5ee11020b9fa4efb59c61bc1c352..a8aee085bb80159d6877508a8eef044b05a8a4df 
> 100644
> --- a/bfd/elf32-arm.c
> +++ b/bfd/elf32-arm.c
> @@ -3123,6 +3123,10 @@ struct elf32_arm_link_hash_table
>    /* True if the target uses REL relocations.  */
>    int use_rel;
>  
> +  /* Nonzero if import library must be a secure gateway import library
> +     as per ARMv8-M Security Extensions.  */
> +  int cmse_implib;
> +
>    /* The index of the next unused R_ARM_TLS_DESC slot in .rel.plt.  */
>    bfd_vma next_tls_desc_index;
>  
> @@ -8179,7 +8183,7 @@ 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 fix_arm1176, int cmse_implib)
>  {
>    struct elf32_arm_link_hash_table *globals;
>  
> @@ -8206,6 +8210,7 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd,
>    globals->pic_veneer = pic_veneer;
>    globals->fix_cortex_a8 = fix_cortex_a8;
>    globals->fix_arm1176 = fix_arm1176;
> +  globals->cmse_implib = cmse_implib;
>  
>    BFD_ASSERT (is_arm_elf (output_bfd));
>    elf_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
> @@ -16692,6 +16697,95 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd,
>    return TRUE;
>  }
>  
> +/* Filter normal symbols of CMSE entry functions of ABFD to include in
> +   the import library.  All SYMCOUNT symbols of ABFD can be examined
> +   from their pointers in SYMS.  Pointers of symbols to keep should be
> +   stored continuously at the beginning of that array.
> +
> +   Returns the number of symbols to keep.  */
> +
> +static unsigned int
> +elf32_arm_filter_cmse_symbols (bfd *abfd ATTRIBUTE_UNUSED,
> +			       struct bfd_link_info *info,
> +			       asymbol **syms, long symcount)
> +{
> +  size_t maxnamelen;
> +  char *cmse_name;
> +  long src_count, dst_count = 0;
> +  struct elf32_arm_link_hash_table *htab;
> +
> +  htab = elf32_arm_hash_table (info);
> +  if (!htab->stub_bfd || !htab->stub_bfd->sections)
> +    symcount = 0;
> +
> +  maxnamelen = 128;
> +  cmse_name = (char *) bfd_malloc (maxnamelen);
> +  for (src_count = 0; src_count < symcount; src_count++)
> +    {
> +      struct elf32_arm_link_hash_entry *cmse_hash;
> +      asymbol *sym;
> +      flagword flags;
> +      char *name;
> +      size_t namelen;
> +
> +      sym = syms[src_count];
> +      flags = sym->flags;
> +      name = (char *) bfd_asymbol_name (sym);
> +
> +      if ((flags & BSF_FUNCTION) != BSF_FUNCTION)
> +	continue;
> +      if (!(flags & (BSF_GLOBAL | BSF_WEAK)))
> +	continue;
> +
> +      namelen = strlen (name) + sizeof (CMSE_PREFIX) + 1;
> +      if (namelen > maxnamelen)
> +	{
> +	  cmse_name = (char *)
> +	    bfd_realloc (cmse_name, namelen);
> +	  maxnamelen = namelen;
> +	}
> +      snprintf (cmse_name, maxnamelen, "%s%s", CMSE_PREFIX, name);
> +      cmse_hash = (struct elf32_arm_link_hash_entry *)
> +	elf_link_hash_lookup (&(htab)->root, cmse_name, FALSE, FALSE, TRUE);
> +
> +      if (!cmse_hash
> +	  || (cmse_hash->root.root.type != bfd_link_hash_defined
> +	      && cmse_hash->root.root.type != bfd_link_hash_defweak)
> +	  || cmse_hash->root.type != STT_FUNC)
> +	continue;
> +
> +      if (!ARM_GET_SYM_CMSE_SPCL (cmse_hash->root.target_internal))
> +	continue;
> +
> +      syms[dst_count++] = sym;
> +    }
> +  free (cmse_name);
> +
> +  syms[dst_count] = NULL;
> +
> +  return dst_count;
> +}
> +
> +/* Filter symbols of ABFD to include in the import library.  All
> +   SYMCOUNT symbols of ABFD can be examined from their pointers in
> +   SYMS.  Pointers of symbols to keep should be stored continuously at
> +   the beginning of that array.
> +
> +   Returns the number of symbols to keep.  */
> +
> +static unsigned int
> +elf32_arm_filter_implib_symbols (bfd *abfd ATTRIBUTE_UNUSED,
> +				 struct bfd_link_info *info,
> +				 asymbol **syms, long symcount)
> +{
> +  struct elf32_arm_link_hash_table *globals = elf32_arm_hash_table (info);
> +
> +  if (globals->cmse_implib)
> +    return elf32_arm_filter_cmse_symbols (abfd, info, syms, symcount);
> +  else
> +    return _bfd_elf_filter_global_symbols (abfd, info, syms, symcount);
> +}
> +
>  /* Allocate target specific section data.  */
>  
>  static bfd_boolean
> @@ -18480,6 +18574,7 @@ elf32_arm_count_additional_relocs (asection *sec)
>  #define elf_backend_modify_segment_map		elf32_arm_modify_segment_map
>  #define elf_backend_additional_program_headers  
> elf32_arm_additional_program_headers
>  #define elf_backend_output_arch_local_syms      
> elf32_arm_output_arch_local_syms
> +#define elf_backend_filter_implib_symbols	elf32_arm_filter_implib_symbols
>  #define elf_backend_begin_write_processing      
> elf32_arm_begin_write_processing
>  #define elf_backend_add_symbol_hook		elf32_arm_add_symbol_hook
>  #define elf_backend_count_additional_relocs	elf32_arm_count_additional_relocs
> diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
> index 
> 6074824f72d6f607449000702e7c5945bfe412ef..c21f6a82335a58a0ab37f3719c73c95e73e6211c 
> 100644
> --- a/ld/emultempl/armelf.em
> +++ b/ld/emultempl/armelf.em
> @@ -42,6 +42,7 @@ static int no_wchar_size_warning = 0;
>  static int pic_veneer = 0;
>  static int merge_exidx_entries = -1;
>  static int fix_arm1176 = 1;
> +static int cmse_implib = 0;
>  
>  static void
>  gld${EMULATION_NAME}_before_parse (void)
> @@ -514,7 +515,7 @@ arm_elf_create_output_section_statements (void)
>  				   no_enum_size_warning,
>  				   no_wchar_size_warning,
>  				   pic_veneer, fix_cortex_a8,
> -				   fix_arm1176);
> +				   fix_arm1176, cmse_implib);
>  
>    stub_file = lang_add_input_file ("linker stubs",
>   				   lang_input_file_is_fake_enum,
> @@ -583,6 +584,7 @@ PARSE_AND_LIST_PROLOGUE='
>  #define OPTION_NO_FIX_ARM1176		318
>  #define OPTION_LONG_PLT			319
>  #define OPTION_STM32L4XX_FIX		320
> +#define OPTION_CMSE_IMPLIB		321
>  '
>  
>  PARSE_AND_LIST_SHORTOPTS=p
> @@ -609,6 +611,7 @@ PARSE_AND_LIST_LONGOPTS='
>    { "fix-arm1176", no_argument, NULL, OPTION_FIX_ARM1176 },
>    { "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 },
>  '
>  
>  PARSE_AND_LIST_OPTIONS='
> @@ -629,6 +632,8 @@ PARSE_AND_LIST_OPTIONS='
>    fprintf (file, _("  --pic-veneer                Always generate PIC 
> interworking veneers\n"));
>    fprintf (file, _("  --long-plt                  Generate long .plt 
> entries\n"
>             "                              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, _("\
>    --stub-group-size=N         Maximum size of a group of input sections 
> that\n\
>                                 can be handled by one stub section.  A 
> negative\n\
> @@ -749,6 +754,10 @@ PARSE_AND_LIST_ARGS_CASES='
>     case OPTION_LONG_PLT:
>        bfd_elf32_arm_use_long_plt ();
>        break;
> +
> +   case OPTION_CMSE_IMPLIB:
> +      cmse_implib = 1;
> +      break;
>  '
>  
>  # We have our own before_allocation etc. functions, but they call
> diff --git a/ld/ld.texinfo b/ld/ld.texinfo
> index 
> a2e864199ab21469fdf1e35364ad43ccbf1a3734..82b40355a698958d84b566c09901960370139b27 
> 100644
> --- a/ld/ld.texinfo
> +++ b/ld/ld.texinfo
> @@ -6810,6 +6810,13 @@ 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 
> these
>  veneers in memory.
>  
> +@kindex --cmse-implib
> +@cindex Secure gateway import library
> +The @samp{--cmse-implib} option requests that the import libraries
> +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.
> +
>  @ifclear GENERIC
>  @lowersections
>  @end ifclear
> diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
> index 
> d6e20504e45f4210a1af6a814fe48d30ff91f6fc..da4bf7e0302de9f1c76bbacf8b64a9318d44c46a 
> 100644
> --- a/ld/testsuite/ld-arm/arm-elf.exp
> +++ b/ld/testsuite/ld-arm/arm-elf.exp
> @@ -661,6 +661,18 @@ set armeabitests_nonacl {
>        {objdump {-h -j .gnu.sgstubs} cmse-veneers.sd}
>        {nm {} cmse-veneers.rd}}
>       "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"
> +     {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"
> +     {cmse-implib.s}
> +     {{readelf {-s tmpdir/cmse-implib.lib} cmse-implib.rd}}
> +     "cmse-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-errors.out b/ld/testsuite/ld-
> arm/cmse-implib-errors.out
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..0026f6be97e682c963ac9cc462784c2cf34fd003
> --- /dev/null
> +++ b/ld/testsuite/ld-arm/cmse-implib-errors.out
> @@ -0,0 +1,7 @@
> +.*: .*: absent standard symbol `not_exported_fct2'.
> +.*: .*: invalid special symbol `__acle_se_not_exported_pseudoentry_var'.
> +.*: It must be a global or weak function symbol.
> +.*: .*: invalid standard symbol `not_exported_pseudoentry_var'.
> +.*: It must be a global or weak function symbol.
> +.* cannot size stub section: Invalid operation
> +#...
> diff --git a/ld/testsuite/ld-arm/cmse-implib.rd b/ld/testsuite/ld-arm/cmse-
> implib.rd
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..c5f7aef8c32bf5b4d693d98f9f9cdbae023861b5
> --- /dev/null
> +++ b/ld/testsuite/ld-arm/cmse-implib.rd
> @@ -0,0 +1,13 @@
> +File: tmpdir/cmse-implib.lib
> +
> +Symbol table '.symtab' contains 5 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: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct1
> +     3: 00020009     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer2
> +     4: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct2
> +
> +File: tmpdir/cmse-implib
> +
> +#...
> diff --git a/ld/testsuite/ld-arm/cmse-implib.s b/ld/testsuite/ld-arm/cmse-
> implib.s
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..a42da63fffebe5322be83f278931754262b0f7ae
> --- /dev/null
> +++ b/ld/testsuite/ld-arm/cmse-implib.s
> @@ -0,0 +1,58 @@
> +	.syntax unified
> +	.text
> +
> +.macro	entry	name, vis, entry_fct
> +	.align	2
> +	.\vis	\name
> +	.\vis	__acle_se_\name
> +	.thumb
> +	.thumb_func
> +	.type	\name, %function
> +	.type	__acle_se_\name, %function
> +\name:
> +.ifnb \entry_fct
> +	\entry_fct
> +.endif
> +__acle_se_\name:
> +	nop
> +	.size	\name, .-\name
> +	.size	__acle_se_\name, .-__acle_se_\name
> +.endm
> +
> +	@ Valid setups for veneer generation
> +	entry exported_entry_veneer2, global
> +	entry exported_entry_veneer3, global
> +
> +	@ Valid setup for entry function without veneer generation
> +	entry exported_entry_fct1, global, sg
> +	entry exported_entry_fct2, global, sg
> +
> +	@ Normal symbol not exported to SG import library
> +	.align	2
> +	.global	not_exported_fct1
> +	.type	not_exported_fct1, %function
> +not_exported_fct1:
> +	nop
> +	.size	not_exported_fct1, .-not_exported_fct1
> +
> +.ifdef CHECK_ERRORS
> +	@ Invalid setups for export to SG import library
> +	.align	2
> +	.global	__acle_se_not_exported_fct2
> +	.type	__acle_se_not_exported_fct2, %function
> +__acle_se_not_exported_fct2:
> +	nop
> +	.size	__acle_se_not_exported_fct2, .-__acle_se_not_exported_fct2
> +
> +	.align	2
> +	.global	__acle_se_not_exported_pseudoentry_var
> +	.global	not_exported_pseudoentry_var
> +	.data
> +	.type	__acle_se_not_exported_pseudoentry_var, %object
> +	.type	not_exported_pseudoentry_var, %object
> +	.size	not_exported_pseudoentry_var, 4
> +	.size	__acle_se_not_exported_pseudoentry_var, 4
> +__acle_se_not_exported_pseudoentry_var:
> +not_exported_pseudoentry_var:
> +	.word	42
> +.endif
> 
> 
> Is this ok for master branch?
> 
> Best regards,
> 
> Thomas
> 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]