Factor our stub creation in ARM backend
2016-05-10 Thomas Preud'homme <thomas.preudhomme@arm.com> bfd/ * elf32-arm.c (elf32_arm_create_stub): New function. (elf32_arm_size_stubs): Use elf32_arm_create_stub for stub creation.
This commit is contained in:
parent
8d9d949014
commit
b715f643ef
@ -1,3 +1,8 @@
|
||||
2016-05-10 Thomas Preud'homme <thomas.preudhomme@arm.com>
|
||||
|
||||
* elf32-arm.c (elf32_arm_create_stub): New function.
|
||||
(elf32_arm_size_stubs): Use elf32_arm_create_stub for stub creation.
|
||||
|
||||
2016-05-10 Thomas Preud'homme <thomas.preudhomme@arm.com>
|
||||
|
||||
* elf32-arm.c (enum elf32_arm_stub_type): Delete
|
||||
|
176
bfd/elf32-arm.c
176
bfd/elf32-arm.c
@ -5107,6 +5107,103 @@ cortex_a8_erratum_scan (bfd *input_bfd,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Create or update a stub entry depending on whether the stub can already be
|
||||
found in HTAB. The stub is identified by:
|
||||
- its type STUB_TYPE
|
||||
- its source branch (note that several can share the same stub) whose
|
||||
section and relocation (if any) are given by SECTION and IRELA
|
||||
respectively
|
||||
- its target symbol whose input section, hash, name, value and branch type
|
||||
are given in SYM_SEC, HASH, SYM_NAME, SYM_VALUE and BRANCH_TYPE
|
||||
respectively
|
||||
|
||||
If found, the value of the stub's target symbol is updated from SYM_VALUE
|
||||
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. */
|
||||
|
||||
static bfd_boolean
|
||||
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,
|
||||
struct elf32_arm_link_hash_entry *hash, char *sym_name,
|
||||
bfd_vma sym_value, enum arm_st_branch_type branch_type,
|
||||
bfd_boolean *new_stub)
|
||||
{
|
||||
const asection *id_sec;
|
||||
char *stub_name;
|
||||
struct elf32_arm_stub_hash_entry *stub_entry;
|
||||
unsigned int r_type;
|
||||
|
||||
BFD_ASSERT (stub_type != arm_stub_none);
|
||||
*new_stub = FALSE;
|
||||
|
||||
BFD_ASSERT (irela);
|
||||
BFD_ASSERT (section);
|
||||
|
||||
/* Support for grouping stub sections. */
|
||||
id_sec = htab->stub_group[section->id].link_sec;
|
||||
|
||||
/* Get the name of this stub. */
|
||||
stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash, irela, stub_type);
|
||||
if (!stub_name)
|
||||
return FALSE;
|
||||
|
||||
stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, stub_name, FALSE,
|
||||
FALSE);
|
||||
/* The proper stub has already been created, just update its value. */
|
||||
if (stub_entry != NULL)
|
||||
{
|
||||
free (stub_name);
|
||||
stub_entry->target_value = sym_value;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
stub_entry = elf32_arm_add_stub (stub_name, section, htab);
|
||||
if (stub_entry == NULL)
|
||||
{
|
||||
free (stub_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
stub_entry->target_value = sym_value;
|
||||
stub_entry->target_section = sym_sec;
|
||||
stub_entry->stub_type = stub_type;
|
||||
stub_entry->h = hash;
|
||||
stub_entry->branch_type = branch_type;
|
||||
|
||||
if (sym_name == NULL)
|
||||
sym_name = "unnamed";
|
||||
stub_entry->output_name = (char *)
|
||||
bfd_alloc (htab->stub_bfd, sizeof (THUMB2ARM_GLUE_ENTRY_NAME)
|
||||
+ strlen (sym_name));
|
||||
if (stub_entry->output_name == NULL)
|
||||
{
|
||||
free (stub_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* For historical reasons, use the existing names for ARM-to-Thumb and
|
||||
Thumb-to-ARM stubs. */
|
||||
r_type = ELF32_R_TYPE (irela->r_info);
|
||||
if ((r_type == (unsigned int) R_ARM_THM_CALL
|
||||
|| r_type == (unsigned int) R_ARM_THM_JUMP24
|
||||
|| r_type == (unsigned int) R_ARM_THM_JUMP19)
|
||||
&& branch_type == ST_BRANCH_TO_ARM)
|
||||
sprintf (stub_entry->output_name, THUMB2ARM_GLUE_ENTRY_NAME, sym_name);
|
||||
else if ((r_type == (unsigned int) R_ARM_CALL
|
||||
|| r_type == (unsigned int) R_ARM_JUMP24)
|
||||
&& branch_type == ST_BRANCH_TO_THUMB)
|
||||
sprintf (stub_entry->output_name, ARM2THUMB_GLUE_ENTRY_NAME, sym_name);
|
||||
else
|
||||
sprintf (stub_entry->output_name, STUB_ENTRY_NAME, sym_name);
|
||||
|
||||
*new_stub = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* 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
|
||||
@ -5250,14 +5347,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
|
||||
{
|
||||
unsigned int r_type, r_indx;
|
||||
enum elf32_arm_stub_type stub_type;
|
||||
struct elf32_arm_stub_hash_entry *stub_entry;
|
||||
asection *sym_sec;
|
||||
bfd_vma sym_value;
|
||||
bfd_vma destination;
|
||||
struct elf32_arm_link_hash_entry *hash;
|
||||
const char *sym_name;
|
||||
char *stub_name;
|
||||
const asection *id_sec;
|
||||
unsigned char st_type;
|
||||
enum arm_st_branch_type branch_type;
|
||||
bfd_boolean created_stub = FALSE;
|
||||
@ -5446,6 +5540,8 @@ elf32_arm_size_stubs (bfd *output_bfd,
|
||||
|
||||
do
|
||||
{
|
||||
bfd_boolean new_stub;
|
||||
|
||||
/* Determine what (if any) linker stub is needed. */
|
||||
stub_type = arm_type_of_stub (info, section, irela,
|
||||
st_type, &branch_type,
|
||||
@ -5454,74 +5550,20 @@ elf32_arm_size_stubs (bfd *output_bfd,
|
||||
if (stub_type == arm_stub_none)
|
||||
break;
|
||||
|
||||
/* Support for grouping stub sections. */
|
||||
id_sec = htab->stub_group[section->id].link_sec;
|
||||
|
||||
/* Get the name of this stub. */
|
||||
stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash,
|
||||
irela, stub_type);
|
||||
if (!stub_name)
|
||||
goto error_ret_free_internal;
|
||||
|
||||
/* We've either created a stub for this reloc already,
|
||||
or we are about to. */
|
||||
created_stub = TRUE;
|
||||
created_stub =
|
||||
elf32_arm_create_stub (htab, stub_type, section, irela,
|
||||
sym_sec, hash,
|
||||
(char *) sym_name, sym_value,
|
||||
branch_type, &new_stub);
|
||||
|
||||
stub_entry = arm_stub_hash_lookup
|
||||
(&htab->stub_hash_table, stub_name,
|
||||
FALSE, FALSE);
|
||||
if (stub_entry != NULL)
|
||||
{
|
||||
/* The proper stub has already been created. */
|
||||
free (stub_name);
|
||||
stub_entry->target_value = sym_value;
|
||||
break;
|
||||
}
|
||||
|
||||
stub_entry = elf32_arm_add_stub (stub_name, section,
|
||||
htab);
|
||||
if (stub_entry == NULL)
|
||||
{
|
||||
free (stub_name);
|
||||
goto error_ret_free_internal;
|
||||
}
|
||||
|
||||
stub_entry->target_value = sym_value;
|
||||
stub_entry->target_section = sym_sec;
|
||||
stub_entry->stub_type = stub_type;
|
||||
stub_entry->h = hash;
|
||||
stub_entry->branch_type = branch_type;
|
||||
|
||||
if (sym_name == NULL)
|
||||
sym_name = "unnamed";
|
||||
stub_entry->output_name = (char *)
|
||||
bfd_alloc (htab->stub_bfd,
|
||||
sizeof (THUMB2ARM_GLUE_ENTRY_NAME)
|
||||
+ strlen (sym_name));
|
||||
if (stub_entry->output_name == NULL)
|
||||
{
|
||||
free (stub_name);
|
||||
goto error_ret_free_internal;
|
||||
}
|
||||
|
||||
/* For historical reasons, use the existing names for
|
||||
ARM-to-Thumb and Thumb-to-ARM stubs. */
|
||||
if ((r_type == (unsigned int) R_ARM_THM_CALL
|
||||
|| r_type == (unsigned int) R_ARM_THM_JUMP24
|
||||
|| r_type == (unsigned int) R_ARM_THM_JUMP19)
|
||||
&& branch_type == ST_BRANCH_TO_ARM)
|
||||
sprintf (stub_entry->output_name,
|
||||
THUMB2ARM_GLUE_ENTRY_NAME, sym_name);
|
||||
else if ((r_type == (unsigned int) R_ARM_CALL
|
||||
|| r_type == (unsigned int) R_ARM_JUMP24)
|
||||
&& branch_type == ST_BRANCH_TO_THUMB)
|
||||
sprintf (stub_entry->output_name,
|
||||
ARM2THUMB_GLUE_ENTRY_NAME, sym_name);
|
||||
if (!created_stub)
|
||||
goto error_ret_free_internal;
|
||||
else if (!new_stub)
|
||||
break;
|
||||
else
|
||||
sprintf (stub_entry->output_name, STUB_ENTRY_NAME,
|
||||
sym_name);
|
||||
|
||||
stub_changed = TRUE;
|
||||
stub_changed = TRUE;
|
||||
}
|
||||
while (0);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user