PowerPC64, correct grouping of stubs for ld.bfd

Like 57f6d32d, this patch ensures that sections containing external
conditional branches limit the group size.

	* elf64-ppc.c (group_sections): Delete stub14_group_size.  Instead,
	track max group size with a new "group_size" var that is reduced
	by a factor of 1024 from the 24-bit branch size whenever a 14-bit
	branch is seen.
This commit is contained in:
Alan Modra
2016-08-30 21:02:58 +09:30
parent 3e8c34ea9d
commit 09f9271771
2 changed files with 26 additions and 24 deletions

View File

@ -1,3 +1,10 @@
2016-08-31 Alan Modra <amodra@gmail.com>
* elf64-ppc.c (group_sections): Delete stub14_group_size. Instead,
track max group size with a new "group_size" var that is reduced
by a factor of 1024 from the 24-bit branch size whenever a 14-bit
branch is seen.
2016-08-31 Alan Modra <amodra@gmail.com> 2016-08-31 Alan Modra <amodra@gmail.com>
* elf32-ppc.c (ppc_elf_section_processing): Delete. * elf32-ppc.c (ppc_elf_section_processing): Delete.

View File

@ -12049,7 +12049,6 @@ group_sections (struct bfd_link_info *info,
{ {
struct ppc_link_hash_table *htab; struct ppc_link_hash_table *htab;
asection *osec; asection *osec;
bfd_size_type stub14_group_size;
bfd_boolean suppress_size_errors; bfd_boolean suppress_size_errors;
htab = ppc_hash_table (info); htab = ppc_hash_table (info);
@ -12057,20 +12056,13 @@ group_sections (struct bfd_link_info *info,
return FALSE; return FALSE;
suppress_size_errors = FALSE; suppress_size_errors = FALSE;
stub14_group_size = stub_group_size >> 10;
if (stub_group_size == 1) if (stub_group_size == 1)
{ {
/* Default values. */ /* Default values. */
if (stubs_always_before_branch) if (stubs_always_before_branch)
{
stub_group_size = 0x1e00000; stub_group_size = 0x1e00000;
stub14_group_size = 0x7800;
}
else else
{
stub_group_size = 0x1c00000; stub_group_size = 0x1c00000;
stub14_group_size = 0x7000;
}
suppress_size_errors = TRUE; suppress_size_errors = TRUE;
} }
@ -12090,12 +12082,15 @@ group_sections (struct bfd_link_info *info,
bfd_boolean big_sec; bfd_boolean big_sec;
bfd_vma curr_toc; bfd_vma curr_toc;
struct map_stub *group; struct map_stub *group;
bfd_size_type group_size;
curr = tail; curr = tail;
total = tail->size; total = tail->size;
big_sec = total > (ppc64_elf_section_data (tail) != NULL group_size = (ppc64_elf_section_data (tail) != NULL
&& ppc64_elf_section_data (tail)->has_14bit_branch && ppc64_elf_section_data (tail)->has_14bit_branch
? stub14_group_size : stub_group_size); ? stub_group_size >> 10 : stub_group_size);
big_sec = total > group_size;
if (big_sec && !suppress_size_errors) if (big_sec && !suppress_size_errors)
(*_bfd_error_handler) (_("%B section %A exceeds stub group size"), (*_bfd_error_handler) (_("%B section %A exceeds stub group size"),
tail->owner, tail); tail->owner, tail);
@ -12105,20 +12100,20 @@ group_sections (struct bfd_link_info *info,
&& ((total += curr->output_offset - prev->output_offset) && ((total += curr->output_offset - prev->output_offset)
< (ppc64_elf_section_data (prev) != NULL < (ppc64_elf_section_data (prev) != NULL
&& ppc64_elf_section_data (prev)->has_14bit_branch && ppc64_elf_section_data (prev)->has_14bit_branch
? stub14_group_size : stub_group_size)) ? (group_size = stub_group_size >> 10) : group_size))
&& htab->sec_info[prev->id].toc_off == curr_toc) && htab->sec_info[prev->id].toc_off == curr_toc)
curr = prev; curr = prev;
/* OK, the size from the start of CURR to the end is less /* OK, the size from the start of CURR to the end is less
than stub_group_size and thus can be handled by one stub than group_size and thus can be handled by one stub
section. (or the tail section is itself larger than section. (or the tail section is itself larger than
stub_group_size, in which case we may be toast.) We group_size, in which case we may be toast.) We should
should really be keeping track of the total size of stubs really be keeping track of the total size of stubs added
added here, as stubs contribute to the final output here, as stubs contribute to the final output section
section size. That's a little tricky, and this way will size. That's a little tricky, and this way will only
only break if stubs added make the total size more than break if stubs added make the total size more than 2^25,
2^25, ie. for the default stub_group_size, if stubs total ie. for the default stub_group_size, if stubs total more
more than 2097152 bytes, or nearly 75000 plt call stubs. */ than 2097152 bytes, or nearly 75000 plt call stubs. */
group = bfd_alloc (curr->owner, sizeof (*group)); group = bfd_alloc (curr->owner, sizeof (*group));
if (group == NULL) if (group == NULL)
return FALSE; return FALSE;
@ -12135,7 +12130,7 @@ group_sections (struct bfd_link_info *info,
} }
while (tail != curr && (tail = prev) != NULL); while (tail != curr && (tail = prev) != NULL);
/* But wait, there's more! Input sections up to stub_group_size /* But wait, there's more! Input sections up to group_size
bytes before the stub section can be handled by it too. bytes before the stub section can be handled by it too.
Don't do this if we have a really large section after the Don't do this if we have a really large section after the
stubs, as adding more stubs increases the chance that stubs, as adding more stubs increases the chance that
@ -12147,7 +12142,7 @@ group_sections (struct bfd_link_info *info,
&& ((total += tail->output_offset - prev->output_offset) && ((total += tail->output_offset - prev->output_offset)
< (ppc64_elf_section_data (prev) != NULL < (ppc64_elf_section_data (prev) != NULL
&& ppc64_elf_section_data (prev)->has_14bit_branch && ppc64_elf_section_data (prev)->has_14bit_branch
? stub14_group_size : stub_group_size)) ? (group_size = stub_group_size >> 10) : group_size))
&& htab->sec_info[prev->id].toc_off == curr_toc) && htab->sec_info[prev->id].toc_off == curr_toc)
{ {
tail = prev; tail = prev;