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]

[RFC PATCH, binutils, ARM 8/9] Add support for creating ARM v8-M secure extensions import libraries


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]

ChangeLog entries are as follow:


*** 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 ***

2015-11-02  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.


*** ld/testsuite/ChangeLog ***

2015-10-30  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * ld-arm/arm-elf.exp (Secure gateway import library generation): New
        test.
        (Secure gateway import library generation: errors): Likewise.
        * ld-arm/cmse-implib.s: New file.
        * ld-arm/cmse-implib-errors.out: Likewise.
        * ld-arm/cmse-implib.rd: Likewise.


diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index 7abc058..d4f0bf4 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 8aeb5d1..864988d 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 ee491aa..37aede1 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -3071,6 +3071,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;
 
@@ -7936,7 +7940,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;
 
@@ -7963,6 +7967,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;
@@ -16327,6 +16332,84 @@ 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)
+{
+  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;
+
+  for (src_count = 0; src_count < symcount; src_count++)
+    {
+      struct elf32_arm_link_hash_entry *cmse_hash;
+      asymbol *sym = syms[src_count];
+      flagword flags = sym->flags;
+      char *cmse_name, *name = (char *) bfd_asymbol_name (sym);
+
+      if ((flags & BSF_FUNCTION) != BSF_FUNCTION)
+	continue;
+      if (!(flags & (BSF_GLOBAL | BSF_WEAK)))
+	continue;
+
+      if (name == NULL)
+	continue;
+
+      cmse_name = (char *) bfd_malloc (sizeof (CMSE_PREFIX) + strlen (name)
+				       + 1);
+      sprintf (cmse_name, "%s%s", CMSE_PREFIX, name);
+      cmse_hash = (struct elf32_arm_link_hash_entry *)
+	elf_link_hash_lookup (&(htab)->root, cmse_name, FALSE, FALSE, TRUE);
+      free (cmse_name);
+
+      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;
+    }
+
+  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
@@ -18037,6 +18120,7 @@ elf32_arm_get_synthetic_symtab (bfd *abfd,
 #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
 
diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
index 19da7c6..ec6dca2 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)
@@ -511,7 +512,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,
@@ -580,6 +581,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
@@ -606,6 +608,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='
@@ -626,6 +629,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\
@@ -746,6 +751,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 b9e7f7c..234716b 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -6804,6 +6804,13 @@ The @samp{--long-plt} option enables the use of 16 byte PLT entries
 which support up to 4Gb of code.  The default is to use 12 byte PLT
 entries which only support 512Mb of code.
 
+@kindex --cmse-implib
+@cindex Secure gateway import library
+The @samp{--cmse-implib} option requests that the import library
+specified by @samp{--out-implib} option is a secure gateway import
+library, 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 d40003b..95b8881 100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -605,6 +605,18 @@ set armeabitests_nonacl {
       {objdump {-h -j .sgstubs} cmse-veneers.sd}
       {nm {} cmse-veneers.rd}}
      "cmse-veneers-mainline"}
+    {"Secure gateway import library generation: errors"
+     "--section-start .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 .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 0000000..0026f6b
--- /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 0000000..8b11637
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-implib.rd
@@ -0,0 +1,12 @@
+File: tmpdir/cmse-implib.lib
+
+Symbol table '.symtab' contains 4 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_veneer1
+     2: [0-9a-f]+     6 FUNC    GLOBAL DEFAULT  ABS exported_entry_fct
+     3: 00020009     8 FUNC    GLOBAL DEFAULT  ABS exported_entry_veneer2
+
+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 0000000..99fa90c
--- /dev/null
+++ b/ld/testsuite/ld-arm/cmse-implib.s
@@ -0,0 +1,57 @@
+	.syntax unified
+	.text
+
+.macro	entry	name, entry_fct
+	.align	2
+	.global	\name
+	.global	__acle_se_\name
+	.thumb
+	.thumb_func
+	.type	\name, %function
+	.type	__acle_se_\name, %function
+\name:
+.ifnb \entry_fct
+	sg
+.endif
+__acle_se_\name:
+	nop
+	.size	\name, .-\name
+	.size	__acle_se_\name, .-__acle_se_\name
+.endm
+
+	@ Valid setups for veneer generation
+	entry exported_entry_veneer1
+	entry exported_entry_veneer2
+
+	@ Valid setup for entry function without veneer generation
+	entry exported_entry_fct, entry_fct
+
+	@ 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


The patch doesn't show any regression when running the binutils-gdb testsuite for the arm-none-eabi target.

Any comments?

Best regards,

Thomas


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