Add support for stable secure gateway veneers addresses
2016-08-26 Thomas Preud'homme <thomas.preudhomme@arm.com> bfd/ * bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new parameter for the input import library bfd. * bfd-in2.h: Regenerate. * elf32-arm.c (struct elf32_arm_link_hash_table): New in_implib_bfd and new_cmse_stub_offset fields. (stub_hash_newfunc): Initialize stub_offset and stub_template_size to -1. (elf32_arm_add_stub): Likewise for stub_offset. (arm_new_stubs_start_offset_ptr): New function. (arm_build_one_stub): Only allocate a stub_offset if it is -1. Allow empty SG veneers to have zero relocations. (arm_size_one_stub): Only initialize stub size and template information for non empty veneers. Do not update veneer section size if veneer already has an offset. (elf32_arm_create_stub): Return the stub entry pointer or NULL instead of a boolean indicating success or failure. (cmse_scan): Change stub_changed parameter into an integer pointer parameter cmse_stub_created to count the number of stub created and adapt to change of return value in elf32_arm_create_stub. (cmse_entry_fct_p): New function. (arm_list_new_cmse_stub): Likewise. (set_cmse_veneer_addr_from_implib): Likewise. (elf32_arm_size_stubs): Define cmse_stub_created, pass its address to cmse_scan instead of that of cmse_stub_changed to compute the number of stub created and use it to initialize stub_changed. Call set_cmse_veneer_addr_from_implib after all cmse_scan. Adapt to change of return value in elf32_arm_create_stub. Use arm_stub_section_start_offset () if not NULL to initialize size of secure gateway veneers section. Initialize stub_offset of Cortex-A8 erratum fix to -1. Use ret to hold return value. (elf32_arm_build_stubs): Use arm_stub_section_start_offset () if not NULL to initialize size of secure gateway veneers section. Adapt comment to stress the importance of zeroing veneer section content. (bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd parameter to initialize eponymous field in struct elf32_arm_link_hash_table. ld/ * emultempl/armelf.em (in_implib_filename): Declare and initialize new variable. (arm_elf_create_output_section_statements): Open import input library file for writing and pass resulting in_implib_bfd to bfd_elf32_arm_set_target_relocs. (PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option. (PARSE_AND_LIST_LONGOPTS): Define --in-implib option. (PARSE_AND_LIST_OPTIONS): Add help message for --in-implib option. (PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case. * ld.texinfo (--cmse-implib): Update to mention --in-implib. (--in-implib): Document new option. * NEWS: Likewise. * testsuite/ld-arm/arm-elf.exp (Secure gateway import library generation): add --defsym VER=1 to gas CLI. (Secure gateway import library generation: errors): Likewise. (Input secure gateway import library): New test. (Input secure gateway import library: no output import library): Likewise. (Input secure gateway import library: not an SG input import library): Likewise. (Input secure gateway import library: earlier stub section base): Likewise. (Input secure gateway import library: later stub section base): Likewise. (Input secure gateway import library: veneer comeback): Likewise. (Input secure gateway import library: entry function change): Likewise. * testsuite/ld-arm/cmse-implib.s: Add input import library testing. * testsuite/ld-arm/cmse-implib.rd: Update accordingly. * testsuite/ld-arm/cmse-new-implib.out: New file. * testsuite/ld-arm/cmse-new-implib.rd: Likewise. * testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise. * testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out: Likewise. * testsuite/ld-arm/cmse-new-earlier-later-implib.out: Likewise. * testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise. * testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise.
This commit is contained in:
parent
4edcc97c1a
commit
0955507f6e
|
@ -1,3 +1,41 @@
|
|||
2016-08-26 Thomas Preud'homme <thomas.preudhomme@arm.com>
|
||||
|
||||
* bfd-in.h (bfd_elf32_arm_set_target_relocs): Add a new parameter for
|
||||
the input import library bfd.
|
||||
* bfd-in2.h: Regenerate.
|
||||
* elf32-arm.c (struct elf32_arm_link_hash_table): New in_implib_bfd
|
||||
and new_cmse_stub_offset fields.
|
||||
(stub_hash_newfunc): Initialize stub_offset and stub_template_size to
|
||||
-1.
|
||||
(elf32_arm_add_stub): Likewise for stub_offset.
|
||||
(arm_new_stubs_start_offset_ptr): New function.
|
||||
(arm_build_one_stub): Only allocate a stub_offset if it is -1. Allow
|
||||
empty SG veneers to have zero relocations.
|
||||
(arm_size_one_stub): Only initialize stub size and template
|
||||
information for non empty veneers. Do not update veneer section size
|
||||
if veneer already has an offset.
|
||||
(elf32_arm_create_stub): Return the stub entry pointer or NULL instead
|
||||
of a boolean indicating success or failure.
|
||||
(cmse_scan): Change stub_changed parameter into an integer pointer
|
||||
parameter cmse_stub_created to count the number of stub created and
|
||||
adapt to change of return value in elf32_arm_create_stub.
|
||||
(cmse_entry_fct_p): New function.
|
||||
(arm_list_new_cmse_stub): Likewise.
|
||||
(set_cmse_veneer_addr_from_implib): Likewise.
|
||||
(elf32_arm_size_stubs): Define cmse_stub_created, pass its address to
|
||||
cmse_scan instead of that of cmse_stub_changed to compute the number
|
||||
of stub created and use it to initialize stub_changed. Call
|
||||
set_cmse_veneer_addr_from_implib after all cmse_scan. Adapt to change
|
||||
of return value in elf32_arm_create_stub. Use
|
||||
arm_stub_section_start_offset () if not NULL to initialize size of
|
||||
secure gateway veneers section. Initialize stub_offset of Cortex-A8
|
||||
erratum fix to -1. Use ret to hold return value.
|
||||
(elf32_arm_build_stubs): Use arm_stub_section_start_offset () if not
|
||||
NULL to initialize size of secure gateway veneers section. Adapt
|
||||
comment to stress the importance of zeroing veneer section content.
|
||||
(bfd_elf32_arm_set_target_relocs): Add new in_implib_bfd parameter to
|
||||
initialize eponymous field in struct elf32_arm_link_hash_table.
|
||||
|
||||
2016-08-25 Andreas Arnez <arnez@linux.vnet.ibm.com>
|
||||
|
||||
* elf32-s390.c (stdarg.h): New include.
|
||||
|
|
|
@ -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, int);
|
||||
bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
|
||||
|
||||
extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
|
||||
(bfd *, struct bfd_link_info *);
|
||||
|
|
|
@ -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, int);
|
||||
bfd_arm_stm32l4xx_fix, int, int, int, int, int, int, bfd *);
|
||||
|
||||
extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
|
||||
(bfd *, struct bfd_link_info *);
|
||||
|
|
438
bfd/elf32-arm.c
438
bfd/elf32-arm.c
|
@ -3148,6 +3148,10 @@ struct elf32_arm_link_hash_table
|
|||
as per ARMv8-M Security Extensions. */
|
||||
int cmse_implib;
|
||||
|
||||
/* The import library whose symbols' address must remain stable in
|
||||
the import library generated. */
|
||||
bfd *in_implib_bfd;
|
||||
|
||||
/* The index of the next unused R_ARM_TLS_DESC slot in .rel.plt. */
|
||||
bfd_vma next_tls_desc_index;
|
||||
|
||||
|
@ -3209,6 +3213,10 @@ struct elf32_arm_link_hash_table
|
|||
/* Input stub section holding secure gateway veneers. */
|
||||
asection *cmse_stub_sec;
|
||||
|
||||
/* Offset in cmse_stub_sec where new SG veneers (not in input import library)
|
||||
start to be allocated. */
|
||||
bfd_vma new_cmse_stub_offset;
|
||||
|
||||
/* Number of elements in stub_group. */
|
||||
unsigned int top_id;
|
||||
|
||||
|
@ -3460,7 +3468,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
|
|||
/* Initialize the local fields. */
|
||||
eh = (struct elf32_arm_stub_hash_entry *) entry;
|
||||
eh->stub_sec = NULL;
|
||||
eh->stub_offset = 0;
|
||||
eh->stub_offset = (bfd_vma) -1;
|
||||
eh->source_value = 0;
|
||||
eh->target_value = 0;
|
||||
eh->target_section = NULL;
|
||||
|
@ -3468,7 +3476,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
|
|||
eh->stub_type = arm_stub_none;
|
||||
eh->stub_size = 0;
|
||||
eh->stub_template = NULL;
|
||||
eh->stub_template_size = 0;
|
||||
eh->stub_template_size = -1;
|
||||
eh->h = NULL;
|
||||
eh->id_sec = NULL;
|
||||
eh->output_name = NULL;
|
||||
|
@ -4467,7 +4475,7 @@ elf32_arm_add_stub (const char *stub_name, asection *section,
|
|||
}
|
||||
|
||||
stub_entry->stub_sec = stub_sec;
|
||||
stub_entry->stub_offset = 0;
|
||||
stub_entry->stub_offset = (bfd_vma) -1;
|
||||
stub_entry->id_sec = link_sec;
|
||||
|
||||
return stub_entry;
|
||||
|
@ -4633,11 +4641,31 @@ arm_dedicated_stub_section_padding (enum elf32_arm_stub_type stub_type)
|
|||
abort (); /* Should be unreachable. */
|
||||
}
|
||||
|
||||
/* If veneers of type STUB_TYPE should go in a dedicated output section,
|
||||
returns the address of the hash table field in HTAB holding the offset at
|
||||
which new veneers should be layed out in the stub section. */
|
||||
|
||||
static bfd_vma*
|
||||
arm_new_stubs_start_offset_ptr (struct elf32_arm_link_hash_table *htab,
|
||||
enum elf32_arm_stub_type stub_type)
|
||||
{
|
||||
switch (stub_type)
|
||||
{
|
||||
case arm_stub_cmse_branch_thumb_only:
|
||||
return &htab->new_cmse_stub_offset;
|
||||
|
||||
default:
|
||||
BFD_ASSERT (!arm_dedicated_stub_output_section_required (stub_type));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
arm_build_one_stub (struct bfd_hash_entry *gen_entry,
|
||||
void * in_arg)
|
||||
{
|
||||
#define MAXRELOCS 3
|
||||
bfd_boolean removed_sg_veneer;
|
||||
struct elf32_arm_stub_hash_entry *stub_entry;
|
||||
struct elf32_arm_link_hash_table *globals;
|
||||
struct bfd_link_info *info;
|
||||
|
@ -4652,6 +4680,7 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
|
|||
int stub_reloc_idx[MAXRELOCS] = {-1, -1};
|
||||
int stub_reloc_offset[MAXRELOCS] = {0, 0};
|
||||
int nrelocs = 0;
|
||||
int just_allocated = 0;
|
||||
|
||||
/* Massage our args to the form they really have. */
|
||||
stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
|
||||
|
@ -4668,8 +4697,12 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
|
|||
/* We have to do less-strictly-aligned fixes last. */
|
||||
return TRUE;
|
||||
|
||||
/* Make a note of the offset within the stubs for this entry. */
|
||||
stub_entry->stub_offset = stub_sec->size;
|
||||
/* Assign a slot at the end of section if none assigned yet. */
|
||||
if (stub_entry->stub_offset == (bfd_vma) -1)
|
||||
{
|
||||
stub_entry->stub_offset = stub_sec->size;
|
||||
just_allocated = 1;
|
||||
}
|
||||
loc = stub_sec->contents + stub_entry->stub_offset;
|
||||
|
||||
stub_bfd = stub_sec->owner;
|
||||
|
@ -4743,7 +4776,8 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
|
|||
}
|
||||
}
|
||||
|
||||
stub_sec->size += size;
|
||||
if (just_allocated)
|
||||
stub_sec->size += size;
|
||||
|
||||
/* Stub size has already been computed in arm_size_one_stub. Check
|
||||
consistency. */
|
||||
|
@ -4753,9 +4787,11 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
|
|||
if (stub_entry->branch_type == ST_BRANCH_TO_THUMB)
|
||||
sym_value |= 1;
|
||||
|
||||
/* Assume there is at least one and at most MAXRELOCS entries to relocate
|
||||
in each stub. */
|
||||
BFD_ASSERT (nrelocs != 0 && nrelocs <= MAXRELOCS);
|
||||
/* Assume non empty slots have at least one and at most MAXRELOCS entries
|
||||
to relocate in each stub. */
|
||||
removed_sg_veneer =
|
||||
(size == 0 && stub_entry->stub_type == arm_stub_cmse_branch_thumb_only);
|
||||
BFD_ASSERT (removed_sg_veneer || (nrelocs != 0 && nrelocs <= MAXRELOCS));
|
||||
|
||||
for (i = 0; i < nrelocs; i++)
|
||||
{
|
||||
|
@ -4857,9 +4893,17 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry,
|
|||
size = find_stub_size_and_template (stub_entry->stub_type, &template_sequence,
|
||||
&template_size);
|
||||
|
||||
stub_entry->stub_size = size;
|
||||
stub_entry->stub_template = template_sequence;
|
||||
stub_entry->stub_template_size = template_size;
|
||||
/* Initialized to -1. Null size indicates an empty slot full of zeros. */
|
||||
if (stub_entry->stub_template_size)
|
||||
{
|
||||
stub_entry->stub_size = size;
|
||||
stub_entry->stub_template = template_sequence;
|
||||
stub_entry->stub_template_size = template_size;
|
||||
}
|
||||
|
||||
/* Already accounted for. */
|
||||
if (stub_entry->stub_offset != (bfd_vma) -1)
|
||||
return TRUE;
|
||||
|
||||
size = (size + 7) & ~7;
|
||||
stub_entry->stub_sec->size += size;
|
||||
|
@ -5424,10 +5468,10 @@ cortex_a8_erratum_scan (bfd *input_bfd,
|
|||
and *NEW_STUB is set to FALSE. Otherwise, *NEW_STUB is set to
|
||||
TRUE and the stub entry is initialized.
|
||||
|
||||
Returns whether the stub could be successfully created or updated, or FALSE
|
||||
if an error occured. */
|
||||
Returns the stub that was created or updated, or NULL if an error
|
||||
occurred. */
|
||||
|
||||
static bfd_boolean
|
||||
static struct elf32_arm_stub_hash_entry *
|
||||
elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
|
||||
enum elf32_arm_stub_type stub_type, asection *section,
|
||||
Elf_Internal_Rela *irela, asection *sym_sec,
|
||||
|
@ -5458,7 +5502,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
|
|||
stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash, irela,
|
||||
stub_type);
|
||||
if (!stub_name)
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, stub_name, FALSE,
|
||||
|
@ -5469,7 +5513,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
|
|||
if (!sym_claimed)
|
||||
free (stub_name);
|
||||
stub_entry->target_value = sym_value;
|
||||
return TRUE;
|
||||
return stub_entry;
|
||||
}
|
||||
|
||||
stub_entry = elf32_arm_add_stub (stub_name, section, htab, stub_type);
|
||||
|
@ -5477,7 +5521,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
|
|||
{
|
||||
if (!sym_claimed)
|
||||
free (stub_name);
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stub_entry->target_value = sym_value;
|
||||
|
@ -5498,7 +5542,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
|
|||
if (stub_entry->output_name == NULL)
|
||||
{
|
||||
free (stub_name);
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* For historical reasons, use the existing names for ARM-to-Thumb and
|
||||
|
@ -5518,7 +5562,7 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
|
|||
}
|
||||
|
||||
*new_stub = TRUE;
|
||||
return TRUE;
|
||||
return stub_entry;
|
||||
}
|
||||
|
||||
/* Scan symbols in INPUT_BFD to identify secure entry functions needing a
|
||||
|
@ -5537,14 +5581,15 @@ elf32_arm_create_stub (struct elf32_arm_link_hash_table *htab,
|
|||
|
||||
OUT_ATTR gives the output attributes, SYM_HASHES the symbol index to hash
|
||||
entry mapping while HTAB gives the name to hash entry mapping.
|
||||
*CMSE_STUB_CREATED is increased by the number of secure gateway veneer
|
||||
created.
|
||||
|
||||
If any secure gateway veneer is created, *STUB_CHANGED is set to TRUE. The
|
||||
return value gives whether a stub failed to be allocated. */
|
||||
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)
|
||||
int *cmse_stub_created)
|
||||
{
|
||||
const struct elf_backend_data *bed;
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
|
@ -5555,7 +5600,8 @@ cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
|
|||
char *sym_name, *lsym_name;
|
||||
bfd_vma sym_value;
|
||||
asection *section;
|
||||
bfd_boolean is_v8m, new_stub, created_stub, cmse_invalid, ret = TRUE;
|
||||
struct elf32_arm_stub_hash_entry *stub_entry;
|
||||
bfd_boolean is_v8m, new_stub, cmse_invalid, ret = TRUE;
|
||||
|
||||
bed = get_elf_backend_data (input_bfd);
|
||||
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
|
||||
|
@ -5700,17 +5746,17 @@ cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
|
|||
if (!ret)
|
||||
continue;
|
||||
branch_type = ARM_GET_SYM_BRANCH_TYPE (hash->root.target_internal);
|
||||
created_stub
|
||||
stub_entry
|
||||
= 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)
|
||||
if (stub_entry == NULL)
|
||||
ret = FALSE;
|
||||
else
|
||||
{
|
||||
BFD_ASSERT (new_stub);
|
||||
*stub_changed = TRUE;
|
||||
(*cmse_stub_created)++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5719,6 +5765,279 @@ cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Return TRUE iff a symbol identified by its linker HASH entry is a secure
|
||||
code entry function, ie can be called from non secure code without using a
|
||||
veneer. */
|
||||
|
||||
static bfd_boolean
|
||||
cmse_entry_fct_p (struct elf32_arm_link_hash_entry *hash)
|
||||
{
|
||||
uint32_t first_insn;
|
||||
asection *section;
|
||||
file_ptr offset;
|
||||
bfd *abfd;
|
||||
|
||||
/* Defined symbol of function type. */
|
||||
if (hash->root.root.type != bfd_link_hash_defined
|
||||
&& hash->root.root.type != bfd_link_hash_defweak)
|
||||
return FALSE;
|
||||
if (hash->root.type != STT_FUNC)
|
||||
return FALSE;
|
||||
|
||||
/* Read first instruction. */
|
||||
section = hash->root.root.u.def.section;
|
||||
abfd = section->owner;
|
||||
offset = hash->root.root.u.def.value - section->vma;
|
||||
if (!bfd_get_section_contents (abfd, section, &first_insn, offset,
|
||||
sizeof (first_insn)))
|
||||
return FALSE;
|
||||
|
||||
/* Start by SG instruction. */
|
||||
return first_insn == 0xe97fe97f;
|
||||
}
|
||||
|
||||
/* Output the name (in symbol table) of the veneer GEN_ENTRY if it is a new
|
||||
secure gateway veneers (ie. the veneers was not in the input import library)
|
||||
and there is no output import library (GEN_INFO->out_implib_bfd is NULL. */
|
||||
|
||||
static bfd_boolean
|
||||
arm_list_new_cmse_stub (struct bfd_hash_entry *gen_entry, void *gen_info)
|
||||
{
|
||||
struct elf32_arm_stub_hash_entry *stub_entry;
|
||||
struct bfd_link_info *info;
|
||||
|
||||
/* Massage our args to the form they really have. */
|
||||
stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
|
||||
info = (struct bfd_link_info *) gen_info;
|
||||
|
||||
if (info->out_implib_bfd)
|
||||
return TRUE;
|
||||
|
||||
if (stub_entry->stub_type != arm_stub_cmse_branch_thumb_only)
|
||||
return TRUE;
|
||||
|
||||
if (stub_entry->stub_offset == (bfd_vma) -1)
|
||||
(*_bfd_error_handler) (" %s", stub_entry->output_name);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Set offset of each secure gateway veneers so that its address remain
|
||||
identical to the one in the input import library referred by
|
||||
HTAB->in_implib_bfd. A warning is issued for veneers that disappeared
|
||||
(present in input import library but absent from the executable being
|
||||
linked) or if new veneers appeared and there is no output import library
|
||||
(INFO->out_implib_bfd is NULL and *CMSE_STUB_CREATED is bigger than the
|
||||
number of secure gateway veneers found in the input import library.
|
||||
|
||||
The function returns whether an error occurred. If no error occurred,
|
||||
*CMSE_STUB_CREATED gives the number of SG veneers created by both cmse_scan
|
||||
and this function and HTAB->new_cmse_stub_offset is set to the biggest
|
||||
veneer observed set for new veneers to be layed out after. */
|
||||
|
||||
static bfd_boolean
|
||||
set_cmse_veneer_addr_from_implib (struct bfd_link_info *info,
|
||||
struct elf32_arm_link_hash_table *htab,
|
||||
int *cmse_stub_created)
|
||||
{
|
||||
long symsize;
|
||||
char *sym_name;
|
||||
flagword flags;
|
||||
long i, symcount;
|
||||
bfd *in_implib_bfd;
|
||||
asection *stub_out_sec;
|
||||
bfd_boolean ret = TRUE;
|
||||
Elf_Internal_Sym *intsym;
|
||||
const char *out_sec_name;
|
||||
bfd_size_type cmse_stub_size;
|
||||
asymbol **sympp = NULL, *sym;
|
||||
struct elf32_arm_link_hash_entry *hash;
|
||||
const insn_sequence *cmse_stub_template;
|
||||
struct elf32_arm_stub_hash_entry *stub_entry;
|
||||
int cmse_stub_template_size, new_cmse_stubs_created = *cmse_stub_created;
|
||||
bfd_vma veneer_value, stub_offset, next_cmse_stub_offset;
|
||||
bfd_vma cmse_stub_array_start = (bfd_vma) -1, cmse_stub_sec_vma = 0;
|
||||
|
||||
/* No input secure gateway import library. */
|
||||
if (!htab->in_implib_bfd)
|
||||
return TRUE;
|
||||
|
||||
in_implib_bfd = htab->in_implib_bfd;
|
||||
if (!htab->cmse_implib)
|
||||
{
|
||||
(*_bfd_error_handler) (_("%B: --in-implib only supported for Secure "
|
||||
"Gateway import libraries."), in_implib_bfd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Get symbol table size. */
|
||||
symsize = bfd_get_symtab_upper_bound (in_implib_bfd);
|
||||
if (symsize < 0)
|
||||
return FALSE;
|
||||
|
||||
/* Read in the input secure gateway import library's symbol table. */
|
||||
sympp = (asymbol **) xmalloc (symsize);
|
||||
symcount = bfd_canonicalize_symtab (in_implib_bfd, sympp);
|
||||
if (symcount < 0)
|
||||
{
|
||||
ret = FALSE;
|
||||
goto free_sym_buf;
|
||||
}
|
||||
|
||||
htab->new_cmse_stub_offset = 0;
|
||||
cmse_stub_size =
|
||||
find_stub_size_and_template (arm_stub_cmse_branch_thumb_only,
|
||||
&cmse_stub_template,
|
||||
&cmse_stub_template_size);
|
||||
out_sec_name =
|
||||
arm_dedicated_stub_output_section_name (arm_stub_cmse_branch_thumb_only);
|
||||
stub_out_sec =
|
||||
bfd_get_section_by_name (htab->obfd, out_sec_name);
|
||||
if (stub_out_sec != NULL)
|
||||
cmse_stub_sec_vma = stub_out_sec->vma;
|
||||
|
||||
/* Set addresses of veneers mentionned in input secure gateway import
|
||||
library's symbol table. */
|
||||
for (i = 0; i < symcount; i++)
|
||||
{
|
||||
sym = sympp[i];
|
||||
flags = sym->flags;
|
||||
sym_name = (char *) bfd_asymbol_name (sym);
|
||||
intsym = &((elf_symbol_type *) sym)->internal_elf_sym;
|
||||
|
||||
if (sym->section != bfd_abs_section_ptr
|
||||
|| !(flags & (BSF_GLOBAL | BSF_WEAK))
|
||||
|| (flags & BSF_FUNCTION) != BSF_FUNCTION
|
||||
|| (ARM_GET_SYM_BRANCH_TYPE (intsym->st_target_internal)
|
||||
!= ST_BRANCH_TO_THUMB))
|
||||
{
|
||||
(*_bfd_error_handler) (_("%B: invalid import library entry: `%s'."),
|
||||
in_implib_bfd, sym_name);
|
||||
(*_bfd_error_handler) (_("Symbol should be absolute, global and "
|
||||
"refer to Thumb functions."));
|
||||
ret = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
veneer_value = bfd_asymbol_value (sym);
|
||||
stub_offset = veneer_value - cmse_stub_sec_vma;
|
||||
stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, sym_name,
|
||||
FALSE, FALSE);
|
||||
hash = (struct elf32_arm_link_hash_entry *)
|
||||
elf_link_hash_lookup (&(htab)->root, sym_name, FALSE, FALSE, TRUE);
|
||||
|
||||
/* Stub entry should have been created by cmse_scan or the symbol be of
|
||||
a secure function callable from non secure code. */
|
||||
if (!stub_entry && !hash)
|
||||
{
|
||||
bfd_boolean new_stub;
|
||||
|
||||
(*_bfd_error_handler)
|
||||
(_("Entry function `%s' disappeared from secure code."), sym_name);
|
||||
hash = (struct elf32_arm_link_hash_entry *)
|
||||
elf_link_hash_lookup (&(htab)->root, sym_name, TRUE, TRUE, TRUE);
|
||||
stub_entry
|
||||
= elf32_arm_create_stub (htab, arm_stub_cmse_branch_thumb_only,
|
||||
NULL, NULL, bfd_abs_section_ptr, hash,
|
||||
sym_name, veneer_value,
|
||||
ST_BRANCH_TO_THUMB, &new_stub);
|
||||
if (stub_entry == NULL)
|
||||
ret = FALSE;
|
||||
else
|
||||
{
|
||||
BFD_ASSERT (new_stub);
|
||||
new_cmse_stubs_created++;
|
||||
(*cmse_stub_created)++;
|
||||
}
|
||||
stub_entry->stub_template_size = stub_entry->stub_size = 0;
|
||||
stub_entry->stub_offset = stub_offset;
|
||||
}
|
||||
/* Symbol found is not callable from non secure code. */
|
||||
else if (!stub_entry)
|
||||
{
|
||||
if (!cmse_entry_fct_p (hash))
|
||||
{
|
||||
(*_bfd_error_handler) (_("`%s' refers to a non entry function."),
|
||||
sym_name);
|
||||
ret = FALSE;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Only stubs for SG veneers should have been created. */
|
||||
BFD_ASSERT (stub_entry->stub_type == arm_stub_cmse_branch_thumb_only);
|
||||
|
||||
/* Check visibility hasn't changed. */
|
||||
if (!!(flags & BSF_GLOBAL)
|
||||
!= (hash->root.root.type == bfd_link_hash_defined))
|
||||
(*_bfd_error_handler)
|
||||
(_("%B: visibility of symbol `%s' has changed."), in_implib_bfd,
|
||||
sym_name);
|
||||
|
||||
stub_entry->stub_offset = stub_offset;
|
||||
}
|
||||
|
||||
/* Size should match that of a SG veneer. */
|
||||
if (intsym->st_size != cmse_stub_size)
|
||||
{
|
||||
(*_bfd_error_handler) (_("%B: incorrect size for symbol `%s'."),
|
||||
in_implib_bfd, sym_name);
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
/* Previous veneer address is before current SG veneer section. */
|
||||
if (veneer_value < cmse_stub_sec_vma)
|
||||
{
|
||||
/* Avoid offset underflow. */
|
||||
if (stub_entry)
|
||||
stub_entry->stub_offset = 0;
|
||||
stub_offset = 0;
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
/* Complain if stub offset not a multiple of stub size. */
|
||||
if (stub_offset % cmse_stub_size)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("Offset of veneer for entry function `%s' not a multiple of "
|
||||
"its size."), sym_name);
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
continue;
|
||||
|
||||
new_cmse_stubs_created--;
|
||||
if (veneer_value < cmse_stub_array_start)
|
||||
cmse_stub_array_start = veneer_value;
|
||||
next_cmse_stub_offset = stub_offset + ((cmse_stub_size + 7) & ~7);
|
||||
if (next_cmse_stub_offset > htab->new_cmse_stub_offset)
|
||||
htab->new_cmse_stub_offset = next_cmse_stub_offset;
|
||||
}
|
||||
|
||||
if (!info->out_implib_bfd && new_cmse_stubs_created != 0)
|
||||
{
|
||||
BFD_ASSERT (new_cmse_stubs_created > 0);
|
||||
(*_bfd_error_handler)
|
||||
(_("new entry function(s) introduced but no output import library "
|
||||
"specified:"));
|
||||
bfd_hash_traverse (&htab->stub_hash_table, arm_list_new_cmse_stub, info);
|
||||
}
|
||||
|
||||
if (cmse_stub_array_start != cmse_stub_sec_vma)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("Start address of `%s' is different from previous link."),
|
||||
out_sec_name);
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
free_sym_buf:
|
||||
free (sympp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
@ -5735,7 +6054,9 @@ elf32_arm_size_stubs (bfd *output_bfd,
|
|||
unsigned int),
|
||||
void (*layout_sections_again) (void))
|
||||
{
|
||||
bfd_boolean ret = TRUE;
|
||||
obj_attribute *out_attr;
|
||||
int cmse_stub_created = 0;
|
||||
bfd_size_type stub_group_size;
|
||||
bfd_boolean m_profile, stubs_always_after_branch, first_veneer_scan = TRUE;
|
||||
struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
|
||||
|
@ -5768,6 +6089,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
|
|||
|
||||
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
|
||||
as the first half of a 32-bit branch straddling two 4K pages. This is a
|
||||
crude way of enforcing that. */
|
||||
|
@ -5841,8 +6163,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
|
|||
|
||||
sym_hashes = elf_sym_hashes (input_bfd);
|
||||
if (!cmse_scan (input_bfd, htab, out_attr, sym_hashes,
|
||||
&stub_changed))
|
||||
&cmse_stub_created))
|
||||
goto error_ret_free_local;
|
||||
|
||||
if (cmse_stub_created != 0)
|
||||
stub_changed = TRUE;
|
||||
}
|
||||
|
||||
/* Walk over each section attached to the input bfd. */
|
||||
|
@ -6074,6 +6399,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
|
|||
do
|
||||
{
|
||||
bfd_boolean new_stub;
|
||||
struct elf32_arm_stub_hash_entry *stub_entry;
|
||||
|
||||
/* Determine what (if any) linker stub is needed. */
|
||||
stub_type = arm_type_of_stub (info, section, irela,
|
||||
|
@ -6085,12 +6411,13 @@ elf32_arm_size_stubs (bfd *output_bfd,
|
|||
|
||||
/* We've either created a stub for this reloc already,
|
||||
or we are about to. */
|
||||
created_stub =
|
||||
stub_entry =
|
||||
elf32_arm_create_stub (htab, stub_type, section, irela,
|
||||
sym_sec, hash,
|
||||
(char *) sym_name, sym_value,
|
||||
branch_type, &new_stub);
|
||||
|
||||
created_stub = stub_entry != NULL;
|
||||
if (!created_stub)
|
||||
goto error_ret_free_internal;
|
||||
else if (!new_stub)
|
||||
|
@ -6172,6 +6499,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
|
|||
}
|
||||
}
|
||||
|
||||
if (first_veneer_scan
|
||||
&& !set_cmse_veneer_addr_from_implib (info, htab,
|
||||
&cmse_stub_created))
|
||||
ret = FALSE;
|
||||
|
||||
if (prev_num_a8_fixes != num_a8_fixes)
|
||||
stub_changed = TRUE;
|
||||
|
||||
|
@ -6191,6 +6523,24 @@ elf32_arm_size_stubs (bfd *output_bfd,
|
|||
stub_sec->size = 0;
|
||||
}
|
||||
|
||||
/* Add new SG veneers after those already in the input import
|
||||
library. */
|
||||
for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
|
||||
stub_type++)
|
||||
{
|
||||
bfd_vma *start_offset_p;
|
||||
asection **stub_sec_p;
|
||||
|
||||
start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type);
|
||||
stub_sec_p = arm_dedicated_stub_input_section_ptr (htab, stub_type);
|
||||
if (start_offset_p == NULL)
|
||||
continue;
|
||||
|
||||
BFD_ASSERT (stub_sec_p != NULL);
|
||||
if (*stub_sec_p != NULL)
|
||||
(*stub_sec_p)->size = *start_offset_p;
|
||||
}
|
||||
|
||||
/* Compute stub section size, considering padding. */
|
||||
bfd_hash_traverse (&htab->stub_hash_table, arm_size_one_stub, htab);
|
||||
for (stub_type = arm_stub_none + 1; stub_type < max_stub_type;
|
||||
|
@ -6259,7 +6609,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
|
|||
}
|
||||
|
||||
stub_entry->stub_sec = stub_sec;
|
||||
stub_entry->stub_offset = 0;
|
||||
stub_entry->stub_offset = (bfd_vma) -1;
|
||||
stub_entry->id_sec = link_sec;
|
||||
stub_entry->stub_type = a8_fixes[i].stub_type;
|
||||
stub_entry->source_value = a8_fixes[i].offset;
|
||||
|
@ -6287,7 +6637,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
|
|||
htab->a8_erratum_fixes = NULL;
|
||||
htab->num_a8_erratum_fixes = 0;
|
||||
}
|
||||
return TRUE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Build all the stubs associated with the current output file. The
|
||||
|
@ -6301,6 +6651,7 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
|
|||
{
|
||||
asection *stub_sec;
|
||||
struct bfd_hash_table *table;
|
||||
enum elf32_arm_stub_type stub_type;
|
||||
struct elf32_arm_link_hash_table *htab;
|
||||
|
||||
htab = elf32_arm_hash_table (info);
|
||||
|
@ -6318,14 +6669,33 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
|
|||
continue;
|
||||
|
||||
/* Allocate memory to hold the linker stubs. Zeroing the stub sections
|
||||
must at least be done for stub section requiring padding. */
|
||||
must at least be done for stub section requiring padding and for SG
|
||||
veneers to ensure that a non secure code branching to a removed SG
|
||||
veneer causes an error. */
|
||||
size = stub_sec->size;
|
||||
stub_sec->contents = (unsigned char *) bfd_zalloc (htab->stub_bfd, size);
|
||||
if (stub_sec->contents == NULL && size != 0)
|
||||
return FALSE;
|
||||
|
||||
stub_sec->size = 0;
|
||||
}
|
||||
|
||||
/* Add new SG veneers after those already in the input import library. */
|
||||
for (stub_type = arm_stub_none + 1; stub_type < max_stub_type; stub_type++)
|
||||
{
|
||||
bfd_vma *start_offset_p;
|
||||
asection **stub_sec_p;
|
||||
|
||||
start_offset_p = arm_new_stubs_start_offset_ptr (htab, stub_type);
|
||||
stub_sec_p = arm_dedicated_stub_input_section_ptr (htab, stub_type);
|
||||
if (start_offset_p == NULL)
|
||||
continue;
|
||||
|
||||
BFD_ASSERT (stub_sec_p != NULL);
|
||||
if (*stub_sec_p != NULL)
|
||||
(*stub_sec_p)->size = *start_offset_p;
|
||||
}
|
||||
|
||||
/* Build the stubs as directed by the stub hash table. */
|
||||
table = &htab->stub_hash_table;
|
||||
bfd_hash_traverse (table, arm_build_one_stub, info);
|
||||
|
@ -8311,7 +8681,8 @@ 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 cmse_implib)
|
||||
int fix_arm1176, int cmse_implib,
|
||||
bfd *in_implib_bfd)
|
||||
{
|
||||
struct elf32_arm_link_hash_table *globals;
|
||||
|
||||
|
@ -8339,6 +8710,7 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd,
|
|||
globals->fix_cortex_a8 = fix_cortex_a8;
|
||||
globals->fix_arm1176 = fix_arm1176;
|
||||
globals->cmse_implib = cmse_implib;
|
||||
globals->in_implib_bfd = in_implib_bfd;
|
||||
|
||||
BFD_ASSERT (is_arm_elf (output_bfd));
|
||||
elf_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
|
||||
|
|
40
ld/ChangeLog
40
ld/ChangeLog
|
@ -1,3 +1,43 @@
|
|||
2016-08-26 Thomas Preud'homme <thomas.preudhomme@arm.com>
|
||||
|
||||
* emultempl/armelf.em (in_implib_filename): Declare and initialize new
|
||||
variable.
|
||||
(arm_elf_create_output_section_statements): Open import input library
|
||||
file for writing and pass resulting in_implib_bfd to
|
||||
bfd_elf32_arm_set_target_relocs.
|
||||
(PARSE_AND_LIST_PROLOGUE): Define OPTION_IN_IMPLIB option.
|
||||
(PARSE_AND_LIST_LONGOPTS): Define --in-implib option.
|
||||
(PARSE_AND_LIST_OPTIONS): Add help message for --in-implib option.
|
||||
(PARSE_AND_LIST_ARGS_CASES): Handle new OPTION_IN_IMPLIB case.
|
||||
* ld.texinfo (--cmse-implib): Update to mention --in-implib.
|
||||
(--in-implib): Document new option.
|
||||
* NEWS: Likewise.
|
||||
* testsuite/ld-arm/arm-elf.exp
|
||||
(Secure gateway import library generation): add --defsym VER=1 to gas
|
||||
CLI.
|
||||
(Secure gateway import library generation: errors): Likewise.
|
||||
(Input secure gateway import library): New test.
|
||||
(Input secure gateway import library: no output import library):
|
||||
Likewise.
|
||||
(Input secure gateway import library: not an SG input import library):
|
||||
Likewise.
|
||||
(Input secure gateway import library: earlier stub section base):
|
||||
Likewise.
|
||||
(Input secure gateway import library: later stub section base):
|
||||
Likewise.
|
||||
(Input secure gateway import library: veneer comeback): Likewise.
|
||||
(Input secure gateway import library: entry function change):
|
||||
Likewise.
|
||||
* testsuite/ld-arm/cmse-implib.s: Add input import library testing.
|
||||
* testsuite/ld-arm/cmse-implib.rd: Update accordingly.
|
||||
* testsuite/ld-arm/cmse-new-implib.out: New file.
|
||||
* testsuite/ld-arm/cmse-new-implib.rd: Likewise.
|
||||
* testsuite/ld-arm/cmse-new-implib-no-output.out: Likewise.
|
||||
* testsuite/ld-arm/cmse-new-implib-not-sg-in-implib.out: Likewise.
|
||||
* testsuite/ld-arm/cmse-new-earlier-later-implib.out: Likewise.
|
||||
* testsuite/ld-arm/cmse-new-comeback-implib.rd: Likewise.
|
||||
* testsuite/ld-arm/cmse-new-wrong-implib.out: Likewise.
|
||||
|
||||
2016-08-25 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* configure.tgt (powerpc*-*-linux* et al): Rewrite, adding LE
|
||||
|
|
5
ld/NEWS
5
ld/NEWS
|
@ -2,6 +2,11 @@
|
|||
|
||||
Changes in 2.28:
|
||||
|
||||
* Add --in-implib=<infile> to the ARM linker to enable specifying a set of
|
||||
Secure Gateway veneers that must exist in the output import library specified
|
||||
by --out-implib=<outfile> and the address they must have. As such,
|
||||
--in-implib is only supported in combination with --cmse-implib.
|
||||
|
||||
* Extended the --out-implib=<file> option, previously restricted to x86 PE
|
||||
targets, to any ELF based target. This allows the generation of an import
|
||||
library for an ELF executable, which can then be used by another application
|
||||
|
|
|
@ -43,6 +43,7 @@ static int pic_veneer = 0;
|
|||
static int merge_exidx_entries = -1;
|
||||
static int fix_arm1176 = 1;
|
||||
static int cmse_implib = 0;
|
||||
static char *in_implib_filename = NULL;
|
||||
|
||||
static void
|
||||
gld${EMULATION_NAME}_before_parse (void)
|
||||
|
@ -499,6 +500,8 @@ gld${EMULATION_NAME}_finish (void)
|
|||
static void
|
||||
arm_elf_create_output_section_statements (void)
|
||||
{
|
||||
bfd *in_implib_bfd;
|
||||
|
||||
if (strstr (bfd_get_target (link_info.output_bfd), "arm") == NULL)
|
||||
{
|
||||
/* The arm backend needs special fields in the output hash structure.
|
||||
|
@ -509,6 +512,20 @@ arm_elf_create_output_section_statements (void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (in_implib_filename)
|
||||
{
|
||||
in_implib_bfd = bfd_openr (in_implib_filename,
|
||||
bfd_get_target (link_info.output_bfd));
|
||||
|
||||
if (in_implib_bfd == NULL)
|
||||
einfo ("%F%s: Can't open: %E\n", in_implib_filename);
|
||||
|
||||
if (!bfd_check_format (in_implib_bfd, bfd_object))
|
||||
einfo ("%F%s: Not a relocatable file: %E\n", in_implib_filename);
|
||||
}
|
||||
else
|
||||
in_implib_bfd = NULL;
|
||||
|
||||
bfd_elf32_arm_set_target_relocs (link_info.output_bfd, &link_info,
|
||||
target1_is_rel,
|
||||
target2_type, fix_v4bx, use_blx,
|
||||
|
@ -516,7 +533,7 @@ arm_elf_create_output_section_statements (void)
|
|||
no_enum_size_warning,
|
||||
no_wchar_size_warning,
|
||||
pic_veneer, fix_cortex_a8,
|
||||
fix_arm1176, cmse_implib);
|
||||
fix_arm1176, cmse_implib, in_implib_bfd);
|
||||
|
||||
stub_file = lang_add_input_file ("linker stubs",
|
||||
lang_input_file_is_fake_enum,
|
||||
|
@ -586,6 +603,7 @@ PARSE_AND_LIST_PROLOGUE='
|
|||
#define OPTION_LONG_PLT 319
|
||||
#define OPTION_STM32L4XX_FIX 320
|
||||
#define OPTION_CMSE_IMPLIB 321
|
||||
#define OPTION_IN_IMPLIB 322
|
||||
'
|
||||
|
||||
PARSE_AND_LIST_SHORTOPTS=p
|
||||
|
@ -613,6 +631,7 @@ PARSE_AND_LIST_LONGOPTS='
|
|||
{ "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 },
|
||||
{ "in-implib", required_argument, NULL, OPTION_IN_IMPLIB },
|
||||
'
|
||||
|
||||
PARSE_AND_LIST_OPTIONS='
|
||||
|
@ -635,6 +654,8 @@ PARSE_AND_LIST_OPTIONS='
|
|||
" 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, _(" --in-implib Import library whose symbols address must\n"
|
||||
" remain stable\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\
|
||||
|
@ -759,6 +780,10 @@ PARSE_AND_LIST_ARGS_CASES='
|
|||
case OPTION_CMSE_IMPLIB:
|
||||
cmse_implib = 1;
|
||||
break;
|
||||
|
||||
case OPTION_IN_IMPLIB:
|
||||
in_implib_filename = optarg;
|
||||
break;
|
||||
'
|
||||
|
||||
# We have our own before_allocation etc. functions, but they call
|
||||
|
|
|
@ -6866,6 +6866,18 @@ 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.
|
||||
|
||||
@kindex --in-implib=@var{file}
|
||||
@cindex Input import library
|
||||
The @samp{--in-implib=file} specifies an input import library whose symbols
|
||||
must keep the same address in the executable being produced. A warning is
|
||||
given if no @samp{--out-implib} is given but new symbols have been introduced
|
||||
in the executable that should be listed in its import library. Otherwise, if
|
||||
@samp{--out-implib} is specified, the symbols are added to the output import
|
||||
library. A warning is also given if some symbols present in the input import
|
||||
library have disappeared from the executable. This option is only effective
|
||||
for Secure Gateway import libraries, ie. when @samp{--cmse-implib} is
|
||||
specified.
|
||||
|
||||
@ifclear GENERIC
|
||||
@lowersections
|
||||
@end ifclear
|
||||
|
|
|
@ -670,16 +670,59 @@ set armeabitests_nonacl {
|
|||
"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"
|
||||
"-march=armv8-m.base -mthumb --defsym CHECK_ERRORS=1 --defsym VER=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"
|
||||
"-march=armv8-m.base -mthumb --defsym VER=1"
|
||||
{cmse-implib.s}
|
||||
{{readelf {-s tmpdir/cmse-implib.lib} cmse-implib.rd}}
|
||||
"cmse-implib"}
|
||||
{"Input secure gateway import library"
|
||||
"--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-new-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
|
||||
"-march=armv8-m.base -mthumb --defsym VER=2"
|
||||
{cmse-implib.s}
|
||||
{{ld cmse-new-implib.out}
|
||||
{readelf {-s tmpdir/cmse-new-implib.lib} cmse-new-implib.rd}}
|
||||
"cmse-new-implib"}
|
||||
{"Input secure gateway import library: no output import library"
|
||||
"--section-start .gnu.sgstubs=0x20000 --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
|
||||
"-march=armv8-m.base -mthumb --defsym VER=2"
|
||||
{cmse-implib.s}
|
||||
{{ld cmse-new-implib-no-output.out}}
|
||||
"cmse-new-implib-no-output"}
|
||||
{"Input secure gateway import library: not an SG input import library"
|
||||
"--section-start .gnu.sgstubs=0x20000 --in-implib=tmpdir/cmse-implib.lib" ""
|
||||
"-march=armv8-m.base -mthumb --defsym VER=2"
|
||||
{cmse-implib.s}
|
||||
{{ld cmse-new-implib-not-sg-in-implib.out}}
|
||||
"cmse-new-implib-not-sg-in-implib"}
|
||||
{"Input secure gateway import library: earlier stub section base"
|
||||
"--section-start .gnu.sgstubs=0x19000 --out-implib=tmpdir/cmse-new-earlier-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
|
||||
"-march=armv8-m.base -mthumb --defsym VER=2"
|
||||
{cmse-implib.s}
|
||||
{{ld cmse-new-earlier-later-implib.out}}
|
||||
"cmse-new-earlier-implib"}
|
||||
{"Input secure gateway import library: later stub section base"
|
||||
"--section-start .gnu.sgstubs=0x30000 --out-implib=tmpdir/cmse-new-later-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
|
||||
"-march=armv8-m.base -mthumb --defsym VER=2"
|
||||
{cmse-implib.s}
|
||||
{{ld cmse-new-earlier-later-implib.out}}
|
||||
"cmse-new-later-implib"}
|
||||
{"Input secure gateway import library: veneer comeback"
|
||||
"--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-new-comeback-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
|
||||
"-march=armv8-m.base -mthumb --defsym VER=3"
|
||||
{cmse-implib.s}
|
||||
{{readelf {-s tmpdir/cmse-new-comeback-implib.lib} cmse-new-comeback-implib.rd}}
|
||||
"cmse-new-comeback-implib"}
|
||||
{"Input secure gateway import library: entry function change"
|
||||
"--section-start .gnu.sgstubs=0x20000 --out-implib=tmpdir/cmse-new-wrong-implib.lib --in-implib=tmpdir/cmse-implib.lib --cmse-implib" ""
|
||||
"-march=armv8-m.base -mthumb --defsym VER=4"
|
||||
{cmse-implib.s}
|
||||
{{ld cmse-new-wrong-implib.out}}
|
||||
"cmse-new-wrong-implib"}
|
||||
|
||||
{"R_ARM_THM_JUMP19 Relocation veneers: Short"
|
||||
"--section-start destsect=0x000108002 --section-start .text=0x8000" ""
|
||||
|
|
|
@ -20,12 +20,29 @@ __acle_se_\name:
|
|||
.endm
|
||||
|
||||
@ Valid setups for veneer generation
|
||||
.if (VER >= 2)
|
||||
entry exported_entry_veneer1, global
|
||||
.endif
|
||||
.if (VER != 4)
|
||||
entry exported_entry_veneer2, global
|
||||
.else
|
||||
entry exported_entry_veneer2, weak
|
||||
.endif
|
||||
.if (VER != 2)
|
||||
entry exported_entry_veneer3, global
|
||||
.endif
|
||||
.if (VER > 1)
|
||||
entry exported_entry_veneer4, global
|
||||
.endif
|
||||
|
||||
@ Valid setup for entry function without veneer generation
|
||||
entry exported_entry_fct1, global, sg
|
||||
.if (VER != 4)
|
||||
entry exported_entry_fct2, global, sg
|
||||
.else
|
||||
@ Invalid setup for entry function without veneer generation
|
||||
entry exported_entry_fct2, global, nop
|
||||
.endif
|
||||
|
||||
@ Normal symbol not exported to SG import library
|
||||
.align 2
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
File: tmpdir/cmse-new-.*implib.lib
|
||||
|
||||
Symbol table '.symtab' contains 7 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: 00020011 8 FUNC GLOBAL DEFAULT ABS exported_entry_veneer4
|
||||
3: 00020019 8 FUNC GLOBAL DEFAULT ABS exported_entry_veneer1
|
||||
4: [0-9a-f]+ 6 FUNC GLOBAL DEFAULT ABS exported_entry_fct1
|
||||
5: 00020009 8 FUNC GLOBAL DEFAULT ABS exported_entry_veneer2
|
||||
6: [0-9a-f]+ 6 FUNC GLOBAL DEFAULT ABS exported_entry_fct2
|
||||
|
||||
File: tmpdir/cmse-new-.*implib
|
||||
|
||||
#...
|
|
@ -0,0 +1,3 @@
|
|||
.*: Entry function `exported_entry_veneer3' disappeared from secure code.
|
||||
.*: Start address of `.gnu.sgstubs' is different from previous link.
|
||||
.*: cannot size stub section: Invalid operation
|
|
@ -0,0 +1,4 @@
|
|||
.*: Entry function `exported_entry_veneer3' disappeared from secure code.
|
||||
.*: new entry function\(s\) introduced but no output import library specified:
|
||||
.*: exported_entry_veneer4
|
||||
.*: exported_entry_veneer1
|
|
@ -0,0 +1,2 @@
|
|||
.*: --in-implib only supported for Secure Gateway import libraries.
|
||||
.*: cannot size stub section: Invalid operation
|
|
@ -0,0 +1 @@
|
|||
.*: Entry function `exported_entry_veneer3' disappeared from secure code.
|
|
@ -0,0 +1,14 @@
|
|||
File: tmpdir/cmse-new-.*implib.lib
|
||||
|
||||
Symbol table '.symtab' contains 6 entries:
|
||||
Num: Value Size Type Bind Vis Ndx Name
|
||||
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
|
||||
1: 00020011 8 FUNC GLOBAL DEFAULT ABS exported_entry_veneer4
|
||||
2: 00020019 8 FUNC GLOBAL DEFAULT ABS exported_entry_veneer1
|
||||
3: [0-9a-f]+ 6 FUNC GLOBAL DEFAULT ABS exported_entry_fct1
|
||||
4: 00020009 8 FUNC GLOBAL DEFAULT ABS exported_entry_veneer2
|
||||
5: [0-9a-f]+ 6 FUNC GLOBAL DEFAULT ABS exported_entry_fct2
|
||||
|
||||
File: tmpdir/cmse-new-.*implib
|
||||
|
||||
#...
|
|
@ -0,0 +1,3 @@
|
|||
.*: .*: visibility of symbol `exported_entry_veneer2' has changed.
|
||||
.*: `exported_entry_fct2' refers to a non entry function.
|
||||
.*: cannot size stub section: Invalid operation
|
Loading…
Reference in New Issue