gdb/copyright.py: Do not forget to remind about MULTIPLE_COPYRIGHT_HEADERS
[deliverable/binutils-gdb.git] / bfd / elf64-ppc.c
index 3f6bff9c7a60341d2094da3202025bc02d69ac78..293f17353cbf6fccc6248b3610663d32043f5cbe 100644 (file)
@@ -101,10 +101,10 @@ static bfd_vma opd_entry_value
 #define elf_backend_notice_as_needed         ppc64_elf_notice_as_needed
 #define elf_backend_archive_symbol_lookup     ppc64_elf_archive_symbol_lookup
 #define elf_backend_check_relocs             ppc64_elf_check_relocs
+#define elf_backend_relocs_compatible        _bfd_elf_relocs_compatible
 #define elf_backend_gc_keep                  ppc64_elf_gc_keep
 #define elf_backend_gc_mark_dynamic_ref       ppc64_elf_gc_mark_dynamic_ref
 #define elf_backend_gc_mark_hook             ppc64_elf_gc_mark_hook
-#define elf_backend_gc_sweep_hook            ppc64_elf_gc_sweep_hook
 #define elf_backend_adjust_dynamic_symbol     ppc64_elf_adjust_dynamic_symbol
 #define elf_backend_hide_symbol                      ppc64_elf_hide_symbol
 #define elf_backend_maybe_function_sym       ppc64_elf_maybe_function_sym
@@ -161,31 +161,31 @@ static bfd_vma opd_entry_value
 #define LD_R11_0R11    0xe96b0000      /* ld    %r11,xxx+16@l(%r11) */
 #define BCTR           0x4e800420      /* bctr                      */
 
-#define ADDI_R11_R11   0x396b0000      /* addi %r11,%r11,off@l  */
-#define ADDIS_R2_R2    0x3c420000      /* addis %r2,%r2,off@ha  */
-#define ADDI_R2_R2     0x38420000      /* addi  %r2,%r2,off@l   */
+#define ADDI_R11_R11   0x396b0000      /* addi %r11,%r11,off@l  */
+#define ADDIS_R2_R2    0x3c420000      /* addis %r2,%r2,off@ha  */
+#define ADDI_R2_R2     0x38420000      /* addi  %r2,%r2,off@l   */
 
-#define XOR_R2_R12_R12 0x7d826278      /* xor   %r2,%r12,%r12   */
-#define ADD_R11_R11_R2 0x7d6b1214      /* add   %r11,%r11,%r2   */
-#define XOR_R11_R12_R12        0x7d8b6278      /* xor   %r11,%r12,%r12  */
-#define ADD_R2_R2_R11  0x7c425a14      /* add   %r2,%r2,%r11    */
-#define CMPLDI_R2_0    0x28220000      /* cmpldi %r2,0          */
-#define BNECTR         0x4ca20420      /* bnectr+               */
-#define BNECTR_P4      0x4ce20420      /* bnectr+               */
+#define XOR_R2_R12_R12 0x7d826278      /* xor   %r2,%r12,%r12   */
+#define ADD_R11_R11_R2 0x7d6b1214      /* add   %r11,%r11,%r2   */
+#define XOR_R11_R12_R12        0x7d8b6278      /* xor   %r11,%r12,%r12  */
+#define ADD_R2_R2_R11  0x7c425a14      /* add   %r2,%r2,%r11    */
+#define CMPLDI_R2_0    0x28220000      /* cmpldi %r2,0          */
+#define BNECTR         0x4ca20420      /* bnectr+               */
+#define BNECTR_P4      0x4ce20420      /* bnectr+               */
 
 #define LD_R12_0R2     0xe9820000      /* ld    %r12,xxx+0(%r2) */
 #define LD_R11_0R2     0xe9620000      /* ld    %r11,xxx+0(%r2) */
-#define LD_R2_0R2      0xe8420000      /* ld    %r2,xxx+0(%r2)  */
+#define LD_R2_0R2      0xe8420000      /* ld    %r2,xxx+0(%r2)  */
 
-#define LD_R2_0R1      0xe8410000      /* ld    %r2,0(%r1)      */
-#define LD_R2_0R12     0xe84c0000      /* ld    %r2,0(%r12)     */
-#define ADD_R2_R2_R12  0x7c426214      /* add   %r2,%r2,%r12    */
+#define LD_R2_0R1      0xe8410000      /* ld    %r2,0(%r1)      */
+#define LD_R2_0R12     0xe84c0000      /* ld    %r2,0(%r12)     */
+#define ADD_R2_R2_R12  0x7c426214      /* add   %r2,%r2,%r12    */
 
-#define LIS_R2         0x3c400000      /* lis %r2,xxx@ha         */
+#define LIS_R2         0x3c400000      /* lis %r2,xxx@ha         */
 #define ADDIS_R2_R12   0x3c4c0000      /* addis %r2,%r12,xxx@ha  */
 #define ADDIS_R12_R2   0x3d820000      /* addis %r12,%r2,xxx@ha  */
 #define ADDIS_R12_R12  0x3d8c0000      /* addis %r12,%r12,xxx@ha */
-#define LD_R12_0R12    0xe98c0000      /* ld    %r12,xxx@l(%r12) */
+#define LD_R12_0R12    0xe98c0000      /* ld    %r12,xxx@l(%r12) */
 
 /* glink call stub instructions.  We enter with the index in R0.  */
 #define GLINK_CALL_STUB_SIZE (16*4)
@@ -3025,13 +3025,13 @@ ppc64_elf_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type,
 
 static const struct bfd_elf_special_section ppc64_elf_special_sections[]=
 {
-  { STRING_COMMA_LEN (".plt"),    0, SHT_NOBITS,   0 },
-  { STRING_COMMA_LEN (".sbss"),  -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
+  { STRING_COMMA_LEN (".plt"),   0, SHT_NOBITS,   0 },
+  { STRING_COMMA_LEN (".sbss"),         -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
   { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
-  { STRING_COMMA_LEN (".toc"),    0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
-  { STRING_COMMA_LEN (".toc1"),   0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+  { STRING_COMMA_LEN (".toc"),   0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+  { STRING_COMMA_LEN (".toc1"),          0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
   { STRING_COMMA_LEN (".tocbss"), 0, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
-  { NULL,                     0,  0, 0,            0 }
+  { NULL,                    0,  0, 0,            0 }
 };
 
 enum _ppc64_sec_type {
@@ -4001,9 +4001,6 @@ struct ppc_link_hash_entry
   /* Track dynamic relocs copied for this symbol.  */
   struct elf_dyn_relocs *dyn_relocs;
 
-  /* Chain of aliases referring to a weakdef.  */
-  struct ppc_link_hash_entry *weakref;
-
   /* Link between function code and descriptor symbols.  */
   struct ppc_link_hash_entry *oh;
 
@@ -4764,18 +4761,11 @@ ppc64_elf_copy_indirect_symbol (struct bfd_link_info *info,
   if (eind->oh != NULL)
     edir->oh = ppc_follow_link (eind->oh);
 
-  /* If called to transfer flags for a weakdef during processing
-     of elf_adjust_dynamic_symbol, don't copy NON_GOT_REF.
-     We clear it ourselves for ELIMINATE_COPY_RELOCS.  */
-  if (!(ELIMINATE_COPY_RELOCS
-       && eind->elf.root.type != bfd_link_hash_indirect
-       && edir->elf.dynamic_adjusted))
-    edir->elf.non_got_ref |= eind->elf.non_got_ref;
-
   if (edir->elf.versioned != versioned_hidden)
     edir->elf.ref_dynamic |= eind->elf.ref_dynamic;
   edir->elf.ref_regular |= eind->elf.ref_regular;
   edir->elf.ref_regular_nonweak |= eind->elf.ref_regular_nonweak;
+  edir->elf.non_got_ref |= eind->elf.non_got_ref;
   edir->elf.needs_plt |= eind->elf.needs_plt;
   edir->elf.pointer_equality_needed |= eind->elf.pointer_equality_needed;
 
@@ -4784,39 +4774,9 @@ ppc64_elf_copy_indirect_symbol (struct bfd_link_info *info,
      in order to simplify readonly_dynrelocs and save a field in the
      symbol hash entry, but that means dyn_relocs can't be used in any
      tests about a specific symbol, or affect other symbol flags which
-     are then tested.
-     Chain weakdefs so we can get from the weakdef back to an alias.
-     The list is circular so that we don't need to use u.weakdef as
-     well as this list to look at all aliases.  */
+     are then tested.  */
   if (eind->elf.root.type != bfd_link_hash_indirect)
-    {
-      struct ppc_link_hash_entry *cur, *add, *next;
-
-      add = eind;
-      do
-       {
-         cur = edir->weakref;
-         if (cur != NULL)
-           {
-             do
-               {
-                 /* We can be called twice for the same symbols.
-                    Don't make multiple loops.  */
-                 if (cur == add)
-                   return;
-                 cur = cur->weakref;
-               } while (cur != edir);
-           }
-         next = add->weakref;
-         if (cur != add)
-           {
-             add->weakref = edir->weakref != NULL ? edir->weakref : edir;
-             edir->weakref = add;
-           }
-         add = next;
-       } while (add != NULL && add != eind);
-      return;
-    }
+    return;
 
   /* Copy over any dynamic relocs we may have on the indirect sym.  */
   if (eind->dyn_relocs != NULL)
@@ -5473,17 +5433,8 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        h = NULL;
       else
        {
-         struct ppc_link_hash_entry *eh;
-
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
          h = elf_follow_link (h);
-         eh = (struct ppc_link_hash_entry *) h;
-
-         /* PR15323, ref flags aren't set for references in the same
-            object.  */
-         h->root.non_ir_ref_regular = 1;
-         if (eh->is_func && eh->oh != NULL)
-           eh->oh->elf.root.non_ir_ref_regular = 1;
 
          if (h == htab->elf.hgot)
            sec->has_toc_reloc = 1;
@@ -6576,8 +6527,8 @@ ppc64_elf_gc_mark_hook (asection *sec,
                     a call reloc.  Mark the function descriptor too
                     against garbage collection.  */
                  fdh->elf.mark = 1;
-                 if (fdh->elf.u.weakdef != NULL)
-                   fdh->elf.u.weakdef->mark = 1;
+                 if (fdh->elf.is_weakalias)
+                   weakdef (&fdh->elf)->mark = 1;
                  eh = fdh;
                }
 
@@ -6626,181 +6577,6 @@ ppc64_elf_gc_mark_hook (asection *sec,
   return rsec;
 }
 
-/* Update the .got, .plt. and dynamic reloc reference counts for the
-   section being removed.  */
-
-static bfd_boolean
-ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
-                        asection *sec, const Elf_Internal_Rela *relocs)
-{
-  struct ppc_link_hash_table *htab;
-  Elf_Internal_Shdr *symtab_hdr;
-  struct elf_link_hash_entry **sym_hashes;
-  struct got_entry **local_got_ents;
-  const Elf_Internal_Rela *rel, *relend;
-
-  if (bfd_link_relocatable (info))
-    return TRUE;
-
-  if ((sec->flags & SEC_ALLOC) == 0)
-    return TRUE;
-
-  elf_section_data (sec)->local_dynrel = NULL;
-
-  htab = ppc_hash_table (info);
-  if (htab == NULL)
-    return FALSE;
-
-  symtab_hdr = &elf_symtab_hdr (abfd);
-  sym_hashes = elf_sym_hashes (abfd);
-  local_got_ents = elf_local_got_ents (abfd);
-
-  relend = relocs + sec->reloc_count;
-  for (rel = relocs; rel < relend; rel++)
-    {
-      unsigned long r_symndx;
-      enum elf_ppc64_reloc_type r_type;
-      struct elf_link_hash_entry *h = NULL;
-      struct plt_entry **plt_list = NULL;
-      unsigned char tls_type = 0;
-
-      r_symndx = ELF64_R_SYM (rel->r_info);
-      r_type = ELF64_R_TYPE (rel->r_info);
-      if (r_symndx >= symtab_hdr->sh_info)
-       {
-         struct ppc_link_hash_entry *eh;
-         struct elf_dyn_relocs **pp;
-         struct elf_dyn_relocs *p;
-
-         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-         h = elf_follow_link (h);
-         eh = (struct ppc_link_hash_entry *) h;
-
-         for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
-           if (p->sec == sec)
-             {
-               /* Everything must go for SEC.  */
-               *pp = p->next;
-               break;
-             }
-       }
-
-      switch (r_type)
-       {
-       case R_PPC64_GOT_TLSLD16:
-       case R_PPC64_GOT_TLSLD16_LO:
-       case R_PPC64_GOT_TLSLD16_HI:
-       case R_PPC64_GOT_TLSLD16_HA:
-         tls_type = TLS_TLS | TLS_LD;
-         goto dogot;
-
-       case R_PPC64_GOT_TLSGD16:
-       case R_PPC64_GOT_TLSGD16_LO:
-       case R_PPC64_GOT_TLSGD16_HI:
-       case R_PPC64_GOT_TLSGD16_HA:
-         tls_type = TLS_TLS | TLS_GD;
-         goto dogot;
-
-       case R_PPC64_GOT_TPREL16_DS:
-       case R_PPC64_GOT_TPREL16_LO_DS:
-       case R_PPC64_GOT_TPREL16_HI:
-       case R_PPC64_GOT_TPREL16_HA:
-         tls_type = TLS_TLS | TLS_TPREL;
-         goto dogot;
-
-       case R_PPC64_GOT_DTPREL16_DS:
-       case R_PPC64_GOT_DTPREL16_LO_DS:
-       case R_PPC64_GOT_DTPREL16_HI:
-       case R_PPC64_GOT_DTPREL16_HA:
-         tls_type = TLS_TLS | TLS_DTPREL;
-         goto dogot;
-
-       case R_PPC64_GOT16:
-       case R_PPC64_GOT16_DS:
-       case R_PPC64_GOT16_HA:
-       case R_PPC64_GOT16_HI:
-       case R_PPC64_GOT16_LO:
-       case R_PPC64_GOT16_LO_DS:
-       dogot:
-         {
-           struct got_entry *ent;
-
-           if (h != NULL)
-             ent = h->got.glist;
-           else
-             ent = local_got_ents[r_symndx];
-
-           for (; ent != NULL; ent = ent->next)
-             if (ent->addend == rel->r_addend
-                 && ent->owner == abfd
-                 && ent->tls_type == tls_type)
-               break;
-           if (ent == NULL)
-             abort ();
-           if (ent->got.refcount > 0)
-             ent->got.refcount -= 1;
-         }
-         if (h != NULL && !bfd_link_pic (info) && abiversion (abfd) != 1)
-           plt_list = &h->plt.plist;
-         break;
-
-       case R_PPC64_PLT16_HA:
-       case R_PPC64_PLT16_HI:
-       case R_PPC64_PLT16_LO:
-       case R_PPC64_PLT32:
-       case R_PPC64_PLT64:
-       case R_PPC64_REL14:
-       case R_PPC64_REL14_BRNTAKEN:
-       case R_PPC64_REL14_BRTAKEN:
-       case R_PPC64_REL24:
-         if (h != NULL)
-           plt_list = &h->plt.plist;
-         else if (local_got_ents != NULL)
-           {
-             struct plt_entry **local_plt = (struct plt_entry **)
-               (local_got_ents + symtab_hdr->sh_info);
-             unsigned char *local_got_tls_masks = (unsigned char *)
-               (local_plt + symtab_hdr->sh_info);
-             if ((local_got_tls_masks[r_symndx] & PLT_IFUNC) != 0)
-               plt_list = local_plt + r_symndx;
-           }
-         break;
-
-       case R_PPC64_ADDR64:
-       case R_PPC64_ADDR16:
-       case R_PPC64_ADDR16_DS:
-       case R_PPC64_ADDR16_HA:
-       case R_PPC64_ADDR16_HI:
-       case R_PPC64_ADDR16_HIGH:
-       case R_PPC64_ADDR16_HIGHA:
-       case R_PPC64_ADDR16_HIGHER:
-       case R_PPC64_ADDR16_HIGHERA:
-       case R_PPC64_ADDR16_HIGHEST:
-       case R_PPC64_ADDR16_HIGHESTA:
-       case R_PPC64_ADDR16_LO:
-       case R_PPC64_ADDR16_LO_DS:
-         if (h != NULL && !bfd_link_pic (info) && abiversion (abfd) != 1
-             && rel->r_addend == 0)
-           plt_list = &h->plt.plist;
-         break;
-
-       default:
-         break;
-       }
-      if (plt_list != NULL)
-       {
-         struct plt_entry *ent;
-
-         for (ent = *plt_list; ent != NULL; ent = ent->next)
-           if (ent->addend == rel->r_addend)
-             break;
-         if (ent != NULL && ent->plt.refcount > 0)
-           ent->plt.refcount -= 1;
-       }
-    }
-  return TRUE;
-}
-
 /* The maximum size of .sfpr.  */
 #define SFPR_MAX (218*4)
 
@@ -7259,10 +7035,9 @@ ppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED,
   return TRUE;
 }
 
-/* Return true if we have dynamic relocs against H that apply to
-   read-only sections.  */
+/* Find dynamic relocs for H that apply to read-only sections.  */
 
-static bfd_boolean
+static asection *
 readonly_dynrelocs (struct elf_link_hash_entry *h)
 {
   struct ppc_link_hash_entry *eh;
@@ -7274,13 +7049,14 @@ readonly_dynrelocs (struct elf_link_hash_entry *h)
       asection *s = p->sec->output_section;
 
       if (s != NULL && (s->flags & SEC_READONLY) != 0)
-       return TRUE;
+       return p->sec;
     }
-  return FALSE;
+  return NULL;
 }
 
 /* Return true if we have dynamic relocs against H or any of its weak
-   aliases, that apply to read-only sections.  */
+   aliases, that apply to read-only sections.  Cannot be used after
+   size_dynamic_sections.  */
 
 static bfd_boolean
 alias_readonly_dynrelocs (struct elf_link_hash_entry *h)
@@ -7292,7 +7068,7 @@ alias_readonly_dynrelocs (struct elf_link_hash_entry *h)
     {
       if (readonly_dynrelocs (&eh->elf))
        return TRUE;
-      eh = eh->weakref;
+      eh = (struct ppc_link_hash_entry *) eh->elf.u.alias;
     } while (eh != NULL && &eh->elf != h);
 
   return FALSE;
@@ -7353,6 +7129,23 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
       || h->type == STT_GNU_IFUNC
       || h->needs_plt)
     {
+      bfd_boolean local = (((struct ppc_link_hash_entry *) h)->save_res
+                          || SYMBOL_CALLS_LOCAL (info, h)
+                          || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
+      /* Discard dyn_relocs when non-pic if we've decided that a
+        function symbol is local and not an ifunc.  We keep dynamic
+        relocs for ifuncs when local rather than always emitting a
+        plt call stub for them and defining the symbol on the call
+        stub.  We can't do that for ELFv1 anyway (a function symbol
+        is defined on a descriptor, not code) and it can be faster at
+        run-time due to not needing to bounce through a stub.  The
+        dyn_relocs for ifuncs will be applied even in a static
+        executable.  */
+      if (!bfd_link_pic (info)
+         && h->type != STT_GNU_IFUNC
+         && local)
+       ((struct ppc_link_hash_entry *) h)->dyn_relocs = NULL;
+
       /* Clear procedure linkage table information for any symbol that
         won't need a .plt entry.  */
       struct plt_entry *ent;
@@ -7360,10 +7153,7 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
        if (ent->plt.refcount > 0)
          break;
       if (ent == NULL
-         || (h->type != STT_GNU_IFUNC
-             && (SYMBOL_CALLS_LOCAL (info, h)
-                 || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)))
-         || ((struct ppc_link_hash_entry *) h)->save_res)
+         || (h->type != STT_GNU_IFUNC && local))
        {
          h->plt.plist = NULL;
          h->needs_plt = 0;
@@ -7378,17 +7168,32 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
             relocs is that calling via a global entry stub costs a
             few more instructions, and pointer_equality_needed causes
             extra work in ld.so when resolving these symbols.  */
-         if (global_entry_stub (h)
-             && !alias_readonly_dynrelocs (h))
+         if (global_entry_stub (h))
            {
-             h->pointer_equality_needed = 0;
-             /* After adjust_dynamic_symbol, non_got_ref set in
-                the non-pic case means that dyn_relocs for this
-                symbol should be discarded.  */
-             h->non_got_ref = 0;
+             if (!readonly_dynrelocs (h))
+               {
+                 h->pointer_equality_needed = 0;
+                 /* If we haven't seen a branch reloc then we don't need
+                    a plt entry.  */
+                 if (!h->needs_plt)
+                   h->plt.plist = NULL;
+               }
+             else if (!bfd_link_pic (info))
+               /* We are going to be defining the function symbol on the
+                  plt stub, so no dyn_relocs needed when non-pic.  */
+               ((struct ppc_link_hash_entry *) h)->dyn_relocs = NULL;
            }
 
-         /* If making a plt entry, then we don't need copy relocs.  */
+         /* ELFv2 function symbols can't have copy relocs.  */
+         return TRUE;
+       }
+      else if (!h->needs_plt
+              && !readonly_dynrelocs (h))
+       {
+         /* If we haven't seen a branch reloc then we don't need a
+            plt entry.  */
+         h->plt.plist = NULL;
+         h->pointer_equality_needed = 0;
          return TRUE;
        }
     }
@@ -7398,14 +7203,15 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   /* If this is a weak symbol, and there is a real definition, the
      processor independent code will have arranged for us to see the
      real definition first, and we can just use the same value.  */
-  if (h->u.weakdef != NULL)
-    {
-      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
-                 || h->u.weakdef->root.type == bfd_link_hash_defweak);
-      h->root.u.def.section = h->u.weakdef->root.u.def.section;
-      h->root.u.def.value = h->u.weakdef->root.u.def.value;
-      if (ELIMINATE_COPY_RELOCS)
-       h->non_got_ref = h->u.weakdef->non_got_ref;
+  if (h->is_weakalias)
+    {
+      struct elf_link_hash_entry *def = weakdef (h);
+      BFD_ASSERT (def->root.type == bfd_link_hash_defined);
+      h->root.u.def.section = def->root.u.def.section;
+      h->root.u.def.value = def->root.u.def.value;
+      if (def->root.u.def.section == htab->elf.sdynbss
+         || def->root.u.def.section == htab->elf.sdynrelro)
+       ((struct ppc_link_hash_entry *) h)->dyn_relocs = NULL;
       return TRUE;
     }
 
@@ -7427,7 +7233,7 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
       /* If -z nocopyreloc was given, don't generate them either.  */
       || info->nocopyreloc
 
-      /* If we didn't find any dynamic relocs in read-only sections, then
+      /* If we don't find any dynamic relocs in read-only sections, then
         we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
       || (ELIMINATE_COPY_RELOCS && !alias_readonly_dynrelocs (h))
 
@@ -7436,10 +7242,7 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
         definition for the variable.  Text relocations are preferable
         to an incorrect program.  */
       || h->protected_def)
-    {
-      h->non_got_ref = 0;
-      return TRUE;
-    }
+    return TRUE;
 
   if (h->plt.plist != NULL)
     {
@@ -7466,11 +7269,6 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
      determine the address it must put in the global offset table, so
      both the dynamic object and the regular object will refer to the
      same memory location for the variable.  */
-
-  /* We must generate a R_PPC64_COPY reloc to tell the dynamic linker
-     to copy the initial value out of the dynamic object and into the
-     runtime process image.  We need to remember the offset into the
-     .rela.bss section we are going to use.  */
   if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
     {
       s = htab->elf.sdynrelro;
@@ -7483,10 +7281,15 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
     }
   if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
     {
+      /* We must generate a R_PPC64_COPY reloc to tell the dynamic
+        linker to copy the initial value out of the dynamic object
+        and into the runtime process image.  */
       srel->size += sizeof (Elf64_External_Rela);
       h->needs_copy = 1;
     }
 
+  /* We no longer want dyn_relocs.  */
+  ((struct ppc_link_hash_entry *) h)->dyn_relocs = NULL;
   return _bfd_elf_adjust_dynamic_copy (info, h, s);
 }
 
@@ -9738,7 +9541,10 @@ allocate_got (struct elf_link_hash_entry *h,
       htab->elf.irelplt->size += rentsize;
       htab->got_reli_size += rentsize;
     }
-  else if ((bfd_link_pic (info)
+  else if (((bfd_link_pic (info)
+            && !((gent->tls_type & TLS_TPREL) != 0
+                 && bfd_link_executable (info)
+                 && SYMBOL_REFERENCES_LOCAL (info, h)))
            || (htab->elf.dynamic_sections_created
                && h->dynindx != -1
                && !SYMBOL_REFERENCES_LOCAL (info, h)))
@@ -9875,6 +9681,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       && h->type != STT_GNU_IFUNC)
     eh->dyn_relocs = NULL;
 
+  /* Discard relocs on undefined symbols that must be local.  */
+  else if (h->root.type == bfd_link_hash_undefined
+          && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+    eh->dyn_relocs = NULL;
+
   /* Also discard relocs on undefined weak syms with non-default
      visibility, or when dynamic_undefined_weak says so.  */
   else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
@@ -9919,36 +9730,14 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
                return FALSE;
            }
        }
-      else if (h->type == STT_GNU_IFUNC)
-       {
-         /* A plt entry is always created when making direct calls to
-            an ifunc, even when building a static executable, but
-            that doesn't cover all cases.  We may have only an ifunc
-            initialised function pointer for a given ifunc symbol.
-
-            For ELFv2, dynamic relocations are not required when
-            generating a global entry PLT stub.  */
-         if (abiversion (info->output_bfd) >= 2)
-           {
-             if (global_entry_stub (h))
-               eh->dyn_relocs = NULL;
-           }
-
-         /* For ELFv1 we have function descriptors.  Descriptors need
-            to be treated like PLT entries and thus have dynamic
-            relocations.  One exception is when the function
-            descriptor is copied into .dynbss (which should only
-            happen with ancient versions of gcc).  */
-         else if (h->needs_copy)
-           eh->dyn_relocs = NULL;
-       }
-      else if (ELIMINATE_COPY_RELOCS)
+      else if (ELIMINATE_COPY_RELOCS && h->type != STT_GNU_IFUNC)
        {
          /* For the non-pic case, discard space for relocs against
             symbols which turn out to need copy relocs or are not
             dynamic.  */
-         if (!h->non_got_ref
-             && !h->def_regular)
+         if (h->dynamic_adjusted
+             && !h->def_regular
+             && !ELF_COMMON_DEF_P (h))
            {
              /* Make sure this symbol is output as a dynamic symbol.  */
              if (!ensure_undef_dynamic (info, h))
@@ -10087,14 +9876,22 @@ size_global_entry_stubs (struct elf_link_hash_entry *h, void *inf)
    read-only sections.  */
 
 static bfd_boolean
-maybe_set_textrel (struct elf_link_hash_entry *h, void *info)
+maybe_set_textrel (struct elf_link_hash_entry *h, void *inf)
 {
+  asection *sec;
+
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (readonly_dynrelocs (h))
+  sec = readonly_dynrelocs (h);
+  if (sec != NULL)
     {
-      ((struct bfd_link_info *) info)->flags |= DF_TEXTREL;
+      struct bfd_link_info *info = (struct bfd_link_info *) inf;
+
+      info->flags |= DF_TEXTREL;
+      info->callbacks->minfo
+       (_("%B: dynamic relocation against `%T' in read-only section `%A'\n"),
+        sec->owner, h->root.root.string, sec);
 
       /* Not an error, just cut short the traversal.  */
       return FALSE;
@@ -10218,7 +10015,9 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
                        htab->elf.irelplt->size += rel_size;
                        htab->got_reli_size += rel_size;
                      }
-                   else if (bfd_link_pic (info))
+                   else if (bfd_link_pic (info)
+                            && !((ent->tls_type & TLS_TPREL) != 0
+                                 && bfd_link_executable (info)))
                      {
                        asection *srel = ppc64_elf_tdata (ibfd)->relgot;
                        srel->size += rel_size;
@@ -10354,6 +10153,10 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
          continue;
        }
 
+      if (bfd_is_abs_section (s->output_section))
+       _bfd_error_handler (_("warning: discarding dynamic section %s"),
+                           s->name);
+
       if ((s->flags & SEC_HAS_CONTENTS) == 0)
        continue;
 
@@ -11148,7 +10951,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
              + htab->brlt->output_section->vma);
 
       off = (dest
-            - elf_gp (htab->brlt->output_section->owner)
+            - elf_gp (info->output_bfd)
             - htab->sec_info[stub_entry->group->link_sec->id].toc_off);
 
       if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
@@ -11299,7 +11102,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
        }
 
       off = (dest
-            - elf_gp (plt->output_section->owner)
+            - elf_gp (info->output_bfd)
             - htab->sec_info[stub_entry->group->link_sec->id].toc_off);
 
       if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
@@ -11447,7 +11250,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
        plt = htab->elf.iplt;
       off += (plt->output_offset
              + plt->output_section->vma
-             - elf_gp (plt->output_section->owner)
+             - elf_gp (info->output_bfd)
              - htab->sec_info[stub_entry->group->link_sec->id].toc_off);
 
       size = plt_stub_size (htab, stub_entry, off);
@@ -11550,7 +11353,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
          off = (br_entry->offset
                 + htab->brlt->output_offset
                 + htab->brlt->output_section->vma
-                - elf_gp (htab->brlt->output_section->owner)
+                - elf_gp (info->output_bfd)
                 - htab->sec_info[stub_entry->group->link_sec->id].toc_off);
 
          if (info->emitrelocations)
@@ -11670,7 +11473,7 @@ ppc64_elf_next_toc_section (struct bfd_link_info *info, asection *isec)
         output toc base plus 0x8000.  Making the input elf_gp an
         offset allows us to move the toc as a whole without
         recalculating input elf_gp.  */
-      off = htab->toc_curr - elf_gp (isec->output_section->owner);
+      off = htab->toc_curr - elf_gp (info->output_bfd);
       off += TOC_BASE_OFF;
 
       /* Die if someone uses a linker script that doesn't keep input
@@ -11699,7 +11502,7 @@ ppc64_elf_next_toc_section (struct bfd_link_info *info, asection *isec)
     }
   addr = (htab->toc_first_sec->output_offset
          + htab->toc_first_sec->output_section->vma);
-  off = addr - elf_gp (isec->output_section->owner) + TOC_BASE_OFF;
+  off = addr - elf_gp (info->output_bfd) + TOC_BASE_OFF;
   elf_gp (isec->owner) = off;
 
   return TRUE;
@@ -12852,7 +12655,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
 
       if (htab->glink_eh_frame != NULL
          && !bfd_is_abs_section (htab->glink_eh_frame->output_section)
-         && htab->glink_eh_frame->output_section->size != 0)
+         && htab->glink_eh_frame->output_section->size > 8)
        {
          size_t size = 0, align = 4;
 
@@ -13444,20 +13247,23 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
 
   if (stats != NULL)
     {
+      size_t len;
       *stats = bfd_malloc (500);
       if (*stats == NULL)
        return FALSE;
 
-      sprintf (*stats, _("linker stubs in %u group%s\n"
-                        "  branch       %lu\n"
-                        "  toc adjust   %lu\n"
-                        "  long branch  %lu\n"
-                        "  long toc adj %lu\n"
-                        "  plt call     %lu\n"
-                        "  plt call toc %lu\n"
-                        "  global entry %lu"),
-              stub_sec_count,
-              stub_sec_count == 1 ? "" : "s",
+      len = sprintf (*stats,
+                    ngettext ("linker stubs in %u group\n",
+                              "linker stubs in %u groups\n",
+                              stub_sec_count),
+                    stub_sec_count);
+      sprintf (*stats + len, _("  branch       %lu\n"
+                              "  toc adjust   %lu\n"
+                              "  long branch  %lu\n"
+                              "  long toc adj %lu\n"
+                              "  plt call     %lu\n"
+                              "  plt call toc %lu\n"
+                              "  global entry %lu"),
               htab->stub_count[ppc_stub_long_branch - 1],
               htab->stub_count[ppc_stub_long_branch_r2off - 1],
               htab->stub_count[ppc_stub_plt_branch - 1],
@@ -14660,7 +14466,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                             && (h == NULL
                                 || !UNDEFWEAK_NO_DYNAMIC_RELOC (info, &h->elf)
                                 || (tls_type == (TLS_TLS | TLS_LD)
-                                    && !h->elf.def_dynamic))))
+                                    && !h->elf.def_dynamic))
+                            && !(tls_type == (TLS_TLS | TLS_TPREL)
+                                 && bfd_link_executable (info)
+                                 && SYMBOL_REFERENCES_LOCAL (info, &h->elf))))
                  relgot = ppc64_elf_tdata (ent->owner)->relgot;
                if (relgot != NULL)
                  {
@@ -15185,7 +14994,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 
       /* Multi-instruction sequences that access the TOC can be
         optimized, eg. addis ra,r2,0; addi rb,ra,x;
-        to             nop;           addi rb,r2,x;  */
+        to             nop;           addi rb,r2,x;  */
       howto = ppc64_elf_howto_table[(int) r_type];
       switch (r_type)
        {
This page took 0.035324 seconds and 4 git commands to generate.