summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Preud'homme <thomas.preudhomme@arm.com>2016-08-04 15:54:57 +0100
committerThomas Preud'homme <thomas.preudhomme@arm.com>2016-08-04 15:54:57 +0100
commit54ddd295b505efe4b07cc1e939d4e150032603d8 (patch)
tree58c9a2c7639072764628a540c2340e221e3b87d5
parent4ba2ef8fbe74716708e5ce0bcba4f3b1cc8ac99a (diff)
downloadbinutils-gdb-54ddd295b505efe4b07cc1e939d4e150032603d8.tar.gz
2016-08-04 Thomas Preud'homme <thomas.preudhomme@arm.com>
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.
-rw-r--r--bfd/ChangeLog13
-rw-r--r--bfd/bfd-in.h2
-rw-r--r--bfd/bfd-in2.h2
-rw-r--r--bfd/elf32-arm.c97
-rw-r--r--ld/ChangeLog18
-rw-r--r--ld/emultempl/armelf.em11
-rw-r--r--ld/ld.texinfo7
-rw-r--r--ld/testsuite/ld-arm/arm-elf.exp12
-rw-r--r--ld/testsuite/ld-arm/cmse-implib-errors.out7
-rw-r--r--ld/testsuite/ld-arm/cmse-implib.rd13
-rw-r--r--ld/testsuite/ld-arm/cmse-implib.s58
11 files changed, 236 insertions, 4 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 312bfae8957..9c0f439b89e 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,18 @@
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.
(elf32_arm_stub_cmse_branch_thumb_only): Define stub sequence.
(cmse_branch_thumb_only): Declare stub.
diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index 99cafba1477..e40d5bc276c 100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.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/bfd-in2.h b/bfd/bfd-in2.h
index f9f0e26729d..ca2e5ee3611 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -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 *);
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 10155125ce6..1eba21b42dd 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -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
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 49f79726f2b..6dcb8ee03a2 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,5 +1,23 @@
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.
* testsuite/ld-arm/arm-elf.exp
(Secure gateway veneers: no .gnu.sgstubs section): New test.
diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
index 6074824f72d..c21f6a82335 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 af8cee39561..e6813f287fe 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -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
diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
index b3c8a84b86f..55240854a24 100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -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
index 00000000000..0026f6be97e
--- /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 00000000000..c5f7aef8c32
--- /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 00000000000..a42da63fffe
--- /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