From 54ddd295b505efe4b07cc1e939d4e150032603d8 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Thu, 4 Aug 2016 15:54:57 +0100 Subject: [PATCH] 2016-08-04 Thomas Preud'homme 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 | 13 +++ bfd/bfd-in.h | 2 +- bfd/bfd-in2.h | 2 +- bfd/elf32-arm.c | 97 +++++++++++++++++++++- ld/ChangeLog | 18 ++++ ld/emultempl/armelf.em | 11 ++- ld/ld.texinfo | 7 ++ ld/testsuite/ld-arm/arm-elf.exp | 12 +++ ld/testsuite/ld-arm/cmse-implib-errors.out | 7 ++ ld/testsuite/ld-arm/cmse-implib.rd | 13 +++ ld/testsuite/ld-arm/cmse-implib.s | 58 +++++++++++++ 11 files changed, 236 insertions(+), 4 deletions(-) create mode 100644 ld/testsuite/ld-arm/cmse-implib-errors.out create mode 100644 ld/testsuite/ld-arm/cmse-implib.rd create mode 100644 ld/testsuite/ld-arm/cmse-implib.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 312bfae8957..9c0f439b89e 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,16 @@ +2016-08-04 Thomas Preud'homme + + * 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 * elf32-arm.c (CMSE_PREFIX): Define macro. 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,3 +1,21 @@ +2016-08-04 Thomas Preud'homme + + * 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 * ld.texinfo (Placement of SG veneers): New concept entry. 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 -- 2.30.2