diff options
author | Daniel Jacobowitz <drow@false.org> | 2009-02-24 22:43:10 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2009-02-24 22:43:10 +0000 |
commit | 07d72278cd2622807aca8bf84f06667bb1c4df96 (patch) | |
tree | 5bc3bddcb4767775cc2b58e2c700f0a16572066c /bfd/elf32-arm.c | |
parent | 2509a395cb1b6f6dd5b72f84d80693eaff977d31 (diff) | |
download | gdb-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.c | 76 |
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) { |