Don't use boolean OR in arithmetic expressions
[deliverable/binutils-gdb.git] / bfd / elf64-ppc.c
index f9c37b5b3decfa2b1c4d201b9f0b0fcdc23f430c..2a9ea1e2d261beea6a44fae81c4e284b7493a4d0 100644 (file)
@@ -687,7 +687,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc64_elf_unhandled_reloc, /* special_function */
         "R_PPC64_PLTREL32",    /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -2490,8 +2490,8 @@ ppc64_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
   type = ELF64_R_TYPE (dst->r_info);
   if (type >= ARRAY_SIZE (ppc64_elf_howto_table))
     {
-      (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
-                            abfd, (int) type);
+      _bfd_error_handler (_("%B: invalid relocation type %d"),
+                         abfd, (int) type);
       type = R_PPC64_NONE;
     }
   cache_ptr->howto = ppc64_elf_howto_table[type];
@@ -2570,6 +2570,7 @@ ppc64_elf_branch_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
       elf_symbol_type *elfsym = (elf_symbol_type *) symbol;
 
       if (symbol->section->owner != abfd
+         && symbol->section->owner != NULL
          && abiversion (symbol->section->owner) >= 2)
        {
          unsigned int i;
@@ -2887,12 +2888,15 @@ ppc64_elf_mkobject (bfd *abfd)
 }
 
 /* Fix bad default arch selected for a 64 bit input bfd when the
-   default is 32 bit.  */
+   default is 32 bit.  Also select arch based on apuinfo.  */
 
 static bfd_boolean
 ppc64_elf_object_p (bfd *abfd)
 {
-  if (abfd->arch_info->the_default && abfd->arch_info->bits_per_word == 32)
+  if (!abfd->arch_info->the_default)
+    return TRUE;
+
+  if (abfd->arch_info->bits_per_word == 32)
     {
       Elf_Internal_Ehdr *i_ehdr = elf_elfheader (abfd);
 
@@ -2903,7 +2907,7 @@ ppc64_elf_object_p (bfd *abfd)
          BFD_ASSERT (abfd->arch_info->bits_per_word == 64);
        }
     }
-  return TRUE;
+  return _bfd_elf_ppc_set_arch (abfd);
 }
 
 /* Support for core dump NOTE sections.  */
@@ -3081,6 +3085,7 @@ get_opd_info (asection * sec)
 \f
 /* Parameters for the qsort hook.  */
 static bfd_boolean synthetic_relocatable;
+static asection *synthetic_opd;
 
 /* qsort comparison function for ppc64_elf_get_synthetic_symtab.  */
 
@@ -3097,12 +3102,15 @@ compare_symbols (const void *ap, const void *bp)
     return 1;
 
   /* then .opd symbols.  */
-  if (strcmp (a->section->name, ".opd") == 0
-      && strcmp (b->section->name, ".opd") != 0)
-    return -1;
-  if (strcmp (a->section->name, ".opd") != 0
-      && strcmp (b->section->name, ".opd") == 0)
-    return 1;
+  if (synthetic_opd != NULL)
+    {
+      if (strcmp (a->section->name, ".opd") == 0
+         && strcmp (b->section->name, ".opd") != 0)
+       return -1;
+      if (strcmp (a->section->name, ".opd") != 0
+         && strcmp (b->section->name, ".opd") == 0)
+       return 1;
+    }
 
   /* then other code symbols.  */
   if ((a->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL))
@@ -3261,6 +3269,7 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
     memcpy (syms, static_syms, (symcount + 1) * sizeof (*syms));
 
   synthetic_relocatable = relocatable;
+  synthetic_opd = opd;
   qsort (syms, symcount, sizeof (*syms), compare_symbols);
 
   if (!relocatable && symcount > 1)
@@ -3277,7 +3286,11 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
     }
 
   i = 0;
-  if (strcmp (syms[i]->section->name, ".opd") == 0)
+  /* Note that here and in compare_symbols we can't compare opd and
+     sym->section directly.  With separate debug info files, the
+     symbols will be extracted from the debug file while abfd passed
+     to this function is the real binary.  */
+  if (opd != NULL && strcmp (syms[i]->section->name, ".opd") == 0)
     ++i;
   codesecsym = i;
 
@@ -3293,9 +3306,10 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
       break;
   secsymend = i;
 
-  for (; i < symcount; ++i)
-    if (strcmp (syms[i]->section->name, ".opd") != 0)
-      break;
+  if (opd != NULL)
+    for (; i < symcount; ++i)
+      if (strcmp (syms[i]->section->name, ".opd") != 0)
+       break;
   opdsymend = i;
 
   for (; i < symcount; ++i)
@@ -3946,6 +3960,9 @@ 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;
 
@@ -4344,14 +4361,20 @@ create_linkage_sections (bfd *dynobj, struct bfd_link_info *info)
 
   htab = ppc_hash_table (info);
 
-  /* Create .sfpr for code to save and restore fp regs.  */
   flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY
           | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
-  htab->sfpr = bfd_make_section_anyway_with_flags (dynobj, ".sfpr",
-                                                  flags);
-  if (htab->sfpr == NULL
-      || ! bfd_set_section_alignment (dynobj, htab->sfpr, 2))
-    return FALSE;
+  if (htab->params->save_restore_funcs)
+    {
+      /* Create .sfpr for code to save and restore fp regs.  */
+      htab->sfpr = bfd_make_section_anyway_with_flags (dynobj, ".sfpr",
+                                                      flags);
+      if (htab->sfpr == NULL
+         || ! bfd_set_section_alignment (dynobj, htab->sfpr, 2))
+       return FALSE;
+    }
+
+  if (bfd_link_relocatable (info))
+    return TRUE;
 
   /* Create .glink for lazy dynamic linking support.  */
   htab->glink = bfd_make_section_anyway_with_flags (dynobj, ".glink",
@@ -4424,14 +4447,9 @@ ppc64_elf_init_stub_bfd (struct bfd_link_info *info,
    linker created stub bfd.  This ensures that the GOT header is at
    the start of the output TOC section.  */
   htab = ppc_hash_table (info);
-  if (htab == NULL)
-    return FALSE;
   htab->elf.dynobj = params->stub_bfd;
   htab->params = params;
 
-  if (bfd_link_relocatable (info))
-    return TRUE;
-
   return create_linkage_sections (htab->elf.dynobj, info);
 }
 
@@ -4500,6 +4518,8 @@ ppc_get_stub_entry (const asection *input_section,
      more than one stub used to reach say, printf, and we need to
      distinguish between them.  */
   group = htab->sec_info[input_section->id].u.group;
+  if (group == NULL)
+    return NULL;
 
   if (h != NULL && h->u.stub_cache != NULL
       && h->u.stub_cache->h == h
@@ -4731,6 +4751,45 @@ ppc64_elf_copy_indirect_symbol (struct bfd_link_info *info,
   edir->elf.needs_plt |= eind->elf.needs_plt;
   edir->elf.pointer_equality_needed |= eind->elf.pointer_equality_needed;
 
+  /* If we were called to copy over info for a weak sym, don't copy
+     dyn_relocs, plt/got info, or dynindx.  We used to copy dyn_relocs
+     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.  */
+  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;
+    }
+
   /* Copy over any dynamic relocs we may have on the indirect sym.  */
   if (eind->dyn_relocs != NULL)
     {
@@ -4763,16 +4822,6 @@ ppc64_elf_copy_indirect_symbol (struct bfd_link_info *info,
       eind->dyn_relocs = NULL;
     }
 
-  /* If we were called to copy over info for a weak sym, that's all.
-     You might think dyn_relocs need not be copied over;  After all,
-     both syms will be dynamic or both non-dynamic so we're just
-     moving reloc accounting around.  However, ELIMINATE_COPY_RELOCS
-     code in ppc64_elf_adjust_dynamic_symbol needs to check for
-     dyn_relocs in read-only sections, and it does so on what is the
-     DIR sym here.  */
-  if (eind->elf.root.type != bfd_link_hash_indirect)
-    return;
-
   /* Copy over got entries that we may have already seen to the
      symbol which just became indirect.  */
   if (eind->elf.got.glist != NULL)
@@ -4893,11 +4942,10 @@ ppc64_elf_add_symbol_hook (bfd *ibfd,
                           asection **sec,
                           bfd_vma *value)
 {
-  if ((ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC
-       || ELF_ST_BIND (isym->st_info) == STB_GNU_UNIQUE)
+  if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC
       && (ibfd->flags & DYNAMIC) == 0
       && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour)
-    elf_tdata (info->output_bfd)->has_gnu_symbols = elf_gnu_symbol_any;
+    elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_ifunc;
 
   if (*sec != NULL
       && strcmp ((*sec)->name, ".opd") == 0)
@@ -5075,7 +5123,7 @@ ppc64_elf_before_check_relocs (bfd *ibfd, struct bfd_link_info *info)
     {
       if (abiversion (ibfd) == 0)
        set_abiversion (ibfd, 1);
-      else if (abiversion (ibfd) == 2)
+      else if (abiversion (ibfd) >= 2)
        {
          info->callbacks->einfo (_("%P: %B .opd not allowed in ABI"
                                    " version %d\n"),
@@ -5149,7 +5197,7 @@ ppc64_elf_before_check_relocs (bfd *ibfd, struct bfd_link_info *info)
     }
 
   /* We need to fix the undefs list for any syms we have twiddled to
-     undef_weak.  */
+     undefweak.  */
   if (htab->twiddled_syms)
     {
       bfd_link_repair_undef_list (&htab->elf.root);
@@ -5968,20 +6016,22 @@ ppc64_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 
   if (iflags & ~EF_PPC64_ABI)
     {
-      (*_bfd_error_handler)
+      _bfd_error_handler
        (_("%B uses unknown e_flags 0x%lx"), ibfd, iflags);
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
     }
   else if (iflags != oflags && iflags != 0)
     {
-      (*_bfd_error_handler)
+      _bfd_error_handler
        (_("%B: ABI version %ld is not compatible with ABI version %ld output"),
         ibfd, iflags, oflags);
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
     }
 
+  _bfd_elf_ppc_merge_fp_attributes (ibfd, obfd);
+
   /* Merge Tag_compatibility attributes and any common GNU ones.  */
   _bfd_elf_merge_object_attributes (ibfd, obfd);
 
@@ -6665,7 +6715,7 @@ sfpr_define (struct bfd_link_info *info,
       sym[len + 0] = i / 10 + '0';
       sym[len + 1] = i % 10 + '0';
       h = (struct ppc_link_hash_entry *)
-       elf_link_hash_lookup (&htab->elf, sym, FALSE, FALSE, TRUE);
+       elf_link_hash_lookup (&htab->elf, sym, writing, TRUE, TRUE);
       if (stub_sec != NULL)
        {
          if (h != NULL
@@ -6706,6 +6756,7 @@ sfpr_define (struct bfd_link_info *info,
              h->elf.root.u.def.value = htab->sfpr->size;
              h->elf.type = STT_FUNC;
              h->elf.def_regular = 1;
+             h->elf.non_elf = 0;
              _bfd_elf_link_hash_hide_symbol (info, &h->elf, TRUE);
              writing = TRUE;
              if (htab->sfpr->contents == NULL)
@@ -7050,14 +7101,28 @@ ppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED,
                            struct bfd_link_info *info)
 {
   struct ppc_link_hash_table *htab;
-  unsigned int i;
 
   htab = ppc_hash_table (info);
   if (htab == NULL)
     return FALSE;
 
-  if (!bfd_link_relocatable (info)
-      && htab->elf.hgot != NULL)
+  /* Provide any missing _save* and _rest* functions.  */
+  if (htab->sfpr != NULL)
+    {
+      unsigned int i;
+
+      htab->sfpr->size = 0;
+      for (i = 0; i < ARRAY_SIZE (save_res_funcs); i++)
+       if (!sfpr_define (info, &save_res_funcs[i], NULL))
+         return FALSE;
+      if (htab->sfpr->size == 0)
+       htab->sfpr->flags |= SEC_EXCLUDE;
+    }
+
+  if (bfd_link_relocatable (info))
+    return TRUE;
+
+  if (htab->elf.hgot != NULL)
     {
       _bfd_elf_link_hash_hide_symbol (info, htab->elf.hgot, TRUE);
       /* Make .TOC. defined so as to prevent it being made dynamic.
@@ -7076,26 +7141,13 @@ ppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED,
                               | STV_HIDDEN);
     }
 
-  if (htab->sfpr == NULL)
-    /* We don't have any relocs.  */
-    return TRUE;
-
-  /* Provide any missing _save* and _rest* functions.  */
-  htab->sfpr->size = 0;
-  if (htab->params->save_restore_funcs)
-    for (i = 0; i < ARRAY_SIZE (save_res_funcs); i++)
-      if (!sfpr_define (info, &save_res_funcs[i], NULL))
-       return FALSE;
-
   elf_link_hash_traverse (&htab->elf, func_desc_adjust, info);
 
-  if (htab->sfpr->size == 0)
-    htab->sfpr->flags |= SEC_EXCLUDE;
-
   return TRUE;
 }
 
-/* Return true if we have dynamic relocs that apply to read-only sections.  */
+/* Return true if we have dynamic relocs against H that apply to
+   read-only sections.  */
 
 static bfd_boolean
 readonly_dynrelocs (struct elf_link_hash_entry *h)
@@ -7114,6 +7166,58 @@ readonly_dynrelocs (struct elf_link_hash_entry *h)
   return FALSE;
 }
 
+/* Return true if we have dynamic relocs against H or any of its weak
+   aliases, that apply to read-only sections.  */
+
+static bfd_boolean
+alias_readonly_dynrelocs (struct elf_link_hash_entry *h)
+{
+  struct ppc_link_hash_entry *eh;
+
+  eh = (struct ppc_link_hash_entry *) h;
+  do
+    {
+      if (readonly_dynrelocs (&eh->elf))
+       return TRUE;
+      eh = eh->weakref;
+    } while (eh != NULL && &eh->elf != h);
+
+  return FALSE;
+}
+
+/* Return whether EH has pc-relative dynamic relocs.  */
+
+static bfd_boolean
+pc_dynrelocs (struct ppc_link_hash_entry *eh)
+{
+  struct elf_dyn_relocs *p;
+
+  for (p = eh->dyn_relocs; p != NULL; p = p->next)
+    if (p->pc_count != 0)
+      return TRUE;
+  return FALSE;
+}
+
+/* Return true if a global entry stub will be created for H.  Valid
+   for ELFv2 before plt entries have been allocated.  */
+
+static bfd_boolean
+global_entry_stub (struct elf_link_hash_entry *h)
+{
+  struct plt_entry *pent;
+
+  if (!h->pointer_equality_needed
+      || h->def_regular)
+    return FALSE;
+
+  for (pent = h->plt.plist; pent != NULL; pent = pent->next)
+    if (pent->plt.refcount > 0
+       && pent->addend == 0)
+      return TRUE;
+
+  return FALSE;
+}
+
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  The current definition is in some section of the
    dynamic object, but we're not including those sections.  We have to
@@ -7153,35 +7257,25 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
          h->needs_plt = 0;
          h->pointer_equality_needed = 0;
        }
-      else if (abiversion (info->output_bfd) == 2)
+      else if (abiversion (info->output_bfd) >= 2)
        {
          /* Taking a function's address in a read/write section
             doesn't require us to define the function symbol in the
             executable on a global entry stub.  A dynamic reloc can
-            be used instead.  */
-         if (h->pointer_equality_needed
-             && h->type != STT_GNU_IFUNC
-             && !readonly_dynrelocs (h))
+            be used instead.  The reason we prefer a few more dynamic
+            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))
            {
              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;
            }
 
-         /* After adjust_dynamic_symbol, non_got_ref set in the
-            non-shared case means that we have allocated space in
-            .dynbss for the symbol and thus dyn_relocs for this
-            symbol should be discarded.
-            If we get here we know we are making a PLT entry for this
-            symbol, and in an executable we'd normally resolve
-            relocations against this symbol to the PLT entry.  Allow
-            dynamic relocs if the reference is weak, and the dynamic
-            relocs will not cause text relocation.  */
-         else if (!h->ref_regular_nonweak
-                  && h->non_got_ref
-                  && h->type != STT_GNU_IFUNC
-                  && !readonly_dynrelocs (h))
-           h->non_got_ref = 0;
-
          /* If making a plt entry, then we don't need copy relocs.  */
          return TRUE;
        }
@@ -7216,29 +7310,20 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
     return TRUE;
 
   /* Don't generate a copy reloc for symbols defined in the executable.  */
-  if (!h->def_dynamic || !h->ref_regular || h->def_regular)
-    return TRUE;
+  if (!h->def_dynamic || !h->ref_regular || h->def_regular
 
-  /* If -z nocopyreloc was given, don't generate them either.  */
-  if (info->nocopyreloc)
-    {
-      h->non_got_ref = 0;
-      return TRUE;
-    }
+      /* 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
-     we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
-  if (ELIMINATE_COPY_RELOCS && !readonly_dynrelocs (h))
-    {
-      h->non_got_ref = 0;
-      return TRUE;
-    }
+      /* If we didn'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))
 
-  /* Protected variables do not work with .dynbss.  The copy in
-     .dynbss won't be used by the shared library with the protected
-     definition for the variable.  Text relocations are preferable
-     to an incorrect program.  */
-  if (h->protected_def)
+      /* Protected variables do not work with .dynbss.  The copy in
+        .dynbss won't be used by the shared library with the protected
+        definition for the variable.  Text relocations are preferable
+        to an incorrect program.  */
+      || h->protected_def)
     {
       h->non_got_ref = 0;
       return TRUE;
@@ -7514,7 +7599,7 @@ tocsave_find (struct ppc_link_hash_table *htab,
     return NULL;
   if (ent.sec == NULL || ent.sec->output_section == NULL)
     {
-      (*_bfd_error_handler)
+      _bfd_error_handler
        (_("%B: undefined symbol on R_PPC64_TOCSAVE relocation"));
       return NULL;
     }
@@ -7832,7 +7917,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
                 something silly in .opd with the assembler.  No .opd
                 optimization for them!  */
            broken_opd:
-             (*_bfd_error_handler)
+             _bfd_error_handler
                (_("%B: .opd is not a regular array of opd entries"), ibfd);
              broken = TRUE;
              break;
@@ -7841,7 +7926,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
          if ((r_type = ELF64_R_TYPE (rel->r_info)) != R_PPC64_ADDR64
              || (r_type = ELF64_R_TYPE ((rel + 1)->r_info)) != R_PPC64_TOC)
            {
-             (*_bfd_error_handler)
+             _bfd_error_handler
                (_("%B: unexpected reloc type %u in .opd section"),
                 ibfd, r_type);
              broken = TRUE;
@@ -7862,7 +7947,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
                sym_name = bfd_elf_sym_name (ibfd, symtab_hdr, sym,
                                             sym_sec);
 
-             (*_bfd_error_handler)
+             _bfd_error_handler
                (_("%B: undefined sym `%s' in .opd section"),
                 ibfd, sym_name);
              broken = TRUE;
@@ -8224,6 +8309,7 @@ ppc64_elf_tls_setup (struct bfd_link_info *info)
                  tga_fd->root.type = bfd_link_hash_indirect;
                  tga_fd->root.u.i.link = &opt_fd->root;
                  ppc64_elf_copy_indirect_symbol (info, opt_fd, tga_fd);
+                 opt_fd->forced_local = 0;
                  if (opt_fd->dynindx != -1)
                    {
                      /* Use __tls_get_addr_opt in dynamic relocations.  */
@@ -8240,6 +8326,7 @@ ppc64_elf_tls_setup (struct bfd_link_info *info)
                      tga->root.type = bfd_link_hash_indirect;
                      tga->root.u.i.link = &opt->root;
                      ppc64_elf_copy_indirect_symbol (info, opt, tga);
+                     opt->forced_local = 0;
                      _bfd_elf_link_hash_hide_symbol (info, opt,
                                                      tga->forced_local);
                      htab->tls_get_addr = (struct ppc_link_hash_entry *) opt;
@@ -8764,7 +8851,7 @@ adjust_toc_syms (struct elf_link_hash_entry *h, void *inf)
 
       if ((toc_inf->skip[i] & (ref_from_discarded | can_optimize)) != 0)
        {
-         (*_bfd_error_handler)
+         _bfd_error_handler
            (_("%s defined on removed toc entry"), eh->elf.root.root.string);
          do
            ++i;
@@ -9388,7 +9475,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
                  if ((skip[i] & (ref_from_discarded | can_optimize)) != 0)
                    {
                      if (local_toc_syms)
-                       (*_bfd_error_handler)
+                       _bfd_error_handler
                          (_("%s defined on removed toc entry"),
                           bfd_elf_sym_name (ibfd, symtab_hdr, sym, NULL));
                      do
@@ -9538,7 +9625,6 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   struct ppc_link_hash_table *htab;
   asection *s;
   struct ppc_link_hash_entry *eh;
-  struct elf_dyn_relocs *p;
   struct got_entry **pgent, *gent;
 
   if (h->root.type == bfd_link_hash_indirect)
@@ -9549,71 +9635,6 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   if (htab == NULL)
     return FALSE;
 
-  if ((htab->elf.dynamic_sections_created
-       && h->dynindx != -1
-       && WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
-      || h->type == STT_GNU_IFUNC)
-    {
-      struct plt_entry *pent;
-      bfd_boolean doneone = FALSE;
-      for (pent = h->plt.plist; pent != NULL; pent = pent->next)
-       if (pent->plt.refcount > 0)
-         {
-           if (!htab->elf.dynamic_sections_created
-               || h->dynindx == -1)
-             {
-               s = htab->elf.iplt;
-               pent->plt.offset = s->size;
-               s->size += PLT_ENTRY_SIZE (htab);
-               s = htab->elf.irelplt;
-             }
-           else
-             {
-               /* If this is the first .plt entry, make room for the special
-                  first entry.  */
-               s = htab->elf.splt;
-               if (s->size == 0)
-                 s->size += PLT_INITIAL_ENTRY_SIZE (htab);
-
-               pent->plt.offset = s->size;
-
-               /* Make room for this entry.  */
-               s->size += PLT_ENTRY_SIZE (htab);
-
-               /* Make room for the .glink code.  */
-               s = htab->glink;
-               if (s->size == 0)
-                 s->size += GLINK_CALL_STUB_SIZE;
-               if (htab->opd_abi)
-                 {
-                   /* We need bigger stubs past index 32767.  */
-                   if (s->size >= GLINK_CALL_STUB_SIZE + 32768*2*4)
-                     s->size += 4;
-                   s->size += 2*4;
-                 }
-               else
-                 s->size += 4;
-
-               /* We also need to make an entry in the .rela.plt section.  */
-               s = htab->elf.srelplt;
-             }
-           s->size += sizeof (Elf64_External_Rela);
-           doneone = TRUE;
-         }
-       else
-         pent->plt.offset = (bfd_vma) -1;
-      if (!doneone)
-       {
-         h->plt.plist = NULL;
-         h->needs_plt = 0;
-       }
-    }
-  else
-    {
-      h->plt.plist = NULL;
-      h->needs_plt = 0;
-    }
-
   eh = (struct ppc_link_hash_entry *) h;
   /* Run through the TLS GD got entries first if we're changing them
      to TPREL.  */
@@ -9683,99 +9704,178 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
        allocate_got (h, info, gent);
       }
 
-  if (eh->dyn_relocs == NULL
-      || (!htab->elf.dynamic_sections_created
-         && h->type != STT_GNU_IFUNC))
-    return TRUE;
-
-  /* In the shared -Bsymbolic case, discard space allocated for
-     dynamic pc-relative relocs against symbols which turn out to be
-     defined in regular objects.  For the normal shared case, discard
-     space for relocs that have become local due to symbol visibility
-     changes.  */
+  if (!htab->elf.dynamic_sections_created
+      && h->type != STT_GNU_IFUNC)
+    eh->dyn_relocs = NULL;
 
-  if (bfd_link_pic (info))
+  if (eh->dyn_relocs != NULL)
     {
-      /* Relocs that use pc_count are those that appear on a call insn,
-        or certain REL relocs (see must_be_dyn_reloc) that can be
-        generated via assembly.  We want calls to protected symbols to
-        resolve directly to the function rather than going via the plt.
-        If people want function pointer comparisons to work as expected
-        then they should avoid writing weird assembly.  */
-      if (SYMBOL_CALLS_LOCAL (info, h))
+      struct elf_dyn_relocs *p, **pp;
+
+      /* In the shared -Bsymbolic case, discard space allocated for
+        dynamic pc-relative relocs against symbols which turn out to
+        be defined in regular objects.  For the normal shared case,
+        discard space for relocs that have become local due to symbol
+        visibility changes.  */
+
+      if (bfd_link_pic (info))
        {
-         struct elf_dyn_relocs **pp;
+         /* Relocs that use pc_count are those that appear on a call
+            insn, or certain REL relocs (see must_be_dyn_reloc) that
+            can be generated via assembly.  We want calls to
+            protected symbols to resolve directly to the function
+            rather than going via the plt.  If people want function
+            pointer comparisons to work as expected then they should
+            avoid writing weird assembly.  */
+         if (SYMBOL_CALLS_LOCAL (info, h))
+           {
+             for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
+               {
+                 p->count -= p->pc_count;
+                 p->pc_count = 0;
+                 if (p->count == 0)
+                   *pp = p->next;
+                 else
+                   pp = &p->next;
+               }
+           }
 
-         for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
+         /* Also discard relocs on undefined weak syms with
+            non-default visibility.  */
+         if (eh->dyn_relocs != NULL
+             && h->root.type == bfd_link_hash_undefweak)
            {
-             p->count -= p->pc_count;
-             p->pc_count = 0;
-             if (p->count == 0)
-               *pp = p->next;
-             else
-               pp = &p->next;
+             if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+               eh->dyn_relocs = NULL;
+
+             /* Make sure this symbol is output as a dynamic symbol.
+                Undefined weak syms won't yet be marked as dynamic.  */
+             else if (h->dynindx == -1
+                      && !h->forced_local)
+               {
+                 if (! bfd_elf_link_record_dynamic_symbol (info, h))
+                   return FALSE;
+               }
            }
        }
-
-      /* Also discard relocs on undefined weak syms with non-default
-        visibility.  */
-      if (eh->dyn_relocs != NULL
-         && h->root.type == bfd_link_hash_undefweak)
+      else if (h->type == STT_GNU_IFUNC)
        {
-         if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
-           eh->dyn_relocs = NULL;
+         /* 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.
 
-         /* Make sure this symbol is output as a dynamic symbol.
-            Undefined weak syms won't yet be marked as dynamic.  */
-         else if (h->dynindx == -1
-                  && !h->forced_local)
+            For ELFv2, dynamic relocations are not required when
+            generating a global entry PLT stub.  */
+         if (abiversion (info->output_bfd) >= 2)
            {
-             if (! bfd_elf_link_record_dynamic_symbol (info, h))
-               return FALSE;
+             if (global_entry_stub (h))
+               eh->dyn_relocs = NULL;
            }
-       }
-    }
-  else if (h->type == STT_GNU_IFUNC)
-    {
-      if (!h->non_got_ref)
-       eh->dyn_relocs = NULL;
-    }
-  else if (ELIMINATE_COPY_RELOCS)
-    {
-      /* For the non-shared 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)
+         /* 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)
        {
-         /* Make sure this symbol is output as a dynamic symbol.
+         /* For the non-pic case, discard space for relocs against
+            symbols which turn out to need copy relocs or are not
+            dynamic.  */
+
+         /* First make sure this symbol is output as a dynamic symbol.
             Undefined weak syms won't yet be marked as dynamic.  */
-         if (h->dynindx == -1
-             && !h->forced_local)
-           {
-             if (! bfd_elf_link_record_dynamic_symbol (info, h))
-               return FALSE;
-           }
+         if (h->root.type == bfd_link_hash_undefweak
+             && !h->non_got_ref
+             && !h->def_regular
+             && h->dynindx == -1
+             && !h->forced_local
+             && !bfd_elf_link_record_dynamic_symbol (info, h))
+           return FALSE;
 
-         /* If that succeeded, we know we'll be keeping all the
-            relocs.  */
-         if (h->dynindx != -1)
-           goto keep;
+         if (h->non_got_ref
+             || h->def_regular
+             || h->dynindx == -1)
+           eh->dyn_relocs = NULL;
        }
 
-      eh->dyn_relocs = NULL;
-
-    keep: ;
+      /* Finally, allocate space.  */
+      for (p = eh->dyn_relocs; p != NULL; p = p->next)
+       {
+         asection *sreloc = elf_section_data (p->sec)->sreloc;
+         if (eh->elf.type == STT_GNU_IFUNC)
+           sreloc = htab->elf.irelplt;
+         sreloc->size += p->count * sizeof (Elf64_External_Rela);
+       }
     }
 
-  /* Finally, allocate space.  */
-  for (p = eh->dyn_relocs; p != NULL; p = p->next)
+  if ((htab->elf.dynamic_sections_created
+       && h->dynindx != -1
+       && WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
+      || h->type == STT_GNU_IFUNC)
     {
-      asection *sreloc = elf_section_data (p->sec)->sreloc;
-      if (eh->elf.type == STT_GNU_IFUNC)
-       sreloc = htab->elf.irelplt;
-      sreloc->size += p->count * sizeof (Elf64_External_Rela);
+      struct plt_entry *pent;
+      bfd_boolean doneone = FALSE;
+      for (pent = h->plt.plist; pent != NULL; pent = pent->next)
+       if (pent->plt.refcount > 0)
+         {
+           if (!htab->elf.dynamic_sections_created
+               || h->dynindx == -1)
+             {
+               s = htab->elf.iplt;
+               pent->plt.offset = s->size;
+               s->size += PLT_ENTRY_SIZE (htab);
+               s = htab->elf.irelplt;
+             }
+           else
+             {
+               /* If this is the first .plt entry, make room for the special
+                  first entry.  */
+               s = htab->elf.splt;
+               if (s->size == 0)
+                 s->size += PLT_INITIAL_ENTRY_SIZE (htab);
+
+               pent->plt.offset = s->size;
+
+               /* Make room for this entry.  */
+               s->size += PLT_ENTRY_SIZE (htab);
+
+               /* Make room for the .glink code.  */
+               s = htab->glink;
+               if (s->size == 0)
+                 s->size += GLINK_CALL_STUB_SIZE;
+               if (htab->opd_abi)
+                 {
+                   /* We need bigger stubs past index 32767.  */
+                   if (s->size >= GLINK_CALL_STUB_SIZE + 32768*2*4)
+                     s->size += 4;
+                   s->size += 2*4;
+                 }
+               else
+                 s->size += 4;
+
+               /* We also need to make an entry in the .rela.plt section.  */
+               s = htab->elf.srelplt;
+             }
+           s->size += sizeof (Elf64_External_Rela);
+           doneone = TRUE;
+         }
+       else
+         pent->plt.offset = (bfd_vma) -1;
+      if (!doneone)
+       {
+         h->plt.plist = NULL;
+         h->needs_plt = 0;
+       }
+    }
+  else
+    {
+      h->plt.plist = NULL;
+      h->needs_plt = 0;
     }
 
   return TRUE;
@@ -9817,6 +9917,7 @@ size_global_entry_stubs (struct elf_link_hash_entry *h, void *inf)
           need to define the symbol in the executable on a call stub.
           This is to avoid text relocations.  */
        s->size = (s->size + 15) & -16;
+       h->root.type = bfd_link_hash_defined;
        h->root.u.def.section = s;
        h->root.u.def.value = s->size;
        s->size += 16;
@@ -11960,7 +12061,6 @@ group_sections (struct bfd_link_info *info,
 {
   struct ppc_link_hash_table *htab;
   asection *osec;
-  bfd_size_type stub14_group_size;
   bfd_boolean suppress_size_errors;
 
   htab = ppc_hash_table (info);
@@ -11968,20 +12068,13 @@ group_sections (struct bfd_link_info *info,
     return FALSE;
 
   suppress_size_errors = FALSE;
-  stub14_group_size = stub_group_size >> 10;
   if (stub_group_size == 1)
     {
       /* Default values.  */
       if (stubs_always_before_branch)
-       {
-         stub_group_size = 0x1e00000;
-         stub14_group_size = 0x7800;
-       }
+       stub_group_size = 0x1e00000;
       else
-       {
-         stub_group_size = 0x1c00000;
-         stub14_group_size = 0x7000;
-       }
+       stub_group_size = 0x1c00000;
       suppress_size_errors = TRUE;
     }
 
@@ -12001,35 +12094,38 @@ group_sections (struct bfd_link_info *info,
          bfd_boolean big_sec;
          bfd_vma curr_toc;
          struct map_stub *group;
+         bfd_size_type group_size;
 
          curr = tail;
          total = tail->size;
-         big_sec = total > (ppc64_elf_section_data (tail) != NULL
-                            && ppc64_elf_section_data (tail)->has_14bit_branch
-                            ? stub14_group_size : stub_group_size);
+         group_size = (ppc64_elf_section_data (tail) != NULL
+                       && ppc64_elf_section_data (tail)->has_14bit_branch
+                       ? stub_group_size >> 10 : stub_group_size);
+
+         big_sec = total > group_size;
          if (big_sec && !suppress_size_errors)
-           (*_bfd_error_handler) (_("%B section %A exceeds stub group size"),
-                                    tail->owner, tail);
+           _bfd_error_handler (_("%B section %A exceeds stub group size"),
+                               tail->owner, tail);
          curr_toc = htab->sec_info[tail->id].toc_off;
 
          while ((prev = htab->sec_info[curr->id].u.list) != NULL
                 && ((total += curr->output_offset - prev->output_offset)
                     < (ppc64_elf_section_data (prev) != NULL
                        && ppc64_elf_section_data (prev)->has_14bit_branch
-                       ? stub14_group_size : stub_group_size))
+                       ? (group_size = stub_group_size >> 10) : group_size))
                 && htab->sec_info[prev->id].toc_off == curr_toc)
            curr = prev;
 
          /* OK, the size from the start of CURR to the end is less
-            than stub_group_size and thus can be handled by one stub
+            than group_size and thus can be handled by one stub
             section.  (or the tail section is itself larger than
-            stub_group_size, in which case we may be toast.)  We
-            should really be keeping track of the total size of stubs
-            added here, as stubs contribute to the final output
-            section size.  That's a little tricky, and this way will
-            only break if stubs added make the total size more than
-            2^25, ie. for the default stub_group_size, if stubs total
-            more than 2097152 bytes, or nearly 75000 plt call stubs.  */
+            group_size, in which case we may be toast.)  We should
+            really be keeping track of the total size of stubs added
+            here, as stubs contribute to the final output section
+            size.  That's a little tricky, and this way will only
+            break if stubs added make the total size more than 2^25,
+            ie. for the default stub_group_size, if stubs total more
+            than 2097152 bytes, or nearly 75000 plt call stubs.  */
          group = bfd_alloc (curr->owner, sizeof (*group));
          if (group == NULL)
            return FALSE;
@@ -12046,7 +12142,7 @@ group_sections (struct bfd_link_info *info,
            }
          while (tail != curr && (tail = prev) != NULL);
 
-         /* But wait, there's more!  Input sections up to stub_group_size
+         /* But wait, there's more!  Input sections up to group_size
             bytes before the stub section can be handled by it too.
             Don't do this if we have a really large section after the
             stubs, as adding more stubs increases the chance that
@@ -12058,7 +12154,7 @@ group_sections (struct bfd_link_info *info,
                     && ((total += tail->output_offset - prev->output_offset)
                         < (ppc64_elf_section_data (prev) != NULL
                            && ppc64_elf_section_data (prev)->has_14bit_branch
-                           ? stub14_group_size : stub_group_size))
+                           ? (group_size = stub_group_size >> 10) : group_size))
                     && htab->sec_info[prev->id].toc_off == curr_toc)
                {
                  tail = prev;
@@ -12177,6 +12273,13 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
   if (!group_sections (info, stub_group_size, stubs_always_before_branch))
     return FALSE;
 
+#define STUB_SHRINK_ITER 20
+  /* Loop until no stubs added.  After iteration 20 of this loop we may
+     exit on a stub section shrinking.  This is to break out of a
+     pathological case where adding stubs on one iteration decreases
+     section gaps (perhaps due to alignment), which then requires
+     fewer or smaller stubs on the next iteration.  */
+
   while (1)
     {
       bfd *input_bfd;
@@ -12558,11 +12661,11 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
           stub_sec != NULL;
           stub_sec = stub_sec->next)
        if ((stub_sec->flags & SEC_LINKER_CREATED) == 0
-           && stub_sec->rawsize != stub_sec->size)
+           && stub_sec->rawsize != stub_sec->size
+           && (htab->stub_iteration <= STUB_SHRINK_ITER
+               || stub_sec->rawsize < stub_sec->size))
          break;
 
-      /* Exit from this loop when no stubs have been added, and no stubs
-        have changed size.  */
       if (stub_sec == NULL
          && (htab->glink_eh_frame == NULL
              || htab->glink_eh_frame->rawsize == htab->glink_eh_frame->size))
@@ -12893,9 +12996,6 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
        stub_sec->contents = bfd_zalloc (htab->params->stub_bfd, stub_sec->size);
        if (stub_sec->contents == NULL)
          return FALSE;
-       /* We want to check that built size is the same as calculated
-          size.  rawsize is a convenient location to use.  */
-       stub_sec->rawsize = stub_sec->size;
        stub_sec->size = 0;
       }
 
@@ -13084,7 +13184,9 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
     if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
       {
        stub_sec_count += 1;
-       if (stub_sec->rawsize != stub_sec->size)
+       if (stub_sec->rawsize != stub_sec->size
+           && (htab->stub_iteration <= STUB_SHRINK_ITER
+               || stub_sec->rawsize < stub_sec->size))
          break;
       }
 
@@ -13915,6 +14017,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
          if (!bfd_link_pic (info)
              && !info->traditional_format
              && !htab->opd_abi
+             && rel->r_addend == d_offset
              && h != NULL && &h->elf == htab->elf.hgot
              && rel + 1 < relend
              && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_REL16_LO)
@@ -14662,22 +14765,12 @@ ppc64_elf_relocate_section (bfd *output_bfd,
          if (NO_OPD_RELOCS && is_opd)
            break;
 
-         if ((bfd_link_pic (info)
-              && (h == NULL
-                  || ELF_ST_VISIBILITY (h->elf.other) == STV_DEFAULT
-                  || h->elf.root.type != bfd_link_hash_undefweak)
-              && (must_be_dyn_reloc (info, r_type)
-                  || !SYMBOL_CALLS_LOCAL (info, &h->elf)))
-             || (ELIMINATE_COPY_RELOCS
-                 && !bfd_link_pic (info)
-                 && h != NULL
-                 && h->elf.dynindx != -1
-                 && !h->elf.non_got_ref
-                 && !h->elf.def_regular)
-             || (!bfd_link_pic (info)
-                 && (h != NULL
-                     ? h->elf.type == STT_GNU_IFUNC
-                     : ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)))
+         if (bfd_link_pic (info)
+             ? ((h != NULL && pc_dynrelocs (h))
+                || must_be_dyn_reloc (info, r_type))
+             : (h != NULL
+                ? h->dyn_relocs != NULL
+                : ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC))
            {
              bfd_boolean skip, relocate;
              asection *sreloc;
@@ -15138,13 +15231,11 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                           && (h->elf.root.type == bfd_link_hash_undefweak
                               || h->elf.root.type == bfd_link_hash_undefined)
                           && is_branch_reloc (r_type))))
-               {
-                 if (!((*info->callbacks->reloc_overflow)
-                       (info, &h->elf.root, sym_name,
-                        reloc_name, orig_rel.r_addend,
-                        input_bfd, input_section, rel->r_offset)))
-                   return FALSE;
-               }
+               info->callbacks->reloc_overflow (info, &h->elf.root,
+                                                sym_name, reloc_name,
+                                                orig_rel.r_addend,
+                                                input_bfd, input_section,
+                                                rel->r_offset);
            }
          else
            {
This page took 0.049098 seconds and 4 git commands to generate.