From 2c6d66debd0d2c63e67642d17b432d05ae98dad6 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Mon, 31 Jan 2011 22:38:24 +0000 Subject: [PATCH] * 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. --- bfd/ChangeLog | 7 +++++++ bfd/elf64-ppc.c | 33 ++++++++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index c643fb74c..35d534f0a 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2011-02-01 Alan Modra + + * 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. + 2011-01-28 Joseph Myers * elf32-ppc.c (ppc_elf_link_hash_newfunc): Initialize has_sda_refs diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 5c35dc159..d0209280c 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -10580,14 +10580,28 @@ ppc64_elf_next_input_section (struct bfd_link_info *info, asection *isec) 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_info *info, const char *name) 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) -- 2.11.4.GIT