2016-08-04 Thomas Preud'homme <thomas.preudhomme@arm.com>
authorThomas Preud'homme <thomas.preudhomme@arm.com>
Thu, 4 Aug 2016 14:54:57 +0000 (15:54 +0100)
committerThomas Preud'homme <thomas.preudhomme@arm.com>
Thu, 4 Aug 2016 14:54:57 +0000 (15:54 +0100)
bfd/
* 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/
* 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.

bfd/ChangeLog
bfd/bfd-in.h
bfd/bfd-in2.h
bfd/elf32-arm.c
ld/ChangeLog
ld/emultempl/armelf.em
ld/ld.texinfo
ld/testsuite/ld-arm/arm-elf.exp
ld/testsuite/ld-arm/cmse-implib-errors.out [new file with mode: 0644]
ld/testsuite/ld-arm/cmse-implib.rd [new file with mode: 0644]
ld/testsuite/ld-arm/cmse-implib.s [new file with mode: 0644]

index 312bfae89571ac4d236ad8004747a694c6d38d63..9c0f439b89eb6548778bfafd2c0e9071b5458963 100644 (file)
@@ -1,3 +1,16 @@
+2016-08-04  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.
+
 2016-08-04  Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
        * elf32-arm.c (CMSE_PREFIX): Define macro.
index 99cafba14770a6de50530d67165e99e1cceb6f02..e40d5bc276ce87429001320efc68101fe318b5d3 100644 (file)
@@ -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 *);
index f9f0e26729d665d719e033b9f534ec72decb428d..ca2e5ee36115111f7ac0d985a6726ebf8676d4eb 100644 (file)
@@ -909,7 +909,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 *);
index 10155125ce6afa06f5a77721b964bbb722195ffd..1eba21b42ddfaf3704860107e4fff36dbbc24d8d 100644 (file)
@@ -3144,6 +3144,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;
 
@@ -8307,7 +8311,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;
 
@@ -8334,6 +8338,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;
@@ -16854,6 +16859,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
@@ -18780,6 +18874,7 @@ elf32_arm_backend_symbol_processing (bfd *abfd, asymbol *sym)
 #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
index 49f79726f2be2fc62e6d43832ea3f5ccd19ed896..6dcb8ee03a2264151d3ed9ec5fb3c9abe05e10c0 100644 (file)
@@ -1,3 +1,21 @@
+2016-08-04  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.
+
 2016-08-04  Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
        * ld.texinfo (Placement of SG veneers): New concept entry.
index 6074824f72d6f607449000702e7c5945bfe412ef..c21f6a82335a58a0ab37f3719c73c95e73e6211c 100644 (file)
@@ -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
index af8cee39561dcec3213137d819bb5588fc41ccdf..e6813f287fe5ce4c916bf93f48b2e9edbc336570 100644 (file)
@@ -6859,6 +6859,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
index b3c8a84b86f9b03679b6b3524cd35af9b4749860..55240854a24951194c8150581b8a40dd2910b5cb 100644 (file)
@@ -668,6 +668,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 (file)
index 0000000..0026f6b
--- /dev/null
@@ -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 (file)
index 0000000..c5f7aef
--- /dev/null
@@ -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 (file)
index 0000000..a42da63
--- /dev/null
@@ -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