aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf64-ppc.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2011-01-31 22:38:26 +0000
committerAlan Modra <amodra@gmail.com>2011-01-31 22:38:26 +0000
commit6683a28dfa81c11b68c50228b4a8bbd99d931754 (patch)
tree32b182949c0ebc5299cb37193327d5432f171496 /bfd/elf64-ppc.c
parentd3f0f8534198879e5fdc771d517dc3286fc53516 (diff)
downloadgdb-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.c33
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)