powerpc stub tweaks
Alan Modra
amodra@bigpond.net.au
Tue Jun 17 09:11:00 GMT 2003
Two bug fixes, and an inprovement. One bug was that input bfds without
a toc were having elf_gp set from the previous input bfd as it appeared
on the linker command line. Linker scripts might move input sections
around, thus ppc64_elf_next_input_section should be setting elf_gp, or
just ignore these bfds as far as setting toc_curr. The other minor bug
was that calls to an absolute address always had a toc adjusting stub.
The improvement is to group input sections without regard to their
output sections. Previously, we kept a list of sections for each
output section, but there's really no need to treat say .init separately
from .text. This change may result in fewer stubs being needed.
* elf64-ppc.c (struct ppc_link_hash_table): Remove top_index. Modify
input_list.
(ppc64_elf_link_hash_table_create): Init input_list here.
(ppc64_elf_setup_section_lists): Remove code setting up input lists
per output section. Set toc_off for abs and other standard sections.
(ppc64_elf_reinit_toc): Don't set elf_gp on input bfds lacking a toc.
(ppc64_elf_next_input_section): Adjust for single input section list.
Don't set toc_curr from input bfds that haven't set elf_gp.
(group_sections): Adjust for single input section list.
Note -w used in the following diff, so formatting looks silly in places.
Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.103
diff -u -p -w -r1.103 elf64-ppc.c
--- bfd/elf64-ppc.c 17 Jun 2003 00:25:45 -0000 1.103
+++ bfd/elf64-ppc.c 17 Jun 2003 08:50:53 -0000
@@ -2773,9 +2773,8 @@ struct ppc_link_hash_table
/* Temp used when calculating TOC pointers. */
bfd_vma toc_curr;
- /* Assorted information used by ppc64_elf_size_stubs. */
- int top_index;
- asection **input_list;
+ /* List of input code sections used by ppc64_elf_size_stubs. */
+ asection *input_list;
/* Short-cuts to get to dynamic linker sections. */
asection *sgot;
@@ -3054,6 +3053,7 @@ ppc64_elf_link_hash_table_create (abfd)
htab->no_multi_toc = 0;
htab->multi_toc_needed = 0;
htab->toc_curr = 0;
+ htab->input_list = NULL;
htab->sgot = NULL;
htab->srelgot = NULL;
htab->splt = NULL;
@@ -6500,9 +6500,8 @@ ppc64_elf_setup_section_lists (output_bf
struct bfd_link_info *info;
{
bfd *input_bfd;
- int top_id, top_index;
+ int top_id, id;
asection *section;
- asection **input_list, **list;
bfd_size_type amt;
struct ppc_link_hash_table *htab = ppc_hash_table (info);
@@ -6510,7 +6509,7 @@ ppc64_elf_setup_section_lists (output_bf
return 0;
/* Find the top input section id. */
- for (input_bfd = info->input_bfds, top_id = 0;
+ for (input_bfd = info->input_bfds, top_id = 3;
input_bfd != NULL;
input_bfd = input_bfd->link_next)
{
@@ -6528,41 +6527,11 @@ ppc64_elf_setup_section_lists (output_bf
if (htab->stub_group == NULL)
return -1;
- elf_gp (output_bfd) = htab->toc_curr = ppc64_elf_toc (output_bfd);
-
- /* We can't use output_bfd->section_count here to find the top output
- section index as some sections may have been removed, and
- _bfd_strip_section_from_output doesn't renumber the indices. */
- for (section = output_bfd->sections, top_index = 0;
- section != NULL;
- section = section->next)
- {
- if (top_index < section->index)
- top_index = section->index;
- }
-
- htab->top_index = top_index;
- amt = sizeof (asection *) * (top_index + 1);
- input_list = (asection **) bfd_malloc (amt);
- htab->input_list = input_list;
- if (input_list == NULL)
- return -1;
-
- /* For sections we aren't interested in, mark their entries with a
- value we can check later. */
- list = input_list + top_index;
- do
- *list = bfd_abs_section_ptr;
- while (list-- != input_list);
-
- for (section = output_bfd->sections;
- section != NULL;
- section = section->next)
- {
- if ((section->flags & SEC_CODE) != 0)
- input_list[section->index] = NULL;
- }
+ /* Set toc_off for com, und, abs and ind sections. */
+ for (id = 0; id < 3; id++)
+ htab->stub_group[id].toc_off = TOC_BASE_OFF;
+ elf_gp (output_bfd) = htab->toc_curr = ppc64_elf_toc (output_bfd);
return 1;
}
@@ -6601,22 +6570,10 @@ ppc64_elf_reinit_toc (output_bfd, info)
struct bfd_link_info *info;
{
struct ppc_link_hash_table *htab = ppc_hash_table (info);
- bfd *ibfd;
- bfd_vma curr;
/* toc_curr tracks the TOC offset used for code sections below in
ppc64_elf_next_input_section. Start off at 0x8000. */
- htab->toc_curr = curr = TOC_BASE_OFF;
-
- /* Set the TOC base in all input bfds. Some may not have a TOC
- section and thus not be set in ppc64_elf_next_toc_section. */
- for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
- {
- if (elf_gp (ibfd) == 0)
- elf_gp (ibfd) = curr;
- else
- curr = elf_gp (ibfd);
- }
+ htab->toc_curr = TOC_BASE_OFF;
}
/* The linker repeatedly calls this function for each input section,
@@ -6631,24 +6588,21 @@ ppc64_elf_next_input_section (info, isec
{
struct ppc_link_hash_table *htab = ppc_hash_table (info);
- if (isec->output_section->index <= htab->top_index)
- {
- asection **list = htab->input_list + isec->output_section->index;
- if (*list != bfd_abs_section_ptr)
+ if ((isec->output_section->flags & SEC_CODE) != 0)
{
/* 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. */
- PREV_SEC (isec) = *list;
- *list = isec;
- }
+ PREV_SEC (isec) = htab->input_list;
+ htab->input_list = isec;
}
/* If a code section has a function that uses the TOC then we need
to use the right TOC (obviously). Also, make sure that .opd gets
the correct TOC value. */
if (isec->has_gp_reloc || (isec->flags & SEC_CODE) == 0)
+ if (elf_gp (isec->owner) != 0)
htab->toc_curr = elf_gp (isec->owner);
/* Functions that don't use the TOC can belong in any TOC group.
@@ -6670,12 +6624,7 @@ group_sections (htab, stub_group_size, s
bfd_size_type stub_group_size;
bfd_boolean stubs_always_before_branch;
{
- asection **list = htab->input_list + htab->top_index;
- do
- {
- asection *tail = *list;
- if (tail == bfd_abs_section_ptr)
- continue;
+ asection *tail = htab->input_list;
while (tail != NULL)
{
asection *curr;
@@ -6693,7 +6642,10 @@ group_sections (htab, stub_group_size, s
curr_toc = htab->stub_group[tail->id].toc_off;
while ((prev = PREV_SEC (curr)) != NULL
- && ((total += curr->output_offset - prev->output_offset)
+ && ((total += (curr->output_section->vma
+ + curr->output_offset
+ - prev->output_section->vma
+ - prev->output_offset))
< stub_group_size)
&& htab->stub_group[prev->id].toc_off == curr_toc)
curr = prev;
@@ -6725,7 +6677,10 @@ group_sections (htab, stub_group_size, s
{
total = 0;
while (prev != NULL
- && ((total += tail->output_offset - prev->output_offset)
+ && ((total += (tail->output_section->vma
+ + tail->output_offset
+ - prev->output_section->vma
+ - prev->output_offset))
< stub_group_size)
&& htab->stub_group[prev->id].toc_off == curr_toc)
{
@@ -6736,9 +6691,6 @@ group_sections (htab, stub_group_size, s
}
tail = prev;
}
- }
- while (list-- != htab->input_list);
- free (htab->input_list);
#undef PREV_SEC
}
--
Alan Modra
IBM OzLabs - Linux Technology Centre
More information about the Binutils
mailing list