Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/external/gpl3/binutils/dist/bfd Bring in 2 patches from binu...
details: https://anonhg.NetBSD.org/src/rev/d8e3bc58c614
branches: trunk
changeset: 335306:d8e3bc58c614
user: christos <christos%NetBSD.org@localhost>
date: Fri Jan 02 19:50:02 2015 +0000
description:
Bring in 2 patches from binutils:
>From Alan Modra: Wed, 3 Jul 2013 11:51:56 +0930: powerpc64 call stubs:
This brings powerpc64 ld in line with gold regarding calls allowed to
go via a plt call stub or toc-adjusting stub without a following nop.
A long time ago ld allowed tail calls, but this is wrong because we'll
return to the caller's caller with the wrong toc pointer. I fixed
that for shared libraries but allowed tail calls in an executable for
some reason. Probably just muddy thinking on my part, because there's
no difference between an executable and a shared library regarding the
need to restore the toc pointer. Perhaps it was because some testcase
failed, most likely due to the g++ issue I comment on in the patch.
>From Alan Modra: 29 Aug 2014 01:22:29 +0000: PowerPC64 call lacks nop error:
Enough people accidentally or otherwise use -mcmodel=small then wonder
why a call that is local is behaving as if it is going via the PLT.
* elf64-ppc.c (ppc64_elf_relocate_section): Report a different
error for calls via a toc adjusting stub without a nop.
diffstat:
external/gpl3/binutils/dist/bfd/elf64-ppc.c | 120 +++++++++++++++++----------
1 files changed, 76 insertions(+), 44 deletions(-)
diffs (158 lines):
diff -r 323f4238db1f -r d8e3bc58c614 external/gpl3/binutils/dist/bfd/elf64-ppc.c
--- a/external/gpl3/binutils/dist/bfd/elf64-ppc.c Fri Jan 02 19:46:02 2015 +0000
+++ b/external/gpl3/binutils/dist/bfd/elf64-ppc.c Fri Jan 02 19:50:02 2015 +0000
@@ -3618,9 +3618,6 @@
struct ppc_link_hash_entry *h;
struct plt_entry *plt_ent;
- /* And the reloc addend that this was derived from. */
- bfd_vma addend;
-
/* Where this stub is being called from, or, in the case of combined
stub sections, the first input section in the group. */
asection *id_sec;
@@ -11669,7 +11666,6 @@
}
stub_entry->h = hash;
stub_entry->plt_ent = plt_ent;
- stub_entry->addend = irela->r_addend;
if (stub_entry->h != NULL)
htab->stub_globals += 1;
@@ -12910,60 +12906,96 @@
{
bfd_boolean can_plt_call = FALSE;
+ /* All of these stubs will modify r2, so there must be a
+ branch and link followed by a nop. The nop is
+ replaced by an insn to restore r2. */
if (rel->r_offset + 8 <= input_section->size)
{
- unsigned long nop;
- nop = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
- if (nop == NOP
- || nop == CROR_151515 || nop == CROR_313131)
+ unsigned long br;
+
+ br = bfd_get_32 (input_bfd,
+ contents + rel->r_offset);
+ if ((br & 1) != 0)
{
- if (h != NULL
- && (h == htab->tls_get_addr_fd
- || h == htab->tls_get_addr)
- && !htab->no_tls_get_addr_opt)
+ unsigned long nop;
+
+ nop = bfd_get_32 (input_bfd,
+ contents + rel->r_offset + 4);
+ if (nop == NOP
+ || nop == CROR_151515 || nop == CROR_313131)
{
- /* Special stub used, leave nop alone. */
+ if (h != NULL
+ && (h == htab->tls_get_addr_fd
+ || h == htab->tls_get_addr)
+ && !htab->no_tls_get_addr_opt)
+ {
+ /* Special stub used, leave nop alone. */
+ }
+ else
+ bfd_put_32 (input_bfd, LD_R2_40R1,
+ contents + rel->r_offset + 4);
+ can_plt_call = TRUE;
}
- else
- bfd_put_32 (input_bfd, LD_R2_40R1,
- contents + rel->r_offset + 4);
+ }
+ }
+
+ if (!can_plt_call && h != NULL)
+ {
+ const char *name = h->elf.root.root.string;
+
+ if (*name == '.')
+ ++name;
+
+ if (strncmp (name, "__libc_start_main", 17) == 0
+ && (name[17] == 0 || name[17] == '@'))
+ {
+ /* Allow crt1 branch to go via a toc adjusting
+ stub. Other calls that never return could do
+ the same, if we could detect such. */
can_plt_call = TRUE;
}
}
if (!can_plt_call)
{
+ /* g++ as of 20130507 emits self-calls without a
+ following nop. This is arguably wrong since we
+ have conflicting information. On the one hand a
+ global symbol and on the other a local call
+ sequence, but don't error for this special case.
+ It isn't possible to cheaply verify we have
+ exactly such a call. Allow all calls to the same
+ section. */
+ asection *code_sec = sec;
+
+ if (get_opd_info (sec) != NULL)
+ {
+ bfd_vma off = (relocation + addend
+ - sec->output_section->vma
+ - sec->output_offset);
+
+ opd_entry_value (sec, off, &code_sec, NULL, FALSE);
+ }
+ if (code_sec == input_section)
+ can_plt_call = TRUE;
+ }
+
+ if (!can_plt_call)
+ {
+
if (stub_entry->stub_type == ppc_stub_plt_call
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
- {
- /* If this is a plain branch rather than a branch
- and link, don't require a nop. However, don't
- allow tail calls in a shared library as they
- will result in r2 being corrupted. */
- unsigned long br;
- br = bfd_get_32 (input_bfd, contents + rel->r_offset);
- if (info->executable && (br & 1) == 0)
- can_plt_call = TRUE;
- else
- stub_entry = NULL;
- }
- else if (h != NULL
- && strcmp (h->elf.root.root.string,
- ".__libc_start_main") == 0)
- {
- /* Allow crt1 branch to go via a toc adjusting stub. */
- can_plt_call = TRUE;
- }
+ info->callbacks->einfo
+ (_("%P: %H: call to `%T' lacks nop, can't restore toc; "
+ "recompile with -fPIC"),
+ input_bfd, input_section, rel->r_offset, sym_name);
else
- {
- info->callbacks->einfo
- (_("%P: %H: call to `%T' lacks nop, can't restore toc; "
- "recompile with -fPIC"),
- input_bfd, input_section, rel->r_offset, sym_name);
-
- bfd_set_error (bfd_error_bad_value);
- ret = FALSE;
- }
+ info->callbacks->einfo
+ (_("%P: %H: call to `%T' lacks nop, can't restore toc; "
+ "(-mcmodel=small toc adjust stub)"),
+ input_bfd, input_section, rel->r_offset, sym_name);
+ bfd_set_error (bfd_error_bad_value);
+ ret = FALSE;
}
if (can_plt_call
Home |
Main Index |
Thread Index |
Old Index