Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 36e0c37c8ef2799767ffad5fdae2152feea9c8a6..6624864bf540bd1bedc2c14b9950d52a33da9a21 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF linking support for BFD.
-   Copyright (C) 1995-2018 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
@@ -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;
            }
@@ -686,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.  */
@@ -751,7 +747,7 @@ bfd_elf_link_record_local_dynamic_symbol (struct bfd_link_info *info,
                                          bfd *input_bfd,
                                          long input_indx)
 {
-  bfd_size_type amt;
+  size_t amt;
   struct elf_link_local_dynamic_entry *entry;
   struct elf_link_hash_table *eht;
   struct elf_strtab_hash *dynstr;
@@ -902,9 +898,6 @@ _bfd_elf_omit_section_dynsym_default (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;
 
@@ -1911,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
@@ -1942,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,
@@ -2036,7 +2039,7 @@ _bfd_elf_add_default_symbol (bfd *abfd,
   /* We also need to define an indirection from the nondefault version
      of the symbol.  */
 
-nondefault:
+ nondefault:
   len = strlen (name);
   shortname = (char *) bfd_hash_allocate (&info->hash->table, len);
   if (shortname == NULL)
@@ -2152,7 +2155,7 @@ _bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h,
   struct elf_find_verdep_info *rinfo = (struct elf_find_verdep_info *) data;
   Elf_Internal_Verneed *t;
   Elf_Internal_Vernaux *a;
-  bfd_size_type amt;
+  size_t amt;
 
   /* We only care about symbols defined in shared objects with version
      information.  */
@@ -2360,13 +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;
+    }
 
   hide = FALSE;
-  bed = get_elf_backend_data (info->output_bfd);
   p = strchr (h->root.root.string, ELF_VER_CHR);
   if (p != NULL && h->verinfo.vertree == NULL)
     {
@@ -2507,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;
 
@@ -2853,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
@@ -2899,8 +2916,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)
@@ -2913,7 +2938,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);
        }
     }
@@ -3073,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)
     {
@@ -3081,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;
     }
 
@@ -3301,8 +3323,8 @@ _bfd_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
 
   elf_hash_table (info)->tls_sec = tls;
 
-  /* Ensure the alignment of the first section is the largest alignment,
-     so that the tls segment starts aligned.  */
+  /* Ensure the alignment of the first section (usually .tdata) is the largest
+     alignment, so that the tls segment starts aligned.  */
   if (tls != NULL)
     tls->alignment_power = align;
 
@@ -3479,23 +3501,119 @@ _bfd_elf_add_dynamic_entry (struct bfd_link_info *info,
   return TRUE;
 }
 
-/* Add a DT_NEEDED entry for this dynamic object if DO_IT is true,
-   otherwise just check whether one already exists.  Returns -1 on error,
+/* Strip zero-sized dynamic sections.  */
+
+bfd_boolean
+_bfd_elf_strip_zero_sized_dynamic_sections (struct bfd_link_info *info)
+{
+  struct elf_link_hash_table *hash_table;
+  const struct elf_backend_data *bed;
+  asection *s, *sdynamic, **pp;
+  asection *rela_dyn, *rel_dyn;
+  Elf_Internal_Dyn dyn;
+  bfd_byte *extdyn, *next;
+  void (*swap_dyn_in) (bfd *, const void *, Elf_Internal_Dyn *);
+  bfd_boolean strip_zero_sized;
+  bfd_boolean strip_zero_sized_plt;
+
+  if (bfd_link_relocatable (info))
+    return TRUE;
+
+  hash_table = elf_hash_table (info);
+  if (!is_elf_hash_table (hash_table))
+    return FALSE;
+
+  if (!hash_table->dynobj)
+    return TRUE;
+
+  sdynamic= bfd_get_linker_section (hash_table->dynobj, ".dynamic");
+  if (!sdynamic)
+    return TRUE;
+
+  bed = get_elf_backend_data (hash_table->dynobj);
+  swap_dyn_in = bed->s->swap_dyn_in;
+
+  strip_zero_sized = FALSE;
+  strip_zero_sized_plt = FALSE;
+
+  /* Strip zero-sized dynamic sections.  */
+  rela_dyn = bfd_get_section_by_name (info->output_bfd, ".rela.dyn");
+  rel_dyn = bfd_get_section_by_name (info->output_bfd, ".rel.dyn");
+  for (pp = &info->output_bfd->sections; (s = *pp) != NULL;)
+    if (s->size == 0
+       && (s == rela_dyn
+           || s == rel_dyn
+           || s == hash_table->srelplt->output_section
+           || s == hash_table->splt->output_section))
+      {
+       *pp = s->next;
+       info->output_bfd->section_count--;
+       strip_zero_sized = TRUE;
+       if (s == rela_dyn)
+         s = rela_dyn;
+       if (s == rel_dyn)
+         s = rel_dyn;
+       else if (s == hash_table->splt->output_section)
+         {
+           s = hash_table->splt;
+           strip_zero_sized_plt = TRUE;
+         }
+       else
+         s = hash_table->srelplt;
+       s->flags |= SEC_EXCLUDE;
+       s->output_section = bfd_abs_section_ptr;
+      }
+    else
+      pp = &s->next;
+
+  if (strip_zero_sized_plt)
+    for (extdyn = sdynamic->contents;
+        extdyn < sdynamic->contents + sdynamic->size;
+        extdyn = next)
+      {
+       next = extdyn + bed->s->sizeof_dyn;
+       swap_dyn_in (hash_table->dynobj, extdyn, &dyn);
+       switch (dyn.d_tag)
+         {
+         default:
+           break;
+         case DT_JMPREL:
+         case DT_PLTRELSZ:
+         case DT_PLTREL:
+           /* Strip DT_PLTRELSZ, DT_JMPREL and DT_PLTREL entries if
+              the procedure linkage table (the .plt section) has been
+              removed.  */
+           memmove (extdyn, next,
+                    sdynamic->size - (next - sdynamic->contents));
+           next = extdyn;
+         }
+      }
+
+  if (strip_zero_sized)
+    {
+      /* Regenerate program headers.  */
+      elf_seg_map (info->output_bfd) = NULL;
+      return _bfd_elf_map_sections_to_segments (info->output_bfd, info);
+    }
+
+  return TRUE;
+}
+
+/* Add a DT_NEEDED entry for this dynamic object.  Returns -1 on error,
    1 if a DT_NEEDED tag already exists, and 0 on success.  */
 
-static int
-elf_add_dt_needed_tag (bfd *abfd,
-                      struct bfd_link_info *info,
-                      const char *soname,
-                      bfd_boolean do_it)
+int
+bfd_elf_add_dt_needed_tag (bfd *abfd, struct bfd_link_info *info)
 {
   struct elf_link_hash_table *hash_table;
   size_t strindex;
+  const char *soname;
 
   if (!_bfd_elf_link_create_dynstrtab (abfd, info))
     return -1;
 
   hash_table = elf_hash_table (info);
+  soname = elf_dt_name (abfd);
   strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, FALSE);
   if (strindex == (size_t) -1)
     return -1;
@@ -3525,17 +3643,11 @@ elf_add_dt_needed_tag (bfd *abfd,
          }
     }
 
-  if (do_it)
-    {
-      if (!_bfd_elf_link_create_dynamic_sections (hash_table->dynobj, info))
-       return -1;
+  if (!_bfd_elf_link_create_dynamic_sections (hash_table->dynobj, info))
+    return -1;
 
-      if (!_bfd_elf_add_dynamic_entry (info, DT_NEEDED, strindex))
-       return -1;
-    }
-  else
-    /* We were just checking for existence of the tag.  */
-    _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
+  if (!_bfd_elf_add_dynamic_entry (info, DT_NEEDED, strindex))
+    return -1;
 
   return 0;
 }
@@ -3565,27 +3677,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
@@ -3853,6 +3998,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;
@@ -3863,7 +4009,6 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   const struct elf_backend_data *bed;
   bfd_boolean add_needed;
   struct elf_link_hash_table *htab;
-  bfd_size_type amt;
   void *alloc_mark = NULL;
   struct bfd_hash_entry **old_table = NULL;
   unsigned int old_size = 0;
@@ -3922,7 +4067,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;
@@ -4014,7 +4159,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       char *audit = NULL;
       struct bfd_link_needed_list *rpath = NULL, *runpath = NULL;
       const Elf_Internal_Phdr *phdr;
-      int ret;
+      struct elf_link_loaded_list *loaded_lib;
 
       /* ld --just-symbols and dynamic objects don't mix very well.
         ld shouldn't allow it.  */
@@ -4042,7 +4187,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 
          if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
            {
-error_free_dyn:
+           error_free_dyn:
              free (dynbuf);
              goto error_return;
            }
@@ -4053,7 +4198,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;
@@ -4071,8 +4216,8 @@ error_free_dyn:
                  struct bfd_link_needed_list *n, **pn;
                  char *fnm, *anm;
                  unsigned int tagv = dyn.d_un.d_val;
+                 size_t amt = sizeof (struct bfd_link_needed_list);
 
-                 amt = sizeof (struct bfd_link_needed_list);
                  n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt);
                  fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
                  if (n == NULL || fnm == NULL)
@@ -4094,8 +4239,8 @@ error_free_dyn:
                  struct bfd_link_needed_list *n, **pn;
                  char *fnm, *anm;
                  unsigned int tagv = dyn.d_un.d_val;
+                 size_t amt = sizeof (struct bfd_link_needed_list);
 
-                 amt = sizeof (struct bfd_link_needed_list);
                  n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt);
                  fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
                  if (n == NULL || fnm == NULL)
@@ -4120,8 +4265,8 @@ error_free_dyn:
                  struct bfd_link_needed_list *n, **pn;
                  char *fnm, *anm;
                  unsigned int tagv = dyn.d_un.d_val;
+                 size_t amt = sizeof (struct bfd_link_needed_list);
 
-                 amt = sizeof (struct bfd_link_needed_list);
                  n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt);
                  fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
                  if (n == NULL || fnm == NULL)
@@ -4167,14 +4312,18 @@ 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)
-             if ((s->flags & SEC_ALLOC) != 0
-                 && s->vma >= phdr->p_vaddr
-                 && s->vma + s->size <= phdr->p_vaddr + phdr->p_memsz)
-               s->flags |= SEC_READONLY;
+             {
+               unsigned int opb = bfd_octets_per_byte (abfd, s);
+
+               if ((s->flags & SEC_ALLOC) != 0
+                   && s->vma * opb >= phdr->p_vaddr
+                   && s->vma * opb + s->size <= phdr->p_vaddr + phdr->p_memsz)
+                 s->flags |= SEC_READONLY;
+             }
            break;
          }
 
@@ -4203,15 +4352,22 @@ error_free_dyn:
         will need to know it.  */
       elf_dt_name (abfd) = soname;
 
-      ret = elf_add_dt_needed_tag (abfd, info, soname, add_needed);
-      if (ret < 0)
-       goto error_return;
-
       /* If we have already included this dynamic object in the
         link, just ignore it.  There is no reason to include a
         particular dynamic object more than once.  */
-      if (ret > 0)
-       return TRUE;
+      for (loaded_lib = htab->dyn_loaded;
+          loaded_lib != NULL;
+          loaded_lib = loaded_lib->next)
+       {
+         if (strcmp (elf_dt_name (loaded_lib->abfd), soname) == 0)
+           return TRUE;
+       }
+
+      /* Create dynamic sections for backends that require that be done
+        before setup_gnu_properties.  */
+      if (add_needed
+         && !_bfd_elf_link_create_dynamic_sections (abfd, info))
+       return FALSE;
 
       /* Save the DT_AUDIT entry for the linker emulation code. */
       elf_dt_audit (abfd) = audit;
@@ -4255,8 +4411,7 @@ error_free_dyn:
        {
          /* We store a pointer to the hash table entry for each
             external symbol.  */
-         amt = extsymcount;
-         amt *= sizeof (struct elf_link_hash_entry *);
+         size_t amt = extsymcount * sizeof (struct elf_link_hash_entry *);
          sym_hash = (struct elf_link_hash_entry **) bfd_zalloc (abfd, amt);
          if (sym_hash == NULL)
            goto error_free_sym;
@@ -4275,16 +4430,16 @@ error_free_dyn:
         to internal format.  */
       if (elf_dynversym (abfd) != 0)
        {
-         Elf_Internal_Shdr *versymhdr;
+         Elf_Internal_Shdr *versymhdr = &elf_tdata (abfd)->dynversym_hdr;
+         bfd_size_type amt = versymhdr->sh_size;
 
-         versymhdr = &elf_tdata (abfd)->dynversym_hdr;
-         extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size);
+         if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0)
+           goto error_free_sym;
+         extversym = (Elf_External_Versym *)
+           _bfd_malloc_and_read (abfd, amt, 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);
        }
     }
 
@@ -4335,9 +4490,13 @@ error_free_dyn:
       old_table = htab->root.table.table;
       old_size = htab->root.table.size;
       old_count = htab->root.table.count;
-      old_strtab = _bfd_elf_strtab_save (htab->dynstr);
-      if (old_strtab == NULL)
-       goto error_free_vers;
+      old_strtab = NULL;
+      if (htab->dynstr != NULL)
+       {
+         old_strtab = _bfd_elf_strtab_save (htab->dynstr);
+         if (old_strtab == NULL)
+           goto error_free_vers;
+       }
 
       for (i = 0; i < htab->root.table.size; i++)
        {
@@ -4359,7 +4518,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))
@@ -4380,6 +4559,7 @@ error_free_dyn:
       bfd_boolean common;
       bfd_boolean discarded;
       unsigned int old_alignment;
+      unsigned int shindex;
       bfd *old_bfd;
       bfd_boolean matched;
 
@@ -4405,7 +4585,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)
@@ -4503,10 +4701,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
@@ -4543,6 +4738,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);
 
@@ -4684,18 +4887,6 @@ error_free_dyn:
              (struct bfd_link_hash_entry **) sym_hash)))
        goto error_free_vers;
 
-      if ((abfd->flags & DYNAMIC) == 0
-         && (bfd_get_flavour (info->output_bfd)
-             == bfd_target_elf_flavour))
-       {
-         if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
-           elf_tdata (info->output_bfd)->has_gnu_symbols
-             |= elf_gnu_symbol_ifunc;
-         if ((flags & BSF_GNU_UNIQUE))
-           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.  */
@@ -4967,8 +5158,8 @@ error_free_dyn:
                     aliases can be checked.  */
                  if (!nondeflt_vers)
                    {
-                     amt = ((isymend - isym + 1)
-                            * sizeof (struct elf_link_hash_entry *));
+                     size_t amt = ((isymend - isym + 1)
+                                   * sizeof (struct elf_link_hash_entry *));
                      nondeflt_vers
                        = (struct elf_link_hash_entry **) bfd_malloc (amt);
                      if (!nondeflt_vers)
@@ -5016,7 +5207,6 @@ error_free_dyn:
                      && !on_needed_list (elf_dt_name (abfd),
                                          htab->needed, NULL))))
            {
-             int ret;
              const char *soname = elf_dt_name (abfd);
 
              info->callbacks->minfo ("%!", soname, old_bfd,
@@ -5041,12 +5231,11 @@ error_free_dyn:
              elf_dyn_lib_class (abfd) = (enum dynamic_lib_link_class)
                (elf_dyn_lib_class (abfd) & ~DYN_AS_NEEDED);
 
+             /* Create dynamic sections for backends that require
+                that be done before setup_gnu_properties.  */
+             if (!_bfd_elf_link_create_dynamic_sections (abfd, info))
+               return FALSE;
              add_needed = TRUE;
-             ret = elf_add_dt_needed_tag (abfd, info, soname, add_needed);
-             if (ret < 0)
-               goto error_free_vers;
-
-             BFD_ASSERT (ret == 0);
            }
        }
     }
@@ -5136,7 +5325,8 @@ error_free_dyn:
       memcpy (htab->root.table.table, old_tab, tabsize);
       htab->root.undefs = old_undefs;
       htab->root.undefs_tail = old_undefs_tail;
-      _bfd_elf_strtab_restore (htab->dynstr, old_strtab);
+      if (htab->dynstr != NULL)
+       _bfd_elf_strtab_restore (htab->dynstr, old_strtab);
       free (old_strtab);
       old_strtab = NULL;
       for (i = 0; i < htab->root.table.size; i++)
@@ -5223,6 +5413,7 @@ error_free_dyn:
        {
          struct elf_link_hash_entry *h = nondeflt_vers[cnt], *hi;
          char *shortname, *p;
+         size_t amt;
 
          p = strchr (h->root.root.string, ELF_VER_CHR);
          if (p == NULL
@@ -5283,14 +5474,13 @@ error_free_dyn:
       struct elf_link_hash_entry **hppend;
       struct elf_link_hash_entry **sorted_sym_hash;
       struct elf_link_hash_entry *h;
-      size_t sym_count;
+      size_t sym_count, amt;
 
       /* Since we have to search the whole symbol list for each weak
         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 = extsymcount * sizeof (*sorted_sym_hash);
+      sorted_sym_hash = bfd_malloc (amt);
       if (sorted_sym_hash == NULL)
        goto error_return;
       sym_hash = sorted_sym_hash;
@@ -5310,8 +5500,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)
@@ -5465,7 +5654,7 @@ error_free_dyn:
        }
     }
 
-  if (is_elf_hash_table (htab) && add_needed)
+  if (dynamic && add_needed)
     {
       /* Add this bfd to the loaded list.  */
       struct elf_link_loaded_list *n;
@@ -5474,9 +5663,12 @@ error_free_dyn:
       if (n == NULL)
        goto error_return;
       n->abfd = abfd;
-      n->next = htab->loaded;
-      htab->loaded = n;
+      n->next = htab->dyn_loaded;
+      htab->dyn_loaded = n;
     }
+  if (dynamic && !add_needed
+      && (elf_dyn_lib_class (abfd) & DYN_DT_NEEDED) != 0)
+    elf_dyn_lib_class (abfd) |= DYN_NO_NEEDED;
 
   return TRUE;
 
@@ -5565,7 +5757,7 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
   unsigned char *included = NULL;
   carsym *symdefs;
   bfd_boolean loop;
-  bfd_size_type amt;
+  size_t amt;
   const struct elf_backend_data *bed;
   struct elf_link_hash_entry * (*archive_symbol_lookup)
     (bfd *, struct bfd_link_info *, const char *);
@@ -5585,8 +5777,7 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
   c = bfd_ardata (abfd)->symdef_count;
   if (c == 0)
     return TRUE;
-  amt = c;
-  amt *= sizeof (*included);
+  amt = c * sizeof (*included);
   included = (unsigned char *) bfd_zmalloc (amt);
   if (included == NULL)
     return FALSE;
@@ -5794,6 +5985,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;
@@ -5858,10 +6050,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;
@@ -5875,7 +6069,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;
     }
 
@@ -5892,7 +6094,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;
 }
 
@@ -6921,7 +7130,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)
@@ -7001,14 +7211,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_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.
@@ -7017,31 +7230,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_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)
+    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))
+    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)
 {
@@ -7208,12 +7425,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;
@@ -7293,6 +7510,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)
                {
@@ -7319,9 +7538,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)
@@ -7574,7 +7795,7 @@ struct bfd_link_hash_table *
 _bfd_elf_link_hash_table_create (bfd *abfd)
 {
   struct elf_link_hash_table *ret;
-  bfd_size_type amt = sizeof (struct elf_link_hash_table);
+  size_t amt = sizeof (struct elf_link_hash_table);
 
   ret = (struct elf_link_hash_table *) bfd_zmalloc (amt);
   if (ret == NULL)
@@ -7728,7 +7949,7 @@ bfd_elf_get_bfd_needed_list (bfd *abfd,
          const char *string;
          struct bfd_link_needed_list *l;
          unsigned int tagv = dyn.d_un.d_val;
-         bfd_size_type amt;
+         size_t amt;
 
          string = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
          if (string == NULL)
@@ -7776,6 +7997,7 @@ struct elf_symbol
     {
       Elf_Internal_Sym *isym;
       struct elf_symbuf_symbol *ssym;
+      void *p;
     } u;
   const char *name;
 };
@@ -7788,7 +8010,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
@@ -7796,7 +8024,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 *
@@ -7805,9 +8038,10 @@ elf_create_symbuf (size_t symcount, Elf_Internal_Sym *isymbuf)
   Elf_Internal_Sym **ind, **indbufend, **indbuf;
   struct elf_symbuf_symbol *ssym;
   struct elf_symbuf_head *ssymbuf, *ssymhead;
-  size_t i, shndx_count, total_size;
+  size_t i, shndx_count, total_size, amt;
 
-  indbuf = (Elf_Internal_Sym **) bfd_malloc2 (symcount, sizeof (*indbuf));
+  amt = symcount * sizeof (*indbuf);
+  indbuf = (Elf_Internal_Sym **) bfd_malloc (amt);
   if (indbuf == NULL)
     return NULL;
 
@@ -7919,8 +8153,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)
@@ -7931,8 +8167,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)
@@ -8073,7 +8311,7 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
 
   result = TRUE;
 
-done:
+ done:
   if (symtable1)
     free (symtable1);
   if (symtable2)
@@ -8322,7 +8560,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;
            }
 
@@ -8617,7 +8856,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)
@@ -8625,6 +8864,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
@@ -8643,8 +8883,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: "
@@ -8676,8 +8916,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;
 }
 
@@ -8974,6 +9213,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)
 {
@@ -9032,7 +9280,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;
@@ -9352,6 +9600,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))
@@ -9386,7 +9639,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;
@@ -9399,7 +9652,7 @@ static bfd_boolean
 elf_link_swap_symbols_out (struct elf_final_link_info *flinfo)
 {
   struct elf_link_hash_table *hash_table = elf_hash_table (flinfo->info);
-  bfd_size_type amt;
+  size_t amt;
   size_t i;
   const struct elf_backend_data *bed;
   bfd_byte *symbuf;
@@ -9448,6 +9701,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;
@@ -9535,7 +9796,7 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
     }
   BFD_ASSERT (abfd != NULL);
 
-  for (loaded = elf_hash_table (info)->loaded;
+  for (loaded = elf_hash_table (info)->dyn_loaded;
        loaded != NULL;
        loaded = loaded->next)
     {
@@ -9555,7 +9816,6 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
 
       /* We check each DSO for a possible hidden versioned definition.  */
       if (input == abfd
-         || (input->flags & DYNAMIC) == 0
          || elf_dynversym (input) == 0)
        continue;
 
@@ -9583,16 +9843,11 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
 
       /* Read in any version definitions.  */
       versymhdr = &elf_tdata (input)->dynversym_hdr;
-      extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size);
-      if (extversym == NULL)
-       goto error_ret;
-
       if (bfd_seek (input, versymhdr->sh_offset, SEEK_SET) != 0
-         || (bfd_bread (extversym, versymhdr->sh_size, input)
-             != versymhdr->sh_size))
+         || (extversym = (Elf_External_Versym *)
+             _bfd_malloc_and_read (input, versymhdr->sh_size,
+                                   versymhdr->sh_size)) == NULL)
        {
-         free (extversym);
-       error_ret:
          free (isymbuf);
          return FALSE;
        }
@@ -9725,15 +9980,17 @@ 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)
-       (*flinfo->info->callbacks->undefined_symbol)
-         (flinfo->info, h->root.root.string,
-          h->ref_regular ? NULL : h->root.u.undef.abfd,
-          NULL, 0,
-          flinfo->info->unresolved_syms_in_shared_libs == RM_GENERATE_ERROR);
+       {
+         flinfo->info->callbacks->undefined_symbol
+           (flinfo->info, h->root.root.string,
+            h->ref_regular ? NULL : h->root.u.undef.abfd, NULL, 0,
+            flinfo->info->unresolved_syms_in_shared_libs == RM_DIAGNOSE
+            && !flinfo->info->warn_unresolved_syms);
+       }
 
       /* Strip a global symbol defined in a discarded section.  */
       if (h->indx == -3)
@@ -10022,9 +10279,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;
 
@@ -10088,7 +10346,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)
@@ -10369,8 +10627,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)
@@ -10410,6 +10667,18 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 
       /* If this symbol is defined in a section which we are
         discarding, we don't need to keep it.  */
+      if (isym->st_shndx != SHN_UNDEF
+         && isym->st_shndx < SHN_LORESERVE
+         && isec->output_section == NULL
+         && flinfo->info->non_contiguous_regions
+         && flinfo->info->non_contiguous_regions_warnings)
+       {
+         _bfd_error_handler (_("warning: --enable-non-contiguous-regions "
+                               "discards section `%s' from '%s'\n"),
+                             isec->name, isec->owner->filename);
+         continue;
+       }
+
       if (isym->st_shndx != SHN_UNDEF
          && isym->st_shndx < SHN_LORESERVE
          && bfd_section_removed_from_list (output_bfd,
@@ -10485,8 +10754,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);
            }
        }
 
@@ -11042,12 +11314,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);
                                }
                            }
 
@@ -11139,7 +11416,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))
                  {
@@ -11273,6 +11550,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);
@@ -11290,8 +11568,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,
@@ -11300,10 +11577,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;
@@ -11347,56 +11624,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 */
-         (_("%pB: warning: sh_link not set for section `%pA'"), 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;
+
+  if (apos < bpos)
+    return -1;
+  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;
 
-  apos = elf_get_linked_section_vma (*(struct bfd_link_order **)a);
-  bpos = elf_get_linked_section_vma (*(struct bfd_link_order **)b);
+  /* 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;
-  return apos > bpos;
+  if (apos > bpos)
+    return 1;
+
+  return asec->id - bsec->id;
 }
 
 
@@ -11408,16 +11672,14 @@ 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;
+  asection *other_sec, *linkorder_sec;
+  bfd_vma offset;  /* Octets.  */
 
   other_sec = NULL;
   linkorder_sec = NULL;
@@ -11427,14 +11689,12 @@ elf_fixup_link_order (bfd *abfd, asection *o)
     {
       if (p->type == bfd_indirect_link_order)
        {
-         s = p->u.indirect.section;
+         asection *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;
@@ -11468,28 +11728,28 @@ 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++)
     {
-      s = sections[n]->u.indirect.section;
-      offset &= ~(bfd_vma) 0 << s->alignment_power;
-      s->output_offset = offset / bfd_octets_per_byte (abfd);
-      sections[n]->offset = offset;
+      bfd_vma mask;
+      asection *s = sections[n]->u.indirect.section;
+      unsigned int opb = bfd_octets_per_byte (abfd, s);
+
+      mask = ~(bfd_vma) 0 << s->alignment_power * opb;
+      offset = (offset + ~mask) & mask;
+      sections[n]->offset = s->output_offset = offset / opb;
       offset += sections[n]->size;
     }
 
@@ -11514,6 +11774,7 @@ elf_output_implib (bfd *abfd, struct bfd_link_info *info)
   long symcount;
   long src_count;
   elf_symbol_type *osymbuf;
+  size_t amt;
 
   implib_bfd = info->out_implib_bfd;
   bed = get_elf_backend_data (abfd);
@@ -11542,7 +11803,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;
@@ -11568,8 +11832,11 @@ elf_output_implib (bfd *abfd, struct bfd_link_info *info)
 
 
   /* Make symbols absolute.  */
-  osymbuf = (elf_symbol_type *) bfd_alloc2 (implib_bfd, symcount,
-                                           sizeof (*osymbuf));
+  amt = symcount * sizeof (*osymbuf);
+  osymbuf = (elf_symbol_type *) bfd_alloc (implib_bfd, amt);
+  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],
@@ -11595,7 +11862,7 @@ elf_output_implib (bfd *abfd, struct bfd_link_info *info)
 
   ret = TRUE;
 
-free_sym_buf:
+ free_sym_buf:
   free (sympp);
   return ret;
 }
@@ -11623,7 +11890,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)
     {
@@ -11666,6 +11934,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;
@@ -11711,10 +11980,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)
        {
@@ -11731,24 +12003,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
@@ -11904,7 +12181,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;
@@ -11924,12 +12201,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
@@ -11945,11 +12227,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;
@@ -12078,7 +12360,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
   if (htab->tls_sec)
     {
-      bfd_vma base, end = 0;
+      bfd_vma base, end = 0;  /* Both bytes.  */
       asection *sec;
 
       for (sec = htab->tls_sec;
@@ -12086,6 +12368,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
           sec = sec->next)
        {
          bfd_size_type size = sec->size;
+         unsigned int opb = bfd_octets_per_byte (abfd, sec);
 
          if (size == 0
              && (sec->flags & SEC_HAS_CONTENTS) == 0)
@@ -12093,9 +12376,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
              struct bfd_link_order *ord = sec->map_tail.link_order;
 
              if (ord != NULL)
-               size = ord->offset + ord->size;
+               size = ord->offset * opb + ord->size;
            }
-         end = sec->vma + size;
+         end = sec->vma + size / opb;
        }
       base = htab->tls_sec->vma;
       /* Only align end of TLS section if static TLS doesn't have special
@@ -12608,6 +12891,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
              if (bed->dtrel_excludes_plt && htab->srelplt != NULL)
                {
+                 unsigned int opb = bfd_octets_per_byte (abfd, o);
+
                  /* Don't count procedure linkage table relocs in the
                     overall reloc count.  */
                  sh_size -= htab->srelplt->size;
@@ -12627,7 +12912,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                  /* If .rela.plt is the first .rela section, exclude
                     it from DT_RELA.  */
                  else if (sh_addr == (htab->srelplt->output_section->vma
-                                      + htab->srelplt->output_offset))
+                                      + htab->srelplt->output_offset) * opb)
                    sh_addr += htab->srelplt->size;
                }
 
@@ -12693,11 +12978,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
@@ -12734,9 +13018,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)
     {
@@ -12955,7 +13240,7 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
                       bfd_boolean *start_stop)
 {
   unsigned long r_symndx;
-  struct elf_link_hash_entry *h;
+  struct elf_link_hash_entry *h, *hw;
 
   r_symndx = cookie->rel->r_info >> cookie->r_sym_shift;
   if (r_symndx == STN_UNDEF)
@@ -12975,12 +13260,16 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
             || h->root.type == bfd_link_hash_warning)
        h = (struct elf_link_hash_entry *) h->root.u.i.link;
       h->mark = 1;
-      /* If this symbol is weak and there is a non-weak definition, we
-        keep the non-weak definition because many backends put
-        dynamic reloc info on the non-weak definition for code
-        handling copy relocs.  */
-      if (h->is_weakalias)
-       weakdef (h)->mark = 1;
+      /* Keep all aliases of the symbol too.  If an object symbol
+        needs to be copied into .dynbss then all of its aliases
+        should be present as dynamic symbols, not just the one used
+        on the copy relocation.  */
+      hw = h;
+      while (hw->is_weakalias)
+       {
+         hw = hw->u.alias;
+         hw->mark = 1;
+       }
 
       if (start_stop != NULL)
        {
@@ -13144,7 +13433,7 @@ _bfd_elf_gc_mark_debug_special_section_group (asection *grp)
 
 bfd_boolean
 _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
-                                elf_gc_mark_hook_fn mark_hook ATTRIBUTE_UNUSED)
+                                elf_gc_mark_hook_fn mark_hook)
 {
   bfd *ibfd;
 
@@ -13173,11 +13462,33 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
                   && (isec->flags & SEC_ALLOC) != 0
                   && elf_section_type (isec) != SHT_NOTE)
            some_kept = TRUE;
+         else
+           {
+             /* Since all sections, except for backend specific ones,
+                have been garbage collected, call mark_hook on this
+                section if any of its linked-to sections is marked.  */
+             asection *linked_to_sec = elf_linked_to_section (isec);
+             for (; linked_to_sec != NULL;
+                  linked_to_sec = elf_linked_to_section (linked_to_sec))
+               if (linked_to_sec->gc_mark)
+                 {
+                   if (!_bfd_elf_gc_mark (info, isec, mark_hook))
+                     return FALSE;
+                   break;
+                 }
+           }
 
          if (!debug_frag_seen
              && (isec->flags & SEC_DEBUGGING)
              && CONST_STRNEQ (isec->name, ".debug_line."))
            debug_frag_seen = TRUE;
+         else if (strcmp (bfd_section_name (isec),
+                          "__patchable_function_entries") == 0
+                  && elf_linked_to_section (isec) == NULL)
+             info->callbacks->einfo (_("%F%P: %pB(%pA): error: "
+                                       "need linked-to section "
+                                       "for --gc-sections\n"),
+                                     isec->owner, isec);
        }
 
       /* If no non-note alloc section in this file will be kept, then
@@ -13187,14 +13498,16 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
 
       /* Keep debug and special sections like .comment when they are
         not part of a group.  Also keep section groups that contain
-        just debug sections or special sections.  */
+        just debug sections or special sections.  NB: Sections with
+        linked-to section has been handled above.  */
       for (isec = ibfd->sections; isec != NULL; isec = isec->next)
        {
          if ((isec->flags & SEC_GROUP) != 0)
            _bfd_elf_gc_mark_debug_special_section_group (isec);
          else if (((isec->flags & SEC_DEBUGGING) != 0
                    || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)
-                  && elf_next_in_group (isec) == NULL)
+                  && elf_next_in_group (isec) == NULL
+                  && elf_linked_to_section (isec) == NULL)
            isec->gc_mark = 1;
          if (isec->gc_mark && (isec->flags & SEC_DEBUGGING) != 0)
            has_kept_debug_info = TRUE;
@@ -13482,7 +13795,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);
@@ -13664,14 +13977,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 *)
@@ -14046,7 +14367,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
     {
       asection *i;
       int eh_changed = 0;
-      unsigned int eh_alignment;
+      unsigned int eh_alignment;  /* Octets.  */
 
       for (i = o->map_head.s; i != NULL; i = i->map_head.s)
        {
@@ -14073,7 +14394,8 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
          fini_reloc_cookie_for_section (&cookie, i);
        }
 
-      eh_alignment = 1 << o->alignment_power;
+      eh_alignment = ((1 << o->alignment_power)
+                     * bfd_octets_per_byte (output_bfd, o));
       /* Skip over zero terminator, and prevent empty sections from
         adding alignment padding at the end.  */
       for (i = o->map_tail.s; i != NULL; i = i->map_tail.s)
@@ -14330,7 +14652,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)
@@ -14413,7 +14735,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;
            }
        }
This page took 0.057967 seconds and 4 git commands to generate.