aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog8
-rw-r--r--bfd/elf64-ppc.c20
2 files changed, 21 insertions, 7 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 6fb242c..bf95751 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,11 @@
+2016-06-27 Alan Modra <amodra@gmail.com>
+
+ PR ld/19264
+ * elf64-ppc.c (STUB_SHRINK_ITER): Define.
+ (ppc64_elf_size_stubs): Exit stub sizing loop past STUB_SHRINK_ITER
+ if shrinking stubs.
+ (ppc64_elf_size_stubs): Adjust to suit.
+
2016-06-27 Trevor Saunders <tbsaunde+binutils@tbsaunde.org>
* elf32-dlx.h: New file.
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 70fa5c3..e06b576 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -12185,6 +12185,13 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
if (!group_sections (info, stub_group_size, stubs_always_before_branch))
return FALSE;
+#define STUB_SHRINK_ITER 20
+ /* Loop until no stubs added. After iteration 20 of this loop we may
+ exit on a stub section shrinking. This is to break out of a
+ pathological case where adding stubs on one iteration decreases
+ section gaps (perhaps due to alignment), which then requires
+ fewer or smaller stubs on the next iteration. */
+
while (1)
{
bfd *input_bfd;
@@ -12566,11 +12573,11 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
stub_sec != NULL;
stub_sec = stub_sec->next)
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0
- && stub_sec->rawsize != stub_sec->size)
+ && stub_sec->rawsize != stub_sec->size
+ && (htab->stub_iteration <= STUB_SHRINK_ITER
+ || stub_sec->rawsize < stub_sec->size))
break;
- /* Exit from this loop when no stubs have been added, and no stubs
- have changed size. */
if (stub_sec == NULL
&& (htab->glink_eh_frame == NULL
|| htab->glink_eh_frame->rawsize == htab->glink_eh_frame->size))
@@ -12901,9 +12908,6 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
stub_sec->contents = bfd_zalloc (htab->params->stub_bfd, stub_sec->size);
if (stub_sec->contents == NULL)
return FALSE;
- /* We want to check that built size is the same as calculated
- size. rawsize is a convenient location to use. */
- stub_sec->rawsize = stub_sec->size;
stub_sec->size = 0;
}
@@ -13092,7 +13096,9 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
{
stub_sec_count += 1;
- if (stub_sec->rawsize != stub_sec->size)
+ if (stub_sec->rawsize != stub_sec->size
+ && (htab->stub_iteration <= STUB_SHRINK_ITER
+ || stub_sec->rawsize < stub_sec->size))
break;
}