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]

powerpc64 ld "sibling call" error


This patch fixes an error seen when compiling current gcc for
powerpc64, using -mcmodel=small -mno-minimal-toc.  A typical error
looks like:

libbackend.a(cse.o)(.text.unlikely+0x60):âsiblingâcallâoptimizationâto
`.opd'âdoesânotâallowâautomaticâmultiple TOCs; recompileâwith
-mminimal-tocâorâ-fno-optimize-sibling-calls,âor makeâ`.opd' extern

The error is quite confusing since the calls involved aren't sibling
calls, and the proper function name isn't given for a local function.
I haven't fixed the error message because ld shouldn't be getting
there anyway..

What's really happening is that we have a local function call from one
section to another section in the same object file, with the two
sections being assigned different toc groups.  The first section
doesn't actually use the toc; ld erroneously decided it could belong
to any toc group, but that isn't true for a section that makes local 
calls.

Committed mainline and 2.21 branch.

	* elf64-ppc.c (ppc64_elf_next_input_section): Use elf_gp value
	for toc pointer on any section having makes_toc_func_call set.
	(check_pasted_section): Ensure pasted .init/.fini fragments use
	the same toc if any has makes_toc_func_call set.

Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.339
diff -u -p -r1.339 elf64-ppc.c
--- bfd/elf64-ppc.c	25 Oct 2010 15:54:15 -0000	1.339
+++ bfd/elf64-ppc.c	31 Jan 2011 22:10:04 -0000
@@ -10580,14 +10580,28 @@ ppc64_elf_next_input_section (struct bfd
 	  if (elf_gp (isec->owner) != 0)
 	    htab->toc_curr = elf_gp (isec->owner);
 	}
-      else if (!isec->call_check_done
-	       && toc_adjusting_stub_needed (info, isec) < 0)
-	return FALSE;
+      else
+	{
+	  if (!isec->call_check_done
+	      && toc_adjusting_stub_needed (info, isec) < 0)
+	    return FALSE;
+	  /* If we make a local call from this section, ie. a branch
+	     without a following nop, then we have no place to put a
+	     toc restoring insn.  We must use the same toc group as
+	     the callee.
+	     Testing makes_toc_func_call actually tests for *any*
+	     calls to functions that need a good toc pointer.  A more
+	     precise test would be better, as this one will set
+	     incorrect values for pasted .init/.fini fragments.
+	     (Fixed later in check_pasted_section.)  */
+	  if (isec->makes_toc_func_call
+	      && 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.
-     Use the last TOC base.  This happens to make _init and _fini
-     pasting work, because the fragments generally don't use the TOC.  */
+     Use the last TOC base.  */
   htab->stub_group[isec->id].toc_off = htab->toc_curr;
   return TRUE;
 }
@@ -10614,6 +10628,15 @@ check_pasted_section (struct bfd_link_in
 	    else if (toc_off != htab->stub_group[i->id].toc_off)
 	      return FALSE;
 	  }
+
+      if (toc_off == 0)
+	for (i = o->map_head.s; i != NULL; i = i->map_head.s)
+	  if (i->makes_toc_func_call)
+	    {
+	      toc_off = htab->stub_group[i->id].toc_off;
+	      break;
+	    }
+
       /* Make sure the whole pasted function uses the same toc offset.  */
       if (toc_off != 0)
 	for (i = o->map_head.s; i != NULL; i = i->map_head.s)

-- 
Alan Modra
Australia Development Lab, IBM


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