This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
powerpc64 ld "sibling call" error
- From: Alan Modra <amodra at gmail dot com>
- To: binutils at sourceware dot org
- Date: Tue, 1 Feb 2011 09:17:30 +1030
- Subject: 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