PR25351 .ARM.attributes not found for symbol
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 58fb83b4b2783d0918fba65a9f5e393040225702..300be3f7437fdd8dc84709521789edb109d759af 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF linking support for BFD.
-   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -20,7 +20,6 @@
 
 #include "sysdep.h"
 #include "bfd.h"
-#include "bfd_stdint.h"
 #include "bfdlink.h"
 #include "libbfd.h"
 #define ARCH_SIZE 0
@@ -77,7 +76,7 @@ _bfd_elf_section_for_symbol (struct elf_reloc_cookie *cookie,
       if ((h->root.type == bfd_link_hash_defined
           || h->root.type == bfd_link_hash_defweak)
           && discarded_section (h->root.u.def.section))
-        return h->root.u.def.section;
+       return h->root.u.def.section;
       else
        return NULL;
     }
@@ -163,13 +162,13 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
                                          (bed->dynamic_sec_flags
                                           | SEC_READONLY));
   if (s == NULL
-      || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+      || !bfd_set_section_alignment (s, bed->s->log_file_align))
     return FALSE;
   htab->srelgot = s;
 
   s = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
   if (s == NULL
-      || !bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+      || !bfd_set_section_alignment (s, bed->s->log_file_align))
     return FALSE;
   htab->sgot = s;
 
@@ -177,8 +176,7 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
     {
       s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
       if (s == NULL
-         || !bfd_set_section_alignment (abfd, s,
-                                        bed->s->log_file_align))
+         || !bfd_set_section_alignment (s, bed->s->log_file_align))
        return FALSE;
       htab->sgotplt = s;
     }
@@ -223,6 +221,7 @@ _bfd_elf_link_create_dynstrtab (bfd *abfd, struct bfd_link_info *info)
            if ((ibfd->flags
                 & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0
                && bfd_get_flavour (ibfd) == bfd_target_elf_flavour
+               && elf_object_id (ibfd) == elf_hash_table_id (hash_table)
                && !((s = ibfd->sections) != NULL
                     && s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS))
              {
@@ -286,25 +285,25 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   s = bfd_make_section_anyway_with_flags (abfd, ".gnu.version_d",
                                          flags | SEC_READONLY);
   if (s == NULL
-      || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+      || !bfd_set_section_alignment (s, bed->s->log_file_align))
     return FALSE;
 
   s = bfd_make_section_anyway_with_flags (abfd, ".gnu.version",
                                          flags | SEC_READONLY);
   if (s == NULL
-      || ! bfd_set_section_alignment (abfd, s, 1))
+      || !bfd_set_section_alignment (s, 1))
     return FALSE;
 
   s = bfd_make_section_anyway_with_flags (abfd, ".gnu.version_r",
                                          flags | SEC_READONLY);
   if (s == NULL
-      || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+      || !bfd_set_section_alignment (s, bed->s->log_file_align))
     return FALSE;
 
   s = bfd_make_section_anyway_with_flags (abfd, ".dynsym",
                                          flags | SEC_READONLY);
   if (s == NULL
-      || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+      || !bfd_set_section_alignment (s, bed->s->log_file_align))
     return FALSE;
   elf_hash_table (info)->dynsym = s;
 
@@ -315,7 +314,7 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 
   s = bfd_make_section_anyway_with_flags (abfd, ".dynamic", flags);
   if (s == NULL
-      || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+      || !bfd_set_section_alignment (s, bed->s->log_file_align))
     return FALSE;
 
   /* The special symbol _DYNAMIC is always set to the start of the
@@ -334,17 +333,17 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
       s = bfd_make_section_anyway_with_flags (abfd, ".hash",
                                              flags | SEC_READONLY);
       if (s == NULL
-         || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+         || !bfd_set_section_alignment (s, bed->s->log_file_align))
        return FALSE;
       elf_section_data (s)->this_hdr.sh_entsize = bed->s->sizeof_hash_entry;
     }
 
-  if (info->emit_gnu_hash)
+  if (info->emit_gnu_hash && bed->record_xhash_symbol == NULL)
     {
       s = bfd_make_section_anyway_with_flags (abfd, ".gnu.hash",
                                              flags | SEC_READONLY);
       if (s == NULL
-         || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+         || !bfd_set_section_alignment (s, bed->s->log_file_align))
        return FALSE;
       /* For 64-bit ELF, .gnu.hash is a non-uniform entity size section:
         4 32-bit words followed by variable count of 64-bit words, then
@@ -395,7 +394,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 
   s = bfd_make_section_anyway_with_flags (abfd, ".plt", pltflags);
   if (s == NULL
-      || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
+      || !bfd_set_section_alignment (s, bed->plt_alignment))
     return FALSE;
   htab->splt = s;
 
@@ -415,7 +414,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
                                           ? ".rela.plt" : ".rel.plt"),
                                          flags | SEC_READONLY);
   if (s == NULL
-      || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+      || !bfd_set_section_alignment (s, bed->s->log_file_align))
     return FALSE;
   htab->srelplt = s;
 
@@ -466,7 +465,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
                                                   ? ".rela.bss" : ".rel.bss"),
                                                  flags | SEC_READONLY);
          if (s == NULL
-             || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+             || !bfd_set_section_alignment (s, bed->s->log_file_align))
            return FALSE;
          htab->srelbss = s;
 
@@ -477,8 +476,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
                           ? ".rela.data.rel.ro" : ".rel.data.rel.ro"),
                    flags | SEC_READONLY));
              if (s == NULL
-                 || ! bfd_set_section_alignment (abfd, s,
-                                                 bed->s->log_file_align))
+                 || !bfd_set_section_alignment (s, bed->s->log_file_align))
                return FALSE;
              htab->sreldynrelro = s;
            }
@@ -586,7 +584,12 @@ bfd_elf_link_mark_dynamic_symbol (struct bfd_link_info *info,
       || (d != NULL
          && h->non_elf
          && (*d->match) (&d->head, NULL, h->root.root.string)))
-    h->dynamic = 1;
+    {
+      h->dynamic = 1;
+      /* NB: If a symbol is made dynamic by --dynamic-list, it has
+        non-IR reference.  */
+      h->root.non_ir_ref_dynamic = 1;
+    }
 }
 
 /* Record an assignment to a symbol made by a linker script.  We need
@@ -681,13 +684,11 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
       && !h->def_regular)
     h->root.type = bfd_link_hash_undefined;
 
-  /* If this symbol is not being provided by the linker script, and it is
-     currently defined by a dynamic object, but not by a regular object,
-     then clear out any version information because the symbol will not be
-     associated with the dynamic object any more.  */
-  if (!provide
-      && h->def_dynamic
-      && !h->def_regular)
+  /* If this symbol is currently defined by a dynamic object, but not
+     by a regular object, then clear out any version information because
+     the symbol will not be associated with the dynamic object any
+     more.  */
+  if (h->def_dynamic && !h->def_regular)
     h->verinfo.verdef = NULL;
 
   /* Make sure this symbol is not garbage collected.  */
@@ -715,6 +716,7 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
        || h->ref_dynamic
        || bfd_link_dll (info)
        || elf_hash_table (info)->is_relocatable_executable)
+      && !h->forced_local
       && h->dynindx == -1)
     {
       if (! bfd_elf_link_record_dynamic_symbol (info, h))
@@ -723,10 +725,12 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
       /* If this is a weak defined symbol, and we know a corresponding
         real symbol from the same dynamic object, make sure the real
         symbol is also made into a dynamic symbol.  */
-      if (h->u.weakdef != NULL
-         && h->u.weakdef->dynindx == -1)
+      if (h->is_weakalias)
        {
-         if (! bfd_elf_link_record_dynamic_symbol (info, h->u.weakdef))
+         struct elf_link_hash_entry *def = weakdef (h);
+
+         if (def->dynindx == -1
+             && !bfd_elf_link_record_dynamic_symbol (info, def))
            return FALSE;
        }
     }
@@ -879,9 +883,9 @@ elf_link_renumber_local_hash_table_dynsyms (struct elf_link_hash_entry *h,
 /* Return true if the dynamic symbol for a given section should be
    omitted when creating a shared library.  */
 bfd_boolean
-_bfd_elf_link_omit_section_dynsym (bfd *output_bfd ATTRIBUTE_UNUSED,
-                                  struct bfd_link_info *info,
-                                  asection *p)
+_bfd_elf_omit_section_dynsym_default (bfd *output_bfd ATTRIBUTE_UNUSED,
+                                     struct bfd_link_info *info,
+                                     asection *p)
 {
   struct elf_link_hash_table *htab;
   asection *ip;
@@ -894,9 +898,6 @@ _bfd_elf_link_omit_section_dynsym (bfd *output_bfd ATTRIBUTE_UNUSED,
         SHT_PROGBITS/SHT_NOBITS.  */
     case SHT_NULL:
       htab = elf_hash_table (info);
-      if (p == htab->tls_sec)
-       return FALSE;
-
       if (htab->text_index_section != NULL)
        return p != htab->text_index_section && p != htab->data_index_section;
 
@@ -911,11 +912,23 @@ _bfd_elf_link_omit_section_dynsym (bfd *output_bfd ATTRIBUTE_UNUSED,
     }
 }
 
+bfd_boolean
+_bfd_elf_omit_section_dynsym_all
+    (bfd *output_bfd ATTRIBUTE_UNUSED,
+     struct bfd_link_info *info ATTRIBUTE_UNUSED,
+     asection *p ATTRIBUTE_UNUSED)
+{
+  return TRUE;
+}
+
 /* Assign dynsym indices.  In a shared library we generate a section
    symbol for each output section, which come first.  Next come symbols
    which have been forced to local binding.  Then all of the back-end
    allocated local dynamic syms, followed by the rest of the global
-   symbols.  */
+   symbols.  If SECTION_SYM_COUNT is NULL, section dynindx is not set.
+   (This prevents the early call before elf_backend_init_index_section
+   and strip_excluded_output_sections setting dynindx for sections
+   that are stripped.)  */
 
 static unsigned long
 _bfd_elf_link_renumber_dynsyms (bfd *output_bfd,
@@ -923,6 +936,7 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd,
                                unsigned long *section_sym_count)
 {
   unsigned long dynsymcount = 0;
+  bfd_boolean do_sec = section_sym_count != NULL;
 
   if (bfd_link_pic (info)
       || elf_hash_table (info)->is_relocatable_executable)
@@ -932,12 +946,18 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd,
       for (p = output_bfd->sections; p ; p = p->next)
        if ((p->flags & SEC_EXCLUDE) == 0
            && (p->flags & SEC_ALLOC) != 0
+           && elf_hash_table (info)->dynamic_relocs
            && !(*bed->elf_backend_omit_section_dynsym) (output_bfd, info, p))
-         elf_section_data (p)->dynindx = ++dynsymcount;
-       else
+         {
+           ++dynsymcount;
+           if (do_sec)
+             elf_section_data (p)->dynindx = dynsymcount;
+         }
+       else if (do_sec)
          elf_section_data (p)->dynindx = 0;
     }
-  *section_sym_count = dynsymcount;
+  if (do_sec)
+    *section_sym_count = dynsymcount;
 
   elf_link_hash_traverse (elf_hash_table (info),
                          elf_link_renumber_local_hash_table_dynsyms,
@@ -1036,6 +1056,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
   bfd_boolean newweak, oldweak, newfunc, oldfunc;
   const struct elf_backend_data *bed;
   char *new_version;
+  bfd_boolean default_sym = *matched;
 
   *skip = FALSE;
   *override = FALSE;
@@ -1161,11 +1182,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
   if (pold_weak)
     *pold_weak = oldweak;
 
-  /* This code is for coping with dynamic objects, and is only useful
-     if we are doing an ELF link.  */
-  if (!(*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
-    return TRUE;
-
   /* We have to check it for every instance since the first few may be
      references and not all compilers emit symbol type for undefined
      symbols.  */
@@ -1234,6 +1250,16 @@ _bfd_elf_merge_symbol (bfd *abfd,
       olddyn = (oldsec->symbol->flags & BSF_DYNAMIC) != 0;
     }
 
+  /* Handle a case where plugin_notice won't be called and thus won't
+     set the non_ir_ref flags on the first pass over symbols.  */
+  if (oldbfd != NULL
+      && (oldbfd->flags & BFD_PLUGIN) != (abfd->flags & BFD_PLUGIN)
+      && newdyn != olddyn)
+    {
+      h->root.non_ir_ref_dynamic = TRUE;
+      hi->root.non_ir_ref_dynamic = TRUE;
+    }
+
   /* NEWDEF and OLDDEF indicate whether the new or old symbol,
      respectively, appear to be a definition rather than reference.  */
 
@@ -1333,26 +1359,26 @@ _bfd_elf_merge_symbol (bfd *abfd,
       if (tdef && ntdef)
        _bfd_error_handler
          /* xgettext:c-format */
-         (_("%s: TLS definition in %B section %A "
-            "mismatches non-TLS definition in %B section %A"),
+         (_("%s: TLS definition in %pB section %pA "
+            "mismatches non-TLS definition in %pB section %pA"),
           h->root.root.string, tbfd, tsec, ntbfd, ntsec);
       else if (!tdef && !ntdef)
        _bfd_error_handler
          /* xgettext:c-format */
-         (_("%s: TLS reference in %B "
-            "mismatches non-TLS reference in %B"),
+         (_("%s: TLS reference in %pB "
+            "mismatches non-TLS reference in %pB"),
           h->root.root.string, tbfd, ntbfd);
       else if (tdef)
        _bfd_error_handler
          /* xgettext:c-format */
-         (_("%s: TLS definition in %B section %A "
-            "mismatches non-TLS reference in %B"),
+         (_("%s: TLS definition in %pB section %pA "
+            "mismatches non-TLS reference in %pB"),
           h->root.root.string, tbfd, tsec, ntbfd);
       else
        _bfd_error_handler
          /* xgettext:c-format */
-         (_("%s: TLS reference in %B "
-            "mismatches non-TLS definition in %B section %A"),
+         (_("%s: TLS reference in %pB "
+            "mismatches non-TLS definition in %pB section %pA"),
           h->root.root.string, tbfd, ntbfd, ntsec);
 
       bfd_set_error (bfd_error_bad_value);
@@ -1463,10 +1489,15 @@ _bfd_elf_merge_symbol (bfd *abfd,
      treated as strong if the new symbol is from a dynamic library.
      This reflects the way glibc's ld.so works.
 
+     Also allow a weak symbol to override a linker script symbol
+     defined by an early pass over the script.  This is done so the
+     linker knows the symbol is defined in an object file, for the
+     DEFINED script function.
+
      Do this before setting *type_change_ok or *size_change_ok so that
      we warn properly when dynamic library symbols are overridden.  */
 
-  if (newdef && !newdyn && olddyn)
+  if (newdef && !newdyn && (olddyn || h->root.ldscript_def))
     newweak = FALSE;
   if (olddef && newdyn)
     oldweak = FALSE;
@@ -1547,6 +1578,21 @@ _bfd_elf_merge_symbol (bfd *abfd,
       sec = *psec;
     }
 
+  /* There are multiple definitions of a normal symbol.  Skip the
+     default symbol as well as definition from an IR object.  */
+  if (olddef && !olddyn && !oldweak && newdef && !newdyn && !newweak
+      && !default_sym && h->def_regular
+      && !(oldbfd != NULL
+          && (oldbfd->flags & BFD_PLUGIN) != 0
+          && (abfd->flags & BFD_PLUGIN) == 0))
+    {
+      /* Handle a multiple definition.  */
+      (*info->callbacks->multiple_definition) (info, &h->root,
+                                              abfd, sec, *pvalue);
+      *skip = TRUE;
+      return TRUE;
+    }
+
   /* If both the old and the new symbols look like common symbols in a
      dynamic object, set the size of the symbol to the larger of the
      two.  */
@@ -1858,7 +1904,7 @@ _bfd_elf_add_default_symbol (bfd *abfd,
   if (skip)
     goto nondefault;
 
-  if (hi->def_regular)
+  if (hi->def_regular || ELF_COMMON_DEF_P (hi))
     {
       /* If the undecorated symbol will have a version added by a
         script different to H, then don't indirect to/from the
@@ -1889,6 +1935,16 @@ _bfd_elf_add_default_symbol (bfd *abfd,
       if (! bfd_link_relocatable (info))
        {
          bh = &hi->root;
+         if (bh->type == bfd_link_hash_defined
+             && bh->u.def.section->owner != NULL
+             && (bh->u.def.section->owner->flags & BFD_PLUGIN) != 0)
+           {
+             /* Mark the previous definition from IR object as
+                undefined so that the generic linker will override
+                it.  */
+             bh->type = bfd_link_hash_undefined;
+             bh->u.undef.abfd = bh->u.def.section->owner;
+           }
          if (! (_bfd_generic_link_add_one_symbol
                 (info, abfd, shortname, BSF_INDIRECT,
                  bfd_ind_section_ptr,
@@ -2012,7 +2068,7 @@ nondefault:
          && hi->root.type != bfd_link_hash_defweak)
        _bfd_error_handler
          /* xgettext:c-format */
-         (_("%B: unexpected redefinition of indirect versioned symbol `%s'"),
+         (_("%pB: unexpected redefinition of indirect versioned symbol `%s'"),
           abfd, shortname);
     }
   else
@@ -2170,6 +2226,115 @@ _bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h,
   return TRUE;
 }
 
+/* Return TRUE and set *HIDE to TRUE if the versioned symbol is
+   hidden.  Set *T_P to NULL if there is no match.  */
+
+static bfd_boolean
+_bfd_elf_link_hide_versioned_symbol (struct bfd_link_info *info,
+                                    struct elf_link_hash_entry *h,
+                                    const char *version_p,
+                                    struct bfd_elf_version_tree **t_p,
+                                    bfd_boolean *hide)
+{
+  struct bfd_elf_version_tree *t;
+
+  /* Look for the version.  If we find it, it is no longer weak.  */
+  for (t = info->version_info; t != NULL; t = t->next)
+    {
+      if (strcmp (t->name, version_p) == 0)
+       {
+         size_t len;
+         char *alc;
+         struct bfd_elf_version_expr *d;
+
+         len = version_p - h->root.root.string;
+         alc = (char *) bfd_malloc (len);
+         if (alc == NULL)
+           return FALSE;
+         memcpy (alc, h->root.root.string, len - 1);
+         alc[len - 1] = '\0';
+         if (alc[len - 2] == ELF_VER_CHR)
+           alc[len - 2] = '\0';
+
+         h->verinfo.vertree = t;
+         t->used = TRUE;
+         d = NULL;
+
+         if (t->globals.list != NULL)
+           d = (*t->match) (&t->globals, NULL, alc);
+
+         /* See if there is anything to force this symbol to
+            local scope.  */
+         if (d == NULL && t->locals.list != NULL)
+           {
+             d = (*t->match) (&t->locals, NULL, alc);
+             if (d != NULL
+                 && h->dynindx != -1
+                 && ! info->export_dynamic)
+               *hide = TRUE;
+           }
+
+         free (alc);
+         break;
+       }
+    }
+
+  *t_p = t;
+
+  return TRUE;
+}
+
+/* Return TRUE if the symbol H is hidden by version script.  */
+
+bfd_boolean
+_bfd_elf_link_hide_sym_by_version (struct bfd_link_info *info,
+                                  struct elf_link_hash_entry *h)
+{
+  const char *p;
+  bfd_boolean hide = FALSE;
+  const struct elf_backend_data *bed
+    = get_elf_backend_data (info->output_bfd);
+
+  /* Version script only hides symbols defined in regular objects.  */
+  if (!h->def_regular && !ELF_COMMON_DEF_P (h))
+    return TRUE;
+
+  p = strchr (h->root.root.string, ELF_VER_CHR);
+  if (p != NULL && h->verinfo.vertree == NULL)
+    {
+      struct bfd_elf_version_tree *t;
+
+      ++p;
+      if (*p == ELF_VER_CHR)
+       ++p;
+
+      if (*p != '\0'
+         && _bfd_elf_link_hide_versioned_symbol (info, h, p, &t, &hide)
+         && hide)
+       {
+         if (hide)
+           (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+         return TRUE;
+       }
+    }
+
+  /* If we don't have a version for this symbol, see if we can find
+     something.  */
+  if (h->verinfo.vertree == NULL && info->version_info != NULL)
+    {
+      h->verinfo.vertree
+       = bfd_find_version_for_sym (info->version_info,
+                                   h->root.root.string, &hide);
+      if (h->verinfo.vertree != NULL && hide)
+       {
+         (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+         return TRUE;
+       }
+    }
+
+  return FALSE;
+}
+
 /* Figure out appropriate versions for all the symbols.  We may not
    have the version number script until we have read all of the input
    files, so until that point we don't know which symbols should be
@@ -2183,6 +2348,7 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
   const struct elf_backend_data *bed;
   struct elf_info_failed eif;
   char *p;
+  bfd_boolean hide;
 
   sinfo = (struct elf_info_failed *) data;
   info = sinfo->info;
@@ -2197,12 +2363,21 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
       return FALSE;
     }
 
+  bed = get_elf_backend_data (info->output_bfd);
+
   /* We only need version numbers for symbols defined in regular
      objects.  */
-  if (!h->def_regular)
-    return TRUE;
+  if (!h->def_regular && !ELF_COMMON_DEF_P (h))
+    {
+      /* Hide symbols defined in discarded input sections.  */
+      if ((h->root.type == bfd_link_hash_defined
+          || h->root.type == bfd_link_hash_defweak)
+         && discarded_section (h->root.u.def.section))
+       (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+      return TRUE;
+    }
 
-  bed = get_elf_backend_data (info->output_bfd);
+  hide = FALSE;
   p = strchr (h->root.root.string, ELF_VER_CHR);
   if (p != NULL && h->verinfo.vertree == NULL)
     {
@@ -2216,50 +2391,15 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
       if (*p == '\0')
        return TRUE;
 
-      /* Look for the version.  If we find it, it is no longer weak.  */
-      for (t = sinfo->info->version_info; t != NULL; t = t->next)
+      if (!_bfd_elf_link_hide_versioned_symbol (info, h, p, &t, &hide))
        {
-         if (strcmp (t->name, p) == 0)
-           {
-             size_t len;
-             char *alc;
-             struct bfd_elf_version_expr *d;
-
-             len = p - h->root.root.string;
-             alc = (char *) bfd_malloc (len);
-             if (alc == NULL)
-               {
-                 sinfo->failed = TRUE;
-                 return FALSE;
-               }
-             memcpy (alc, h->root.root.string, len - 1);
-             alc[len - 1] = '\0';
-             if (alc[len - 2] == ELF_VER_CHR)
-               alc[len - 2] = '\0';
-
-             h->verinfo.vertree = t;
-             t->used = TRUE;
-             d = NULL;
-
-             if (t->globals.list != NULL)
-               d = (*t->match) (&t->globals, NULL, alc);
-
-             /* See if there is anything to force this symbol to
-                local scope.  */
-             if (d == NULL && t->locals.list != NULL)
-               {
-                 d = (*t->match) (&t->locals, NULL, alc);
-                 if (d != NULL
-                     && h->dynindx != -1
-                     && ! info->export_dynamic)
-                   (*bed->elf_backend_hide_symbol) (info, h, TRUE);
-               }
-
-             free (alc);
-             break;
-           }
+         sinfo->failed = TRUE;
+         return FALSE;
        }
 
+      if (hide)
+       (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+
       /* If we are building an application, we need to create a
         version node for this version.  */
       if (t == NULL && bfd_link_executable (info))
@@ -2305,7 +2445,7 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
             generating a shared archive.  Return an error.  */
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B: version node not found for symbol %s"),
+           (_("%pB: version node not found for symbol %s"),
             info->output_bfd, h->root.root.string);
          bfd_set_error (bfd_error_bad_value);
          sinfo->failed = TRUE;
@@ -2315,10 +2455,10 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
 
   /* If we don't have a version for this symbol, see if we can find
      something.  */
-  if (h->verinfo.vertree == NULL && sinfo->info->version_info != NULL)
+  if (!hide
+      && h->verinfo.vertree == NULL
+      && sinfo->info->version_info != NULL)
     {
-      bfd_boolean hide;
-
       h->verinfo.vertree
        = bfd_find_version_for_sym (sinfo->info->version_info,
                                    h->root.root.string, &hide);
@@ -2378,9 +2518,11 @@ elf_link_read_relocs_from_section (bfd *abfd,
     }
 
   erela = (const bfd_byte *) external_relocs;
-  erelaend = erela + shdr->sh_size;
+  /* Setting erelaend like this and comparing with <= handles case of
+     a fuzzed object with sh_size not a multiple of sh_entsize.  */
+  erelaend = erela + shdr->sh_size - shdr->sh_entsize;
   irela = internal_relocs;
-  while (erela < erelaend)
+  while (erela <= erelaend)
     {
       bfd_vma r_symndx;
 
@@ -2394,10 +2536,10 @@ elf_link_read_relocs_from_section (bfd *abfd,
            {
              _bfd_error_handler
                /* xgettext:c-format */
-               (_("%B: bad reloc symbol index (%#Lx >= %#lx)"
-                  " for offset %#Lx in section `%A'"),
-                abfd, r_symndx, (unsigned long) nsyms,
-                irela->r_offset, sec);
+               (_("%pB: bad reloc symbol index (%#" PRIx64 " >= %#lx)"
+                  " for offset %#" PRIx64 " in section `%pA'"),
+                abfd, (uint64_t) r_symndx, (unsigned long) nsyms,
+                (uint64_t) irela->r_offset, sec);
              bfd_set_error (bfd_error_bad_value);
              return FALSE;
            }
@@ -2406,11 +2548,11 @@ elf_link_read_relocs_from_section (bfd *abfd,
        {
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B: non-zero symbol index (%#Lx)"
-              " for offset %#Lx in section `%A'"
+           (_("%pB: non-zero symbol index (%#" PRIx64 ")"
+              " for offset %#" PRIx64 " in section `%pA'"
               " when the object file has no symbol table"),
-            abfd, r_symndx,
-            irela->r_offset, sec);
+            abfd, (uint64_t) r_symndx,
+            (uint64_t) irela->r_offset, sec);
          bfd_set_error (bfd_error_bad_value);
          return FALSE;
        }
@@ -2597,7 +2739,7 @@ _bfd_elf_link_output_relocs (bfd *output_bfd,
     {
       _bfd_error_handler
        /* xgettext:c-format */
-       (_("%B: relocation size mismatch in %B section %A"),
+       (_("%pB: relocation size mismatch in %pB section %pA"),
         output_bfd, input_section->owner, input_section);
       bfd_set_error (bfd_error_wrong_format);
       return FALSE;
@@ -2724,10 +2866,14 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
       && (h->root.u.def.section->owner->flags & (DYNAMIC | BFD_PLUGIN)) == 0)
     h->def_regular = 1;
 
+  /* Symbols defined in discarded sections shouldn't be dynamic.  */
+  if (h->root.type == bfd_link_hash_undefined && h->indx == -3)
+    (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
+
   /* If a weak undefined symbol has non-default visibility, we also
      hide it from the dynamic linker.  */
-  if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
-      && h->root.type == bfd_link_hash_undefweak)
+  else if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+          && h->root.type == bfd_link_hash_undefweak)
     (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
 
   /* A hidden versioned symbol in executable should be forced local if
@@ -2764,26 +2910,35 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
   /* If this is a weak defined symbol in a dynamic object, and we know
      the real definition in the dynamic object, copy interesting flags
      over to the real definition.  */
-  if (h->u.weakdef != NULL)
+  if (h->is_weakalias)
     {
+      struct elf_link_hash_entry *def = weakdef (h);
+
       /* If the real definition is defined by a regular object file,
         don't do anything special.  See the longer description in
-        _bfd_elf_adjust_dynamic_symbol, below.  */
-      if (h->u.weakdef->def_regular)
-       h->u.weakdef = NULL;
+        _bfd_elf_adjust_dynamic_symbol, below.  If the def is not
+        bfd_link_hash_defined as it was when put on the alias list
+        then it must have originally been a versioned symbol (for
+        which a non-versioned indirect symbol is created) and later
+        a definition for the non-versioned symbol is found.  In that
+        case the indirection is flipped with the versioned symbol
+        becoming an indirect pointing at the non-versioned symbol.
+        Thus, not an alias any more.  */
+      if (def->def_regular
+         || def->root.type != bfd_link_hash_defined)
+       {
+         h = def;
+         while ((h = h->u.alias) != def)
+           h->is_weakalias = 0;
+       }
       else
        {
-         struct elf_link_hash_entry *weakdef = h->u.weakdef;
-
          while (h->root.type == bfd_link_hash_indirect)
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
          BFD_ASSERT (h->root.type == bfd_link_hash_defined
                      || h->root.type == bfd_link_hash_defweak);
-         BFD_ASSERT (weakdef->def_dynamic);
-         BFD_ASSERT (weakdef->root.type == bfd_link_hash_defined
-                     || weakdef->root.type == bfd_link_hash_defweak);
-         (*bed->elf_backend_copy_indirect_symbol) (eif->info, weakdef, h);
+         BFD_ASSERT (def->def_dynamic);
+         (*bed->elf_backend_copy_indirect_symbol) (eif->info, def, h);
        }
     }
 
@@ -2798,7 +2953,7 @@ static bfd_boolean
 _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
 {
   struct elf_info_failed *eif = (struct elf_info_failed *) data;
-  bfd *dynobj;
+  struct elf_link_hash_table *htab;
   const struct elf_backend_data *bed;
 
   if (! is_elf_hash_table (eif->info->hash))
@@ -2812,10 +2967,13 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
   if (! _bfd_elf_fix_symbol_flags (h, eif))
     return FALSE;
 
+  htab = elf_hash_table (eif->info);
+  bed = get_elf_backend_data (htab->dynobj);
+
   if (h->root.type == bfd_link_hash_undefweak)
     {
       if (eif->info->dynamic_undefined_weak == 0)
-       _bfd_elf_link_hash_hide_symbol (eif->info, h, TRUE);
+       (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
       else if (eif->info->dynamic_undefined_weak > 0
               && h->ref_regular
               && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
@@ -2842,7 +3000,7 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
       && (h->def_regular
          || !h->def_dynamic
          || (!h->ref_regular
-             && (h->u.weakdef == NULL || h->u.weakdef->dynindx == -1))))
+             && (!h->is_weakalias || weakdef (h)->dynindx == -1))))
     {
       h->plt = elf_hash_table (eif->info)->init_plt_offset;
       return TRUE;
@@ -2887,15 +3045,17 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
      wind up at different memory locations.  The tzset call will set
      _timezone, leaving timezone unchanged.  */
 
-  if (h->u.weakdef != NULL)
+  if (h->is_weakalias)
     {
+      struct elf_link_hash_entry *def = weakdef (h);
+
       /* If we get to this point, there is an implicit reference to
-        H->U.WEAKDEF by a regular object file via the weak symbol H.  */
-      h->u.weakdef->ref_regular = 1;
+        the alias by a regular object file via the weak symbol H.  */
+      def->ref_regular = 1;
 
       /* Ensure that the backend adjust_dynamic_symbol function sees
-        H->U.WEAKDEF before H by recursively calling ourselves.  */
-      if (! _bfd_elf_adjust_dynamic_symbol (h->u.weakdef, eif))
+        the strong alias before H by recursively calling ourselves.  */
+      if (!_bfd_elf_adjust_dynamic_symbol (def, eif))
        return FALSE;
     }
 
@@ -2911,9 +3071,6 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
       (_("warning: type and size of dynamic symbol `%s' are not defined"),
        h->root.root.string);
 
-  dynobj = elf_hash_table (eif->info)->dynobj;
-  bed = get_elf_backend_data (dynobj);
-
   if (! (*bed->elf_backend_adjust_dynamic_symbol) (eif->info, h))
     {
       eif->failed = TRUE;
@@ -2940,7 +3097,7 @@ _bfd_elf_adjust_dynamic_copy (struct bfd_link_info *info,
      know the symbol alignment requirement, we start with the
      maximum alignment and check low bits of the symbol address
      for the minimum alignment.  */
-  power_of_two = bfd_get_section_alignment (sec->owner, sec);
+  power_of_two = bfd_section_alignment (sec);
   mask = ((bfd_vma) 1 << power_of_two) - 1;
   while ((h->root.u.def.value & mask) != 0)
     {
@@ -2948,12 +3105,10 @@ _bfd_elf_adjust_dynamic_copy (struct bfd_link_info *info,
        --power_of_two;
     }
 
-  if (power_of_two > bfd_get_section_alignment (dynbss->owner,
-                                               dynbss))
+  if (power_of_two > bfd_section_alignment (dynbss))
     {
       /* Adjust the section alignment if needed.  */
-      if (! bfd_set_section_alignment (dynbss->owner, dynbss,
-                                      power_of_two))
+      if (!bfd_set_section_alignment (dynbss, power_of_two))
        return FALSE;
     }
 
@@ -2973,7 +3128,7 @@ _bfd_elf_adjust_dynamic_copy (struct bfd_link_info *info,
          || (info->extern_protected_data < 0
              && !get_elf_backend_data (dynbss->owner)->extern_protected_data)))
     info->callbacks->einfo
-      (_("%P: copy reloc against protected `%T' is dangerous\n"),
+      (_("%P: copy reloc against protected `%pT' is dangerous\n"),
        h->root.root.string);
 
   return TRUE;
@@ -3324,6 +3479,9 @@ _bfd_elf_add_dynamic_entry (struct bfd_link_info *info,
   if (! is_elf_hash_table (hash_table))
     return FALSE;
 
+  if (tag == DT_RELA || tag == DT_REL)
+    hash_table->dynamic_relocs = TRUE;
+
   bed = get_elf_backend_data (hash_table->dynobj);
   s = bfd_get_linker_section (hash_table->dynobj, ".dynamic");
   BFD_ASSERT (s != NULL);
@@ -3429,27 +3587,60 @@ on_needed_list (const char *soname,
   return FALSE;
 }
 
-/* Sort symbol by value, section, and size.  */
+/* Sort symbol by value, section, size, and type.  */
 static int
 elf_sort_symbol (const void *arg1, const void *arg2)
 {
   const struct elf_link_hash_entry *h1;
   const struct elf_link_hash_entry *h2;
   bfd_signed_vma vdiff;
+  int sdiff;
+  const char *n1;
+  const char *n2;
 
   h1 = *(const struct elf_link_hash_entry **) arg1;
   h2 = *(const struct elf_link_hash_entry **) arg2;
   vdiff = h1->root.u.def.value - h2->root.u.def.value;
   if (vdiff != 0)
     return vdiff > 0 ? 1 : -1;
-  else
-    {
-      int sdiff = h1->root.u.def.section->id - h2->root.u.def.section->id;
-      if (sdiff != 0)
-       return sdiff > 0 ? 1 : -1;
-    }
+
+  sdiff = h1->root.u.def.section->id - h2->root.u.def.section->id;
+  if (sdiff != 0)
+    return sdiff;
+
+  /* Sort so that sized symbols are selected over zero size symbols.  */
   vdiff = h1->size - h2->size;
-  return vdiff == 0 ? 0 : vdiff > 0 ? 1 : -1;
+  if (vdiff != 0)
+    return vdiff > 0 ? 1 : -1;
+
+  /* Sort so that STT_OBJECT is selected over STT_NOTYPE.  */
+  if (h1->type != h2->type)
+    return h1->type - h2->type;
+
+  /* If symbols are properly sized and typed, and multiple strong
+     aliases are not defined in a shared library by the user we
+     shouldn't get here.  Unfortunately linker script symbols like
+     __bss_start sometimes match a user symbol defined at the start of
+     .bss without proper size and type.  We'd like to preference the
+     user symbol over reserved system symbols.  Sort on leading
+     underscores.  */
+  n1 = h1->root.root.string;
+  n2 = h2->root.root.string;
+  while (*n1 == *n2)
+    {
+      if (*n1 == 0)
+       break;
+      ++n1;
+      ++n2;
+    }
+  if (*n1 == '_')
+    return -1;
+  if (*n2 == '_')
+    return 1;
+
+  /* Final sort on name selects user symbols like '_u' over reserved
+     system symbols like '_Z' and also will avoid qsort instability.  */
+  return *n1 - *n2;
 }
 
 /* This function is used to adjust offsets into .dynstr for
@@ -3717,6 +3908,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   struct elf_link_hash_entry **sym_hash;
   bfd_boolean dynamic;
   Elf_External_Versym *extversym = NULL;
+  Elf_External_Versym *extversym_end = NULL;
   Elf_External_Versym *ever;
   struct elf_link_hash_entry *weaks;
   struct elf_link_hash_entry **nondeflt_vers = NULL;
@@ -3772,9 +3964,9 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
           && ehdr->e_machine == bed->elf_machine_alt1)
          || (bed->elf_machine_alt2 != 0
              && ehdr->e_machine == bed->elf_machine_alt2)))
-    info->callbacks->einfo
+    _bfd_error_handler
       /* xgettext:c-format */
-      (_("%P: alternate ELF machine code found (%d) in %B, expecting %d\n"),
+      (_("alternate ELF machine code found (%d) in %pB, expecting %d"),
        ehdr->e_machine, abfd, bed->elf_machine_code);
 
   /* As a GNU extension, any input sections which are named
@@ -3786,7 +3978,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
     {
       const char *name;
 
-      name = bfd_get_section_name (abfd, s);
+      name = bfd_section_name (s);
       if (CONST_STRNEQ (name, ".gnu.warning."))
        {
          char *msg;
@@ -3917,7 +4109,7 @@ error_free_dyn:
          shlink = elf_elfsections (abfd)[elfsec]->sh_link;
 
          for (extdyn = dynbuf;
-              extdyn < dynbuf + s->size;
+              extdyn <= dynbuf + s->size - bed->s->sizeof_dyn;
               extdyn += bed->s->sizeof_dyn)
            {
              Elf_Internal_Dyn dyn;
@@ -4031,7 +4223,7 @@ error_free_dyn:
         all sections contained fully therein.  This makes relro
         shared library sections appear as they will at run-time.  */
       phdr = elf_tdata (abfd)->phdr + elf_elfheader (abfd)->e_phnum;
-      while (--phdr >= elf_tdata (abfd)->phdr)
+      while (phdr-- > elf_tdata (abfd)->phdr)
        if (phdr->p_type == PT_GNU_RELRO)
          {
            for (s = abfd->sections; s != NULL; s = s->next)
@@ -4142,13 +4334,14 @@ error_free_dyn:
          Elf_Internal_Shdr *versymhdr;
 
          versymhdr = &elf_tdata (abfd)->dynversym_hdr;
-         extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size);
+         amt = versymhdr->sh_size;
+         extversym = (Elf_External_Versym *) bfd_malloc (amt);
          if (extversym == NULL)
            goto error_free_sym;
-         amt = versymhdr->sh_size;
          if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0
              || bfd_bread (extversym, amt, abfd) != amt)
            goto error_free_vers;
+         extversym_end = extversym + (amt / sizeof (* extversym));
        }
     }
 
@@ -4223,7 +4416,27 @@ error_free_dyn:
     }
 
   weaks = NULL;
-  ever = extversym != NULL ? extversym + extsymoff : NULL;
+  if (extversym == NULL)
+    ever = NULL;
+  else if (extversym + extsymoff < extversym_end)
+    ever = extversym + extsymoff;
+  else
+    {
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%pB: invalid version offset %lx (max %lx)"),
+                         abfd, (long) extsymoff,
+                         (long) (extversym_end - extversym) / sizeof (* extversym));
+      bfd_set_error (bfd_error_bad_value);
+      goto error_free_vers;
+    }
+
+  if (!bfd_link_relocatable (info)
+      && abfd->lto_slim_object)
+    {
+      _bfd_error_handler
+       (_("%pB: plugin needed to handle lto object"), abfd);
+    }
+
   for (isym = isymbuf, isymend = isymbuf + extsymcount;
        isym < isymend;
        isym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL))
@@ -4238,13 +4451,13 @@ error_free_dyn:
       bfd_boolean definition;
       bfd_boolean size_change_ok;
       bfd_boolean type_change_ok;
-      bfd_boolean new_weakdef;
       bfd_boolean new_weak;
       bfd_boolean old_weak;
       bfd_boolean override;
       bfd_boolean common;
       bfd_boolean discarded;
       unsigned int old_alignment;
+      unsigned int shindex;
       bfd *old_bfd;
       bfd_boolean matched;
 
@@ -4270,7 +4483,25 @@ error_free_dyn:
             global symbols follow all local symbols, and that sh_info
             point to the first global symbol.  Unfortunately, Irix 5
             screws this up.  */
-         continue;
+         if (elf_bad_symtab (abfd))
+           continue;
+
+         /* If we aren't prepared to handle locals within the globals
+            then we'll likely segfault on a NULL symbol hash if the
+            symbol is ever referenced in relocations.  */
+         shindex = elf_elfheader (abfd)->e_shstrndx;
+         name = bfd_elf_string_from_elf_section (abfd, shindex, hdr->sh_name);
+         _bfd_error_handler (_("%pB: %s local symbol at index %lu"
+                               " (>= sh_info of %lu)"),
+                             abfd, name, (long) (isym - isymbuf + extsymoff),
+                             (long) extsymoff);
+
+         /* Dynamic object relocations are not processed by ld, so
+            ld won't run into the problem mentioned above.  */
+         if (dynamic)
+           continue;
+         bfd_set_error (bfd_error_bad_value);
+         goto error_free_vers;
 
        case STB_GLOBAL:
          if (isym->st_shndx != SHN_UNDEF && !common)
@@ -4368,10 +4599,7 @@ error_free_dyn:
 
       /* Sanity check that all possibilities were handled.  */
       if (sec == NULL)
-       {
-         bfd_set_error (bfd_error_bad_value);
-         goto error_free_vers;
-       }
+       abort ();
 
       /* Silently discard TLS symbols from --just-syms.  There's
         no way to combine a static TLS block with a new TLS block
@@ -4408,6 +4636,14 @@ error_free_dyn:
              else
                iver.vs_vers = 0;
            }
+         else if (ever >= extversym_end)
+           {
+             /* xgettext:c-format */
+             _bfd_error_handler (_("%pB: not enough version information"),
+                                 abfd);
+             bfd_set_error (bfd_error_bad_value);
+             goto error_free_vers;
+           }
          else
            _bfd_elf_swap_versym_in (abfd, ever, &iver);
 
@@ -4441,7 +4677,7 @@ error_free_dyn:
                    {
                      _bfd_error_handler
                        /* xgettext:c-format */
-                       (_("%B: %s: invalid version %u (max %d)"),
+                       (_("%pB: %s: invalid version %u (max %d)"),
                         abfd, name, vernum,
                         elf_tdata (abfd)->cverdefs);
                      bfd_set_error (bfd_error_bad_value);
@@ -4478,7 +4714,7 @@ error_free_dyn:
                    {
                      _bfd_error_handler
                        /* xgettext:c-format */
-                       (_("%B: %s: invalid needed version %d"),
+                       (_("%pB: %s: invalid needed version %d"),
                         abfd, name, vernum);
                      bfd_set_error (bfd_error_bad_value);
                      goto error_free_vers;
@@ -4549,11 +4785,6 @@ error_free_dyn:
              (struct bfd_link_hash_entry **) sym_hash)))
        goto error_free_vers;
 
-      if ((flags & BSF_GNU_UNIQUE)
-         && (abfd->flags & DYNAMIC) == 0
-         && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour)
-       elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_unique;
-
       h = *sym_hash;
       /* We need to make sure that indirect symbol dynamic flags are
         updated.  */
@@ -4570,29 +4801,27 @@ error_free_dyn:
       *sym_hash = h;
 
       new_weak = (flags & BSF_WEAK) != 0;
-      new_weakdef = FALSE;
       if (dynamic
          && definition
          && new_weak
          && !bed->is_function_type (ELF_ST_TYPE (isym->st_info))
          && is_elf_hash_table (htab)
-         && h->u.weakdef == NULL)
+         && h->u.alias == NULL)
        {
          /* Keep a list of all weak defined non function symbols from
-            a dynamic object, using the weakdef field.  Later in this
-            function we will set the weakdef field to the correct
+            a dynamic object, using the alias field.  Later in this
+            function we will set the alias field to the correct
             value.  We only put non-function symbols from dynamic
             objects on this list, because that happens to be the only
             time we need to know the normal symbol corresponding to a
             weak symbol, and the information is time consuming to
-            figure out.  If the weakdef field is not already NULL,
+            figure out.  If the alias field is not already NULL,
             then this symbol was already defined by some previous
             dynamic object, and we will be using that previous
             definition anyhow.  */
 
-         h->u.weakdef = weaks;
+         h->u.alias = weaks;
          weaks = h;
-         new_weakdef = TRUE;
        }
 
       /* Set the alignment of a common symbol.  */
@@ -4671,9 +4900,8 @@ error_free_dyn:
              if ((h == hi || !hi->forced_local)
                  && (h->def_regular
                      || h->ref_regular
-                     || (h->u.weakdef != NULL
-                         && ! new_weakdef
-                         && h->u.weakdef->dynindx != -1)))
+                     || (h->is_weakalias
+                         && weakdef (h)->dynindx != -1)))
                dynsym = TRUE;
            }
 
@@ -4733,15 +4961,15 @@ error_free_dyn:
                  if (normal_bfd == NULL)
                    _bfd_error_handler
                      /* xgettext:c-format */
-                     (_("Warning: alignment %u of common symbol `%s' in %B is"
-                        " greater than the alignment (%u) of its section %A"),
+                     (_("warning: alignment %u of common symbol `%s' in %pB is"
+                        " greater than the alignment (%u) of its section %pA"),
                       1 << common_align, name, common_bfd,
                       1 << normal_align, h->root.u.def.section);
                  else
                    _bfd_error_handler
                      /* xgettext:c-format */
-                     (_("Warning: alignment %u of symbol `%s' in %B"
-                        " is smaller than %u in %B"),
+                     (_("warning: alignment %u of symbol `%s' in %pB"
+                        " is smaller than %u in %pB"),
                       1 << normal_align, name, normal_bfd,
                       1 << common_align, common_bfd);
                }
@@ -4757,9 +4985,10 @@ error_free_dyn:
                  && ! size_change_ok)
                _bfd_error_handler
                  /* xgettext:c-format */
-                 (_("Warning: size of symbol `%s' changed"
-                    " from %Lu in %B to %Lu in %B"),
-                  name, h->size, old_bfd, isym->st_size, abfd);
+                 (_("warning: size of symbol `%s' changed"
+                    " from %" PRIu64 " in %pB to %" PRIu64 " in %pB"),
+                  name, (uint64_t) h->size, old_bfd,
+                  (uint64_t) isym->st_size, abfd);
 
              h->size = isym->st_size;
            }
@@ -4791,8 +5020,8 @@ error_free_dyn:
                  if (h->type != STT_NOTYPE && ! type_change_ok)
                    /* xgettext:c-format */
                    _bfd_error_handler
-                     (_("Warning: type of symbol `%s' changed"
-                        " from %d to %d in %B"),
+                     (_("warning: type of symbol `%s' changed"
+                        " from %d to %d in %pB"),
                       name, h->type, type, abfd);
 
                  h->type = type;
@@ -4842,11 +5071,10 @@ error_free_dyn:
            {
              if (! bfd_elf_link_record_dynamic_symbol (info, h))
                goto error_free_vers;
-             if (h->u.weakdef != NULL
-                 && ! new_weakdef
-                 && h->u.weakdef->dynindx == -1)
+             if (h->is_weakalias
+                 && weakdef (h)->dynindx == -1)
                {
-                 if (!bfd_elf_link_record_dynamic_symbol (info, h->u.weakdef))
+                 if (!bfd_elf_link_record_dynamic_symbol (info, weakdef (h)))
                    goto error_free_vers;
                }
            }
@@ -4893,7 +5121,7 @@ error_free_dyn:
                {
                  _bfd_error_handler
                    /* xgettext:c-format */
-                   (_("%B: undefined reference to symbol '%s'"),
+                   (_("%pB: undefined reference to symbol '%s'"),
                     old_bfd, name);
                  bfd_set_error (bfd_error_missing_dso);
                  goto error_free_vers;
@@ -4912,6 +5140,65 @@ error_free_dyn:
        }
     }
 
+  if (info->lto_plugin_active
+      && !bfd_link_relocatable (info)
+      && (abfd->flags & BFD_PLUGIN) == 0
+      && !just_syms
+      && extsymcount)
+    {
+      int r_sym_shift;
+
+      if (bed->s->arch_size == 32)
+       r_sym_shift = 8;
+      else
+       r_sym_shift = 32;
+
+      /* If linker plugin is enabled, set non_ir_ref_regular on symbols
+        referenced in regular objects so that linker plugin will get
+        the correct symbol resolution.  */
+
+      sym_hash = elf_sym_hashes (abfd);
+      for (s = abfd->sections; s != NULL; s = s->next)
+       {
+         Elf_Internal_Rela *internal_relocs;
+         Elf_Internal_Rela *rel, *relend;
+
+         /* Don't check relocations in excluded sections.  */
+         if ((s->flags & SEC_RELOC) == 0
+             || s->reloc_count == 0
+             || (s->flags & SEC_EXCLUDE) != 0
+             || ((info->strip == strip_all
+                  || info->strip == strip_debugger)
+                 && (s->flags & SEC_DEBUGGING) != 0))
+           continue;
+
+         internal_relocs = _bfd_elf_link_read_relocs (abfd, s, NULL,
+                                                      NULL,
+                                                      info->keep_memory);
+         if (internal_relocs == NULL)
+           goto error_free_vers;
+
+         rel = internal_relocs;
+         relend = rel + s->reloc_count;
+         for ( ; rel < relend; rel++)
+           {
+             unsigned long r_symndx = rel->r_info >> r_sym_shift;
+             struct elf_link_hash_entry *h;
+
+             /* Skip local symbols.  */
+             if (r_symndx < extsymoff)
+               continue;
+
+             h = sym_hash[r_symndx - extsymoff];
+             if (h != NULL)
+               h->root.non_ir_ref_regular = 1;
+           }
+
+         if (elf_section_data (s)->relocs != internal_relocs)
+           free (internal_relocs);
+       }
+    }
+
   if (extversym != NULL)
     {
       free (extversym);
@@ -5066,7 +5353,7 @@ error_free_dyn:
       nondeflt_vers = NULL;
     }
 
-  /* Now set the weakdefs field correctly for all the weak defined
+  /* Now set the alias field correctly for all the weak defined
      symbols we found.  The only way to do this is to search all the
      symbols.  Since we only need the information for non functions in
      dynamic objects, that's the only time we actually put anything on
@@ -5091,8 +5378,8 @@ error_free_dyn:
         defined symbol, search time for N weak defined symbols will be
         O(N^2). Binary search will cut it down to O(NlogN).  */
       amt = extsymcount;
-      amt *= sizeof (struct elf_link_hash_entry *);
-      sorted_sym_hash = (struct elf_link_hash_entry **) bfd_malloc (amt);
+      amt *= sizeof (*sorted_sym_hash);
+      sorted_sym_hash = bfd_malloc (amt);
       if (sorted_sym_hash == NULL)
        goto error_return;
       sym_hash = sorted_sym_hash;
@@ -5112,8 +5399,7 @@ error_free_dyn:
            }
        }
 
-      qsort (sorted_sym_hash, sym_count,
-            sizeof (struct elf_link_hash_entry *),
+      qsort (sorted_sym_hash, sym_count, sizeof (*sorted_sym_hash),
             elf_sort_symbol);
 
       while (weaks != NULL)
@@ -5124,13 +5410,13 @@ error_free_dyn:
          size_t i, j, idx = 0;
 
          hlook = weaks;
-         weaks = hlook->u.weakdef;
-         hlook->u.weakdef = NULL;
+         weaks = hlook->u.alias;
+         hlook->u.alias = NULL;
+
+         if (hlook->root.type != bfd_link_hash_defined
+             && hlook->root.type != bfd_link_hash_defweak)
+           continue;
 
-         BFD_ASSERT (hlook->root.type == bfd_link_hash_defined
-                     || hlook->root.type == bfd_link_hash_defweak
-                     || hlook->root.type == bfd_link_hash_common
-                     || hlook->root.type == bfd_link_hash_indirect);
          slook = hlook->root.u.def.section;
          vlook = hlook->root.u.def.value;
 
@@ -5187,7 +5473,15 @@ error_free_dyn:
                break;
              else if (h != hlook)
                {
-                 hlook->u.weakdef = h;
+                 struct elf_link_hash_entry *t;
+
+                 hlook->u.alias = h;
+                 hlook->is_weakalias = 1;
+                 t = h;
+                 if (t->u.alias != NULL)
+                   while (t->u.alias != h)
+                     t = t->u.alias;
+                 t->u.alias = hlook;
 
                  /* If the weak definition is in the list of dynamic
                     symbols, make sure the real definition is put
@@ -5224,10 +5518,6 @@ error_free_dyn:
       && !(*bed->check_directives) (abfd, info))
     return FALSE;
 
-  if (!info->check_relocs_after_open_input
-      && !_bfd_elf_link_check_relocs (abfd, info))
-    return FALSE;
-
   /* If this is a non-traditional link, try to optimize the handling
      of the .stab/.stabstr sections.  */
   if (! dynamic
@@ -5323,7 +5613,7 @@ _bfd_elf_archive_symbol_lookup (bfd *abfd,
   len = strlen (name);
   copy = (char *) bfd_alloc (abfd, len);
   if (copy == NULL)
-    return (struct elf_link_hash_entry *) 0 - 1;
+    return (struct elf_link_hash_entry *) -1;
 
   first = p - name + 1;
   memcpy (copy, name, first);
@@ -5421,7 +5711,7 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
            }
 
          h = archive_symbol_lookup (abfd, info, symdef->name);
-         if (h == (struct elf_link_hash_entry *) 0 - 1)
+         if (h == (struct elf_link_hash_entry *) -1)
            goto error_return;
 
          if (h == NULL)
@@ -5592,6 +5882,7 @@ struct collect_gnu_hash_codes
   unsigned long int *counts;
   bfd_vma *bitmask;
   bfd_byte *contents;
+  bfd_size_type xlat;
   long int min_dynindx;
   unsigned long int bucketcount;
   unsigned long int symindx;
@@ -5656,10 +5947,12 @@ elf_collect_gnu_hash_codes (struct elf_link_hash_entry *h, void *data)
 }
 
 /* This function will be called though elf_link_hash_traverse to do
-   final dynaminc symbol renumbering.  */
+   final dynamic symbol renumbering in case of .gnu.hash.
+   If using .MIPS.xhash, invoke record_xhash_symbol to add symbol index
+   to the translation table.  */
 
 static bfd_boolean
-elf_renumber_gnu_hash_syms (struct elf_link_hash_entry *h, void *data)
+elf_gnu_hash_process_symidx (struct elf_link_hash_entry *h, void *data)
 {
   struct collect_gnu_hash_codes *s = (struct collect_gnu_hash_codes *) data;
   unsigned long int bucket;
@@ -5673,7 +5966,15 @@ elf_renumber_gnu_hash_syms (struct elf_link_hash_entry *h, void *data)
   if (! (*s->bed->elf_hash_symbol) (h))
     {
       if (h->dynindx >= s->min_dynindx)
-       h->dynindx = s->local_indx++;
+       {
+         if (s->bed->record_xhash_symbol != NULL)
+           {
+             (*s->bed->record_xhash_symbol) (h, 0);
+             s->local_indx++;
+           }
+         else
+           h->dynindx = s->local_indx++;
+       }
       return TRUE;
     }
 
@@ -5690,7 +5991,14 @@ elf_renumber_gnu_hash_syms (struct elf_link_hash_entry *h, void *data)
   bfd_put_32 (s->output_bfd, val,
              s->contents + (s->indx[bucket] - s->symindx) * 4);
   --s->counts[bucket];
-  h->dynindx = s->indx[bucket]++;
+  if (s->bed->record_xhash_symbol != NULL)
+    {
+      bfd_vma xlat_loc = s->xlat + (s->indx[bucket]++ - s->symindx) * 4;
+
+      (*s->bed->record_xhash_symbol) (h, xlat_loc);
+    }
+  else
+    h->dynindx = s->indx[bucket]++;
   return TRUE;
 }
 
@@ -5906,11 +6214,11 @@ bfd_elf_stack_segment_size (bfd *output_bfd,
       h->type = STT_OBJECT;
       if (info->stacksize)
        /* xgettext:c-format */
-       _bfd_error_handler (_("%B: stack size specified and %s set"),
+       _bfd_error_handler (_("%pB: stack size specified and %s set"),
                            output_bfd, legacy_symbol);
       else if (h->root.u.def.section != bfd_abs_section_ptr)
        /* xgettext:c-format */
-       _bfd_error_handler (_("%B: %s not absolute"),
+       _bfd_error_handler (_("%pB: %s not absolute"),
                            output_bfd, legacy_symbol);
       else
        info->stacksize = h->root.u.def.value;
@@ -6006,19 +6314,18 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       struct elf_info_failed asvinfo;
       struct bfd_elf_version_tree *t;
       struct bfd_elf_version_expr *d;
-      struct elf_info_failed eif;
-      bfd_boolean all_defined;
       asection *s;
       size_t soname_indx;
 
-      eif.info = info;
-      eif.failed = FALSE;
-
       /* If we are supposed to export all symbols into the dynamic symbol
         table (this is not the normal case), then do so.  */
       if (info->export_dynamic
          || (bfd_link_executable (info) && info->dynamic))
        {
+         struct elf_info_failed eif;
+
+         eif.info = info;
+         eif.failed = FALSE;
          elf_link_hash_traverse (elf_hash_table (info),
                                  _bfd_elf_export_symbol,
                                  &eif);
@@ -6102,7 +6409,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       if (!info->allow_undefined_version)
        {
          /* Check if all global versions have a definition.  */
-         all_defined = TRUE;
+         bfd_boolean all_defined = TRUE;
          for (t = info->version_info; t != NULL; t = t->next)
            for (d = t->globals.list; d != NULL; d = d->next)
              if (d->literal && !d->symver && !d->script)
@@ -6355,134 +6662,128 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
          elf_tdata (output_bfd)->cverdefs = cdefs;
        }
+    }
+
+  bed = get_elf_backend_data (output_bfd);
+
+  if (info->gc_sections && bed->can_gc_sections)
+    {
+      struct elf_gc_sweep_symbol_info sweep_info;
+
+      /* Remove the symbols that were in the swept sections from the
+        dynamic symbol table.  */
+      sweep_info.info = info;
+      sweep_info.hide_symbol = bed->elf_backend_hide_symbol;
+      elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
+                             &sweep_info);
+    }
+
+  if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
+    {
+      asection *s;
+      struct elf_find_verdep_info sinfo;
 
       /* Work out the size of the version reference section.  */
 
       s = bfd_get_linker_section (dynobj, ".gnu.version_r");
       BFD_ASSERT (s != NULL);
-      {
-       struct elf_find_verdep_info sinfo;
 
-       sinfo.info = info;
-       sinfo.vers = elf_tdata (output_bfd)->cverdefs;
-       if (sinfo.vers == 0)
-         sinfo.vers = 1;
-       sinfo.failed = FALSE;
+      sinfo.info = info;
+      sinfo.vers = elf_tdata (output_bfd)->cverdefs;
+      if (sinfo.vers == 0)
+       sinfo.vers = 1;
+      sinfo.failed = FALSE;
 
-       elf_link_hash_traverse (elf_hash_table (info),
-                               _bfd_elf_link_find_version_dependencies,
-                               &sinfo);
-       if (sinfo.failed)
-         return FALSE;
-
-       if (elf_tdata (output_bfd)->verref == NULL)
-         s->flags |= SEC_EXCLUDE;
-       else
-         {
-           Elf_Internal_Verneed *vn;
-           unsigned int size;
-           unsigned int crefs;
-           bfd_byte *p;
-
-           /* Build the version dependency section.  */
-           size = 0;
-           crefs = 0;
-           for (vn = elf_tdata (output_bfd)->verref;
-                vn != NULL;
-                vn = vn->vn_nextref)
-             {
-               Elf_Internal_Vernaux *a;
+      elf_link_hash_traverse (elf_hash_table (info),
+                             _bfd_elf_link_find_version_dependencies,
+                             &sinfo);
+      if (sinfo.failed)
+       return FALSE;
 
-               size += sizeof (Elf_External_Verneed);
-               ++crefs;
-               for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
-                 size += sizeof (Elf_External_Vernaux);
-             }
+      if (elf_tdata (output_bfd)->verref == NULL)
+       s->flags |= SEC_EXCLUDE;
+      else
+       {
+         Elf_Internal_Verneed *vn;
+         unsigned int size;
+         unsigned int crefs;
+         bfd_byte *p;
 
-           s->size = size;
-           s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
-           if (s->contents == NULL)
-             return FALSE;
+         /* Build the version dependency section.  */
+         size = 0;
+         crefs = 0;
+         for (vn = elf_tdata (output_bfd)->verref;
+              vn != NULL;
+              vn = vn->vn_nextref)
+           {
+             Elf_Internal_Vernaux *a;
 
-           p = s->contents;
-           for (vn = elf_tdata (output_bfd)->verref;
-                vn != NULL;
-                vn = vn->vn_nextref)
-             {
-               unsigned int caux;
-               Elf_Internal_Vernaux *a;
-               size_t indx;
-
-               caux = 0;
-               for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
-                 ++caux;
-
-               vn->vn_version = VER_NEED_CURRENT;
-               vn->vn_cnt = caux;
-               indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                           elf_dt_name (vn->vn_bfd) != NULL
-                                           ? elf_dt_name (vn->vn_bfd)
-                                           : lbasename (vn->vn_bfd->filename),
-                                           FALSE);
-               if (indx == (size_t) -1)
-                 return FALSE;
-               vn->vn_file = indx;
-               vn->vn_aux = sizeof (Elf_External_Verneed);
-               if (vn->vn_nextref == NULL)
-                 vn->vn_next = 0;
-               else
-                 vn->vn_next = (sizeof (Elf_External_Verneed)
-                               + caux * sizeof (Elf_External_Vernaux));
+             size += sizeof (Elf_External_Verneed);
+             ++crefs;
+             for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
+               size += sizeof (Elf_External_Vernaux);
+           }
 
-               _bfd_elf_swap_verneed_out (output_bfd, vn,
-                                          (Elf_External_Verneed *) p);
-               p += sizeof (Elf_External_Verneed);
+         s->size = size;
+         s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
+         if (s->contents == NULL)
+           return FALSE;
 
-               for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
-                 {
-                   a->vna_hash = bfd_elf_hash (a->vna_nodename);
-                   indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                               a->vna_nodename, FALSE);
-                   if (indx == (size_t) -1)
-                     return FALSE;
-                   a->vna_name = indx;
-                   if (a->vna_nextptr == NULL)
-                     a->vna_next = 0;
-                   else
-                     a->vna_next = sizeof (Elf_External_Vernaux);
+         p = s->contents;
+         for (vn = elf_tdata (output_bfd)->verref;
+              vn != NULL;
+              vn = vn->vn_nextref)
+           {
+             unsigned int caux;
+             Elf_Internal_Vernaux *a;
+             size_t indx;
 
-                   _bfd_elf_swap_vernaux_out (output_bfd, a,
-                                              (Elf_External_Vernaux *) p);
-                   p += sizeof (Elf_External_Vernaux);
-                 }
-             }
+             caux = 0;
+             for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
+               ++caux;
 
-           elf_tdata (output_bfd)->cverrefs = crefs;
-         }
-      }
-    }
+             vn->vn_version = VER_NEED_CURRENT;
+             vn->vn_cnt = caux;
+             indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                         elf_dt_name (vn->vn_bfd) != NULL
+                                         ? elf_dt_name (vn->vn_bfd)
+                                         : lbasename (vn->vn_bfd->filename),
+                                         FALSE);
+             if (indx == (size_t) -1)
+               return FALSE;
+             vn->vn_file = indx;
+             vn->vn_aux = sizeof (Elf_External_Verneed);
+             if (vn->vn_nextref == NULL)
+               vn->vn_next = 0;
+             else
+               vn->vn_next = (sizeof (Elf_External_Verneed)
+                              + caux * sizeof (Elf_External_Vernaux));
 
-  bed = get_elf_backend_data (output_bfd);
+             _bfd_elf_swap_verneed_out (output_bfd, vn,
+                                        (Elf_External_Verneed *) p);
+             p += sizeof (Elf_External_Verneed);
 
-  if (info->gc_sections && bed->can_gc_sections)
-    {
-      struct elf_gc_sweep_symbol_info sweep_info;
-      unsigned long section_sym_count;
+             for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
+               {
+                 a->vna_hash = bfd_elf_hash (a->vna_nodename);
+                 indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                             a->vna_nodename, FALSE);
+                 if (indx == (size_t) -1)
+                   return FALSE;
+                 a->vna_name = indx;
+                 if (a->vna_nextptr == NULL)
+                   a->vna_next = 0;
+                 else
+                   a->vna_next = sizeof (Elf_External_Vernaux);
 
-      /* Remove the symbols that were in the swept sections from the
-        dynamic symbol table.  GCFIXME: Anyone know how to get them
-        out of the static symbol table as well?  */
-      sweep_info.info = info;
-      sweep_info.hide_symbol = bed->elf_backend_hide_symbol;
-      elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
-                             &sweep_info);
+                 _bfd_elf_swap_vernaux_out (output_bfd, a,
+                                            (Elf_External_Vernaux *) p);
+                 p += sizeof (Elf_External_Vernaux);
+               }
+           }
 
-      /* We need to reassign dynsym indices now that symbols may have
-        been removed.  See the call in `bfd_elf_size_dynsym_hash_dynstr'
-        for the details of the conditions used here.  */
-      if (elf_hash_table (info)->dynamic_sections_created
-         || bed->always_renumber_dynsyms)
-       _bfd_elf_link_renumber_dynsyms (output_bfd, info, &section_sym_count);
+         elf_tdata (output_bfd)->cverrefs = crefs;
+       }
     }
 
   /* Any syms created from now on start with -1 in
@@ -6685,7 +6986,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                        == SHT_PREINIT_ARRAY)
                      {
                        _bfd_error_handler
-                         (_("%B: .preinit_array section is not allowed in DSO"),
+                         (_("%pB: .preinit_array section is not allowed in DSO"),
                           sub);
                        break;
                      }
@@ -6726,7 +7027,8 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          if ((info->emit_hash
               && !_bfd_elf_add_dynamic_entry (info, DT_HASH, 0))
              || (info->emit_gnu_hash
-                 && !_bfd_elf_add_dynamic_entry (info, DT_GNU_HASH, 0))
+                 && (bed->record_xhash_symbol == NULL
+                     && !_bfd_elf_add_dynamic_entry (info, DT_GNU_HASH, 0)))
              || !_bfd_elf_add_dynamic_entry (info, DT_STRTAB, 0)
              || !_bfd_elf_add_dynamic_entry (info, DT_SYMTAB, 0)
              || !_bfd_elf_add_dynamic_entry (info, DT_STRSZ, strsize)
@@ -6748,8 +7050,6 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
   if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
     {
-      unsigned long section_sym_count;
-
       if (elf_tdata (output_bfd)->cverdefs)
        {
          unsigned int crefs = elf_tdata (output_bfd)->cverdefs;
@@ -6791,8 +7091,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
       if ((elf_tdata (output_bfd)->cverrefs == 0
           && elf_tdata (output_bfd)->cverdefs == 0)
-         || _bfd_elf_link_renumber_dynsyms (output_bfd, info,
-                                            &section_sym_count) == 0)
+         || _bfd_elf_link_renumber_dynsyms (output_bfd, info, NULL) <= 1)
        {
          asection *s;
 
@@ -6809,14 +7108,17 @@ void
 _bfd_elf_init_1_index_section (bfd *output_bfd, struct bfd_link_info *info)
 {
   asection *s;
+  asection *found = NULL;
 
   for (s = output_bfd->sections; s != NULL; s = s->next)
     if ((s->flags & (SEC_EXCLUDE | SEC_ALLOC)) == SEC_ALLOC
-       && !_bfd_elf_link_omit_section_dynsym (output_bfd, info, s))
+       && !_bfd_elf_omit_section_dynsym_default (output_bfd, info, s))
       {
-       elf_hash_table (info)->text_index_section = s;
-       break;
+       found = s;
+       if ((s->flags & SEC_THREAD_LOCAL) == 0)
+         break;
       }
+  elf_hash_table (info)->text_index_section = found;
 }
 
 /* Find two non-excluded output sections, one for code, one for data.
@@ -6825,31 +7127,35 @@ void
 _bfd_elf_init_2_index_sections (bfd *output_bfd, struct bfd_link_info *info)
 {
   asection *s;
+  asection *found = NULL;
 
   /* Data first, since setting text_index_section changes
-     _bfd_elf_link_omit_section_dynsym.  */
+     _bfd_elf_omit_section_dynsym_default.  */
   for (s = output_bfd->sections; s != NULL; s = s->next)
-    if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY)) == SEC_ALLOC)
-       && !_bfd_elf_link_omit_section_dynsym (output_bfd, info, s))
+    if ((s->flags & (SEC_EXCLUDE | SEC_ALLOC)) == SEC_ALLOC
+       && !(s->flags & SEC_READONLY)
+       && !_bfd_elf_omit_section_dynsym_default (output_bfd, info, s))
       {
-       elf_hash_table (info)->data_index_section = s;
-       break;
+       found = s;
+       if ((s->flags & SEC_THREAD_LOCAL) == 0)
+         break;
       }
+  elf_hash_table (info)->data_index_section = found;
 
   for (s = output_bfd->sections; s != NULL; s = s->next)
-    if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY))
-        == (SEC_ALLOC | SEC_READONLY))
-       && !_bfd_elf_link_omit_section_dynsym (output_bfd, info, s))
+    if ((s->flags & (SEC_EXCLUDE | SEC_ALLOC)) == SEC_ALLOC
+       && (s->flags & SEC_READONLY)
+       && !_bfd_elf_omit_section_dynsym_default (output_bfd, info, s))
       {
-       elf_hash_table (info)->text_index_section = s;
+       found = s;
        break;
       }
-
-  if (elf_hash_table (info)->text_index_section == NULL)
-    elf_hash_table (info)->text_index_section
-      = elf_hash_table (info)->data_index_section;
+  elf_hash_table (info)->text_index_section = found;
 }
 
+#define GNU_HASH_SECTION_NAME(bed)                         \
+  (bed)->record_xhash_symbol != NULL ? ".MIPS.xhash" : ".gnu.hash"
+
 bfd_boolean
 bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
 {
@@ -7016,12 +7322,12 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
              return FALSE;
            }
 
-         s = bfd_get_linker_section (dynobj, ".gnu.hash");
+         s = bfd_get_linker_section (dynobj, GNU_HASH_SECTION_NAME (bed));
          BFD_ASSERT (s != NULL);
 
          if (cinfo.nsyms == 0)
            {
-             /* Empty .gnu.hash section is special.  */
+             /* Empty .gnu.hash or .MIPS.xhash section is special.  */
              BFD_ASSERT (cinfo.min_dynindx == -1);
              free (cinfo.hashcodes);
              s->size = 5 * 4 + bed->s->arch_size / 8;
@@ -7101,6 +7407,8 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
 
              s->size = (4 + bucketcount + cinfo.nsyms) * 4;
              s->size += cinfo.maskbits / 8;
+             if (bed->record_xhash_symbol != NULL)
+               s->size += cinfo.nsyms * 4;
              contents = (unsigned char *) bfd_zalloc (output_bfd, s->size);
              if (contents == NULL)
                {
@@ -7127,9 +7435,11 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
 
              cinfo.contents = contents;
 
-             /* Renumber dynamic symbols, populate .gnu.hash section.  */
+             cinfo.xlat = contents + cinfo.nsyms * 4 - s->contents;
+             /* Renumber dynamic symbols, if populating .gnu.hash section.
+                If using .MIPS.xhash, populate the translation table.  */
              elf_link_hash_traverse (elf_hash_table (info),
-                                     elf_renumber_gnu_hash_syms, &cinfo);
+                                     elf_gnu_hash_process_symidx, &cinfo);
 
              contents = s->contents + 16;
              for (i = 0; i < maskwords; ++i)
@@ -7325,6 +7635,26 @@ _bfd_elf_link_hash_hide_symbol (struct bfd_link_info *info,
     }
 }
 
+/* Hide a symbol. */
+
+void
+_bfd_elf_link_hide_symbol (bfd *output_bfd,
+                          struct bfd_link_info *info,
+                          struct bfd_link_hash_entry *h)
+{
+  if (is_elf_hash_table (info->hash))
+    {
+      const struct elf_backend_data *bed
+       = get_elf_backend_data (output_bfd);
+      struct elf_link_hash_entry *eh
+       = (struct elf_link_hash_entry *) h;
+      bed->elf_backend_hide_symbol (info, eh, TRUE);
+      eh->def_dynamic = 0;
+      eh->ref_dynamic = 0;
+      eh->dynamic_def = 0;
+    }
+}
+
 /* Initialize an ELF linker hash table.  *TABLE has been zeroed by our
    caller.  */
 
@@ -7564,6 +7894,7 @@ struct elf_symbol
     {
       Elf_Internal_Sym *isym;
       struct elf_symbuf_symbol *ssym;
+      void *p;
     } u;
   const char *name;
 };
@@ -7576,7 +7907,13 @@ elf_sort_elf_symbol (const void *arg1, const void *arg2)
   const Elf_Internal_Sym *s1 = *(const Elf_Internal_Sym **) arg1;
   const Elf_Internal_Sym *s2 = *(const Elf_Internal_Sym **) arg2;
 
-  return s1->st_shndx - s2->st_shndx;
+  if (s1->st_shndx != s2->st_shndx)
+    return s1->st_shndx > s2->st_shndx ? 1 : -1;
+  /* Final sort by the address of the sym in the symbuf ensures
+     a stable sort.  */
+  if (s1 != s2)
+    return s1 > s2 ? 1 : -1;
+  return 0;
 }
 
 static int
@@ -7584,7 +7921,12 @@ elf_sym_name_compare (const void *arg1, const void *arg2)
 {
   const struct elf_symbol *s1 = (const struct elf_symbol *) arg1;
   const struct elf_symbol *s2 = (const struct elf_symbol *) arg2;
-  return strcmp (s1->name, s2->name);
+  int ret = strcmp (s1->name, s2->name);
+  if (ret != 0)
+    return ret;
+  if (s1->u.p != s2->u.p)
+    return s1->u.p > s2->u.p ? 1 : -1;
+  return 0;
 }
 
 static struct elf_symbuf_head *
@@ -7707,8 +8049,10 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
        goto done;
 
       if (!info->reduce_memory_overheads)
-       elf_tdata (bfd1)->symbuf = ssymbuf1
-         = elf_create_symbuf (symcount1, isymbuf1);
+       {
+         ssymbuf1 = elf_create_symbuf (symcount1, isymbuf1);
+         elf_tdata (bfd1)->symbuf = ssymbuf1;
+       }
     }
 
   if (ssymbuf1 == NULL || ssymbuf2 == NULL)
@@ -7719,8 +8063,10 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
        goto done;
 
       if (ssymbuf1 != NULL && !info->reduce_memory_overheads)
-       elf_tdata (bfd2)->symbuf = ssymbuf2
-         = elf_create_symbuf (symcount2, isymbuf2);
+       {
+         ssymbuf2 = elf_create_symbuf (symcount2, isymbuf2);
+         elf_tdata (bfd2)->symbuf = ssymbuf2;
+       }
     }
 
   if (ssymbuf1 != NULL && ssymbuf2 != NULL)
@@ -7959,12 +8305,12 @@ struct elf_outext_info
    addend field.  The symbol mangling format is:
 
    <node> := <literal>
-          |  <unary-operator> ':' <node>
-          |  <binary-operator> ':' <node> ':' <node>
+         |  <unary-operator> ':' <node>
+         |  <binary-operator> ':' <node> ':' <node>
          ;
 
    <literal> := 's' <digits=N> ':' <N character symbol name>
-             |  'S' <digits=N> ':' <N character section name>
+            |  'S' <digits=N> ':' <N character section name>
             |  '#' <hexdigits>
             ;
 
@@ -8081,7 +8427,7 @@ resolve_symbol (const char *name,
 /* Looks up NAME in SECTIONS.  If found sets RESULT to NAME's address (in
    bytes) and returns TRUE, otherwise returns FALSE.  Accepts pseudo-section
    names like "foo.end" which is the end address of section "foo".  */
-   
+
 static bfd_boolean
 resolve_section (const char *name,
                 asection *sections,
@@ -8110,7 +8456,8 @@ resolve_section (const char *name,
        {
          if (strncmp (".end", name + len, 4) == 0)
            {
-             *result = curr->vma + curr->size / bfd_octets_per_byte (abfd);
+             *result = (curr->vma
+                        + curr->size / bfd_octets_per_byte (abfd, curr));
              return TRUE;
            }
 
@@ -8393,8 +8740,8 @@ decode_complex_addend (unsigned long *start,   /* in bits */
                       unsigned long *trunc_p,
                       unsigned long encoded)
 {
-  * start     =  encoded        & 0x3F;
-  * len       = (encoded >>  6) & 0x3F;
+  * start     =         encoded        & 0x3F;
+  * len              = (encoded >>  6) & 0x3F;
   * oplen     = (encoded >> 12) & 0x3F;
   * wordsz    = (encoded >> 18) & 0xF;
   * chunksz   = (encoded >> 22) & 0xF;
@@ -8405,7 +8752,7 @@ decode_complex_addend (unsigned long *start,   /* in bits */
 
 bfd_reloc_status_type
 bfd_elf_perform_complex_relocation (bfd *input_bfd,
-                                   asection *input_section ATTRIBUTE_UNUSED,
+                                   asection *input_section,
                                    bfd_byte *contents,
                                    Elf_Internal_Rela *rel,
                                    bfd_vma relocation)
@@ -8413,6 +8760,7 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd,
   bfd_vma shift, x, mask;
   unsigned long start, oplen, len, wordsz, chunksz, lsb0_p, signed_p, trunc_p;
   bfd_reloc_status_type r;
+  bfd_size_type octets;
 
   /*  Perform this reloc, since it is complex.
       (this is not to say that it necessarily refers to a complex
@@ -8431,8 +8779,8 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd,
   else
     shift = (8 * wordsz) - (start + len);
 
-  x = get_value (wordsz, chunksz, input_bfd,
-                contents + rel->r_offset * bfd_octets_per_byte (input_bfd));
+  octets = rel->r_offset * bfd_octets_per_byte (input_bfd, input_section);
+  x = get_value (wordsz, chunksz, input_bfd, contents + octets);
 
 #ifdef DEBUG
   printf ("Doing complex reloc: "
@@ -8464,8 +8812,7 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd,
          (unsigned long) relocation, (unsigned long) (mask << shift),
          (unsigned long) ((relocation & mask) << shift), (unsigned long) x);
 #endif
-  put_value (wordsz, chunksz, input_bfd, x,
-            contents + rel->r_offset * bfd_octets_per_byte (input_bfd));
+  put_value (wordsz, chunksz, input_bfd, x, contents + octets);
   return r;
 }
 
@@ -8618,10 +8965,10 @@ elf_link_adjust_relocs (bfd *abfd,
          && ! info->gc_keep_exported)
        {
          /* PR 21524: Let the user know if a symbol was removed by garbage collection.  */
-         _bfd_error_handler (_("%B:%A: error: relocation references symbol %s which was removed by garbage collection."),
+         _bfd_error_handler (_("%pB:%pA: error: relocation references symbol %s which was removed by garbage collection"),
                              abfd, sec,
                              (*rel_hash)->root.root.string);
-         _bfd_error_handler (_("%B:%A: error: try relinking with --gc-keep-exported enabled."),
+         _bfd_error_handler (_("%pB:%pA: error: try relinking with --gc-keep-exported enabled"),
                              abfd, sec);
          bfd_set_error (bfd_error_invalid_operation);
          return FALSE;
@@ -8762,6 +9109,15 @@ struct elf_link_sort_rela
   Elf_Internal_Rela rela[1];
 };
 
+/* qsort stability here and for cmp2 is only an issue if multiple
+   dynamic relocations are emitted at the same address.  But targets
+   that apply a series of dynamic relocations each operating on the
+   result of the prior relocation can't use -z combreloc as
+   implemented anyway.  Such schemes tend to be broken by sorting on
+   symbol index.  That leaves dynamic NONE relocs as the only other
+   case where ld might emit multiple relocs at the same address, and
+   those are only emitted due to target bugs.  */
+
 static int
 elf_link_sort_cmp1 (const void *A, const void *B)
 {
@@ -8820,7 +9176,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
   struct elf_link_sort_rela *sq;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   int i2e = bed->s->int_rels_per_ext_rel;
-  unsigned int opb = bfd_octets_per_byte (abfd);
+  unsigned int opb = bfd_octets_per_byte (abfd, NULL);
   void (*swap_in) (bfd *, const bfd_byte *, Elf_Internal_Rela *);
   void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
   struct bfd_link_order *lo;
@@ -8857,7 +9213,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
                    /* Section size is only divisible by rela.  */
                    if (use_rela_initialised && !use_rela)
                      {
-                       _bfd_error_handler (_("%B: Unable to sort relocs - "
+                       _bfd_error_handler (_("%pB: unable to sort relocs - "
                                              "they are in more than one size"),
                                            abfd);
                        bfd_set_error (bfd_error_invalid_operation);
@@ -8875,7 +9231,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
                /* Section size is only divisible by rel.  */
                if (use_rela_initialised && use_rela)
                  {
-                   _bfd_error_handler (_("%B: Unable to sort relocs - "
+                   _bfd_error_handler (_("%pB: unable to sort relocs - "
                                          "they are in more than one size"),
                                        abfd);
                    bfd_set_error (bfd_error_invalid_operation);
@@ -8891,7 +9247,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
              {
                /* The section size is not divisible by either -
                   something is wrong.  */
-               _bfd_error_handler (_("%B: Unable to sort relocs - "
+               _bfd_error_handler (_("%pB: unable to sort relocs - "
                                      "they are of an unknown size"), abfd);
                bfd_set_error (bfd_error_invalid_operation);
                return 0;
@@ -8914,7 +9270,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
                    /* Section size is only divisible by rela.  */
                    if (use_rela_initialised && !use_rela)
                      {
-                       _bfd_error_handler (_("%B: Unable to sort relocs - "
+                       _bfd_error_handler (_("%pB: unable to sort relocs - "
                                              "they are in more than one size"),
                                            abfd);
                        bfd_set_error (bfd_error_invalid_operation);
@@ -8932,7 +9288,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
                /* Section size is only divisible by rel.  */
                if (use_rela_initialised && use_rela)
                  {
-                   _bfd_error_handler (_("%B: Unable to sort relocs - "
+                   _bfd_error_handler (_("%pB: unable to sort relocs - "
                                          "they are in more than one size"),
                                        abfd);
                    bfd_set_error (bfd_error_invalid_operation);
@@ -8948,7 +9304,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
              {
                /* The section size is not divisible by either -
                   something is wrong.  */
-               _bfd_error_handler (_("%B: Unable to sort relocs - "
+               _bfd_error_handler (_("%pB: unable to sort relocs - "
                                      "they are of an unknown size"), abfd);
                bfd_set_error (bfd_error_invalid_operation);
                return 0;
@@ -9000,7 +9356,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
   if (sort == NULL)
     {
       (*info->callbacks->warning)
-       (info, _("Not enough memory to sort relocations"), 0, abfd, 0, 0);
+       (info, _("not enough memory to sort relocations"), 0, abfd, 0, 0);
       return 0;
     }
 
@@ -9140,6 +9496,11 @@ elf_link_output_symstrtab (struct elf_final_link_info *flinfo,
        return ret;
     }
 
+  if (ELF_ST_TYPE (elfsym->st_info) == STT_GNU_IFUNC)
+    elf_tdata (flinfo->output_bfd)->has_gnu_osabi |= elf_gnu_osabi_ifunc;
+  if (ELF_ST_BIND (elfsym->st_info) == STB_GNU_UNIQUE)
+    elf_tdata (flinfo->output_bfd)->has_gnu_osabi |= elf_gnu_osabi_unique;
+
   if (name == NULL
       || *name == '\0'
       || (input_sec->flags & SEC_EXCLUDE))
@@ -9174,7 +9535,7 @@ elf_link_output_symstrtab (struct elf_final_link_info *flinfo,
   hash_table->strtab[hash_table->strtabcount].destshndx_index
     = flinfo->symshndxbuf ? bfd_get_symcount (flinfo->output_bfd) : 0;
 
-  bfd_get_symcount (flinfo->output_bfd) += 1;
+  flinfo->output_bfd->symcount += 1;
   hash_table->strtabcount += 1;
 
   return 1;
@@ -9236,6 +9597,14 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo)
                                + elfsym->destshndx_index));
     }
 
+  /* Allow the linker to examine the strtab and symtab now they are
+     populated.  */
+
+  if (flinfo->info->callbacks->examine_strtab)
+    flinfo->info->callbacks->examine_strtab (hash_table->strtab,
+                                            hash_table->strtabcount,
+                                            flinfo->symstrtab);
+
   hdr = &elf_tdata (flinfo->output_bfd)->symtab_hdr;
   pos = hdr->sh_offset + hdr->sh_size;
   amt = hash_table->strtabcount * bed->s->sizeof_sym;
@@ -9268,7 +9637,7 @@ check_dynsym (bfd *abfd, Elf_Internal_Sym *sym)
         beyond 64k.  */
       _bfd_error_handler
        /* xgettext:c-format */
-       (_("%B: Too many sections: %d (>= %d)"),
+       (_("%pB: too many sections: %d (>= %d)"),
         abfd, bfd_count_sections (abfd), SHN_LORESERVE & 0xffff);
       bfd_set_error (bfd_error_nonrepresentable_section);
       return FALSE;
@@ -9513,7 +9882,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
 
       /* If we are reporting errors for this situation then do so now.  */
       if (!ignore_undef
-         && h->ref_dynamic
+         && h->ref_dynamic_nonweak
          && (!h->ref_regular || flinfo->info->gc_sections)
          && !elf_link_check_versioned_symbol (flinfo->info, bed, h)
          && flinfo->info->unresolved_syms_in_shared_libs != RM_IGNORE)
@@ -9548,13 +9917,13 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
 
       if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)
        /* xgettext:c-format */
-       msg = _("%B: internal symbol `%s' in %B is referenced by DSO");
+       msg = _("%pB: internal symbol `%s' in %pB is referenced by DSO");
       else if (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN)
        /* xgettext:c-format */
-       msg = _("%B: hidden symbol `%s' in %B is referenced by DSO");
+       msg = _("%pB: hidden symbol `%s' in %pB is referenced by DSO");
       else
        /* xgettext:c-format */
-       msg = _("%B: local symbol `%s' in %B is referenced by DSO");
+       msg = _("%pB: local symbol `%s' in %pB is referenced by DSO");
       def_bfd = flinfo->output_bfd;
       if (hi->root.u.def.section != bfd_abs_section_ptr)
        def_bfd = hi->root.u.def.section->owner;
@@ -9640,7 +10009,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
              {
                _bfd_error_handler
                  /* xgettext:c-format */
-                 (_("%B: could not find output section %A for input section %A"),
+                 (_("%pB: could not find output section %pA for input section %pA"),
                   flinfo->output_bfd, input_sec->output_section, input_sec);
                bfd_set_error (bfd_error_nonrepresentable_section);
                eoinfo->failed = TRUE;
@@ -9794,13 +10163,13 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
 
       if (ELF_ST_VISIBILITY (sym.st_other) == STV_PROTECTED)
        /* xgettext:c-format */
-       msg = _("%B: protected symbol `%s' isn't defined");
+       msg = _("%pB: protected symbol `%s' isn't defined");
       else if (ELF_ST_VISIBILITY (sym.st_other) == STV_INTERNAL)
        /* xgettext:c-format */
-       msg = _("%B: internal symbol `%s' isn't defined");
+       msg = _("%pB: internal symbol `%s' isn't defined");
       else
        /* xgettext:c-format */
-       msg = _("%B: hidden symbol `%s' isn't defined");
+       msg = _("%pB: hidden symbol `%s' isn't defined");
       _bfd_error_handler (msg, flinfo->output_bfd, h->root.root.string);
       bfd_set_error (bfd_error_bad_value);
       eoinfo->failed = TRUE;
@@ -9810,9 +10179,10 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
   /* If this symbol should be put in the .dynsym section, then put it
      there now.  We already know the symbol index.  We also fill in
      the entry in the .hash section.  */
-  if (elf_hash_table (flinfo->info)->dynsym != NULL
-      && h->dynindx != -1
-      && elf_hash_table (flinfo->info)->dynamic_sections_created)
+  if (h->dynindx != -1
+      && elf_hash_table (flinfo->info)->dynamic_sections_created
+      && elf_hash_table (flinfo->info)->dynsym != NULL
+      && !discarded_section (elf_hash_table (flinfo->info)->dynsym))
     {
       bfd_byte *esym;
 
@@ -9831,7 +10201,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
            {
              _bfd_error_handler
                /* xgettext:c-format */
-               (_("%B: No symbol version section for versioned symbol `%s'"),
+               (_("%pB: no symbol version section for versioned symbol `%s'"),
                 flinfo->output_bfd, h->root.root.string);
              eoinfo->failed = TRUE;
              return FALSE;
@@ -9876,7 +10246,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
          Elf_Internal_Versym iversym;
          Elf_External_Versym *eversym;
 
-         if (!h->def_regular)
+         if (!h->def_regular && !ELF_COMMON_DEF_P (h))
            {
              if (h->verinfo.verdef == NULL
                  || (elf_dyn_lib_class (h->verinfo.verdef->vd_bfd)
@@ -9911,8 +10281,11 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
      relocatable output or when needed for --emit-relocs.  */
   else if (input_sec == bfd_und_section_ptr
           && h->indx != -2
+          /* PR 22319 Do not strip global undefined symbols marked as being needed.  */
+          && (h->mark != 1 || ELF_ST_BIND (sym.st_info) != STB_GLOBAL)
           && !bfd_link_relocatable (flinfo->info))
     return TRUE;
+
   /* Also strip others that we couldn't earlier due to dynamic symbol
      processing.  */
   if (strip)
@@ -10154,8 +10527,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
            {
              /* Don't attempt to output symbols with st_shnx in the
                 reserved range other than SHN_ABS and SHN_COMMON.  */
-             *ppsection = NULL;
-             continue;
+             isec = bfd_und_section_ptr;
            }
          else if (isec->sec_info_type == SEC_INFO_TYPE_MERGE
                   && ELF_ST_TYPE (isym->st_info) != STT_SECTION)
@@ -10270,8 +10642,11 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
          if (ELF_ST_TYPE (osym.st_info) == STT_TLS)
            {
              /* STT_TLS symbols are relative to PT_TLS segment base.  */
-             BFD_ASSERT (elf_hash_table (flinfo->info)->tls_sec != NULL);
-             osym.st_value -= elf_hash_table (flinfo->info)->tls_sec->vma;
+             if (elf_hash_table (flinfo->info)->tls_sec != NULL)
+               osym.st_value -= elf_hash_table (flinfo->info)->tls_sec->vma;
+             else
+               osym.st_info = ELF_ST_INFO (ELF_ST_BIND (osym.st_info),
+                                           STT_NOTYPE);
            }
        }
 
@@ -10438,10 +10813,10 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                {
                  _bfd_error_handler
                    /* xgettext:c-format */
-                   (_("error: %B: size of section %A is not "
+                   (_("error: %pB: size of section %pA is not "
                       "multiple of address size"),
                     input_bfd, o);
-                 bfd_set_error (bfd_error_on_input);
+                 bfd_set_error (bfd_error_bad_value);
                  return FALSE;
                }
              o->flags |= SEC_ELF_REVERSE_COPY;
@@ -10483,9 +10858,9 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                    {
                      _bfd_error_handler
                        /* xgettext:c-format */
-                       (_("error: %B contains a reloc (%#Lx) for section %A "
+                       (_("error: %pB contains a reloc (%#" PRIx64 ") for section %pA "
                           "that references a non-existent global symbol"),
-                        input_bfd, rel->r_info, o);
+                        input_bfd, (uint64_t) rel->r_info, o);
                      bfd_set_error (bfd_error_bad_value);
                      return FALSE;
                    }
@@ -10569,8 +10944,8 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                      if (action_discarded & COMPLAIN)
                        (*flinfo->info->callbacks->einfo)
                          /* xgettext:c-format */
-                         (_("%X`%s' referenced in section `%A' of %B: "
-                            "defined in discarded section `%A' of %B\n"),
+                         (_("%X`%s' referenced in section `%pA' of %pB: "
+                            "defined in discarded section `%pA' of %pB\n"),
                           sym_name, o, input_bfd, sec, sec->owner);
 
                      /* Try to do the best we can to support buggy old
@@ -10827,12 +11202,17 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                              sym.st_value += osec->vma;
                              if (ELF_ST_TYPE (sym.st_info) == STT_TLS)
                                {
+                                 struct elf_link_hash_table *htab
+                                   = elf_hash_table (flinfo->info);
+
                                  /* STT_TLS symbols are relative to PT_TLS
                                     segment base.  */
-                                 BFD_ASSERT (elf_hash_table (flinfo->info)
-                                             ->tls_sec != NULL);
-                                 sym.st_value -= (elf_hash_table (flinfo->info)
-                                                  ->tls_sec->vma);
+                                 if (htab->tls_sec != NULL)
+                                   sym.st_value -= htab->tls_sec->vma;
+                                 else
+                                   sym.st_info
+                                     = ELF_ST_INFO (ELF_ST_BIND (sym.st_info),
+                                                    STT_NOTYPE);
                                }
                            }
 
@@ -10924,7 +11304,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                file_ptr offset = (file_ptr) o->output_offset;
                bfd_size_type todo = o->size;
 
-               offset *= bfd_octets_per_byte (output_bfd);
+               offset *= bfd_octets_per_byte (output_bfd, o);
 
                if ((o->flags & SEC_ELF_REVERSE_COPY))
                  {
@@ -11058,6 +11438,7 @@ elf_reloc_link_order (bfd *output_bfd,
       bfd_byte *buf;
       bfd_boolean ok;
       const char *sym_name;
+      bfd_size_type octets;
 
       size = (bfd_size_type) bfd_get_reloc_size (howto);
       buf = (bfd_byte *) bfd_zmalloc (size);
@@ -11075,8 +11456,7 @@ elf_reloc_link_order (bfd *output_bfd,
 
        case bfd_reloc_overflow:
          if (link_order->type == bfd_section_reloc_link_order)
-           sym_name = bfd_section_name (output_bfd,
-                                        link_order->u.reloc.p->u.section);
+           sym_name = bfd_section_name (link_order->u.reloc.p->u.section);
          else
            sym_name = link_order->u.reloc.p->u.name;
          (*info->callbacks->reloc_overflow) (info, NULL, sym_name,
@@ -11085,10 +11465,10 @@ elf_reloc_link_order (bfd *output_bfd,
          break;
        }
 
+      octets = link_order->offset * bfd_octets_per_byte (output_bfd,
+                                                        output_section);
       ok = bfd_set_section_contents (output_bfd, output_section, buf,
-                                    link_order->offset
-                                    * bfd_octets_per_byte (output_bfd),
-                                    size);
+                                    octets, size);
       free (buf);
       if (! ok)
        return FALSE;
@@ -11132,56 +11512,43 @@ elf_reloc_link_order (bfd *output_bfd,
 }
 
 
-/* Get the output vma of the section pointed to by the sh_link field.  */
-
-static bfd_vma
-elf_get_linked_section_vma (struct bfd_link_order *p)
-{
-  Elf_Internal_Shdr **elf_shdrp;
-  asection *s;
-  int elfsec;
-
-  s = p->u.indirect.section;
-  elf_shdrp = elf_elfsections (s->owner);
-  elfsec = _bfd_elf_section_from_bfd_section (s->owner, s);
-  elfsec = elf_shdrp[elfsec]->sh_link;
-  /* PR 290:
-     The Intel C compiler generates SHT_IA_64_UNWIND with
-     SHF_LINK_ORDER.  But it doesn't set the sh_link or
-     sh_info fields.  Hence we could get the situation
-     where elfsec is 0.  */
-  if (elfsec == 0)
-    {
-      const struct elf_backend_data *bed
-       = get_elf_backend_data (s->owner);
-      if (bed->link_order_error_handler)
-       bed->link_order_error_handler
-         /* xgettext:c-format */
-         (_("%B: warning: sh_link not set for section `%A'"), s->owner, s);
-      return 0;
-    }
-  else
-    {
-      s = elf_shdrp[elfsec]->bfd_section;
-      return s->output_section->vma + s->output_offset;
-    }
-}
-
-
 /* Compare two sections based on the locations of the sections they are
    linked to.  Used by elf_fixup_link_order.  */
 
 static int
-compare_link_order (const void * a, const void * b)
+compare_link_order (const void *a, const void *b)
 {
-  bfd_vma apos;
-  bfd_vma bpos;
+  const struct bfd_link_order *alo = *(const struct bfd_link_order **) a;
+  const struct bfd_link_order *blo = *(const struct bfd_link_order **) b;
+  asection *asec = elf_linked_to_section (alo->u.indirect.section);
+  asection *bsec = elf_linked_to_section (blo->u.indirect.section);
+  bfd_vma apos = asec->output_section->lma + asec->output_offset;
+  bfd_vma bpos = bsec->output_section->lma + bsec->output_offset;
 
-  apos = elf_get_linked_section_vma (*(struct bfd_link_order **)a);
-  bpos = elf_get_linked_section_vma (*(struct bfd_link_order **)b);
   if (apos < bpos)
     return -1;
-  return apos > bpos;
+  if (apos > bpos)
+    return 1;
+
+  /* The only way we should get matching LMAs is when the first of two
+     sections has zero size.  */
+  if (asec->size < bsec->size)
+    return -1;
+  if (asec->size > bsec->size)
+    return 1;
+
+  /* If they are both zero size then they almost certainly have the same
+     VMA and thus are not ordered with respect to each other.  Test VMA
+     anyway, and fall back to id to make the result reproducible across
+     qsort implementations.  */
+  apos = asec->output_section->vma + asec->output_offset;
+  bpos = bsec->output_section->vma + bsec->output_offset;
+  if (apos < bpos)
+    return -1;
+  if (apos > bpos)
+    return 1;
+
+  return asec->id - bsec->id;
 }
 
 
@@ -11193,13 +11560,11 @@ compare_link_order (const void * a, const void * b)
 static bfd_boolean
 elf_fixup_link_order (bfd *abfd, asection *o)
 {
-  int seen_linkorder;
-  int seen_other;
-  int n;
+  size_t seen_linkorder;
+  size_t seen_other;
+  size_t n;
   struct bfd_link_order *p;
   bfd *sub;
-  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-  unsigned elfsec;
   struct bfd_link_order **sections;
   asection *s, *other_sec, *linkorder_sec;
   bfd_vma offset;
@@ -11214,12 +11579,10 @@ elf_fixup_link_order (bfd *abfd, asection *o)
        {
          s = p->u.indirect.section;
          sub = s->owner;
-         if (bfd_get_flavour (sub) == bfd_target_elf_flavour
-             && elf_elfheader (sub)->e_ident[EI_CLASS] == bed->s->elfclass
-             && (elfsec = _bfd_elf_section_from_bfd_section (sub, s))
-             && elfsec < elf_numsections (sub)
-             && elf_elfsections (sub)[elfsec]->sh_flags & SHF_LINK_ORDER
-             && elf_elfsections (sub)[elfsec]->sh_link < elf_numsections (sub))
+         if ((s->flags & SEC_LINKER_CREATED) == 0
+             && bfd_get_flavour (sub) == bfd_target_elf_flavour
+             && elf_section_data (s) != NULL
+             && elf_linked_to_section (s) != NULL)
            {
              seen_linkorder++;
              linkorder_sec = s;
@@ -11238,13 +11601,13 @@ elf_fixup_link_order (bfd *abfd, asection *o)
          if (other_sec && linkorder_sec)
            _bfd_error_handler
              /* xgettext:c-format */
-             (_("%A has both ordered [`%A' in %B] "
-                "and unordered [`%A' in %B] sections"),
+             (_("%pA has both ordered [`%pA' in %pB] "
+                "and unordered [`%pA' in %pB] sections"),
               o, linkorder_sec, linkorder_sec->owner,
               other_sec, other_sec->owner);
          else
            _bfd_error_handler
-             (_("%A has both ordered and unordered sections"), o);
+             (_("%pA has both ordered and unordered sections"), o);
          bfd_set_error (bfd_error_bad_value);
          return FALSE;
        }
@@ -11253,27 +11616,26 @@ elf_fixup_link_order (bfd *abfd, asection *o)
   if (!seen_linkorder)
     return TRUE;
 
-  sections = (struct bfd_link_order **)
-    bfd_malloc (seen_linkorder * sizeof (struct bfd_link_order *));
+  sections = bfd_malloc (seen_linkorder * sizeof (*sections));
   if (sections == NULL)
     return FALSE;
-  seen_linkorder = 0;
 
+  seen_linkorder = 0;
   for (p = o->map_head.link_order; p != NULL; p = p->next)
-    {
-      sections[seen_linkorder++] = p;
-    }
+    sections[seen_linkorder++] = p;
+
   /* Sort the input sections in the order of their linked section.  */
-  qsort (sections, seen_linkorder, sizeof (struct bfd_link_order *),
-        compare_link_order);
+  qsort (sections, seen_linkorder, sizeof (*sections), compare_link_order);
 
   /* Change the offsets of the sections.  */
   offset = 0;
   for (n = 0; n < seen_linkorder; n++)
     {
+      bfd_vma mask;
       s = sections[n]->u.indirect.section;
-      offset &= ~(bfd_vma) 0 << s->alignment_power;
-      s->output_offset = offset / bfd_octets_per_byte (abfd);
+      mask = ~(bfd_vma) 0 << s->alignment_power;
+      offset = (offset + ~mask) & mask;
+      s->output_offset = offset / bfd_octets_per_byte (abfd, s);
       sections[n]->offset = offset;
       offset += sections[n]->size;
     }
@@ -11327,7 +11689,10 @@ elf_output_implib (bfd *abfd, struct bfd_link_info *info)
     return FALSE;
 
   /* Read in the symbol table.  */
-  sympp = (asymbol **) xmalloc (symsize);
+  sympp = (asymbol **) bfd_malloc (symsize);
+  if (sympp == NULL)
+    return FALSE;
+
   symcount = bfd_canonicalize_symtab (abfd, sympp);
   if (symcount < 0)
     goto free_sym_buf;
@@ -11346,7 +11711,7 @@ elf_output_implib (bfd *abfd, struct bfd_link_info *info)
   if (symcount == 0)
     {
       bfd_set_error (bfd_error_no_symbols);
-      _bfd_error_handler (_("%B: no symbol found for import library"),
+      _bfd_error_handler (_("%pB: no symbol found for import library"),
                          implib_bfd);
       goto free_sym_buf;
     }
@@ -11355,6 +11720,9 @@ elf_output_implib (bfd *abfd, struct bfd_link_info *info)
   /* Make symbols absolute.  */
   osymbuf = (elf_symbol_type *) bfd_alloc2 (implib_bfd, symcount,
                                            sizeof (*osymbuf));
+  if (osymbuf == NULL)
+    goto free_sym_buf;
+
   for (src_count = 0; src_count < symcount; src_count++)
     {
       memcpy (&osymbuf[src_count], (elf_symbol_type *) sympp[src_count],
@@ -11408,7 +11776,8 @@ elf_final_link_free (bfd *obfd, struct elf_final_link_info *flinfo)
     free (flinfo->indices);
   if (flinfo->sections != NULL)
     free (flinfo->sections);
-  if (flinfo->symshndxbuf != NULL)
+  if (flinfo->symshndxbuf != NULL
+      && flinfo->symshndxbuf != (Elf_External_Sym_Shndx *) -1)
     free (flinfo->symshndxbuf);
   for (o = obfd->sections; o != NULL; o = o->next)
     {
@@ -11451,6 +11820,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   bfd_vma attr_size = 0;
   const char *std_attrs_section;
   struct elf_link_hash_table *htab = elf_hash_table (info);
+  bfd_boolean sections_removed;
 
   if (!is_elf_hash_table (htab))
     return FALSE;
@@ -11496,10 +11866,13 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
   /* The object attributes have been merged.  Remove the input
      sections from the link, and set the contents of the output
-     secton.  */
+     section.  */
+  sections_removed = FALSE;
   std_attrs_section = get_elf_backend_data (abfd)->obj_attrs_section;
   for (o = abfd->sections; o != NULL; o = o->next)
     {
+      bfd_boolean remove_section = FALSE;
+
       if ((std_attrs_section && strcmp (o->name, std_attrs_section) == 0)
          || strcmp (o->name, ".gnu.attributes") == 0)
        {
@@ -11516,17 +11889,29 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
            }
 
          attr_size = bfd_elf_obj_attr_size (abfd);
+         bfd_set_section_size (o, attr_size);
+         /* Skip this section later on.  */
+         o->map_head.link_order = NULL;
          if (attr_size)
-           {
-             bfd_set_section_size (abfd, o, attr_size);
-             attr_section = o;
-             /* Skip this section later on.  */
-             o->map_head.link_order = NULL;
-           }
+           attr_section = o;
          else
-           o->flags |= SEC_EXCLUDE;
+           remove_section = TRUE;
+       }
+      else if ((o->flags & SEC_GROUP) != 0 && o->size == 0)
+       {
+         /* Remove empty group section from linker output.  */
+         remove_section = TRUE;
+       }
+      if (remove_section)
+       {
+         o->flags |= SEC_EXCLUDE;
+         bfd_section_list_remove (abfd, o);
+         abfd->section_count--;
+         sections_removed = TRUE;
        }
     }
+  if (sections_removed)
+    _bfd_fix_excluded_sec_syms (abfd, info);
 
   /* Count up the number of relocations we will output for each output
      section, so that we know the sizes of the reloc sections.  We
@@ -11682,7 +12067,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   /* Figure out the file positions for everything but the symbol table
      and the relocs.  We set symcount to force assign_section_numbers
      to create a symbol table.  */
-  bfd_get_symcount (abfd) = info->strip != strip_all || emit_relocs;
+  abfd->symcount = info->strip != strip_all || emit_relocs;
   BFD_ASSERT (! abfd->output_has_begun);
   if (! _bfd_elf_compute_section_file_positions (abfd, info))
     goto error_return;
@@ -11702,12 +12087,17 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
            goto error_return;
        }
 
+      /* _bfd_elf_compute_section_file_positions makes temporary use
+        of target_index.  Reset it.  */
+      o->target_index = 0;
+
       /* Now, reset REL_COUNT and REL_COUNT2 so that we can use them
         to count upwards while actually outputting the relocations.  */
       esdo->rel.count = 0;
       esdo->rela.count = 0;
 
-      if (esdo->this_hdr.sh_offset == (file_ptr) -1)
+      if ((esdo->this_hdr.sh_offset == (file_ptr) -1)
+         && !bfd_section_is_ctf (o))
        {
          /* Cache the section contents so that they can be compressed
             later.  Use bfd_malloc since it will be freed by
@@ -11723,11 +12113,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
        }
     }
 
-  /* We have now assigned file positions for all the sections except
-     .symtab, .strtab, and non-loaded reloc sections.  We start the
-     .symtab section at the current file position, and write directly
-     to it.  We build the .strtab section in memory.  */
-  bfd_get_symcount (abfd) = 0;
+  /* We have now assigned file positions for all the sections except .symtab,
+     .strtab, and non-loaded reloc and compressed debugging sections.  We start
+     the .symtab section at the current file position, and write directly to it.
+     We build the .strtab section in memory.  */
+  abfd->symcount = 0;
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   /* sh_name is set in prep_headers.  */
   symtab_hdr->sh_type = SHT_SYMTAB;
@@ -11968,7 +12358,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                      bfd_set_error (bfd_error_wrong_format);
                      _bfd_error_handler
                        /* xgettext:c-format */
-                       (_("%B: file class %s incompatible with %s"),
+                       (_("%pB: file class %s incompatible with %s"),
                         sub, iclass, oclass);
                    }
 
@@ -12185,7 +12575,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
   if (info->out_implib_bfd && !elf_output_implib (abfd, info))
     {
-      _bfd_error_handler (_("%B: failed to generate import library"),
+      _bfd_error_handler (_("%pB: failed to generate import library"),
                          info->out_implib_bfd);
       return FALSE;
     }
@@ -12444,10 +12834,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                {
                  if (info->error_textrel)
                    info->callbacks->einfo
-                     (_("%P%X: read-only segment has dynamic relocations.\n"));
+                     (_("%P%X: read-only segment has dynamic relocations\n"));
                  else
                    info->callbacks->einfo
-                     (_("%P: warning: creating a DT_TEXTREL in a shared object.\n"));
+                     (_("%P: warning: creating a DT_TEXTREL in a shared object\n"));
                  break;
                }
            }
@@ -12471,11 +12861,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
            continue;
          if (strcmp (o->name, ".dynstr") != 0)
            {
-             if (! bfd_set_section_contents (abfd, o->output_section,
-                                             o->contents,
-                                             (file_ptr) o->output_offset
-                                             * bfd_octets_per_byte (abfd),
-                                             o->size))
+             bfd_size_type octets = ((file_ptr) o->output_offset
+                                     * bfd_octets_per_byte (abfd, o));
+             if (!bfd_set_section_contents (abfd, o->output_section,
+                                            o->contents, octets, o->size))
                goto error_return;
            }
          else
@@ -12512,9 +12901,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info))
     goto error_return;
 
-  elf_final_link_free (abfd, &flinfo);
+  if (info->callbacks->emit_ctf)
+      info->callbacks->emit_ctf ();
 
-  elf_linker (abfd) = TRUE;
+  elf_final_link_free (abfd, &flinfo);
 
   if (attr_section)
     {
@@ -12693,20 +13083,31 @@ _bfd_elf_gc_mark_hook (asection *sec,
   return NULL;
 }
 
-/* Return the global debug definition section.  */
+/* Return the debug definition section.  */
 
 static asection *
 elf_gc_mark_debug_section (asection *sec ATTRIBUTE_UNUSED,
                           struct bfd_link_info *info ATTRIBUTE_UNUSED,
                           Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
                           struct elf_link_hash_entry *h,
-                          Elf_Internal_Sym *sym ATTRIBUTE_UNUSED)
+                          Elf_Internal_Sym *sym)
 {
-  if (h != NULL
-      && (h->root.type == bfd_link_hash_defined
-         || h->root.type == bfd_link_hash_defweak)
-      && (h->root.u.def.section->flags & SEC_DEBUGGING) != 0)
-    return h->root.u.def.section;
+  if (h != NULL)
+    {
+      /* Return the global debug definition section.  */
+      if ((h->root.type == bfd_link_hash_defined
+          || h->root.type == bfd_link_hash_defweak)
+         && (h->root.u.def.section->flags & SEC_DEBUGGING) != 0)
+       return h->root.u.def.section;
+    }
+  else
+    {
+      /* Return the local debug definition section.  */
+      asection *isec = bfd_section_from_elf_index (sec->owner,
+                                                  sym->st_shndx);
+      if ((isec->flags & SEC_DEBUGGING) != 0)
+       return isec;
+    }
 
   return NULL;
 }
@@ -12734,7 +13135,7 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
       h = cookie->sym_hashes[r_symndx - cookie->extsymoff];
       if (h == NULL)
        {
-         info->callbacks->einfo (_("%F%P: corrupt input: %B\n"),
+         info->callbacks->einfo (_("%F%P: corrupt input: %pB\n"),
                                  sec->owner);
          return NULL;
        }
@@ -12746,8 +13147,8 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
         keep the non-weak definition because many backends put
         dynamic reloc info on the non-weak definition for code
         handling copy relocs.  */
-      if (h->u.weakdef != NULL)
-       h->u.weakdef->mark = 1;
+      if (h->is_weakalias)
+       weakdef (h)->mark = 1;
 
       if (start_stop != NULL)
        {
@@ -12981,7 +13382,7 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
              ilen = strlen (isec->name);
 
              /* Association is determined by the name of the debug
-                section containing the name of the code section as
+                section containing the name of the code section as
                 a suffix.  For example .debug_line.text.foo is a
                 debug section associated with .text.foo.  */
              for (dsec = ibfd->sections; dsec != NULL; dsec = dsec->next)
@@ -13013,23 +13414,18 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
   return TRUE;
 }
 
-/* The sweep phase of garbage collection.  Remove all garbage sections.  */
-
-typedef bfd_boolean (*gc_sweep_hook_fn)
-  (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
-
 static bfd_boolean
 elf_gc_sweep (bfd *abfd, struct bfd_link_info *info)
 {
   bfd *sub;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-  gc_sweep_hook_fn gc_sweep_hook = bed->gc_sweep_hook;
 
   for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
     {
       asection *o;
 
       if (bfd_get_flavour (sub) != bfd_target_elf_flavour
+         || elf_object_id (sub) != elf_hash_table_id (elf_hash_table (info))
          || !(*bed->relocs_compatible) (sub->xvec, abfd->xvec))
        continue;
       o = sub->sections;
@@ -13061,35 +13457,8 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info)
 
          if (info->print_gc_sections && o->size != 0)
            /* xgettext:c-format */
-           _bfd_error_handler (_("Removing unused section '%A' in file '%B'"),
+           _bfd_error_handler (_("removing unused section '%pA' in file '%pB'"),
                                o, sub);
-
-         /* But we also have to update some of the relocation
-            info we collected before.  */
-         if (gc_sweep_hook
-             && (o->flags & SEC_RELOC) != 0
-             && o->reloc_count != 0
-             && !((info->strip == strip_all || info->strip == strip_debugger)
-                  && (o->flags & SEC_DEBUGGING) != 0)
-             && !bfd_is_abs_section (o->output_section))
-           {
-             Elf_Internal_Rela *internal_relocs;
-             bfd_boolean r;
-
-             internal_relocs
-               = _bfd_elf_link_read_relocs (o->owner, o, NULL, NULL,
-                                            info->keep_memory);
-             if (internal_relocs == NULL)
-               return FALSE;
-
-             r = (*gc_sweep_hook) (o->owner, info, o, internal_relocs);
-
-             if (elf_section_data (o)->relocs != internal_relocs)
-               free (internal_relocs);
-
-             if (!r)
-               return FALSE;
-           }
        }
     }
 
@@ -13217,7 +13586,7 @@ bfd_elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h, void *inf)
 
   if ((h->root.type == bfd_link_hash_defined
        || h->root.type == bfd_link_hash_defweak)
-      && (h->ref_dynamic
+      && ((h->ref_dynamic && !h->forced_local)
          || ((h->def_regular || ELF_COMMON_DEF_P (h))
              && ELF_ST_VISIBILITY (h->other) != STV_INTERNAL
              && ELF_ST_VISIBILITY (h->other) != STV_HIDDEN
@@ -13281,7 +13650,7 @@ bfd_elf_parse_eh_frame_entries (bfd *abfd ATTRIBUTE_UNUSED,
 
       for (sec = ibfd->sections; sec; sec = sec->next)
        {
-         if (CONST_STRNEQ (bfd_section_name (ibfd, sec), ".eh_frame_entry")
+         if (CONST_STRNEQ (bfd_section_name (sec), ".eh_frame_entry")
              && init_reloc_cookie_rels (&cookie, info, ibfd, sec))
            {
              _bfd_elf_parse_eh_frame_entry (info, sec, &cookie);
@@ -13306,7 +13675,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
   if (!bed->can_gc_sections
       || !is_elf_hash_table (info->hash))
     {
-      _bfd_error_handler(_("Warning: gc-sections option ignored"));
+      _bfd_error_handler(_("warning: gc-sections option ignored"));
       return TRUE;
     }
 
@@ -13358,6 +13727,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
       asection *o;
 
       if (bfd_get_flavour (sub) != bfd_target_elf_flavour
+         || elf_object_id (sub) != elf_hash_table_id (htab)
          || !(*bed->relocs_compatible) (sub->xvec, abfd->xvec))
        continue;
 
@@ -13367,11 +13737,19 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
 
       /* Start at sections marked with SEC_KEEP (ref _bfd_elf_gc_keep).
         Also treat note sections as a root, if the section is not part
-        of a group.  */
+        of a group.  We must keep all PREINIT_ARRAY, INIT_ARRAY as
+        well as FINI_ARRAY sections for ld -r.  */
       for (o = sub->sections; o != NULL; o = o->next)
        if (!o->gc_mark
            && (o->flags & SEC_EXCLUDE) == 0
            && ((o->flags & SEC_KEEP) != 0
+               || (bfd_link_relocatable (info)
+                   && ((elf_section_data (o)->this_hdr.sh_type
+                        == SHT_PREINIT_ARRAY)
+                       || (elf_section_data (o)->this_hdr.sh_type
+                           == SHT_INIT_ARRAY)
+                       || (elf_section_data (o)->this_hdr.sh_type
+                           == SHT_FINI_ARRAY)))
                || (elf_section_data (o)->this_hdr.sh_type == SHT_NOTE
                    && elf_next_in_group (o) == NULL )))
          {
@@ -13423,8 +13801,8 @@ bfd_elf_gc_record_vtinherit (bfd *abfd,
     }
 
   /* xgettext:c-format */
-  _bfd_error_handler (_("%B: %A+%#Lx: No symbol found for INHERIT"),
-                     abfd, sec, offset);
+  _bfd_error_handler (_("%pB: %pA+%#" PRIx64 ": no symbol found for INHERIT"),
+                     abfd, sec, (uint64_t) offset);
   bfd_set_error (bfd_error_invalid_operation);
   return FALSE;
 
@@ -13454,14 +13832,22 @@ bfd_elf_gc_record_vtinherit (bfd *abfd,
 /* Called from check_relocs to record the existence of a VTENTRY reloc.  */
 
 bfd_boolean
-bfd_elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED,
-                          asection *sec ATTRIBUTE_UNUSED,
+bfd_elf_gc_record_vtentry (bfd *abfd, asection *sec,
                           struct elf_link_hash_entry *h,
                           bfd_vma addend)
 {
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   unsigned int log_file_align = bed->s->log_file_align;
 
+  if (!h)
+    {
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%pB: section '%pA': corrupt VTENTRY entry"),
+                         abfd, sec);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+
   if (!h->u2.vtable)
     {
       h->u2.vtable = ((struct elf_link_virtual_table_entry *)
@@ -13599,7 +13985,7 @@ bfd_elf_lookup_section_flags (struct bfd_link_info *info,
          if (!tf->valid)
            {
              info->callbacks->einfo
-               (_("Unrecognized INPUT_SECTION_FLAG %s\n"), tf->name);
+               (_("unrecognized INPUT_SECTION_FLAG %s\n"), tf->name);
              return FALSE;
            }
        }
@@ -14120,7 +14506,7 @@ get_dynamic_reloc_section_name (bfd *       abfd,
                                bfd_boolean is_rela)
 {
   char *name;
-  const char *old_name = bfd_get_section_name (NULL, sec);
+  const char *old_name = bfd_section_name (sec);
   const char *prefix = is_rela ? ".rela" : ".rel";
 
   if (old_name == NULL)
@@ -14203,7 +14589,7 @@ _bfd_elf_make_dynamic_reloc_section (asection *sec,
                 section named "auto" we'll get ".relauto" which is
                 seen to be a .rela section.  */
              elf_section_type (reloc_sec) = is_rela ? SHT_RELA : SHT_REL;
-             if (! bfd_set_section_alignment (dynobj, reloc_sec, alignment))
+             if (!bfd_set_section_alignment (reloc_sec, alignment))
                reloc_sec = NULL;
            }
        }
@@ -14269,8 +14655,9 @@ bfd_elf_define_start_stop (struct bfd_link_info *info,
   if (h != NULL
       && (h->root.type == bfd_link_hash_undefined
          || h->root.type == bfd_link_hash_undefweak
-         || (h->ref_regular && !h->def_regular)))
+         || ((h->ref_regular || h->def_dynamic) && !h->def_regular)))
     {
+      bfd_boolean was_dynamic = h->ref_dynamic || h->def_dynamic;
       h->root.type = bfd_link_hash_defined;
       h->root.u.def.section = sec;
       h->root.u.def.value = 0;
@@ -14281,10 +14668,17 @@ bfd_elf_define_start_stop (struct bfd_link_info *info,
       if (symbol[0] == '.')
        {
          /* .startof. and .sizeof. symbols are local.  */
-         _bfd_elf_link_hash_hide_symbol (info, h, TRUE);
+         const struct elf_backend_data *bed;
+         bed = get_elf_backend_data (info->output_bfd);
+         (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+       }
+      else
+       {
+         if (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
+           h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_PROTECTED;
+         if (was_dynamic)
+           bfd_elf_link_record_dynamic_symbol (info, h);
        }
-      else if (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
-       h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_PROTECTED;
       return &h->root;
     }
   return NULL;
This page took 0.068252 seconds and 4 git commands to generate.