Blame SOURCES/binutils-2.25.1-ppc-stub-counting.patch

d9d3dc
--- binutils.orig/bfd/elf64-ppc.c	2017-04-26 18:13:33.128533528 +0100
d9d3dc
+++ binutils-2.25.1/bfd/elf64-ppc.c	2017-04-27 08:25:36.008300396 +0100
d9d3dc
@@ -12087,6 +12087,13 @@ ppc64_elf_size_stubs (struct bfd_link_in
d9d3dc
 
d9d3dc
   group_sections (htab, stub_group_size, stubs_always_before_branch);
d9d3dc
 
d9d3dc
+#define STUB_SHRINK_ITER 20
d9d3dc
+  /* Loop until no stubs added.  After iteration 20 of this loop we may
d9d3dc
+     exit on a stub section shrinking.  This is to break out of a
d9d3dc
+     pathological case where adding stubs on one iteration decreases
d9d3dc
+     section gaps (perhaps due to alignment), which then requires
d9d3dc
+     fewer or smaller stubs on the next iteration.  */
d9d3dc
+
d9d3dc
   while (1)
d9d3dc
     {
d9d3dc
       bfd *input_bfd;
d9d3dc
@@ -12404,7 +12411,10 @@ ppc64_elf_size_stubs (struct bfd_link_in
d9d3dc
 	   stub_sec = stub_sec->next)
d9d3dc
 	if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
d9d3dc
 	  {
d9d3dc
-	    stub_sec->rawsize = stub_sec->size;
d9d3dc
+	    if (htab->stub_iteration <= STUB_SHRINK_ITER
d9d3dc
+		|| stub_sec->rawsize < stub_sec->size)
d9d3dc
+	      /* Past STUB_SHRINK_ITER, rawsize is the max size seen.  */
d9d3dc
+	      stub_sec->rawsize = stub_sec->size;
d9d3dc
 	    stub_sec->size = 0;
d9d3dc
 	    stub_sec->reloc_count = 0;
d9d3dc
 	    stub_sec->flags &= ~SEC_RELOC;
d9d3dc
@@ -12461,7 +12471,9 @@ ppc64_elf_size_stubs (struct bfd_link_in
d9d3dc
 	   stub_sec != NULL;
d9d3dc
 	   stub_sec = stub_sec->next)
d9d3dc
 	if ((stub_sec->flags & SEC_LINKER_CREATED) == 0
d9d3dc
-	    && stub_sec->rawsize != stub_sec->size)
d9d3dc
+	    && stub_sec->rawsize != stub_sec->size
d9d3dc
+	    && (htab->stub_iteration <= STUB_SHRINK_ITER
d9d3dc
+		|| stub_sec->rawsize < stub_sec->size))
d9d3dc
 	  break;
d9d3dc
 
d9d3dc
       /* Exit from this loop when no stubs have been added, and no stubs
d9d3dc
@@ -12939,7 +12951,9 @@ ppc64_elf_build_stubs (struct bfd_link_i
d9d3dc
     if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
d9d3dc
       {
d9d3dc
 	stub_sec_count += 1;
d9d3dc
-	if (stub_sec->rawsize != stub_sec->size)
d9d3dc
+	if (stub_sec->rawsize != stub_sec->size
d9d3dc
+	    && (htab->stub_iteration <= STUB_SHRINK_ITER
d9d3dc
+		|| stub_sec->rawsize < stub_sec->size))
d9d3dc
 	  break;
d9d3dc
       }
d9d3dc