This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

ppc64 long branch stub error


An IBM bugzilla entry reported that the assert in ppc_build_one_stub was
being triggered, indicating that a long branch stub couldn't reach its
target.  I don't have a testcase for it, but the likely cause is that
addition of stubs changed the layout sufficiently that some of the long
branch stubs need to be replaced with plt branch stubs.  The change to
ppc64_elf_size_stubs below should fix this problem.  I've also made the
linker warn when a single input section exceeds the stub group size,
since that may lead to later relocation overflows.

	* elf64-ppc.c (ppc_build_one_stub): Replace assertion that long
	branch offset is in range with an error.  Print full stub name on
	errors.
	(ppc_size_one_stub): Print full stub name on errors.
	(group_sections): Warn if section size exceeds group size.
	(ppc64_elf_size_stubs): Continue relaxing when stub types change.

Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.220
diff -u -p -r1.220 elf64-ppc.c
--- bfd/elf64-ppc.c	18 Aug 2005 01:28:24 -0000	1.220
+++ bfd/elf64-ppc.c	19 Sep 2005 08:23:07 -0000
@@ -8015,7 +8015,13 @@ ppc_build_one_stub (struct bfd_hash_entr
 	}
       bfd_put_32 (htab->stub_bfd, B_DOT | (off & 0x3fffffc), loc);
 
-      BFD_ASSERT (off + (1 << 25) < (bfd_vma) (1 << 26));
+      if (off + (1 << 25) >= (bfd_vma) (1 << 26))
+	{
+	  (*_bfd_error_handler) (_("long branch stub `%s' offset overflow"),
+				 stub_entry->root.string);
+	  htab->stub_error = TRUE;
+	  return FALSE;
+	}
 
       if (info->emitrelocations)
 	{
@@ -8087,7 +8093,7 @@ ppc_build_one_stub (struct bfd_hash_entr
       if (br_entry == NULL)
 	{
 	  (*_bfd_error_handler) (_("can't find branch stub `%s'"),
-				 stub_entry->root.string + 9);
+				 stub_entry->root.string);
 	  htab->stub_error = TRUE;
 	  return FALSE;
 	}
@@ -8331,7 +8337,7 @@ ppc_size_one_stub (struct bfd_hash_entry
 	  if (br_entry == NULL)
 	    {
 	      (*_bfd_error_handler) (_("can't build branch stub `%s'"),
-				     stub_entry->root.string + 9);
+				     stub_entry->root.string);
 	      htab->stub_error = TRUE;
 	      return FALSE;
 	    }
@@ -8752,7 +8758,10 @@ group_sections (struct ppc_link_hash_tab
 
 	  curr = tail;
 	  total = tail->size;
-	  big_sec = total >= stub_group_size;
+	  big_sec = total > stub_group_size;
+	  if (big_sec)
+	    (*_bfd_error_handler) (_("%B section %A exceeds stub group size"),
+				     tail->owner, tail);
 	  curr_toc = htab->stub_group[tail->id].toc_off;
 
 	  while ((prev = PREV_SEC (curr)) != NULL
@@ -8854,10 +8863,8 @@ ppc64_elf_size_stubs (bfd *output_bfd,
       bfd *input_bfd;
       unsigned int bfd_indx;
       asection *stub_sec;
-      bfd_boolean stub_changed;
 
       htab->stub_iteration += 1;
-      stub_changed = FALSE;
 
       for (input_bfd = info->input_bfds, bfd_indx = 0;
 	   input_bfd != NULL;
@@ -9106,8 +9113,6 @@ ppc64_elf_size_stubs (bfd *output_bfd,
 
 		  if (stub_entry->h != NULL)
 		    htab->stub_globals += 1;
-
-		  stub_changed = TRUE;
 		}
 
 	      /* We're done with the internal relocs, free them.  */
@@ -9125,16 +9130,14 @@ ppc64_elf_size_stubs (bfd *output_bfd,
 	    }
 	}
 
-      if (!stub_changed)
-	break;
-
-      /* OK, we've added some stubs.  Find out the new size of the
+      /* We may have added some stubs.  Find out the new size of the
 	 stub sections.  */
       for (stub_sec = htab->stub_bfd->sections;
 	   stub_sec != NULL;
 	   stub_sec = stub_sec->next)
 	if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
 	  {
+	    stub_sec->rawsize = stub_sec->size;
 	    stub_sec->size = 0;
 	    stub_sec->reloc_count = 0;
 	  }
@@ -9145,6 +9148,18 @@ ppc64_elf_size_stubs (bfd *output_bfd,
 
       bfd_hash_traverse (&htab->stub_hash_table, ppc_size_one_stub, info);
 
+      for (stub_sec = htab->stub_bfd->sections;
+	   stub_sec != NULL;
+	   stub_sec = stub_sec->next)
+	if ((stub_sec->flags & SEC_LINKER_CREATED) == 0
+	    && 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)
+	break;
+
       /* Ask the linker to do its stuff.  */
       (*htab->layout_sections_again) ();
     }

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]