mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-23 11:39:26 +08:00
2016-08-04 Thomas Preud'homme <thomas.preudhomme@arm.com>
bfd/ * elf32-arm.c (CMSE_PREFIX): Define macro. (elf32_arm_stub_cmse_branch_thumb_only): Define stub sequence. (cmse_branch_thumb_only): Declare stub. (struct elf32_arm_link_hash_table): Define cmse_stub_sec field. (elf32_arm_get_plt_info): Add globals parameter. Use it to return FALSE if there is no PLT. (arm_type_of_stub): Adapt to new elf32_arm_get_plt_info signature. (elf32_arm_final_link_relocate): Likewise. (elf32_arm_gc_sweep_hook): Likewise. (elf32_arm_gc_mark_extra_sections): Mark sections holding ARMv8-M secure entry functions. (arm_stub_is_thumb): Add case for arm_stub_cmse_branch_thumb_only. (arm_dedicated_stub_output_section_required): Change to a switch case and add a case for arm_stub_cmse_branch_thumb_only. (arm_dedicated_stub_output_section_required_alignment): Likewise. (arm_stub_dedicated_output_section_name): Likewise. (arm_stub_dedicated_input_section_ptr): Likewise and remove ATTRIBUTE_UNUSED for htab parameter. (arm_stub_required_alignment): Likewise. (arm_stub_sym_claimed): Likewise. (arm_dedicated_stub_section_padding): Likewise. (cmse_scan): New function. (elf32_arm_size_stubs): Call cmse_scan for ARM M profile targets. Set stub_changed to TRUE if such veneers were created. (elf32_arm_swap_symbol_in): Add detection code for CMSE special symbols. include/ * arm.h (ARM_GET_SYM_CMSE_SPCL): Define macro. (ARM_SET_SYM_CMSE_SPCL): Likewise. ld/ * ld.texinfo (Placement of SG veneers): New concept entry. * testsuite/ld-arm/arm-elf.exp (Secure gateway veneers: no .gnu.sgstubs section): New test. (Secure gateway veneers: wrong entry functions): Likewise. (Secure gateway veneers (ARMv8-M Baseline)): Likewise. (Secure gateway veneers (ARMv8-M Mainline)): Likewise. * testsuite/ld-arm/cmse-veneers.s: New file. * testsuite/ld-arm/cmse-veneers.d: Likewise. * testsuite/ld-arm/cmse-veneers.rd: Likewise. * testsuite/ld-arm/cmse-veneers.sd: Likewise. * testsuite/ld-arm/cmse-veneers-no-gnu_sgstubs.out: Likewise. * testsuite/ld-arm/cmse-veneers-wrong-entryfct.out: Likewise.
This commit is contained in:
@ -1,3 +1,32 @@
|
|||||||
|
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.
|
||||||
|
(struct elf32_arm_link_hash_table): Define cmse_stub_sec field.
|
||||||
|
(elf32_arm_get_plt_info): Add globals parameter. Use it to return
|
||||||
|
FALSE if there is no PLT.
|
||||||
|
(arm_type_of_stub): Adapt to new elf32_arm_get_plt_info signature.
|
||||||
|
(elf32_arm_final_link_relocate): Likewise.
|
||||||
|
(elf32_arm_gc_sweep_hook): Likewise.
|
||||||
|
(elf32_arm_gc_mark_extra_sections): Mark sections holding ARMv8-M
|
||||||
|
secure entry functions.
|
||||||
|
(arm_stub_is_thumb): Add case for arm_stub_cmse_branch_thumb_only.
|
||||||
|
(arm_dedicated_stub_output_section_required): Change to a switch case
|
||||||
|
and add a case for arm_stub_cmse_branch_thumb_only.
|
||||||
|
(arm_dedicated_stub_output_section_required_alignment): Likewise.
|
||||||
|
(arm_stub_dedicated_output_section_name): Likewise.
|
||||||
|
(arm_stub_dedicated_input_section_ptr): Likewise and remove
|
||||||
|
ATTRIBUTE_UNUSED for htab parameter.
|
||||||
|
(arm_stub_required_alignment): Likewise.
|
||||||
|
(arm_stub_sym_claimed): Likewise.
|
||||||
|
(arm_dedicated_stub_section_padding): Likewise.
|
||||||
|
(cmse_scan): New function.
|
||||||
|
(elf32_arm_size_stubs): Call cmse_scan for ARM M profile targets.
|
||||||
|
Set stub_changed to TRUE if such veneers were created.
|
||||||
|
(elf32_arm_swap_symbol_in): Add detection code for CMSE special
|
||||||
|
symbols.
|
||||||
|
|
||||||
2016-08-02 Alan Modra <amodra@gmail.com>
|
2016-08-02 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
PR ld/20428
|
PR ld/20428
|
||||||
|
363
bfd/elf32-arm.c
363
bfd/elf32-arm.c
@ -2138,6 +2138,8 @@ typedef unsigned short int insn16;
|
|||||||
|
|
||||||
#define STUB_ENTRY_NAME "__%s_veneer"
|
#define STUB_ENTRY_NAME "__%s_veneer"
|
||||||
|
|
||||||
|
#define CMSE_PREFIX "__acle_se_"
|
||||||
|
|
||||||
/* The name of the dynamic interpreter. This is put in the .interp
|
/* The name of the dynamic interpreter. This is put in the .interp
|
||||||
section. */
|
section. */
|
||||||
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
|
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
|
||||||
@ -2561,6 +2563,13 @@ static const insn_sequence elf32_arm_stub_long_branch_arm_nacl_pic[] =
|
|||||||
DATA_WORD (0, R_ARM_NONE, 0), /* .word 0 */
|
DATA_WORD (0, R_ARM_NONE, 0), /* .word 0 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Stub used for transition to secure state (aka SG veneer). */
|
||||||
|
static const insn_sequence elf32_arm_stub_cmse_branch_thumb_only[] =
|
||||||
|
{
|
||||||
|
THUMB32_INSN (0xe97fe97f), /* sg. */
|
||||||
|
THUMB32_B_INSN (0xf000b800, -4), /* b.w original_branch_dest. */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Cortex-A8 erratum-workaround stubs. */
|
/* Cortex-A8 erratum-workaround stubs. */
|
||||||
|
|
||||||
@ -2640,6 +2649,7 @@ static const insn_sequence elf32_arm_stub_a8_veneer_blx[] =
|
|||||||
DEF_STUB(long_branch_v4t_thumb_tls_pic) \
|
DEF_STUB(long_branch_v4t_thumb_tls_pic) \
|
||||||
DEF_STUB(long_branch_arm_nacl) \
|
DEF_STUB(long_branch_arm_nacl) \
|
||||||
DEF_STUB(long_branch_arm_nacl_pic) \
|
DEF_STUB(long_branch_arm_nacl_pic) \
|
||||||
|
DEF_STUB(cmse_branch_thumb_only) \
|
||||||
DEF_STUB(a8_veneer_b_cond) \
|
DEF_STUB(a8_veneer_b_cond) \
|
||||||
DEF_STUB(a8_veneer_b) \
|
DEF_STUB(a8_veneer_b) \
|
||||||
DEF_STUB(a8_veneer_bl) \
|
DEF_STUB(a8_veneer_bl) \
|
||||||
@ -3192,6 +3202,9 @@ struct elf32_arm_link_hash_table
|
|||||||
information on stub grouping. */
|
information on stub grouping. */
|
||||||
struct map_stub *stub_group;
|
struct map_stub *stub_group;
|
||||||
|
|
||||||
|
/* Input stub section holding secure gateway veneers. */
|
||||||
|
asection *cmse_stub_sec;
|
||||||
|
|
||||||
/* Number of elements in stub_group. */
|
/* Number of elements in stub_group. */
|
||||||
unsigned int top_id;
|
unsigned int top_id;
|
||||||
|
|
||||||
@ -3340,12 +3353,16 @@ elf32_arm_create_local_iplt (bfd *abfd, unsigned long r_symndx)
|
|||||||
union and *ARM_PLT at the ARM-specific information. */
|
union and *ARM_PLT at the ARM-specific information. */
|
||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
elf32_arm_get_plt_info (bfd *abfd, struct elf32_arm_link_hash_entry *h,
|
elf32_arm_get_plt_info (bfd *abfd, struct elf32_arm_link_hash_table *globals,
|
||||||
|
struct elf32_arm_link_hash_entry *h,
|
||||||
unsigned long r_symndx, union gotplt_union **root_plt,
|
unsigned long r_symndx, union gotplt_union **root_plt,
|
||||||
struct arm_plt_info **arm_plt)
|
struct arm_plt_info **arm_plt)
|
||||||
{
|
{
|
||||||
struct arm_local_iplt_info *local_iplt;
|
struct arm_local_iplt_info *local_iplt;
|
||||||
|
|
||||||
|
if (globals->root.splt == NULL && globals->root.iplt == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (h != NULL)
|
if (h != NULL)
|
||||||
{
|
{
|
||||||
*root_plt = &h->root.plt;
|
*root_plt = &h->root.plt;
|
||||||
@ -3826,6 +3843,7 @@ arm_stub_is_thumb (enum elf32_arm_stub_type stub_type)
|
|||||||
case arm_stub_long_branch_v4t_thumb_arm_pic:
|
case arm_stub_long_branch_v4t_thumb_arm_pic:
|
||||||
case arm_stub_long_branch_v4t_thumb_tls_pic:
|
case arm_stub_long_branch_v4t_thumb_tls_pic:
|
||||||
case arm_stub_long_branch_thumb_only_pic:
|
case arm_stub_long_branch_thumb_only_pic:
|
||||||
|
case arm_stub_cmse_branch_thumb_only:
|
||||||
return TRUE;
|
return TRUE;
|
||||||
case arm_stub_none:
|
case arm_stub_none:
|
||||||
BFD_FAIL ();
|
BFD_FAIL ();
|
||||||
@ -3897,8 +3915,9 @@ arm_type_of_stub (struct bfd_link_info *info,
|
|||||||
the address of the appropriate trampoline. */
|
the address of the appropriate trampoline. */
|
||||||
if (r_type != R_ARM_TLS_CALL
|
if (r_type != R_ARM_TLS_CALL
|
||||||
&& r_type != R_ARM_THM_TLS_CALL
|
&& r_type != R_ARM_THM_TLS_CALL
|
||||||
&& elf32_arm_get_plt_info (input_bfd, hash, ELF32_R_SYM (rel->r_info),
|
&& elf32_arm_get_plt_info (input_bfd, globals, hash,
|
||||||
&root_plt, &arm_plt)
|
ELF32_R_SYM (rel->r_info), &root_plt,
|
||||||
|
&arm_plt)
|
||||||
&& root_plt->offset != (bfd_vma) -1)
|
&& root_plt->offset != (bfd_vma) -1)
|
||||||
{
|
{
|
||||||
asection *splt;
|
asection *splt;
|
||||||
@ -4250,9 +4269,18 @@ arm_dedicated_stub_output_section_required (enum elf32_arm_stub_type stub_type)
|
|||||||
if (stub_type >= max_stub_type)
|
if (stub_type >= max_stub_type)
|
||||||
abort (); /* Should be unreachable. */
|
abort (); /* Should be unreachable. */
|
||||||
|
|
||||||
|
switch (stub_type)
|
||||||
|
{
|
||||||
|
case arm_stub_cmse_branch_thumb_only:
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
default:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abort (); /* Should be unreachable. */
|
||||||
|
}
|
||||||
|
|
||||||
/* Required alignment (as a power of 2) for the dedicated section holding
|
/* Required alignment (as a power of 2) for the dedicated section holding
|
||||||
veneers of type STUB_TYPE, or 0 if veneers of this type are interspersed
|
veneers of type STUB_TYPE, or 0 if veneers of this type are interspersed
|
||||||
with input sections. */
|
with input sections. */
|
||||||
@ -4264,10 +4292,21 @@ arm_dedicated_stub_output_section_required_alignment
|
|||||||
if (stub_type >= max_stub_type)
|
if (stub_type >= max_stub_type)
|
||||||
abort (); /* Should be unreachable. */
|
abort (); /* Should be unreachable. */
|
||||||
|
|
||||||
|
switch (stub_type)
|
||||||
|
{
|
||||||
|
/* Vectors of Secure Gateway veneers must be aligned on 32byte
|
||||||
|
boundary. */
|
||||||
|
case arm_stub_cmse_branch_thumb_only:
|
||||||
|
return 5;
|
||||||
|
|
||||||
|
default:
|
||||||
BFD_ASSERT (!arm_dedicated_stub_output_section_required (stub_type));
|
BFD_ASSERT (!arm_dedicated_stub_output_section_required (stub_type));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abort (); /* Should be unreachable. */
|
||||||
|
}
|
||||||
|
|
||||||
/* Name of the dedicated output section to put veneers of type STUB_TYPE, or
|
/* Name of the dedicated output section to put veneers of type STUB_TYPE, or
|
||||||
NULL if veneers of this type are interspersed with input sections. */
|
NULL if veneers of this type are interspersed with input sections. */
|
||||||
|
|
||||||
@ -4277,26 +4316,43 @@ arm_dedicated_stub_output_section_name (enum elf32_arm_stub_type stub_type)
|
|||||||
if (stub_type >= max_stub_type)
|
if (stub_type >= max_stub_type)
|
||||||
abort (); /* Should be unreachable. */
|
abort (); /* Should be unreachable. */
|
||||||
|
|
||||||
|
switch (stub_type)
|
||||||
|
{
|
||||||
|
case arm_stub_cmse_branch_thumb_only:
|
||||||
|
return ".gnu.sgstubs";
|
||||||
|
|
||||||
|
default:
|
||||||
BFD_ASSERT (!arm_dedicated_stub_output_section_required (stub_type));
|
BFD_ASSERT (!arm_dedicated_stub_output_section_required (stub_type));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abort (); /* Should be unreachable. */
|
||||||
|
}
|
||||||
|
|
||||||
/* If veneers of type STUB_TYPE should go in a dedicated output section,
|
/* If veneers of type STUB_TYPE should go in a dedicated output section,
|
||||||
returns the address of the hash table field in HTAB holding a pointer to the
|
returns the address of the hash table field in HTAB holding a pointer to the
|
||||||
corresponding input section. Otherwise, returns NULL. */
|
corresponding input section. Otherwise, returns NULL. */
|
||||||
|
|
||||||
static asection **
|
static asection **
|
||||||
arm_dedicated_stub_input_section_ptr
|
arm_dedicated_stub_input_section_ptr (struct elf32_arm_link_hash_table *htab,
|
||||||
(struct elf32_arm_link_hash_table *htab ATTRIBUTE_UNUSED,
|
|
||||||
enum elf32_arm_stub_type stub_type)
|
enum elf32_arm_stub_type stub_type)
|
||||||
{
|
{
|
||||||
if (stub_type >= max_stub_type)
|
if (stub_type >= max_stub_type)
|
||||||
abort (); /* Should be unreachable. */
|
abort (); /* Should be unreachable. */
|
||||||
|
|
||||||
|
switch (stub_type)
|
||||||
|
{
|
||||||
|
case arm_stub_cmse_branch_thumb_only:
|
||||||
|
return &htab->cmse_stub_sec;
|
||||||
|
|
||||||
|
default:
|
||||||
BFD_ASSERT (!arm_dedicated_stub_output_section_required (stub_type));
|
BFD_ASSERT (!arm_dedicated_stub_output_section_required (stub_type));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abort (); /* Should be unreachable. */
|
||||||
|
}
|
||||||
|
|
||||||
/* Find or create a stub section to contain a stub of type STUB_TYPE. SECTION
|
/* Find or create a stub section to contain a stub of type STUB_TYPE. SECTION
|
||||||
is the section that branch into veneer and can be NULL if stub should go in
|
is the section that branch into veneer and can be NULL if stub should go in
|
||||||
a dedicated output section. Returns a pointer to the stub section, and the
|
a dedicated output section. Returns a pointer to the stub section, and the
|
||||||
@ -4518,6 +4574,7 @@ arm_stub_required_alignment (enum elf32_arm_stub_type stub_type)
|
|||||||
case arm_stub_long_branch_thumb_only_pic:
|
case arm_stub_long_branch_thumb_only_pic:
|
||||||
case arm_stub_long_branch_any_tls_pic:
|
case arm_stub_long_branch_any_tls_pic:
|
||||||
case arm_stub_long_branch_v4t_thumb_tls_pic:
|
case arm_stub_long_branch_v4t_thumb_tls_pic:
|
||||||
|
case arm_stub_cmse_branch_thumb_only:
|
||||||
case arm_stub_a8_veneer_blx:
|
case arm_stub_a8_veneer_blx:
|
||||||
return 4;
|
return 4;
|
||||||
|
|
||||||
@ -4539,9 +4596,18 @@ arm_stub_sym_claimed (enum elf32_arm_stub_type stub_type)
|
|||||||
if (stub_type >= max_stub_type)
|
if (stub_type >= max_stub_type)
|
||||||
abort (); /* Should be unreachable. */
|
abort (); /* Should be unreachable. */
|
||||||
|
|
||||||
|
switch (stub_type)
|
||||||
|
{
|
||||||
|
case arm_stub_cmse_branch_thumb_only:
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
default:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abort (); /* Should be unreachable. */
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns the padding needed for the dedicated section used stubs of type
|
/* Returns the padding needed for the dedicated section used stubs of type
|
||||||
STUB_TYPE. */
|
STUB_TYPE. */
|
||||||
|
|
||||||
@ -4551,9 +4617,18 @@ arm_dedicated_stub_section_padding (enum elf32_arm_stub_type stub_type)
|
|||||||
if (stub_type >= max_stub_type)
|
if (stub_type >= max_stub_type)
|
||||||
abort (); /* Should be unreachable. */
|
abort (); /* Should be unreachable. */
|
||||||
|
|
||||||
|
switch (stub_type)
|
||||||
|
{
|
||||||
|
case arm_stub_cmse_branch_thumb_only:
|
||||||
|
return 32;
|
||||||
|
|
||||||
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abort (); /* Should be unreachable. */
|
||||||
|
}
|
||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
arm_build_one_stub (struct bfd_hash_entry *gen_entry,
|
arm_build_one_stub (struct bfd_hash_entry *gen_entry,
|
||||||
void * in_arg)
|
void * in_arg)
|
||||||
@ -5442,6 +5517,204 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Scan symbols in INPUT_BFD to identify secure entry functions needing a
|
||||||
|
gateway veneer to transition from non secure to secure state and create them
|
||||||
|
accordingly.
|
||||||
|
|
||||||
|
"ARMv8-M Security Extensions: Requirements on Development Tools" document
|
||||||
|
defines the conditions that govern Secure Gateway veneer creation for a
|
||||||
|
given symbol <SYM> as follows:
|
||||||
|
- it has function type
|
||||||
|
- it has non local binding
|
||||||
|
- a symbol named __acle_se_<SYM> (called special symbol) exists with the
|
||||||
|
same type, binding and value as <SYM> (called normal symbol).
|
||||||
|
An entry function can handle secure state transition itself in which case
|
||||||
|
its special symbol would have a different value from the normal symbol.
|
||||||
|
|
||||||
|
OUT_ATTR gives the output attributes, SYM_HASHES the symbol index to hash
|
||||||
|
entry mapping while HTAB gives the name to hash entry mapping.
|
||||||
|
|
||||||
|
If any secure gateway veneer is created, *STUB_CHANGED is set to TRUE. The
|
||||||
|
return value gives whether a stub failed to be allocated. */
|
||||||
|
|
||||||
|
static bfd_boolean
|
||||||
|
cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
|
||||||
|
obj_attribute *out_attr, struct elf_link_hash_entry **sym_hashes,
|
||||||
|
bfd_boolean *stub_changed)
|
||||||
|
{
|
||||||
|
const struct elf_backend_data *bed;
|
||||||
|
Elf_Internal_Shdr *symtab_hdr;
|
||||||
|
unsigned i, j, sym_count, ext_start;
|
||||||
|
Elf_Internal_Sym *cmse_sym, *local_syms;
|
||||||
|
struct elf32_arm_link_hash_entry *hash, *cmse_hash = NULL;
|
||||||
|
enum arm_st_branch_type branch_type;
|
||||||
|
char *sym_name, *lsym_name;
|
||||||
|
bfd_vma sym_value;
|
||||||
|
asection *section;
|
||||||
|
bfd_boolean is_v8m, new_stub, created_stub, cmse_invalid, ret = TRUE;
|
||||||
|
|
||||||
|
bed = get_elf_backend_data (input_bfd);
|
||||||
|
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
|
||||||
|
sym_count = symtab_hdr->sh_size / bed->s->sizeof_sym;
|
||||||
|
ext_start = symtab_hdr->sh_info;
|
||||||
|
is_v8m = (out_attr[Tag_CPU_arch].i >= TAG_CPU_ARCH_V8M_BASE
|
||||||
|
&& out_attr[Tag_CPU_arch_profile].i == 'M');
|
||||||
|
|
||||||
|
local_syms = (Elf_Internal_Sym *) symtab_hdr->contents;
|
||||||
|
if (local_syms == NULL)
|
||||||
|
local_syms = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
|
||||||
|
symtab_hdr->sh_info, 0, NULL, NULL,
|
||||||
|
NULL);
|
||||||
|
if (symtab_hdr->sh_info && local_syms == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Scan symbols. */
|
||||||
|
for (i = 0; i < sym_count; i++)
|
||||||
|
{
|
||||||
|
cmse_invalid = FALSE;
|
||||||
|
|
||||||
|
if (i < ext_start)
|
||||||
|
{
|
||||||
|
cmse_sym = &local_syms[i];
|
||||||
|
/* Not a special symbol. */
|
||||||
|
if (!ARM_GET_SYM_CMSE_SPCL (cmse_sym->st_target_internal))
|
||||||
|
continue;
|
||||||
|
sym_name = bfd_elf_string_from_elf_section (input_bfd,
|
||||||
|
symtab_hdr->sh_link,
|
||||||
|
cmse_sym->st_name);
|
||||||
|
/* Special symbol with local binding. */
|
||||||
|
cmse_invalid = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmse_hash = elf32_arm_hash_entry (sym_hashes[i - ext_start]);
|
||||||
|
sym_name = (char *) cmse_hash->root.root.root.string;
|
||||||
|
|
||||||
|
/* Not a special symbol. */
|
||||||
|
if (!ARM_GET_SYM_CMSE_SPCL (cmse_hash->root.target_internal))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Special symbol has incorrect binding or type. */
|
||||||
|
if ((cmse_hash->root.root.type != bfd_link_hash_defined
|
||||||
|
&& cmse_hash->root.root.type != bfd_link_hash_defweak)
|
||||||
|
|| cmse_hash->root.type != STT_FUNC)
|
||||||
|
cmse_invalid = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_v8m)
|
||||||
|
{
|
||||||
|
(*_bfd_error_handler) (_("%B: Special symbol `%s' only allowed for "
|
||||||
|
"ARMv8-M architecture or later."),
|
||||||
|
input_bfd, sym_name);
|
||||||
|
is_v8m = TRUE; /* Avoid multiple warning. */
|
||||||
|
ret = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmse_invalid)
|
||||||
|
{
|
||||||
|
(*_bfd_error_handler) (_("%B: invalid special symbol `%s'."),
|
||||||
|
input_bfd, sym_name);
|
||||||
|
(*_bfd_error_handler) (_("It must be a global or weak function "
|
||||||
|
"symbol."));
|
||||||
|
ret = FALSE;
|
||||||
|
if (i < ext_start)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sym_name += strlen (CMSE_PREFIX);
|
||||||
|
hash = (struct elf32_arm_link_hash_entry *)
|
||||||
|
elf_link_hash_lookup (&(htab)->root, sym_name, FALSE, FALSE, TRUE);
|
||||||
|
|
||||||
|
/* No associated normal symbol or it is neither global nor weak. */
|
||||||
|
if (!hash
|
||||||
|
|| (hash->root.root.type != bfd_link_hash_defined
|
||||||
|
&& hash->root.root.type != bfd_link_hash_defweak)
|
||||||
|
|| hash->root.type != STT_FUNC)
|
||||||
|
{
|
||||||
|
/* Initialize here to avoid warning about use of possibly
|
||||||
|
uninitialized variable. */
|
||||||
|
j = 0;
|
||||||
|
|
||||||
|
if (!hash)
|
||||||
|
{
|
||||||
|
/* Searching for a normal symbol with local binding. */
|
||||||
|
for (; j < ext_start; j++)
|
||||||
|
{
|
||||||
|
lsym_name =
|
||||||
|
bfd_elf_string_from_elf_section (input_bfd,
|
||||||
|
symtab_hdr->sh_link,
|
||||||
|
local_syms[j].st_name);
|
||||||
|
if (!strcmp (sym_name, lsym_name))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hash || j < ext_start)
|
||||||
|
{
|
||||||
|
(*_bfd_error_handler)
|
||||||
|
(_("%B: invalid standard symbol `%s'."), input_bfd, sym_name);
|
||||||
|
(*_bfd_error_handler)
|
||||||
|
(_("It must be a global or weak function symbol."));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
(*_bfd_error_handler)
|
||||||
|
(_("%B: absent standard symbol `%s'."), input_bfd, sym_name);
|
||||||
|
ret = FALSE;
|
||||||
|
if (!hash)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sym_value = hash->root.root.u.def.value;
|
||||||
|
section = hash->root.root.u.def.section;
|
||||||
|
|
||||||
|
if (cmse_hash->root.root.u.def.section != section)
|
||||||
|
{
|
||||||
|
(*_bfd_error_handler)
|
||||||
|
(_("%B: `%s' and its special symbol are in different sections."),
|
||||||
|
input_bfd, sym_name);
|
||||||
|
ret = FALSE;
|
||||||
|
}
|
||||||
|
if (cmse_hash->root.root.u.def.value != sym_value)
|
||||||
|
continue; /* Ignore: could be an entry function starting with SG. */
|
||||||
|
|
||||||
|
/* If this section is a link-once section that will be discarded, then
|
||||||
|
don't create any stubs. */
|
||||||
|
if (section->output_section == NULL)
|
||||||
|
{
|
||||||
|
(*_bfd_error_handler)
|
||||||
|
(_("%B: entry function `%s' not output."), input_bfd, sym_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hash->root.size == 0)
|
||||||
|
{
|
||||||
|
(*_bfd_error_handler)
|
||||||
|
(_("%B: entry function `%s' is empty."), input_bfd, sym_name);
|
||||||
|
ret = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
continue;
|
||||||
|
branch_type = ARM_GET_SYM_BRANCH_TYPE (hash->root.target_internal);
|
||||||
|
created_stub
|
||||||
|
= elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
|
||||||
|
NULL, NULL, section, hash, sym_name,
|
||||||
|
sym_value, branch_type, &new_stub);
|
||||||
|
|
||||||
|
if (!created_stub)
|
||||||
|
ret = FALSE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BFD_ASSERT (new_stub);
|
||||||
|
*stub_changed = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!symtab_hdr->contents)
|
||||||
|
free (local_syms);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Determine and set the size of the stub section for a final link.
|
/* Determine and set the size of the stub section for a final link.
|
||||||
|
|
||||||
The basic idea here is to examine all the relocations looking for
|
The basic idea here is to examine all the relocations looking for
|
||||||
@ -5458,8 +5731,9 @@ elf32_arm_size_stubs (bfd *output_bfd,
|
|||||||
unsigned int),
|
unsigned int),
|
||||||
void (*layout_sections_again) (void))
|
void (*layout_sections_again) (void))
|
||||||
{
|
{
|
||||||
|
obj_attribute *out_attr;
|
||||||
bfd_size_type stub_group_size;
|
bfd_size_type stub_group_size;
|
||||||
bfd_boolean stubs_always_after_branch;
|
bfd_boolean m_profile, stubs_always_after_branch, first_veneer_scan = TRUE;
|
||||||
struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
|
struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
|
||||||
struct a8_erratum_fix *a8_fixes = NULL;
|
struct a8_erratum_fix *a8_fixes = NULL;
|
||||||
unsigned int num_a8_fixes = 0, a8_fix_table_size = 10;
|
unsigned int num_a8_fixes = 0, a8_fix_table_size = 10;
|
||||||
@ -5488,6 +5762,8 @@ elf32_arm_size_stubs (bfd *output_bfd,
|
|||||||
htab->layout_sections_again = layout_sections_again;
|
htab->layout_sections_again = layout_sections_again;
|
||||||
stubs_always_after_branch = group_size < 0;
|
stubs_always_after_branch = group_size < 0;
|
||||||
|
|
||||||
|
out_attr = elf_known_obj_attributes_proc (output_bfd);
|
||||||
|
m_profile = out_attr[Tag_CPU_arch_profile].i == 'M';
|
||||||
/* The Cortex-A8 erratum fix depends on stubs not being in the same 4K page
|
/* The Cortex-A8 erratum fix depends on stubs not being in the same 4K page
|
||||||
as the first half of a 32-bit branch straddling two 4K pages. This is a
|
as the first half of a 32-bit branch straddling two 4K pages. This is a
|
||||||
crude way of enforcing that. */
|
crude way of enforcing that. */
|
||||||
@ -5553,6 +5829,18 @@ elf32_arm_size_stubs (bfd *output_bfd,
|
|||||||
if (symtab_hdr->sh_info == 0)
|
if (symtab_hdr->sh_info == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* Limit scan of symbols to object file whose profile is
|
||||||
|
Microcontroller to not hinder performance in the general case. */
|
||||||
|
if (m_profile && first_veneer_scan)
|
||||||
|
{
|
||||||
|
struct elf_link_hash_entry **sym_hashes;
|
||||||
|
|
||||||
|
sym_hashes = elf_sym_hashes (input_bfd);
|
||||||
|
if (!cmse_scan (input_bfd, htab, out_attr, sym_hashes,
|
||||||
|
&stub_changed))
|
||||||
|
goto error_ret_free_local;
|
||||||
|
}
|
||||||
|
|
||||||
/* Walk over each section attached to the input bfd. */
|
/* Walk over each section attached to the input bfd. */
|
||||||
for (section = input_bfd->sections;
|
for (section = input_bfd->sections;
|
||||||
section != NULL;
|
section != NULL;
|
||||||
@ -5939,6 +6227,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
|
|||||||
|
|
||||||
/* Ask the linker to do its stuff. */
|
/* Ask the linker to do its stuff. */
|
||||||
(*htab->layout_sections_again) ();
|
(*htab->layout_sections_again) ();
|
||||||
|
first_veneer_scan = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add stubs for Cortex-A8 erratum fixes now. */
|
/* Add stubs for Cortex-A8 erratum fixes now. */
|
||||||
@ -9280,7 +9569,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
|
|||||||
/* Find out whether the symbol has a PLT. Set ST_VALUE, BRANCH_TYPE and
|
/* Find out whether the symbol has a PLT. Set ST_VALUE, BRANCH_TYPE and
|
||||||
VALUE appropriately for relocations that we resolve at link time. */
|
VALUE appropriately for relocations that we resolve at link time. */
|
||||||
has_iplt_entry = FALSE;
|
has_iplt_entry = FALSE;
|
||||||
if (elf32_arm_get_plt_info (input_bfd, eh, r_symndx, &root_plt, &arm_plt)
|
if (elf32_arm_get_plt_info (input_bfd, globals, eh, r_symndx, &root_plt,
|
||||||
|
&arm_plt)
|
||||||
&& root_plt->offset != (bfd_vma) -1)
|
&& root_plt->offset != (bfd_vma) -1)
|
||||||
{
|
{
|
||||||
plt_offset = root_plt->offset;
|
plt_offset = root_plt->offset;
|
||||||
@ -13693,7 +13983,8 @@ elf32_arm_gc_sweep_hook (bfd * abfd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (may_need_local_target_p
|
if (may_need_local_target_p
|
||||||
&& elf32_arm_get_plt_info (abfd, eh, r_symndx, &root_plt, &arm_plt))
|
&& elf32_arm_get_plt_info (abfd, globals, eh, r_symndx, &root_plt,
|
||||||
|
&arm_plt))
|
||||||
{
|
{
|
||||||
/* If PLT refcount book-keeping is wrong and too low, we'll
|
/* If PLT refcount book-keeping is wrong and too low, we'll
|
||||||
see a zero value (going to -1) for the root PLT reference
|
see a zero value (going to -1) for the root PLT reference
|
||||||
@ -14161,7 +14452,11 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Unwinding tables are not referenced directly. This pass marks them as
|
/* Unwinding tables are not referenced directly. This pass marks them as
|
||||||
required if the corresponding code section is marked. */
|
required if the corresponding code section is marked. Similarly, ARMv8-M
|
||||||
|
secure entry functions can only be referenced by SG veneers which are
|
||||||
|
created after the GC process. They need to be marked in case they reside in
|
||||||
|
their own section (as would be the case if code was compiled with
|
||||||
|
-ffunction-sections). */
|
||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
elf32_arm_gc_mark_extra_sections (struct bfd_link_info *info,
|
elf32_arm_gc_mark_extra_sections (struct bfd_link_info *info,
|
||||||
@ -14169,10 +14464,21 @@ elf32_arm_gc_mark_extra_sections (struct bfd_link_info *info,
|
|||||||
{
|
{
|
||||||
bfd *sub;
|
bfd *sub;
|
||||||
Elf_Internal_Shdr **elf_shdrp;
|
Elf_Internal_Shdr **elf_shdrp;
|
||||||
bfd_boolean again;
|
asection *cmse_sec;
|
||||||
|
obj_attribute *out_attr;
|
||||||
|
Elf_Internal_Shdr *symtab_hdr;
|
||||||
|
unsigned i, sym_count, ext_start;
|
||||||
|
const struct elf_backend_data *bed;
|
||||||
|
struct elf_link_hash_entry **sym_hashes;
|
||||||
|
struct elf32_arm_link_hash_entry *cmse_hash;
|
||||||
|
bfd_boolean again, is_v8m, first_bfd_browse = TRUE;
|
||||||
|
|
||||||
_bfd_elf_gc_mark_extra_sections (info, gc_mark_hook);
|
_bfd_elf_gc_mark_extra_sections (info, gc_mark_hook);
|
||||||
|
|
||||||
|
out_attr = elf_known_obj_attributes_proc (info->output_bfd);
|
||||||
|
is_v8m = out_attr[Tag_CPU_arch].i >= TAG_CPU_ARCH_V8M_BASE
|
||||||
|
&& out_attr[Tag_CPU_arch_profile].i == 'M';
|
||||||
|
|
||||||
/* Marking EH data may cause additional code sections to be marked,
|
/* Marking EH data may cause additional code sections to be marked,
|
||||||
requiring multiple passes. */
|
requiring multiple passes. */
|
||||||
again = TRUE;
|
again = TRUE;
|
||||||
@ -14203,8 +14509,35 @@ elf32_arm_gc_mark_extra_sections (struct bfd_link_info *info,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mark section holding ARMv8-M secure entry functions. We mark all
|
||||||
|
of them so no need for a second browsing. */
|
||||||
|
if (is_v8m && first_bfd_browse)
|
||||||
|
{
|
||||||
|
sym_hashes = elf_sym_hashes (sub);
|
||||||
|
bed = get_elf_backend_data (sub);
|
||||||
|
symtab_hdr = &elf_tdata (sub)->symtab_hdr;
|
||||||
|
sym_count = symtab_hdr->sh_size / bed->s->sizeof_sym;
|
||||||
|
ext_start = symtab_hdr->sh_info;
|
||||||
|
|
||||||
|
/* Scan symbols. */
|
||||||
|
for (i = ext_start; i < sym_count; i++)
|
||||||
|
{
|
||||||
|
cmse_hash = elf32_arm_hash_entry (sym_hashes[i - ext_start]);
|
||||||
|
|
||||||
|
/* Assume it is a special symbol. If not, cmse_scan will
|
||||||
|
warn about it and user can do something about it. */
|
||||||
|
if (ARM_GET_SYM_CMSE_SPCL (cmse_hash->root.target_internal))
|
||||||
|
{
|
||||||
|
cmse_sec = cmse_hash->root.root.u.def.section;
|
||||||
|
if (!_bfd_elf_gc_mark (info, cmse_sec, gc_mark_hook))
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
first_bfd_browse = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -17855,6 +18188,9 @@ elf32_arm_swap_symbol_in (bfd * abfd,
|
|||||||
const void *pshn,
|
const void *pshn,
|
||||||
Elf_Internal_Sym *dst)
|
Elf_Internal_Sym *dst)
|
||||||
{
|
{
|
||||||
|
Elf_Internal_Shdr *symtab_hdr;
|
||||||
|
const char *name = NULL;
|
||||||
|
|
||||||
if (!bfd_elf32_swap_symbol_in (abfd, psrc, pshn, dst))
|
if (!bfd_elf32_swap_symbol_in (abfd, psrc, pshn, dst))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
dst->st_target_internal = 0;
|
dst->st_target_internal = 0;
|
||||||
@ -17883,6 +18219,13 @@ elf32_arm_swap_symbol_in (bfd * abfd,
|
|||||||
else
|
else
|
||||||
ARM_SET_SYM_BRANCH_TYPE (dst->st_target_internal, ST_BRANCH_UNKNOWN);
|
ARM_SET_SYM_BRANCH_TYPE (dst->st_target_internal, ST_BRANCH_UNKNOWN);
|
||||||
|
|
||||||
|
/* Mark CMSE special symbols. */
|
||||||
|
symtab_hdr = & elf_symtab_hdr (abfd);
|
||||||
|
if (symtab_hdr->sh_size)
|
||||||
|
name = bfd_elf_sym_name (abfd, symtab_hdr, dst, NULL);
|
||||||
|
if (name && CONST_STRNEQ (name, CMSE_PREFIX))
|
||||||
|
ARM_SET_SYM_CMSE_SPCL (dst->st_target_internal);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2016-08-04 Thomas Preud'homme <thomas.preudhomme@arm.com>
|
||||||
|
|
||||||
|
* arm.h (ARM_GET_SYM_CMSE_SPCL): Define macro.
|
||||||
|
(ARM_SET_SYM_CMSE_SPCL): Likewise.
|
||||||
|
|
||||||
2016-08-01 Andrew Jenner <andrew@codesourcery.com>
|
2016-08-01 Andrew Jenner <andrew@codesourcery.com>
|
||||||
|
|
||||||
* opcode/ppc.h (PPC_OPCODE_E200Z4): New define.
|
* opcode/ppc.h (PPC_OPCODE_E200Z4): New define.
|
||||||
|
@ -384,4 +384,11 @@ enum arm_st_branch_type {
|
|||||||
| ((TYPE) & ENUM_ARM_ST_BRANCH_TYPE_BITMASK))
|
| ((TYPE) & ENUM_ARM_ST_BRANCH_TYPE_BITMASK))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Get or set whether a symbol is a special symbol of an entry function of CMSE
|
||||||
|
secure code. */
|
||||||
|
#define ARM_GET_SYM_CMSE_SPCL(SYM_TARGET_INTERNAL) \
|
||||||
|
(((SYM_TARGET_INTERNAL) >> 2) & 1)
|
||||||
|
#define ARM_SET_SYM_CMSE_SPCL(SYM_TARGET_INTERNAL) \
|
||||||
|
(SYM_TARGET_INTERNAL) |= 4
|
||||||
|
|
||||||
#endif /* _ELF_ARM_H */
|
#endif /* _ELF_ARM_H */
|
||||||
|
15
ld/ChangeLog
15
ld/ChangeLog
@ -1,3 +1,18 @@
|
|||||||
|
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.
|
||||||
|
(Secure gateway veneers: wrong entry functions): Likewise.
|
||||||
|
(Secure gateway veneers (ARMv8-M Baseline)): Likewise.
|
||||||
|
(Secure gateway veneers (ARMv8-M Mainline)): Likewise.
|
||||||
|
* testsuite/ld-arm/cmse-veneers.s: New file.
|
||||||
|
* testsuite/ld-arm/cmse-veneers.d: Likewise.
|
||||||
|
* testsuite/ld-arm/cmse-veneers.rd: Likewise.
|
||||||
|
* testsuite/ld-arm/cmse-veneers.sd: Likewise.
|
||||||
|
* testsuite/ld-arm/cmse-veneers-no-gnu_sgstubs.out: Likewise.
|
||||||
|
* testsuite/ld-arm/cmse-veneers-wrong-entryfct.out: Likewise.
|
||||||
|
|
||||||
2016-08-02 Nick Clifton <nickc@redhat.com>
|
2016-08-02 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
PR ld/17739
|
PR ld/17739
|
||||||
|
@ -6853,6 +6853,12 @@ entries which only support 512Mb of code.
|
|||||||
The @samp{--no-apply-dynamic-relocs} option makes AArch64 linker do not apply
|
The @samp{--no-apply-dynamic-relocs} option makes AArch64 linker do not apply
|
||||||
link-time values for dynamic relocations.
|
link-time values for dynamic relocations.
|
||||||
|
|
||||||
|
@cindex Placement of SG veneers
|
||||||
|
All SG veneers are placed in the special output section @code{.gnu.sgstubs}.
|
||||||
|
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.
|
||||||
|
|
||||||
@ifclear GENERIC
|
@ifclear GENERIC
|
||||||
@lowersections
|
@lowersections
|
||||||
@end ifclear
|
@end ifclear
|
||||||
|
@ -642,6 +642,33 @@ set armeabitests_nonacl {
|
|||||||
{{objdump -d jump-reloc-veneers-long.d}}
|
{{objdump -d jump-reloc-veneers-long.d}}
|
||||||
"jump-reloc-veneers-long"}
|
"jump-reloc-veneers-long"}
|
||||||
|
|
||||||
|
{"Secure gateway veneers: no .gnu.sgstubs section" "" ""
|
||||||
|
"-march=armv8-m.base -mthumb"
|
||||||
|
{cmse-veneers.s}
|
||||||
|
{{ld cmse-veneers-no-gnu_sgstubs.out}}
|
||||||
|
"cmse-veneers-no-gnu_sgstubs"}
|
||||||
|
{"Secure gateway veneers: wrong entry functions" "" ""
|
||||||
|
"-march=armv7-m -mthumb --defsym CHECK_ERRORS=1"
|
||||||
|
{cmse-veneers.s}
|
||||||
|
{{ld cmse-veneers-wrong-entryfct.out}}
|
||||||
|
"cmse-veneers-wrong-entryfct"}
|
||||||
|
{"Secure gateway veneers (ARMv8-M Baseline)"
|
||||||
|
"-Ttext=0x8000 --section-start .gnu.sgstubs=0x20000 --gc-sections" ""
|
||||||
|
"-march=armv8-m.base -mthumb"
|
||||||
|
{cmse-veneers.s}
|
||||||
|
{{objdump {-d -j .gnu.sgstubs} cmse-veneers.d}
|
||||||
|
{objdump {-h -j .gnu.sgstubs} cmse-veneers.sd}
|
||||||
|
{nm {} cmse-veneers.rd}}
|
||||||
|
"cmse-veneers-baseline"}
|
||||||
|
{"Secure gateway veneers (ARMv8-M Mainline)"
|
||||||
|
"-Ttext=0x8000 --section-start .gnu.sgstubs=0x20000 --gc-sections" ""
|
||||||
|
"-march=armv8-m.main -mthumb"
|
||||||
|
{cmse-veneers.s}
|
||||||
|
{{objdump {-d -j .gnu.sgstubs} cmse-veneers.d}
|
||||||
|
{objdump {-h -j .gnu.sgstubs} cmse-veneers.sd}
|
||||||
|
{nm {} cmse-veneers.rd}}
|
||||||
|
"cmse-veneers-mainline"}
|
||||||
|
|
||||||
{"R_ARM_THM_JUMP19 Relocation veneers: Short"
|
{"R_ARM_THM_JUMP19 Relocation veneers: Short"
|
||||||
"--section-start destsect=0x000108002 --section-start .text=0x8000" ""
|
"--section-start destsect=0x000108002 --section-start .text=0x8000" ""
|
||||||
"-march=armv7-m -mthumb"
|
"-march=armv7-m -mthumb"
|
||||||
|
3
ld/testsuite/ld-arm/cmse-veneers-no-gnu_sgstubs.out
Normal file
3
ld/testsuite/ld-arm/cmse-veneers-no-gnu_sgstubs.out
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.*: No address assigned to the veneers output section .gnu.sgstubs
|
||||||
|
.*: cannot size stub section: Invalid operation
|
||||||
|
#...
|
19
ld/testsuite/ld-arm/cmse-veneers-wrong-entryfct.out
Normal file
19
ld/testsuite/ld-arm/cmse-veneers-wrong-entryfct.out
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
.*: .*: Special symbol `__acle_se_loc_entry_veneer1' only allowed for ARMv8-M architecture or later.
|
||||||
|
.*: .*: invalid .* symbol `.*loc_entry_veneer1'.
|
||||||
|
.*: It must be a global or weak function symbol.
|
||||||
|
.*: .*: invalid special symbol `__acle_se_loc_entry_veneer2'.
|
||||||
|
.*: It must be a global or weak function symbol.
|
||||||
|
.*: .*: invalid special symbol `__acle_se_loc_entry_veneer4'.
|
||||||
|
.*: It must be a global or weak function symbol.
|
||||||
|
.*: .*: invalid standard symbol `loc_entry_veneer3'.
|
||||||
|
.*: It must be a global or weak function symbol.
|
||||||
|
.*: .*: invalid standard symbol `loc_entry_veneer5'.
|
||||||
|
.*: It must be a global or weak function symbol.
|
||||||
|
.*: .*: absent standard symbol `fake_entry_veneer1'.
|
||||||
|
.*: .*: invalid standard symbol `obj_entry_veneer1'.
|
||||||
|
.*: It must be a global or weak function symbol.
|
||||||
|
.*: .*: invalid special symbol `__acle_se_obj_entry_veneer2'.
|
||||||
|
.*: It must be a global or weak function symbol.
|
||||||
|
.*: .*: `fake_entry_veneer2' and its special symbol are in different sections.
|
||||||
|
.*: cannot size stub section: Invalid operation
|
||||||
|
#...
|
21
ld/testsuite/ld-arm/cmse-veneers.d
Normal file
21
ld/testsuite/ld-arm/cmse-veneers.d
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
.*
|
||||||
|
|
||||||
|
|
||||||
|
Disassembly of section \.gnu.sgstubs:
|
||||||
|
|
||||||
|
00020000 <glob_entry_veneer2>:
|
||||||
|
20000: e97f e97f sg
|
||||||
|
20004: f7e8 b800 b\.w 8008 <__acle_se_glob_entry_veneer2>
|
||||||
|
|
||||||
|
00020008 <weak_entry_veneer2>:
|
||||||
|
20008: e97f e97f sg
|
||||||
|
2000c: f7e7 bffe b\.w 800c <__acle_se_weak_entry_veneer2>
|
||||||
|
|
||||||
|
00020010 <glob_entry_veneer1>:
|
||||||
|
20010: e97f e97f sg
|
||||||
|
20014: f7e7 bff4 b\.w 8000 <__acle_se_glob_entry_veneer1>
|
||||||
|
|
||||||
|
00020018 <weak_entry_veneer1>:
|
||||||
|
20018: e97f e97f sg
|
||||||
|
2001c: f7e7 bff2 b\.w 8004 <__acle_se_weak_entry_veneer1>
|
9
ld/testsuite/ld-arm/cmse-veneers.rd
Normal file
9
ld/testsuite/ld-arm/cmse-veneers.rd
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#...
|
||||||
|
[0-9a-f]+ T glob_entry_fct
|
||||||
|
#...
|
||||||
|
[0-9a-f]+ T glob_entry_veneer1
|
||||||
|
[0-9a-f]+ T glob_entry_veneer2
|
||||||
|
#...
|
||||||
|
[0-9a-f]+ W weak_entry_veneer1
|
||||||
|
[0-9a-f]+ W weak_entry_veneer2
|
||||||
|
#...
|
97
ld/testsuite/ld-arm/cmse-veneers.s
Normal file
97
ld/testsuite/ld-arm/cmse-veneers.s
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
.syntax unified
|
||||||
|
.thumb
|
||||||
|
.file "foo.c"
|
||||||
|
.text
|
||||||
|
|
||||||
|
.macro decltype name, type
|
||||||
|
.ifc \type,object
|
||||||
|
.data
|
||||||
|
.else
|
||||||
|
.thumb
|
||||||
|
.thumb_func
|
||||||
|
.endif
|
||||||
|
.type \name, %\type
|
||||||
|
.endm
|
||||||
|
|
||||||
|
|
||||||
|
.macro entry name, type, vis, typespc, visspc, entry_fct
|
||||||
|
.align 2
|
||||||
|
.ifb \visspc
|
||||||
|
.\vis __acle_se_\name
|
||||||
|
.else
|
||||||
|
.\visspc __acle_se_\name
|
||||||
|
.endif
|
||||||
|
.\vis \name
|
||||||
|
.thumb
|
||||||
|
.thumb_func
|
||||||
|
.ifb \typespc
|
||||||
|
decltype __acle_se_\name, \type
|
||||||
|
.else
|
||||||
|
decltype __acle_se_\name, \typespc
|
||||||
|
.endif
|
||||||
|
decltype \name, \type
|
||||||
|
__acle_se_\name:
|
||||||
|
\entry_fct
|
||||||
|
\name:
|
||||||
|
.ifc \type,object
|
||||||
|
.word 42
|
||||||
|
.else
|
||||||
|
nop
|
||||||
|
.endif
|
||||||
|
.size \name, .-\name
|
||||||
|
.size __acle_se_\name, .-__acle_se_\name
|
||||||
|
.endm
|
||||||
|
|
||||||
|
|
||||||
|
.ifndef CHECK_ERRORS
|
||||||
|
@ Valid setups for veneer generation
|
||||||
|
entry glob_entry_veneer1, function, global
|
||||||
|
entry weak_entry_veneer1, function, weak
|
||||||
|
entry glob_entry_veneer2, function, global, visspc=weak
|
||||||
|
entry weak_entry_veneer2, function, weak, visspc=global
|
||||||
|
|
||||||
|
@ Valid setup for entry function without SG veneer
|
||||||
|
entry glob_entry_fct, function, global, entry_fct=nop
|
||||||
|
|
||||||
|
.else
|
||||||
|
@ Invalid setups for veneer generation (visibility)
|
||||||
|
entry loc_entry_veneer1, function, local
|
||||||
|
entry loc_entry_veneer2, function, global, visspc=local
|
||||||
|
entry loc_entry_veneer3, function, local, visspc=global
|
||||||
|
entry loc_entry_veneer4, function, weak, visspc=local
|
||||||
|
entry loc_entry_veneer5, function, local, visspc=weak
|
||||||
|
|
||||||
|
@ Invalid setups for veneer generation (absent standard symbol)
|
||||||
|
.align 2
|
||||||
|
.global __acle_se_fake_entry_veneer1
|
||||||
|
.thumb
|
||||||
|
.thumb_func
|
||||||
|
.type __acle_se_fake_entry_veneer1, %function
|
||||||
|
__acle_se_fake_entry_veneer1:
|
||||||
|
nop
|
||||||
|
.size __acle_se_fake_entry_veneer1, .-__acle_se_fake_entry_veneer1
|
||||||
|
|
||||||
|
@ Invalid setups for veneer generation (type)
|
||||||
|
entry obj_entry_veneer1, object, global, typespc=function
|
||||||
|
entry obj_entry_veneer2, function, global, typespc=object
|
||||||
|
|
||||||
|
@ Invalid setup for veneer generation (sections)
|
||||||
|
.section .text.sub1
|
||||||
|
.align 2
|
||||||
|
.thumb
|
||||||
|
.thumb_func
|
||||||
|
.global __acle_se_fake_entry_veneer2
|
||||||
|
.type __acle_se_fake_entry_veneer2, %function
|
||||||
|
__acle_se_fake_entry_veneer2:
|
||||||
|
nop
|
||||||
|
.size __acle_se_fake_entry_veneer2, .-__acle_se_fake_entry_veneer2
|
||||||
|
.section .text.sub2
|
||||||
|
.align 2
|
||||||
|
.thumb
|
||||||
|
.thumb_func
|
||||||
|
.global fake_entry_veneer2
|
||||||
|
.type fake_entry_veneer2, %function
|
||||||
|
fake_entry_veneer2:
|
||||||
|
nop
|
||||||
|
.size fake_entry_veneer2, .-fake_entry_veneer2
|
||||||
|
.endif
|
7
ld/testsuite/ld-arm/cmse-veneers.sd
Normal file
7
ld/testsuite/ld-arm/cmse-veneers.sd
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
.*
|
||||||
|
|
||||||
|
Sections:
|
||||||
|
Idx Name Size VMA LMA File off Algn
|
||||||
|
\d+ \.gnu\.sgstubs 00000020 00020000 00020000 00010000 2\*\*5
|
||||||
|
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
Reference in New Issue
Block a user