This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: ARM stub sizing fix
On Thu, Jan 14, 2010 at 02:48:20PM -0500, Daniel Jacobowitz wrote:
> Yes, this is busted.
Easily fixed. Breaks arm-call test due to different stub ordering,
but I'll leave fixing the testsuite to an ARM maintainer.
* elf32-arm.c (arm_type_of_stub): Wrap overlong lines.
(cortex_a8_erratum_scan): Fix uninitialised warning.
(elf32_arm_stub_name): Add stub_type param. Encode stub_type in name.
Update all callers.
(elf32_arm_get_stub_entry): Add stub_type param. Update all callers.
(elf32_arm_final_link_relocate): Call arm_type_of_stub to determine
stub type, if any.
Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.218
diff -u -p -r1.218 elf32-arm.c
--- bfd/elf32-arm.c 28 Dec 2009 18:55:16 -0000 1.218
+++ bfd/elf32-arm.c 14 Jan 2010 23:33:09 -0000
@@ -3075,7 +3075,9 @@ arm_type_of_stub (struct bfd_link_info *
r_type = ELF32_R_TYPE (rel->r_info);
/* Keep a simpler condition, for the sake of clarity. */
- if (globals->splt != NULL && hash != NULL && hash->root.plt.offset != (bfd_vma) -1)
+ if (globals->splt != NULL
+ && hash != NULL
+ && hash->root.plt.offset != (bfd_vma) -1)
{
use_plt = 1;
/* Note when dealing with PLT entries: the main PLT stub is in
@@ -3181,7 +3183,9 @@ arm_type_of_stub (struct bfd_link_info *
}
}
}
- else if (r_type == R_ARM_CALL || r_type == R_ARM_JUMP24 || r_type == R_ARM_PLT32)
+ else if (r_type == R_ARM_CALL
+ || r_type == R_ARM_JUMP24
+ || r_type == R_ARM_PLT32)
{
if (st_type == STT_ARM_TFUNC)
{
@@ -3245,31 +3249,34 @@ static char *
elf32_arm_stub_name (const asection *input_section,
const asection *sym_sec,
const struct elf32_arm_link_hash_entry *hash,
- const Elf_Internal_Rela *rel)
+ const Elf_Internal_Rela *rel,
+ enum elf32_arm_stub_type stub_type)
{
char *stub_name;
bfd_size_type len;
if (hash)
{
- len = 8 + 1 + strlen (hash->root.root.root.string) + 1 + 8 + 1;
+ len = 8 + 1 + strlen (hash->root.root.root.string) + 1 + 8 + 1 + 2 + 1;
stub_name = (char *) bfd_malloc (len);
if (stub_name != NULL)
- sprintf (stub_name, "%08x_%s+%x",
+ sprintf (stub_name, "%08x_%s+%x_%d",
input_section->id & 0xffffffff,
hash->root.root.root.string,
- (int) rel->r_addend & 0xffffffff);
+ (int) rel->r_addend & 0xffffffff,
+ (int) stub_type);
}
else
{
- len = 8 + 1 + 8 + 1 + 8 + 1 + 8 + 1;
+ len = 8 + 1 + 8 + 1 + 8 + 1 + 8 + 1 + 2 + 1;
stub_name = (char *) bfd_malloc (len);
if (stub_name != NULL)
- sprintf (stub_name, "%08x_%x:%x+%x",
+ sprintf (stub_name, "%08x_%x:%x+%x_%d",
input_section->id & 0xffffffff,
sym_sec->id & 0xffffffff,
(int) ELF32_R_SYM (rel->r_info) & 0xffffffff,
- (int) rel->r_addend & 0xffffffff);
+ (int) rel->r_addend & 0xffffffff,
+ (int) stub_type);
}
return stub_name;
@@ -3283,7 +3290,8 @@ elf32_arm_get_stub_entry (const asection
const asection *sym_sec,
struct elf_link_hash_entry *hash,
const Elf_Internal_Rela *rel,
- struct elf32_arm_link_hash_table *htab)
+ struct elf32_arm_link_hash_table *htab,
+ enum elf32_arm_stub_type stub_type)
{
struct elf32_arm_stub_hash_entry *stub_entry;
struct elf32_arm_link_hash_entry *h = (struct elf32_arm_link_hash_entry *) hash;
@@ -3309,7 +3317,7 @@ elf32_arm_get_stub_entry (const asection
{
char *stub_name;
- stub_name = elf32_arm_stub_name (id_sec, sym_sec, h, rel);
+ stub_name = elf32_arm_stub_name (id_sec, sym_sec, h, rel, stub_type);
if (stub_name == NULL)
return NULL;
@@ -4022,7 +4030,7 @@ cortex_a8_erratum_scan (bfd *input_bfd,
&& last_was_32bit
&& ! last_was_branch)
{
- bfd_signed_vma offset;
+ bfd_signed_vma offset = 0;
bfd_boolean force_target_arm = FALSE;
bfd_boolean force_target_thumb = FALSE;
bfd_vma target;
@@ -4512,7 +4520,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
/* Get the name of this stub. */
stub_name = elf32_arm_stub_name (id_sec, sym_sec, hash,
- irela);
+ irela, stub_type);
if (!stub_name)
goto error_ret_free_internal;
@@ -7004,7 +7012,6 @@ elf32_arm_final_link_relocate (reloc_how
case R_ARM_PC24: /* Arm B/BL instruction. */
case R_ARM_PLT32:
{
- bfd_signed_vma branch_offset;
struct elf32_arm_stub_hash_entry *stub_entry = NULL;
if (r_type == R_ARM_XPC25)
@@ -7040,8 +7047,9 @@ elf32_arm_final_link_relocate (reloc_how
|| r_type == R_ARM_JUMP24
|| r_type == R_ARM_PLT32)
{
- bfd_vma from;
-
+ enum elf32_arm_stub_type stub_type;
+ struct elf32_arm_link_hash_entry *hash;
+
/* If the call goes through a PLT entry, make sure to
check distance to the right destination address. */
if (h != NULL && splt != NULL && h->plt.offset != (bfd_vma) -1)
@@ -7055,25 +7063,21 @@ elf32_arm_final_link_relocate (reloc_how
sym_flags = STT_FUNC;
}
- from = (input_section->output_section->vma
- + input_section->output_offset
- + rel->r_offset);
- branch_offset = (bfd_signed_vma)(value - from);
-
- if (branch_offset > ARM_MAX_FWD_BRANCH_OFFSET
- || branch_offset < ARM_MAX_BWD_BRANCH_OFFSET
- || ((sym_flags == STT_ARM_TFUNC)
- && (((r_type == R_ARM_CALL) && !globals->use_blx)
- || (r_type == R_ARM_JUMP24)
- || (r_type == R_ARM_PLT32) ))
- )
+ hash = (struct elf32_arm_link_hash_entry *) h;
+ stub_type = arm_type_of_stub (info, input_section, rel,
+ sym_flags, hash,
+ value, sym_sec,
+ input_bfd, sym_name);
+
+ if (stub_type != arm_stub_none)
{
/* The target is out of reach, so redirect the
branch to the local stub for this function. */
stub_entry = elf32_arm_get_stub_entry (input_section,
sym_sec, h,
- rel, globals);
+ rel, globals,
+ stub_type);
if (stub_entry != NULL)
value = (stub_entry->stub_offset
+ stub_entry->stub_sec->output_offset
@@ -7489,32 +7493,24 @@ elf32_arm_final_link_relocate (reloc_how
{
/* Check if a stub has to be inserted because the destination
is too far. */
- bfd_vma from;
- bfd_signed_vma branch_offset;
- struct elf32_arm_stub_hash_entry *stub_entry = NULL;
-
- from = (input_section->output_section->vma
- + input_section->output_offset
- + rel->r_offset);
- branch_offset = (bfd_signed_vma)(value - from);
-
- if ((!thumb2
- && (branch_offset > THM_MAX_FWD_BRANCH_OFFSET
- || (branch_offset < THM_MAX_BWD_BRANCH_OFFSET)))
- ||
- (thumb2
- && (branch_offset > THM2_MAX_FWD_BRANCH_OFFSET
- || (branch_offset < THM2_MAX_BWD_BRANCH_OFFSET)))
- || ((sym_flags != STT_ARM_TFUNC)
- && (((r_type == R_ARM_THM_CALL) && !globals->use_blx)
- || r_type == R_ARM_THM_JUMP24)))
+ enum elf32_arm_stub_type stub_type;
+ struct elf32_arm_stub_hash_entry *stub_entry;
+ struct elf32_arm_link_hash_entry *hash;
+
+ hash = (struct elf32_arm_link_hash_entry *) h;
+ stub_type = arm_type_of_stub (info, input_section, rel,
+ sym_flags, hash, value, sym_sec,
+ input_bfd, sym_name);
+
+ if (stub_type != arm_stub_none)
{
/* The target is out of reach or we are changing modes, so
redirect the branch to the local stub for this
function. */
stub_entry = elf32_arm_get_stub_entry (input_section,
sym_sec, h,
- rel, globals);
+ rel, globals,
+ stub_type);
if (stub_entry != NULL)
value = (stub_entry->stub_offset
+ stub_entry->stub_sec->output_offset
--
Alan Modra
Australia Development Lab, IBM