aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-arm.c
diff options
context:
space:
mode:
authorPaul Brook <paul@codesourcery.com>2005-12-12 17:03:40 +0000
committerPaul Brook <paul@codesourcery.com>2005-12-12 17:03:40 +0000
commit39b41c9ca83ec4e504d90bd6e2137e67a27585e2 (patch)
treef013eec4e858d0da7385c4b83ce0181227ede26c /bfd/elf32-arm.c
parent4970f871a701ce55f5018f31bca1b478448c57ff (diff)
downloadgdb-39b41c9ca83ec4e504d90bd6e2137e67a27585e2.zip
gdb-39b41c9ca83ec4e504d90bd6e2137e67a27585e2.tar.gz
gdb-39b41c9ca83ec4e504d90bd6e2137e67a27585e2.tar.bz2
2005-12-12 Paul Brook <paul@codesourcery.com>
bfd/ * bfd-in2.h: Regenerate. * elf32-arm.c (elf32_arm_reloc_map): Add BFD_RELOC_ARM_PCREL_CALL and BFD_RELOC_ARM_PCREL_JUMP. (check_use_blx): New function. (bfd_elf32_arm_process_before_allocation): Don't allocate glue if using BLX. (elf32_arm_final_link_relocate): Perform bl<->blx conversion for R_ARM_CALL and R_ARM_THM. (elf32_arm_get_eabi_attr_int): New function. (elf32_arm_size_dynamic_sections): Call check_use_blx. * libbfd.h: Regenerate. * reloc.c: Add BFD_RELOC_ARM_PCREL_CALL and BFD_RELOC_ARM_PCREL_JUMP. gas/ * config/tc-arm.c (do_branch): Generate EABI branch relocations. (do_bl): New function. (do_blx): Generate BFD_RELOC_ARM_PCREL_CALL relocation. (do_t_blx): Generate BFD_RELOC_THUMB_PCREL_BRANCH23. (insns): Use do_bl. (md_pcrel_from_section): Add BFD_RELOC_ARM_PCREL_CALL and BFD_RELOC_ARM_PCREL_JUMP. (md_apply_fix): Merge BFD_RELOC_ARM_PCREL_BRANCH and BFD_RELOC_ARM_PCREL_BLX cases. Handle BFD_RELOC_ARM_PCREL_CALL and BFD_RELOC_ARM_PCREL_JUMP. (tc_gen_reloc): Handle BFD_RELOC_ARM_PCREL_CALL and BFD_RELOC_ARM_PCREL_JUMP. gas/testsuite/ * gas/arm/pic.d: Allow R_ARM_CALL relocations. include/elf/ * arm.h (elf32_arm_get_eabi_attr_int): Add prototype. ld/testsuite/ * ld-arm/arm-call.d: New test. * ld-arm/arm-call1.s: New file. * ld-arm/arm-call1.s: New file. * ld-arm/arm-elf.exp: Add arm-call and mixed-app-v5. * ld-arm/arm.ld: Add .glue_7 and .ARM.attribues. * ld-arm/mixed-app-v5.d: New file. * ld-arm/mixed-app.r: Tweak expected output.
Diffstat (limited to 'bfd/elf32-arm.c')
-rw-r--r--bfd/elf32-arm.c97
1 files changed, 76 insertions, 21 deletions
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 6f220e9..d9648af 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -1297,6 +1297,8 @@ static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] =
{
{BFD_RELOC_NONE, R_ARM_NONE},
{BFD_RELOC_ARM_PCREL_BRANCH, R_ARM_PC24},
+ {BFD_RELOC_ARM_PCREL_CALL, R_ARM_CALL},
+ {BFD_RELOC_ARM_PCREL_JUMP, R_ARM_JUMP24},
{BFD_RELOC_ARM_PCREL_BLX, R_ARM_XPC25},
{BFD_RELOC_THUMB_PCREL_BLX, R_ARM_THM_XPC22},
{BFD_RELOC_32, R_ARM_ABS32},
@@ -2285,6 +2287,12 @@ bfd_elf32_arm_get_bfd_for_interworking (bfd *abfd, struct bfd_link_info *info)
return TRUE;
}
+static void check_use_blx(struct elf32_arm_link_hash_table *globals)
+{
+ if (elf32_arm_get_eabi_attr_int (globals->obfd, Tag_CPU_arch) > 2)
+ globals->use_blx = 1;
+}
+
bfd_boolean
bfd_elf32_arm_process_before_allocation (bfd *abfd,
struct bfd_link_info *link_info,
@@ -2306,6 +2314,7 @@ bfd_elf32_arm_process_before_allocation (bfd *abfd,
/* Here we have a bfd that is to be included on the link. We have a hook
to do reloc rummaging, before section sizes are nailed down. */
globals = elf32_arm_hash_table (link_info);
+ check_use_blx (globals);
BFD_ASSERT (globals != NULL);
BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
@@ -2403,7 +2412,8 @@ bfd_elf32_arm_process_before_allocation (bfd *abfd,
/* 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. */
- if (ELF_ST_TYPE(h->type) == STT_ARM_TFUNC)
+ if (ELF_ST_TYPE(h->type) == STT_ARM_TFUNC
+ && !(r_type == R_ARM_CALL && globals->use_blx))
record_arm_to_thumb_glue (link_info, h);
break;
@@ -2411,7 +2421,7 @@ bfd_elf32_arm_process_before_allocation (bfd *abfd,
/* 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)
+ if (ELF_ST_TYPE (h->type) != STT_ARM_TFUNC && !globals->use_blx)
record_thumb_to_arm_glue (link_info, h);
break;
@@ -3045,7 +3055,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
input_bfd,
h ? h->root.root.string : "(local)");
}
- else
+ else if (r_type != R_ARM_CALL || !globals->use_blx)
{
/* Check for Arm calling Thumb function. */
if (sym_flags == STT_ARM_TFUNC)
@@ -3101,14 +3111,30 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
return bfd_reloc_overflow;
}
- /* If necessary set the H bit in the BLX instruction. */
- if (r_type == R_ARM_XPC25 && ((value & 2) == 2))
- value = (signed_addend & howto->dst_mask)
- | (bfd_get_32 (input_bfd, hit_data) & (~ howto->dst_mask))
- | (1 << 24);
- else
- value = (signed_addend & howto->dst_mask)
- | (bfd_get_32 (input_bfd, hit_data) & (~ howto->dst_mask));
+ addend = (value & 2);
+
+ 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)
+ {
+ /* Select the correct instruction (BL or BLX). */
+ if (sym_flags == STT_ARM_TFUNC)
+ value |= (1 << 28);
+ else
+ {
+ value &= ~(bfd_vma)(1 << 28);
+ value |= (1 << 24);
+ }
+ }
break;
case R_ARM_ABS32:
@@ -3204,7 +3230,6 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
bfd_vma check;
bfd_signed_vma signed_check;
- bfd_boolean thumb_plt_call = FALSE;
/* Need to refetch the addend and squish the two 11 bit pieces
together. */
@@ -3238,13 +3263,23 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
&& (h == NULL || splt == NULL
|| h->plt.offset == (bfd_vma) -1))
{
- if (elf32_thumb_to_arm_stub
+ if (globals->use_blx)
+ {
+ /* Convert BL to BLX. */
+ lower_insn = (lower_insn & ~0x1000) | 0x0800;
+ }
+ else if (elf32_thumb_to_arm_stub
(info, sym_name, input_bfd, output_bfd, input_section,
hit_data, sym_sec, rel->r_offset, signed_addend, value))
return bfd_reloc_ok;
else
return bfd_reloc_dangerous;
}
+ else if (sym_flags == STT_ARM_TFUNC && globals->use_blx)
+ {
+ /* Make sure this is a BL. */
+ lower_insn |= 0x1800;
+ }
}
/* Handle calls via the PLT. */
@@ -3257,11 +3292,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
{
/* If the Thumb BLX instruction is available, convert the
BL to a BLX instruction to call the ARM-mode PLT entry. */
- if ((lower_insn & (0x3 << 11)) == 0x3 << 11)
- {
- lower_insn = (lower_insn & ~(0x3 << 11)) | 0x1 << 11;
- thumb_plt_call = TRUE;
- }
+ lower_insn = (lower_insn & ~0x1000) | 0x0800;
}
else
/* Target the Thumb stub before the ARM PLT entry. */
@@ -3288,9 +3319,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
if (signed_check > reloc_signed_max || signed_check < reloc_signed_min)
overflow = TRUE;
- if ((r_type == R_ARM_THM_XPC22
- && ((lower_insn & 0x1800) == 0x0800))
- || thumb_plt_call)
+ if ((lower_insn & 0x1800) == 0x0800)
/* For a BLX instruction, make sure that the relocation is rounded up
to a word boundary. This follows the semantics of the instruction
which specifies that bit 1 of the target address will come from bit
@@ -4474,6 +4503,31 @@ elf32_arm_new_eabi_attr (bfd *abfd, int tag)
return attr;
}
+int
+elf32_arm_get_eabi_attr_int (bfd *abfd, int tag)
+{
+ aeabi_attribute_list *p;
+
+ if (tag < NUM_KNOWN_ATTRIBUTES)
+ {
+ /* Knwon tags are preallocated. */
+ return elf32_arm_tdata (abfd)->known_eabi_attributes[tag].i;
+ }
+ else
+ {
+ for (p = elf32_arm_tdata (abfd)->other_eabi_attributes;
+ p;
+ p = p->next)
+ {
+ if (tag == p->tag)
+ return p->attr.i;
+ if (tag < p->tag)
+ break;
+ }
+ return 0;
+ }
+}
+
void
elf32_arm_add_eabi_attr_int (bfd *abfd, int tag, unsigned int i)
{
@@ -6381,6 +6435,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
htab = elf32_arm_hash_table (info);
dynobj = elf_hash_table (info)->dynobj;
BFD_ASSERT (dynobj != NULL);
+ check_use_blx (htab);
if (elf_hash_table (info)->dynamic_sections_created)
{