gdb/fortran: Remove some dead code from the parser
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 4c92a048cea8ebd359c5b5a4f8770061b671e875..16d83bb7a3035357bb47260800c83085bc039fa6 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF linking support for BFD.
-   Copyright (C) 1995-2018 Free Software Foundation, Inc.
+   Copyright (C) 1995-2019 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
@@ -223,6 +222,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))
              {
@@ -339,7 +339,7 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
       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);
@@ -586,7 +586,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 +686,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 +718,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))
@@ -881,9 +885,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;
@@ -896,9 +900,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;
 
@@ -913,6 +914,15 @@ _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
@@ -938,6 +948,7 @@ _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))
          {
            ++dynsymcount;
@@ -1350,26 +1361,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);
@@ -1926,6 +1937,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,
@@ -2049,7 +2070,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
@@ -2207,6 +2228,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
@@ -2220,6 +2350,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;
@@ -2234,12 +2365,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;
+    {
+      /* 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)
     {
@@ -2253,50 +2393,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))
@@ -2342,7 +2447,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;
@@ -2352,10 +2457,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);
@@ -2415,9 +2520,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;
 
@@ -2431,10 +2538,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;
            }
@@ -2443,11 +2550,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;
        }
@@ -2634,7 +2741,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;
@@ -2761,10 +2868,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
@@ -2807,8 +2918,16 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *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 (def->def_regular)
+        _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)
@@ -2821,7 +2940,6 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
          BFD_ASSERT (h->root.type == bfd_link_hash_defined
                      || h->root.type == bfd_link_hash_defweak);
          BFD_ASSERT (def->def_dynamic);
-         BFD_ASSERT (def->root.type == bfd_link_hash_defined);
          (*bed->elf_backend_copy_indirect_symbol) (eif->info, def, h);
        }
     }
@@ -3014,7 +3132,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;
@@ -3365,6 +3483,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);
@@ -3758,6 +3879,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;
@@ -3813,9 +3935,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
@@ -3958,7 +4080,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;
@@ -4072,7 +4194,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)
@@ -4183,13 +4305,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));
        }
     }
 
@@ -4264,7 +4387,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))
@@ -4285,6 +4428,7 @@ error_free_dyn:
       bfd_boolean common;
       bfd_boolean discarded;
       unsigned int old_alignment;
+      unsigned int shindex;
       bfd *old_bfd;
       bfd_boolean matched;
 
@@ -4310,7 +4454,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)
@@ -4408,10 +4570,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
@@ -4448,6 +4607,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);
 
@@ -4481,7 +4648,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);
@@ -4518,7 +4685,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;
@@ -4589,11 +4756,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.  */
@@ -4770,15 +4932,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);
                }
@@ -4794,9 +4956,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;
            }
@@ -4828,8 +4991,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;
@@ -4929,7 +5092,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;
@@ -5422,7 +5585,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);
@@ -5520,7 +5683,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)
@@ -5691,6 +5854,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;
@@ -5755,10 +5919,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;
@@ -5772,7 +5938,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;
     }
 
@@ -5789,7 +5963,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;
 }
 
@@ -6005,11 +6186,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;
@@ -6777,7 +6958,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;
                      }
@@ -6818,7 +6999,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)
@@ -6898,14 +7080,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.
@@ -6914,31 +7099,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)
 {
@@ -7105,12 +7294,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;
@@ -7190,6 +7379,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)
                {
@@ -7216,9 +7407,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)
@@ -7414,6 +7607,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.  */
 
@@ -8707,10 +8920,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;
@@ -8946,7 +9159,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);
@@ -8964,7 +9177,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);
@@ -8980,7 +9193,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;
@@ -9003,7 +9216,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);
@@ -9021,7 +9234,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);
@@ -9037,7 +9250,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;
@@ -9089,7 +9302,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;
     }
 
@@ -9229,6 +9442,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))
@@ -9357,7 +9575,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;
@@ -9602,7 +9820,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)
@@ -9637,13 +9855,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;
@@ -9729,7 +9947,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;
@@ -9883,13 +10101,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;
@@ -9899,9 +10117,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;
 
@@ -9920,7 +10139,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;
@@ -10246,8 +10465,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)
@@ -10362,8 +10580,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);
            }
        }
 
@@ -10530,7 +10751,7 @@ 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_bad_value);
@@ -10575,9 +10796,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;
                    }
@@ -10661,8 +10882,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
@@ -10919,12 +11140,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);
                                }
                            }
 
@@ -11249,7 +11475,7 @@ elf_get_linked_section_vma (struct bfd_link_order *p)
       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);
+         (_("%pB: warning: sh_link not set for section `%pA'"), s->owner, s);
       return 0;
     }
   else
@@ -11330,13 +11556,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;
        }
@@ -11438,7 +11664,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;
     }
@@ -11500,7 +11726,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)
     {
@@ -11592,6 +11819,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   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)
        {
@@ -11608,15 +11837,24 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
            }
 
          attr_size = bfd_elf_obj_attr_size (abfd);
+         bfd_set_section_size (abfd, 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--;
        }
     }
 
@@ -12060,7 +12298,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);
                    }
 
@@ -12277,7 +12515,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;
     }
@@ -12536,10 +12774,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;
                }
            }
@@ -12606,8 +12844,6 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
   elf_final_link_free (abfd, &flinfo);
 
-  elf_linker (abfd) = TRUE;
-
   if (attr_section)
     {
       bfd_byte *contents = (bfd_byte *) bfd_malloc (attr_size);
@@ -12785,20 +13021,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;
 }
@@ -12826,7 +13073,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;
        }
@@ -13148,7 +13395,7 @@ 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);
        }
     }
@@ -13277,7 +13524,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
@@ -13366,7 +13613,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;
     }
 
@@ -13492,8 +13739,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;
 
@@ -13523,14 +13770,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 *)
@@ -13668,7 +13923,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;
            }
        }
@@ -14338,8 +14593,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;
@@ -14354,8 +14610,13 @@ bfd_elf_define_start_stop (struct bfd_link_info *info,
          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;
+      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);
+       }
       return &h->root;
     }
   return NULL;
This page took 0.049363 seconds and 4 git commands to generate.