diff options
author | Alan Modra <amodra@gmail.com> | 2011-01-31 22:38:26 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2011-01-31 22:38:26 +0000 |
commit | 6683a28dfa81c11b68c50228b4a8bbd99d931754 (patch) | |
tree | 32b182949c0ebc5299cb37193327d5432f171496 /bfd/elf64-ppc.c | |
parent | d3f0f8534198879e5fdc771d517dc3286fc53516 (diff) | |
download | gdb-6683a28dfa81c11b68c50228b4a8bbd99d931754.zip gdb-6683a28dfa81c11b68c50228b4a8bbd99d931754.tar.gz gdb-6683a28dfa81c11b68c50228b4a8bbd99d931754.tar.bz2 |
* 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.
Diffstat (limited to 'bfd/elf64-ppc.c')
-rw-r--r-- | bfd/elf64-ppc.c | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 5c35dc1..d020928 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) |