aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-arm.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2008-05-23 13:53:27 +0000
committerNick Clifton <nickc@redhat.com>2008-05-23 13:53:27 +0000
commitda5938a216697f120702fe275362302c8855c94b (patch)
tree35700ff54ab89ed2842023cf41f0c8744135b153 /bfd/elf32-arm.c
parent50ee75353252ec07aa1f062a2b409a2f6eb0d48d (diff)
downloadgdb-da5938a216697f120702fe275362302c8855c94b.zip
gdb-da5938a216697f120702fe275362302c8855c94b.tar.gz
gdb-da5938a216697f120702fe275362302c8855c94b.tar.bz2
bfd/
* elf32-arm.c (arm_type_of_stub): Ignore STT_SECTION symbols. (elf32_arm_stub_add_mapping_symbol): Remove. (elf32_arm_add_stub): Don't generate mapping symbols. Change prototype. (elf32_arm_size_stubs): Use new elf32_arm_add_stub prototype. Don't generate thumb to arm glue for calls. (arm_map_one_stub): Define. (elf32_arm_output_arch_local_syms): Generate mapping symbols for long calls stubs. ld/testsuite/ * ld-arm/farcall-arm-arm.s: Force function type on 'bar'. * ld-arm/farcall-thumb-arm.s: Likewise. * ld-arm/farcall-thumb-arm-blx.d: Fix encoding. * ld-arm/farcall-thumb-arm.d: Likewise. * ld-arm/farcall-thumb-arm-blx-pic-veneer.d: Likewise. * ld-arm/arm-elf.exp (armelftests): Add farcall-mix, farcall-mix2, farcall-group-default, farcall-group-size2, farcall-section Ignore gas warnings in farcall-thumb-arm, farcall-thumb-arm-blx, farcall-thumb-arm-blx-pic-veneer.
Diffstat (limited to 'bfd/elf32-arm.c')
-rw-r--r--bfd/elf32-arm.c150
1 files changed, 98 insertions, 52 deletions
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 2f10f02..548dfc0 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -2233,9 +2233,9 @@ struct elf32_arm_link_hash_entry
symbols with Arm stubs. */
struct elf_link_hash_entry *export_glue;
- /* A pointer to the most recently used stub hash entry against this
+ /* A pointer to the most recently used stub hash entry against this
symbol. */
- struct elf32_arm_stub_hash_entry *stub_cache;
+ struct elf32_arm_stub_hash_entry *stub_cache;
};
/* Traverse an arm ELF linker hash table. */
@@ -2731,6 +2731,11 @@ arm_type_of_stub (struct bfd_link_info *info,
int thumb_only;
enum elf32_arm_stub_type stub_type = arm_stub_none;
+ /* We don't know the actual type of destination in case it is of
+ type STT_SECTION: give up */
+ if (st_type == STT_SECTION)
+ return stub_type;
+
globals = elf32_arm_hash_table (info);
thumb_only = using_thumb_only (globals);
@@ -2915,33 +2920,13 @@ elf32_arm_get_stub_entry (const asection *input_section,
return stub_entry;
}
-static void elf32_arm_stub_add_mapping_symbol (struct bfd_link_info * link_info,
- asection *stub_sec,
- char* name,
- bfd_vma val)
-{
- struct bfd_link_hash_entry * bh = NULL;
- struct elf_link_hash_entry * myh;
-
- _bfd_generic_link_add_one_symbol (link_info,
- stub_sec->owner, name,
- BSF_LOCAL, stub_sec, stub_sec->size + val,
- NULL, TRUE, FALSE, &bh);
-
- myh = (struct elf_link_hash_entry *) bh;
- myh->type = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE);
- myh->forced_local = 1;
-}
-
/* Add a new stub entry to the stub hash. Not all fields of the new
stub entry are initialised. */
static struct elf32_arm_stub_hash_entry *
elf32_arm_add_stub (const char *stub_name,
asection *section,
- struct elf32_arm_link_hash_table *htab,
- struct bfd_link_info * link_info,
- enum elf32_arm_stub_type stub_type)
+ struct elf32_arm_link_hash_table *htab)
{
asection *link_sec;
asection *stub_sec;
@@ -2989,33 +2974,6 @@ elf32_arm_add_stub (const char *stub_name,
stub_entry->stub_offset = 0;
stub_entry->id_sec = link_sec;
- switch (stub_type)
- {
- case arm_stub_long_branch:
- elf32_arm_stub_add_mapping_symbol (link_info, stub_sec, "$a", 0);
- elf32_arm_stub_add_mapping_symbol (link_info, stub_sec, "$d", 4);
- break;
- case arm_thumb_v4t_stub_long_branch:
- elf32_arm_stub_add_mapping_symbol (link_info, stub_sec, "$a", 0);
- elf32_arm_stub_add_mapping_symbol (link_info, stub_sec, "$d", 8);
- break;
- case arm_thumb_thumb_stub_long_branch:
- elf32_arm_stub_add_mapping_symbol (link_info, stub_sec, "$t", 0);
- elf32_arm_stub_add_mapping_symbol (link_info, stub_sec, "$d", 12);
- break;
- case arm_thumb_arm_v4t_stub_long_branch:
- elf32_arm_stub_add_mapping_symbol (link_info, stub_sec, "$t", 0);
- elf32_arm_stub_add_mapping_symbol (link_info, stub_sec, "$a", 8);
- elf32_arm_stub_add_mapping_symbol (link_info, stub_sec, "$d", 16);
- break;
- case arm_stub_pic_long_branch:
- elf32_arm_stub_add_mapping_symbol (link_info, stub_sec, "$a", 0);
- elf32_arm_stub_add_mapping_symbol (link_info, stub_sec, "$d", 8);
- break;
- default:
- BFD_FAIL ();
- }
-
return stub_entry;
}
@@ -3627,7 +3585,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
continue;
}
- stub_entry = elf32_arm_add_stub (stub_name, section, htab, info, stub_type);
+ stub_entry = elf32_arm_add_stub (stub_name, section, htab);
if (stub_entry == NULL)
{
free (stub_name);
@@ -6413,7 +6371,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
/* Convert BL to BLX. */
lower_insn = (lower_insn & ~0x1000) | 0x0800;
}
- else if (elf32_thumb_to_arm_stub
+ else if (r_type != R_ARM_THM_CALL) {
+ 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,
error_message))
@@ -6421,6 +6380,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
else
return bfd_reloc_dangerous;
}
+ }
else if (sym_flags == STT_ARM_TFUNC && globals->use_blx
&& r_type == R_ARM_THM_CALL)
{
@@ -11137,6 +11097,72 @@ elf32_arm_output_plt_map (struct elf_link_hash_entry *h, void *inf)
}
+static bfd_boolean
+arm_map_one_stub (struct bfd_hash_entry *gen_entry,
+ PTR in_arg)
+{
+ struct elf32_arm_stub_hash_entry *stub_entry;
+ struct bfd_link_info *info;
+ struct elf32_arm_link_hash_table *htab;
+ asection *stub_sec;
+ bfd_vma addr;
+
+ /* Massage our args to the form they really have. */
+ stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
+
+ output_arch_syminfo *osi = (output_arch_syminfo *) in_arg;
+ info = osi->info;
+
+ htab = elf32_arm_hash_table (info);
+ stub_sec = stub_entry->stub_sec;
+
+ /* Ensure this stub is attached to the current section being
+ processed */
+ if (stub_sec != osi->sec)
+ return TRUE;
+
+ addr = (bfd_vma)stub_entry->stub_offset;
+
+ switch(stub_entry->stub_type) {
+ case arm_stub_long_branch:
+ if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_ARM, addr))
+ return FALSE;
+ if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_DATA, addr + 4))
+ return FALSE;
+ break;
+ case arm_thumb_v4t_stub_long_branch:
+ if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_ARM, addr))
+ return FALSE;
+ if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_DATA, addr + 8))
+ return FALSE;
+ break;
+ case arm_thumb_thumb_stub_long_branch:
+ if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_THUMB, addr))
+ return FALSE;
+ if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_DATA, addr + 12))
+ return FALSE;
+ break;
+ case arm_thumb_arm_v4t_stub_long_branch:
+ if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_THUMB, addr))
+ return FALSE;
+ if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_ARM, addr + 8))
+ return FALSE;
+ if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_DATA, addr + 16))
+ return FALSE;
+ break;
+ case arm_stub_pic_long_branch:
+ if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_ARM, addr))
+ return FALSE;
+ if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_DATA, addr + 8))
+ return FALSE;
+ break;
+ default:
+ BFD_FAIL ();
+ }
+
+ return TRUE;
+}
+
/* Output mapping symbols for linker generated sections. */
static bfd_boolean
@@ -11212,6 +11238,26 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd,
elf32_arm_ouput_plt_map_sym (&osi, ARM_MAP_ARM, 0);
}
+ /* Long calls stubs. */
+ if (htab->stub_bfd && htab->stub_bfd->sections) {
+ asection* stub_sec;
+ for (stub_sec = htab->stub_bfd->sections;
+ stub_sec != NULL;
+ stub_sec = stub_sec->next) {
+
+ /* Ignore non-stub sections */
+ if (!strstr(stub_sec->name, STUB_SUFFIX))
+ continue;
+
+ osi.sec = stub_sec;
+
+ osi.sec_shndx = _bfd_elf_section_from_bfd_section
+ (output_bfd, osi.sec->output_section);
+
+ bfd_hash_traverse (&htab->stub_hash_table, arm_map_one_stub, &osi);
+ }
+ }
+
/* Finally, output mapping symbols for the PLT. */
if (!htab->splt || htab->splt->size == 0)
return TRUE;