aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2009-08-05 12:36:14 +0000
committerNathan Sidwell <nathan@codesourcery.com>2009-08-05 12:36:14 +0000
commiteb7c4339fafb5fcc63a227bf134c0eb97e5d85f7 (patch)
tree77784cd300c5e95ea7bd5ce65a1c715d5dd795cc /bfd
parent30f8113aa76f852675280e7f1575de4c8018dea4 (diff)
downloadgdb-eb7c4339fafb5fcc63a227bf134c0eb97e5d85f7.zip
gdb-eb7c4339fafb5fcc63a227bf134c0eb97e5d85f7.tar.gz
gdb-eb7c4339fafb5fcc63a227bf134c0eb97e5d85f7.tar.bz2
bfd/
* elf32-arm.c (elf32_arm_stub_type): Add arm_stub_a8_veneer_lwm. (arm_build_one_stub): Build a8 veneers as a separate pass. (cortex_a8_erratum_scan): Add prev_num_a8_fixes and stub_changed_p parameters. Use them to check if we create a different a8 fixup than the previous pass. (elf32_arm_size_stubs): Move scope of stub_changed and prev_num_a8_fixes into main loop. (elf32_arm_build_stubs): Build a8 veneers in a second pass. ld/testsuite/ * ld-arm/cortex-a8-far-1.s: New. * ld-arm/cortex-a8-far-2.s: New. * ld-arm/cortex-a8-far.d: New. * ld-arm/arm-elf.exp: Add new test.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog11
-rw-r--r--bfd/elf32-arm.c63
2 files changed, 61 insertions, 13 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 50866fc..577918c 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,14 @@
+2009-08-05 Nathan Sidwell <nathan@codesourcery.com>
+
+ * elf32-arm.c (elf32_arm_stub_type): Add arm_stub_a8_veneer_lwm.
+ (arm_build_one_stub): Build a8 veneers as a separate pass.
+ (cortex_a8_erratum_scan): Add prev_num_a8_fixes and stub_changed_p
+ parameters. Use them to check if we create a different a8 fixup
+ than the previous pass.
+ (elf32_arm_size_stubs): Move scope of stub_changed and
+ prev_num_a8_fixes into main loop.
+ (elf32_arm_build_stubs): Build a8 veneers in a second pass.
+
2009-08-04 Alan Modra <amodra@bigpond.net.au>
* elf32-ppc.c (ppc_elf_relax_section): Correct conditions under
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 1e23626..5aba3f3 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -2228,6 +2228,8 @@ static const insn_sequence elf32_arm_stub_a8_veneer_blx[] =
enum elf32_arm_stub_type {
arm_stub_none,
DEF_STUBS
+ /* Note the first a8_veneer type */
+ arm_stub_a8_veneer_lwm = arm_stub_a8_veneer_b_cond
};
#undef DEF_STUB
@@ -3437,6 +3439,12 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
htab = elf32_arm_hash_table (info);
stub_sec = stub_entry->stub_sec;
+ if ((htab->fix_cortex_a8 < 0)
+ != (stub_entry->stub_type >= arm_stub_a8_veneer_lwm))
+ /* We have to do the a8 fixes last, as they are less aligned than
+ the other veneers. */
+ return TRUE;
+
/* Make a note of the offset within the stubs for this entry. */
stub_entry->stub_offset = stub_sec->size;
loc = stub_sec->contents + stub_entry->stub_offset;
@@ -3893,7 +3901,9 @@ cortex_a8_erratum_scan (bfd *input_bfd,
unsigned int *num_a8_fixes_p,
unsigned int *a8_fix_table_size_p,
struct a8_erratum_reloc *a8_relocs,
- unsigned int num_a8_relocs)
+ unsigned int num_a8_relocs,
+ unsigned prev_num_a8_fixes,
+ bfd_boolean *stub_changed_p)
{
asection *section;
struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
@@ -4105,7 +4115,7 @@ cortex_a8_erratum_scan (bfd *input_bfd,
if (((base_vma + i) & ~0xfff) == (target & ~0xfff))
{
- char *stub_name;
+ char *stub_name = NULL;
if (num_a8_fixes == a8_fix_table_size)
{
@@ -4115,9 +4125,28 @@ cortex_a8_erratum_scan (bfd *input_bfd,
* a8_fix_table_size);
}
- stub_name = bfd_malloc (8 + 1 + 8 + 1);
- if (stub_name != NULL)
- sprintf (stub_name, "%x:%x", section->id, i);
+ if (num_a8_fixes < prev_num_a8_fixes)
+ {
+ /* If we're doing a subsequent scan,
+ check if we've found the same fix as
+ before, and try and reuse the stub
+ name. */
+ stub_name = a8_fixes[num_a8_fixes].stub_name;
+ if ((a8_fixes[num_a8_fixes].section != section)
+ || (a8_fixes[num_a8_fixes].offset != i))
+ {
+ free (stub_name);
+ stub_name = NULL;
+ *stub_changed_p = TRUE;
+ }
+ }
+
+ if (!stub_name)
+ {
+ stub_name = bfd_malloc (8 + 1 + 8 + 1);
+ if (stub_name != NULL)
+ sprintf (stub_name, "%x:%x", section->id, i);
+ }
a8_fixes[num_a8_fixes].input_bfd = input_bfd;
a8_fixes[num_a8_fixes].section = section;
@@ -4165,10 +4194,9 @@ elf32_arm_size_stubs (bfd *output_bfd,
{
bfd_size_type stub_group_size;
bfd_boolean stubs_always_after_branch;
- bfd_boolean stub_changed = 0;
struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
struct a8_erratum_fix *a8_fixes = NULL;
- unsigned int num_a8_fixes = 0, prev_num_a8_fixes = 0, a8_fix_table_size = 10;
+ unsigned int num_a8_fixes = 0, a8_fix_table_size = 10;
struct a8_erratum_reloc *a8_relocs = NULL;
unsigned int num_a8_relocs = 0, a8_reloc_table_size = 10, i;
@@ -4223,9 +4251,10 @@ elf32_arm_size_stubs (bfd *output_bfd,
bfd *input_bfd;
unsigned int bfd_indx;
asection *stub_sec;
+ bfd_boolean stub_changed = FALSE;
+ unsigned prev_num_a8_fixes = num_a8_fixes;
num_a8_fixes = 0;
-
for (input_bfd = info->input_bfds, bfd_indx = 0;
input_bfd != NULL;
input_bfd = input_bfd->link_next, bfd_indx++)
@@ -4452,6 +4481,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
{
/* The proper stub has already been created. */
free (stub_name);
+ stub_entry->target_value = sym_value;
break;
}
@@ -4548,18 +4578,21 @@ elf32_arm_size_stubs (bfd *output_bfd,
if (htab->fix_cortex_a8)
{
/* Sort relocs which might apply to Cortex-A8 erratum. */
- qsort (a8_relocs, num_a8_relocs, sizeof (struct a8_erratum_reloc),
+ qsort (a8_relocs, num_a8_relocs,
+ sizeof (struct a8_erratum_reloc),
&a8_reloc_compare);
/* Scan for branches which might trigger Cortex-A8 erratum. */
if (cortex_a8_erratum_scan (input_bfd, info, &a8_fixes,
&num_a8_fixes, &a8_fix_table_size,
- a8_relocs, num_a8_relocs) != 0)
+ a8_relocs, num_a8_relocs,
+ prev_num_a8_fixes, &stub_changed)
+ != 0)
goto error_ret_free_local;
}
}
- if (htab->fix_cortex_a8 && num_a8_fixes != prev_num_a8_fixes)
+ if (prev_num_a8_fixes != num_a8_fixes)
stub_changed = TRUE;
if (!stub_changed)
@@ -4598,8 +4631,6 @@ elf32_arm_size_stubs (bfd *output_bfd,
/* Ask the linker to do its stuff. */
(*htab->layout_sections_again) ();
- stub_changed = FALSE;
- prev_num_a8_fixes = num_a8_fixes;
}
/* Add stubs for Cortex-A8 erratum fixes now. */
@@ -4696,6 +4727,12 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
/* Build the stubs as directed by the stub hash table. */
table = &htab->stub_hash_table;
bfd_hash_traverse (table, arm_build_one_stub, info);
+ if (htab->fix_cortex_a8)
+ {
+ /* Place the cortex a8 stubs last. */
+ htab->fix_cortex_a8 = -1;
+ bfd_hash_traverse (table, arm_build_one_stub, info);
+ }
return TRUE;
}