aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog12
-rw-r--r--bfd/elf32-arm.c189
-rw-r--r--ld/testsuite/ChangeLog7
-rw-r--r--ld/testsuite/ld-arm/arm-call.d22
-rw-r--r--ld/testsuite/ld-arm/arm-pic-veneer.d2
-rw-r--r--ld/testsuite/ld-arm/thumb2-b-interwork.d3
6 files changed, 93 insertions, 142 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index c0c1204..07cd593 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,15 @@
+2009-04-22 Christophe Lyon <christophe.lyon@st.com>
+
+ PR9743
+ * elf32-arm.c (arm_type_of_stub): Handle R_ARM_THM_JUMP24,
+ R_ARM_JUMP24 and R_ARM_PLT32 relocations.
+ (elf32_arm_size_stubs): Likewise.
+ (record_thumb_to_arm_glue): Deleted unused function.
+ (bfd_elf32_arm_process_before_allocation): No longer handle
+ R_ARM_THM_JUMP24, R_ARM_JUMP24 and R_ARM_PLT32 relocations here.
+ (elf32_arm_final_link_relocate): Handle R_ARM_THM_JUMP24,
+ R_ARM_JUMP24 and R_ARM_PLT32 relocations.
+
2009-04-21 Daniel Jacobowitz <dan@codesourcery.com>
* elf32-arm.c (INTERWORK_FLAG): Check BFD_LINKER_CREATED.
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 84365c4..d94744a 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -2921,14 +2921,15 @@ arm_type_of_stub (struct bfd_link_info *info,
places. */
}
- if (r_type == R_ARM_THM_CALL)
+ if (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24)
{
/* Handle cases where:
- this call goes too far (different Thumb/Thumb2 max
distance)
- - it's a Thumb->Arm call and blx is not available. A stub is
- needed in this case, but only if this call is not through a
- PLT entry. Indeed, PLT stubs handle mode switching already.
+ - it's a Thumb->Arm call and blx is not available, or it's a
+ Thumb->Arm branch (not bl). A stub is needed in this case,
+ but only if this call is not through a PLT entry. Indeed,
+ PLT stubs handle mode switching already.
*/
if ((!thumb2
&& (branch_offset > THM_MAX_FWD_BRANCH_OFFSET
@@ -2937,7 +2938,8 @@ arm_type_of_stub (struct bfd_link_info *info,
&& (branch_offset > THM2_MAX_FWD_BRANCH_OFFSET
|| (branch_offset < THM2_MAX_BWD_BRANCH_OFFSET)))
|| ((st_type != STT_ARM_TFUNC)
- && ((r_type == R_ARM_THM_CALL) && !globals->use_blx)
+ && (((r_type == R_ARM_THM_CALL) && !globals->use_blx)
+ || (r_type == R_ARM_THM_JUMP24))
&& !use_plt))
{
if (st_type == STT_ARM_TFUNC)
@@ -2947,14 +2949,19 @@ arm_type_of_stub (struct bfd_link_info *info,
{
stub_type = (info->shared | globals->pic_veneer)
/* PIC stubs. */
- ? ((globals->use_blx)
- /* V5T and above. */
+ ? ((globals->use_blx
+ && (r_type ==R_ARM_THM_CALL))
+ /* V5T and above. Stub starts with ARM code, so
+ we must be able to switch mode before
+ reaching it, which is only possible for 'bl'
+ (ie R_ARM_THM_CALL relocation). */
? arm_stub_long_branch_any_thumb_pic
/* On V4T, use Thumb code only. */
: arm_stub_long_branch_v4t_thumb_thumb_pic)
/* non-PIC stubs. */
- : ((globals->use_blx)
+ : ((globals->use_blx
+ && (r_type ==R_ARM_THM_CALL))
/* V5T and above. */
? arm_stub_long_branch_any_any
/* V4T. */
@@ -2984,14 +2991,16 @@ arm_type_of_stub (struct bfd_link_info *info,
stub_type = (info->shared | globals->pic_veneer)
/* PIC stubs. */
- ? ((globals->use_blx)
+ ? ((globals->use_blx
+ && (r_type ==R_ARM_THM_CALL))
/* V5T and above. */
? arm_stub_long_branch_any_arm_pic
/* V4T PIC stub. */
: arm_stub_long_branch_v4t_thumb_arm_pic)
/* non-PIC stubs. */
- : ((globals->use_blx)
+ : ((globals->use_blx
+ && (r_type ==R_ARM_THM_CALL))
/* V5T and above. */
? arm_stub_long_branch_any_any
/* V4T. */
@@ -3005,7 +3014,7 @@ arm_type_of_stub (struct bfd_link_info *info,
}
}
}
- else if (r_type == R_ARM_CALL)
+ else if (r_type == R_ARM_CALL || r_type == R_ARM_JUMP24 || r_type == R_ARM_PLT32)
{
if (st_type == STT_ARM_TFUNC)
{
@@ -3025,7 +3034,9 @@ arm_type_of_stub (struct bfd_link_info *info,
the mode change (bit 24 (H) of BLX encoding). */
if (branch_offset > (ARM_MAX_FWD_BRANCH_OFFSET + 2)
|| (branch_offset < ARM_MAX_BWD_BRANCH_OFFSET)
- || !globals->use_blx)
+ || ((r_type == R_ARM_CALL) && !globals->use_blx)
+ || (r_type == R_ARM_JUMP24)
+ || (r_type == R_ARM_PLT32))
{
stub_type = (info->shared | globals->pic_veneer)
/* PIC stubs. */
@@ -3769,9 +3780,12 @@ elf32_arm_size_stubs (bfd *output_bfd,
goto error_ret_free_local;
}
- /* Only look for stubs on call instructions. */
+ /* Only look for stubs on branch instructions. */
if ((r_type != (unsigned int) R_ARM_CALL)
- && (r_type != (unsigned int) R_ARM_THM_CALL))
+ && (r_type != (unsigned int) R_ARM_THM_CALL)
+ && (r_type != (unsigned int) R_ARM_JUMP24)
+ && (r_type != (unsigned int) R_ARM_THM_JUMP24)
+ && (r_type != (unsigned int) R_ARM_PLT32))
continue;
/* Now determine the call target, its name, value,
@@ -3922,11 +3936,13 @@ elf32_arm_size_stubs (bfd *output_bfd,
/* 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
- && st_type != STT_ARM_TFUNC)
+ if ( ((r_type == (unsigned int) R_ARM_THM_CALL)
+ || (r_type == (unsigned int) R_ARM_THM_JUMP24))
+ && st_type != STT_ARM_TFUNC)
sprintf (stub_entry->output_name, THUMB2ARM_GLUE_ENTRY_NAME,
sym_name);
- else if (r_type == (unsigned int) R_ARM_CALL
+ else if ( ((r_type == (unsigned int) R_ARM_CALL)
+ || (r_type == (unsigned int) R_ARM_JUMP24))
&& st_type == STT_ARM_TFUNC)
sprintf (stub_entry->output_name, ARM2THUMB_GLUE_ENTRY_NAME,
sym_name);
@@ -4276,86 +4292,6 @@ record_arm_to_thumb_glue (struct bfd_link_info * link_info,
return myh;
}
-static void
-record_thumb_to_arm_glue (struct bfd_link_info *link_info,
- struct elf_link_hash_entry *h)
-{
- const char *name = h->root.root.string;
- asection *s;
- char *tmp_name;
- struct elf_link_hash_entry *myh;
- struct bfd_link_hash_entry *bh;
- struct elf32_arm_link_hash_table *hash_table;
- bfd_vma val;
-
- hash_table = elf32_arm_hash_table (link_info);
-
- BFD_ASSERT (hash_table != NULL);
- BFD_ASSERT (hash_table->bfd_of_glue_owner != NULL);
-
- s = bfd_get_section_by_name
- (hash_table->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
-
- BFD_ASSERT (s != NULL);
-
- tmp_name = bfd_malloc ((bfd_size_type) strlen (name)
- + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1);
-
- BFD_ASSERT (tmp_name);
-
- sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name);
-
- myh = elf_link_hash_lookup
- (&(hash_table)->root, tmp_name, FALSE, FALSE, TRUE);
-
- if (myh != NULL)
- {
- /* We've already seen this guy. */
- free (tmp_name);
- return;
- }
-
- /* The only trick here is using hash_table->thumb_glue_size as the value.
- Even though the section isn't allocated yet, this is where we will be
- putting it. The +1 on the value marks that the stub has not been
- output yet - not that it is a Thumb function. */
- bh = NULL;
- val = hash_table->thumb_glue_size + 1;
- _bfd_generic_link_add_one_symbol (link_info, hash_table->bfd_of_glue_owner,
- tmp_name, BSF_GLOBAL, s, val,
- NULL, TRUE, FALSE, &bh);
-
- /* If we mark it 'Thumb', the disassembler will do a better job. */
- myh = (struct elf_link_hash_entry *) bh;
- myh->type = ELF_ST_INFO (STB_LOCAL, STT_ARM_TFUNC);
- myh->forced_local = 1;
-
- free (tmp_name);
-
-#define CHANGE_TO_ARM "__%s_change_to_arm"
-#define BACK_FROM_ARM "__%s_back_from_arm"
-
- /* Allocate another symbol to mark where we switch to Arm mode. */
- tmp_name = bfd_malloc ((bfd_size_type) strlen (name)
- + strlen (CHANGE_TO_ARM) + 1);
-
- BFD_ASSERT (tmp_name);
-
- sprintf (tmp_name, CHANGE_TO_ARM, name);
-
- bh = NULL;
- val = hash_table->thumb_glue_size + 4,
- _bfd_generic_link_add_one_symbol (link_info, hash_table->bfd_of_glue_owner,
- tmp_name, BSF_LOCAL, s, val,
- NULL, TRUE, FALSE, &bh);
-
- free (tmp_name);
-
- s->size += THUMB2ARM_GLUE_SIZE;
- hash_table->thumb_glue_size += THUMB2ARM_GLUE_SIZE;
-}
-
-
/* Allocate space for ARMv4 BX veneers. */
static void
@@ -4725,9 +4661,6 @@ bfd_elf32_arm_process_before_allocation (bfd *abfd,
/* These are the only relocation types we care about. */
if ( r_type != R_ARM_PC24
- && r_type != R_ARM_PLT32
- && r_type != R_ARM_JUMP24
- && r_type != R_ARM_THM_JUMP24
&& (r_type != R_ARM_V4BX || globals->fix_v4bx < 2))
continue;
@@ -4779,8 +4712,6 @@ bfd_elf32_arm_process_before_allocation (bfd *abfd,
switch (r_type)
{
case R_ARM_PC24:
- case R_ARM_PLT32:
- case R_ARM_JUMP24:
/* This one is a call from arm code. We need to look up
the target of the call. If it is a thumb target, we
insert glue. */
@@ -4788,16 +4719,6 @@ bfd_elf32_arm_process_before_allocation (bfd *abfd,
record_arm_to_thumb_glue (link_info, h);
break;
- case R_ARM_THM_JUMP24:
- /* This one is a call from thumb code. We look
- up the target of the call. If it is not a thumb
- target, we insert glue. */
- if (ELF_ST_TYPE (h->type) != STT_ARM_TFUNC
- && !(globals->use_blx && r_type == R_ARM_THM_CALL)
- && h->root.type != bfd_link_hash_undefweak)
- record_thumb_to_arm_glue (link_info, h);
- break;
-
default:
abort ();
}
@@ -6143,7 +6064,9 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
far away, in which case a long branch stub should be inserted. */
if ((r_type != R_ARM_ABS32 && r_type != R_ARM_REL32
&& r_type != R_ARM_ABS32_NOI && r_type != R_ARM_REL32_NOI
- && r_type != R_ARM_CALL)
+ && r_type != R_ARM_CALL
+ && r_type != R_ARM_JUMP24
+ && r_type != R_ARM_PLT32)
&& h != NULL
&& splt != NULL
&& h->plt.offset != (bfd_vma) -1)
@@ -6311,7 +6234,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
input_bfd,
h ? h->root.root.string : "(local)");
}
- else if (r_type != R_ARM_CALL)
+ else if (r_type == R_ARM_PC24)
{
/* Check for Arm calling Thumb function. */
if (sym_flags == STT_ARM_TFUNC)
@@ -6329,7 +6252,9 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
/* Check if a stub has to be inserted because the
destination is too far or we are changing mode. */
- if (r_type == R_ARM_CALL)
+ if ( r_type == R_ARM_CALL
+ || r_type == R_ARM_JUMP24
+ || r_type == R_ARM_PLT32)
{
/* If the call goes through a PLT entry, make sure to
check distance to the right destination address. */
@@ -6348,7 +6273,11 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
if (branch_offset > ARM_MAX_FWD_BRANCH_OFFSET
|| branch_offset < ARM_MAX_BWD_BRANCH_OFFSET
- || sym_flags == STT_ARM_TFUNC)
+ || ((sym_flags == STT_ARM_TFUNC)
+ && (((r_type == R_ARM_CALL) && !globals->use_blx)
+ || (r_type == R_ARM_JUMP24)
+ || (r_type == R_ARM_PLT32) ))
+ )
{
/* The target is out of reach, so redirect the
branch to the local stub for this function. */
@@ -6414,16 +6343,17 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
value = (signed_addend & howto->dst_mask)
| (bfd_get_32 (input_bfd, hit_data) & (~ howto->dst_mask));
- /* Set the H bit in the BLX instruction. */
- if (sym_flags == STT_ARM_TFUNC)
- {
- if (addend)
- value |= (1 << 24);
- else
- value &= ~(bfd_vma)(1 << 24);
- }
if (r_type == R_ARM_CALL)
{
+ /* Set the H bit in the BLX instruction. */
+ if (sym_flags == STT_ARM_TFUNC)
+ {
+ if (addend)
+ value |= (1 << 24);
+ else
+ value &= ~(bfd_vma)(1 << 24);
+ }
+
/* Select the correct instruction (BL or BLX). */
/* Only if we are not handling a BL to a stub. In this
case, mode switching is performed by the stub. */
@@ -6667,7 +6597,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
/* Convert BL to BLX. */
lower_insn = (lower_insn & ~0x1000) | 0x0800;
}
- else if (r_type != R_ARM_THM_CALL)
+ else if (( r_type != R_ARM_THM_CALL)
+ && (r_type != R_ARM_THM_JUMP24))
{
if (elf32_thumb_to_arm_stub
(info, sym_name, input_bfd, output_bfd, input_section,
@@ -6704,7 +6635,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
*unresolved_reloc_p = FALSE;
}
- if (r_type == R_ARM_THM_CALL)
+ if (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24)
{
/* Check if a stub has to be inserted because the destination
is too far. */
@@ -6724,7 +6655,9 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
(thumb2
&& (branch_offset > THM2_MAX_FWD_BRANCH_OFFSET
|| (branch_offset < THM2_MAX_BWD_BRANCH_OFFSET)))
- || ((sym_flags != STT_ARM_TFUNC) && !globals->use_blx))
+ || ((sym_flags != STT_ARM_TFUNC)
+ && (((r_type == R_ARM_THM_CALL) && !globals->use_blx)
+ || r_type == R_ARM_THM_JUMP24)))
{
/* The target is out of reach or we are changing modes, so
redirect the branch to the local stub for this
@@ -6738,7 +6671,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
+ stub_entry->stub_sec->output_section->vma);
/* If this call becomes a call to Arm, force BLX. */
- if (globals->use_blx)
+ if (globals->use_blx && (r_type == R_ARM_THM_CALL))
{
if ((stub_entry
&& !arm_stub_is_thumb (stub_entry->stub_type))
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 4e893a7..aacfffe 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2009-04-22 Christophe Lyon <christophe.lyon@st.com>
+
+ PR9743
+ * ld-arm/arm-call.d: Update expected result.
+ * ld-arm/arm-pic-veneer.d: Likewise.
+ * ld-arm/thumb2-b-interwork.d: Likewise.
+
2009-04-22 Nathan Sidwell <nathan@codesourcery.com>
* ld-scripts/rgn-at1.d: Cope with larger padding on sections.
diff --git a/ld/testsuite/ld-arm/arm-call.d b/ld/testsuite/ld-arm/arm-call.d
index 34c31d9..f4a9d78 100644
--- a/ld/testsuite/ld-arm/arm-call.d
+++ b/ld/testsuite/ld-arm/arm-call.d
@@ -10,10 +10,10 @@ Disassembly of section .text:
800c: fb00000d blx 804a <t5>
8010: fa00000a blx 8040 <t1>
8014: fb000009 blx 8042 <t2>
- 8018: ea00000f b 805c <__t1_from_arm>
- 801c: ea000010 b 8064 <__t2_from_arm>
- 8020: 1b00000d blne 805c <__t1_from_arm>
- 8024: 1b00000e blne 8064 <__t2_from_arm>
+ 8018: ea000012 b 8068 <__t1_from_arm>
+ 801c: ea00000f b 8060 <__t2_from_arm>
+ 8020: 1b000010 blne 8068 <__t1_from_arm>
+ 8024: 1b00000d blne 8060 <__t2_from_arm>
8028: 1b000003 blne 803c <arm>
802c: eb000002 bl 803c <arm>
8030: faffffff blx 8034 <thumblocal>
@@ -46,11 +46,13 @@ Disassembly of section .text:
8050: f7ff fff1 bl 8036 <t3>
8054: f7ff efd4 blx 8000 <_start>
8058: f7ff efd2 blx 8000 <_start>
+ 805c: 0000 lsls r0, r0, #0
+ ...
-0000805c <__t1_from_arm>:
- 805c: e51ff004 ldr pc, \[pc, #-4\] ; 8060 <__t1_from_arm\+0x4>
- 8060: 00008041 .word 0x00008041
+00008060 <__t2_from_arm>:
+ 8060: e51ff004 ldr pc, \[pc, #-4\] ; 8064 <__t2_from_arm\+0x4>
+ 8064: 00008043 .word 0x00008043
-00008064 <__t2_from_arm>:
- 8064: e51ff004 ldr pc, \[pc, #-4\] ; 8068 <__t2_from_arm\+0x4>
- 8068: 00008043 .word 0x00008043
+00008068 <__t1_from_arm>:
+ 8068: e51ff004 ldr pc, \[pc, #-4\] ; 806c <__t1_from_arm\+0x4>
+ 806c: 00008041 .word 0x00008041
diff --git a/ld/testsuite/ld-arm/arm-pic-veneer.d b/ld/testsuite/ld-arm/arm-pic-veneer.d
index 97eeb52..d3a8cf6 100644
--- a/ld/testsuite/ld-arm/arm-pic-veneer.d
+++ b/ld/testsuite/ld-arm/arm-pic-veneer.d
@@ -12,6 +12,6 @@ Disassembly of section .text:
00008008 <__foo_from_arm>:
8008: e59fc004 ldr ip, \[pc, #4\] ; 8014 <__foo_from_arm\+0xc>
- 800c: e08cc00f add ip, ip, pc
+ 800c: e08fc00c add ip, pc, ip
8010: e12fff1c bx ip
8014: fffffff1 .word 0xfffffff1
diff --git a/ld/testsuite/ld-arm/thumb2-b-interwork.d b/ld/testsuite/ld-arm/thumb2-b-interwork.d
index 00bc4d4..b2f9a01 100644
--- a/ld/testsuite/ld-arm/thumb2-b-interwork.d
+++ b/ld/testsuite/ld-arm/thumb2-b-interwork.d
@@ -8,12 +8,9 @@ Disassembly of section .text:
00008004 <bar>:
8004: e12fff1e bx lr
-Disassembly of section .glue_7t:
00008008 <__bar_from_thumb>:
8008: 4778 bx pc
800a: 46c0 nop \(mov r8, r8\)
-
-0000800c <__bar_change_to_arm>:
800c: eafffffc b 8004 <bar>