aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-arm.c
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2009-02-24 22:43:10 +0000
committerDaniel Jacobowitz <drow@false.org>2009-02-24 22:43:10 +0000
commit07d72278cd2622807aca8bf84f06667bb1c4df96 (patch)
tree5bc3bddcb4767775cc2b58e2c700f0a16572066c /bfd/elf32-arm.c
parent2509a395cb1b6f6dd5b72f84d80693eaff977d31 (diff)
downloadgdb-07d72278cd2622807aca8bf84f06667bb1c4df96.zip
gdb-07d72278cd2622807aca8bf84f06667bb1c4df96.tar.gz
gdb-07d72278cd2622807aca8bf84f06667bb1c4df96.tar.bz2
2009-02-24 Joseph Myers <joseph@codesourcery.com>
bfd/ * elf32-arm.c (PREV_SEC): Update comment. (group_sections): Rename argument to stubs_always_after_branch. Reverse the list and place stubs at the end of input sections. Undefine NEXT_SEC. (elf32_arm_size_stubs): Update to use stubs_always_after_branch. ld/ * ld.texinfo (ARM): Document changed meaning of --stub-group-size. * emultempl/armelf.em (hook_in_stub): Insert after the input section. (elf32_arm_add_stub_section): Update comment. (PARSE_AND_LIST_OPTIONS): Update help for --stub-group-size. 2009-02-24 Daniel Jacobowitz <dan@codesourcery.com> ld/testsuite/ * ld-arm/arm-elf.exp (armeabitests): Update duplicate test names. Use normal output files for big-endian. * ld-arm/farcall-arm-arm-be.d, ld-arm/farcall-thumb-arm-be.d: Delete. * ld-arm/farcall-arm-arm-be8.d, ld-arm/farcall-arm-arm-pic-veneer.d, ld-arm/farcall-arm-arm.d, ld-arm/farcall-arm-thumb-blx-pic-veneer.d, ld-arm/farcall-arm-thumb-blx.d, ld-arm/farcall-arm-thumb-pic-veneer.d, ld-arm/farcall-arm-thumb.d, ld-arm/farcall-group-size2.d, ld-arm/farcall-group.d, ld-arm/farcall-mix.d, ld-arm/farcall-mix2.d, ld-arm/farcall-thumb-arm-be8.d, ld-arm/farcall-thumb-arm-blx-pic-veneer.d, ld-arm/farcall-thumb-arm-blx.d, ld-arm/farcall-thumb-arm-short.d, ld-arm/farcall-thumb-arm.d, ld-arm/farcall-thumb-thumb-blx-pic-veneer.d, ld-arm/farcall-thumb-thumb-blx.d, ld-arm/farcall-thumb-thumb-m.d, ld-arm/farcall-thumb-thumb.d, ld-arm/thumb2-bl-as-thumb1-bad.d, ld-arm/thumb2-bl-bad.d: Update for moved stubs.
Diffstat (limited to 'bfd/elf32-arm.c')
-rw-r--r--bfd/elf32-arm.c76
1 files changed, 48 insertions, 28 deletions
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 9f4911c..8424322 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -3417,7 +3417,7 @@ elf32_arm_next_input_section (struct bfd_link_info *info,
/* Steal the link_sec pointer for our list. */
#define PREV_SEC(sec) (htab->stub_group[(sec)->id].link_sec)
/* This happens to make the list in reverse order,
- which is what we want. */
+ which we reverse later. */
PREV_SEC (isec) = *list;
*list = isec;
}
@@ -3426,7 +3426,7 @@ elf32_arm_next_input_section (struct bfd_link_info *info,
/* See whether we can group stub sections together. Grouping stub
sections may result in fewer stubs. More importantly, we need to
- put all .init* and .fini* stubs at the beginning of the .init or
+ put all .init* and .fini* stubs at the end of the .init or
.fini output sections respectively, because glibc splits the
_init and _fini functions into multiple parts. Putting a stub in
the middle of a function is not a good idea. */
@@ -3434,66 +3434,86 @@ elf32_arm_next_input_section (struct bfd_link_info *info,
static void
group_sections (struct elf32_arm_link_hash_table *htab,
bfd_size_type stub_group_size,
- bfd_boolean stubs_always_before_branch)
+ bfd_boolean stubs_always_after_branch)
{
- asection **list = htab->input_list + htab->top_index;
+ asection **list = htab->input_list;
do
{
asection *tail = *list;
+ asection *head;
+ asection *tp;
if (tail == bfd_abs_section_ptr)
continue;
- while (tail != NULL)
+ /* Reverse the list: we must avoid placing stubs at the
+ beginning of the section because the beginning of the text
+ section may be required for an interrupt vector in bare metal
+ code. */
+#define NEXT_SEC PREV_SEC
+ head = tail;
+ tp = NULL;
+ for (;;)
+ {
+ asection *h = PREV_SEC (head);
+ NEXT_SEC (head) = tp;
+ if (h == NULL)
+ break;
+ tp = head;
+ head = h;
+ }
+
+ while (head != NULL)
{
asection *curr;
- asection *prev;
+ asection *next;
bfd_size_type total;
- curr = tail;
- total = tail->size;
- while ((prev = PREV_SEC (curr)) != NULL
- && ((total += curr->output_offset - prev->output_offset)
+ curr = head;
+ total = head->size;
+ while ((next = NEXT_SEC (curr)) != NULL
+ && ((total += next->output_offset - curr->output_offset)
< stub_group_size))
- curr = prev;
+ curr = next;
- /* OK, the size from the start of CURR to the end is less
+ /* OK, the size from the start to the start of CURR is less
than stub_group_size and thus can be handled by one stub
- section. (Or the tail section is itself larger than
+ section. (Or the head section is itself larger than
stub_group_size, in which case we may be toast.)
We should really be keeping track of the total size of
stubs added here, as stubs contribute to the final output
section size. */
do
{
- prev = PREV_SEC (tail);
+ next = NEXT_SEC (head);
/* Set up this stub group. */
- htab->stub_group[tail->id].link_sec = curr;
+ htab->stub_group[head->id].link_sec = curr;
}
- while (tail != curr && (tail = prev) != NULL);
+ while (head != curr && (head = next) != NULL);
/* But wait, there's more! Input sections up to stub_group_size
- bytes before the stub section can be handled by it too. */
- if (!stubs_always_before_branch)
+ bytes after the stub section can be handled by it too. */
+ if (!stubs_always_after_branch)
{
total = 0;
- while (prev != NULL
- && ((total += tail->output_offset - prev->output_offset)
+ while (next != NULL
+ && ((total += next->output_offset - head->output_offset)
< stub_group_size))
{
- tail = prev;
- prev = PREV_SEC (tail);
- htab->stub_group[tail->id].link_sec = curr;
+ head = next;
+ next = NEXT_SEC (head);
+ htab->stub_group[head->id].link_sec = curr;
}
}
- tail = prev;
+ head = next;
}
}
- while (list-- != htab->input_list);
+ while (list++ != htab->input_list + htab->top_index);
free (htab->input_list);
#undef PREV_SEC
+#undef NEXT_SEC
}
/* Determine and set the size of the stub section for a final link.
@@ -3511,7 +3531,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
void (*layout_sections_again) (void))
{
bfd_size_type stub_group_size;
- bfd_boolean stubs_always_before_branch;
+ bfd_boolean stubs_always_after_branch;
bfd_boolean stub_changed = 0;
struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
@@ -3524,7 +3544,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
htab->stub_bfd = stub_bfd;
htab->add_stub_section = add_stub_section;
htab->layout_sections_again = layout_sections_again;
- stubs_always_before_branch = group_size < 0;
+ stubs_always_after_branch = group_size < 0;
if (group_size < 0)
stub_group_size = -group_size;
else
@@ -3544,7 +3564,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
stub_group_size = 4170000;
}
- group_sections (htab, stub_group_size, stubs_always_before_branch);
+ group_sections (htab, stub_group_size, stubs_always_after_branch);
while (1)
{