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