This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
ARM stub sizing fix
- From: Alan Modra <amodra at gmail dot com>
- To: binutils at sourceware dot org
- Date: Thu, 14 Jan 2010 22:25:28 +1030
- Subject: ARM stub sizing fix
This patch fixes a problem with stub sizing in the ARM backend. I
started looking at this when I became curious about PR 10409, but I
now suspect that PR was fixed by Nathan's 2009-08-05 elf32-arm.c
patch.
The problem is due to the ARM backend creating stubs based only on the
destination symbol (also on input section stub group and reloc addend,
but within a single stub group you basically have only one stub per
destination); We don't get multiple stubs if one branch to a
particular destination requires a different type of stub to that
required on another branch to the same destination. However, the code
in arm_type_of_stub clearly returns stub types that depend on branch
offset and reloc type. You could easily have both a
short_branch_v4t_thumb_arm and a long_branch_v4t_thumb_arm to the same
destination, with sorry results if the short version happened to be
created first. Also, addition of stubs for one iteration of stub
sizing may cause a stub that was initially a
short_branch_v4t_thumb_arm to become a long_branch_v4t_thumb_arm on
the next iteration. Fixed by updating existing stub_type for this
case.
I also add an assert that will trigger if there is a dependence on
reloc type. I don't know enough about ARM code to know whether it's
possible to have, say, one branch to a function using R_ARM_THM_CALL
and another using R_ARM_THM_JUMP24 (possible tail call?).
OK to apply?
* elf32-arm.c (arm_type_of_stub): Wrap overlong lines.
(cortex_a8_erratum_scan): Fix uninitialised warning.
(elf32_arm_size_stubs): Check and update stub_type in existing stubs.
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 08:36:37 -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)
{
@@ -4022,7 +4026,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;
@@ -4528,6 +4532,16 @@ elf32_arm_size_stubs (bfd *output_bfd,
/* The proper stub has already been created. */
free (stub_name);
stub_entry->target_value = sym_value;
+ if (stub_entry->stub_type
+ == arm_stub_short_branch_v4t_thumb_arm
+ && (stub_type
+ == arm_stub_long_branch_v4t_thumb_arm))
+ {
+ stub_entry->stub_type = stub_type;
+ stub_changed = TRUE;
+ }
+ else
+ BFD_ASSERT (stub_entry->stub_type == stub_type);
break;
}
--
Alan Modra
Australia Development Lab, IBM