]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/elflink.c
Use startswith more for strncmp function calls.
[thirdparty/binutils-gdb.git] / bfd / elflink.c
index bfd0f019aad402b0743677d2e57a07aa1a9a0810..f8d6313168003ba58a08b46bc645e5bfd50f22a4 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF linking support for BFD.
-   Copyright (C) 1995-2019 Free Software Foundation, Inc.
+   Copyright (C) 1995-2021 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
 #include "plugin.h"
 #endif
 
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
 /* This struct is used to pass information to routines called via
    elf_link_hash_traverse which must return failure.  */
 
 struct elf_info_failed
 {
   struct bfd_link_info *info;
-  bfd_boolean failed;
+  bool failed;
 };
 
 /* This structure is used to pass information to
@@ -51,16 +58,16 @@ struct elf_find_verdep_info
   /* The number of dependencies.  */
   unsigned int vers;
   /* Whether we had a failure.  */
-  bfd_boolean failed;
+  bool failed;
 };
 
-static bfd_boolean _bfd_elf_fix_symbol_flags
+static bool _bfd_elf_fix_symbol_flags
   (struct elf_link_hash_entry *, struct elf_info_failed *);
 
 asection *
 _bfd_elf_section_for_symbol (struct elf_reloc_cookie *cookie,
                             unsigned long r_symndx,
-                            bfd_boolean discard)
+                            bool discard)
 {
   if (r_symndx >= cookie->locsymcount
       || ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL)
@@ -110,7 +117,7 @@ _bfd_elf_define_linkage_sym (bfd *abfd,
   struct bfd_link_hash_entry *bh;
   const struct elf_backend_data *bed;
 
-  h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, FALSE);
+  h = elf_link_hash_lookup (elf_hash_table (info), name, false, false, false);
   if (h != NULL)
     {
       /* Zap symbol defined in an as-needed lib that wasn't linked.
@@ -125,7 +132,7 @@ _bfd_elf_define_linkage_sym (bfd *abfd,
 
   bed = get_elf_backend_data (abfd);
   if (!_bfd_generic_link_add_one_symbol (info, abfd, name, BSF_GLOBAL,
-                                        sec, 0, NULL, FALSE, bed->collect,
+                                        sec, 0, NULL, false, bed->collect,
                                         &bh))
     return NULL;
   h = (struct elf_link_hash_entry *) bh;
@@ -137,11 +144,11 @@ _bfd_elf_define_linkage_sym (bfd *abfd,
   if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
     h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
 
-  (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+  (*bed->elf_backend_hide_symbol) (info, h, true);
   return h;
 }
 
-bfd_boolean
+bool
 _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
 {
   flagword flags;
@@ -152,7 +159,7 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
 
   /* This function may be called more than once.  */
   if (htab->sgot != NULL)
-    return TRUE;
+    return true;
 
   flags = bed->dynamic_sec_flags;
 
@@ -163,13 +170,13 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
                                           | SEC_READONLY));
   if (s == NULL
       || !bfd_set_section_alignment (s, bed->s->log_file_align))
-    return FALSE;
+    return false;
   htab->srelgot = s;
 
   s = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
   if (s == NULL
       || !bfd_set_section_alignment (s, bed->s->log_file_align))
-    return FALSE;
+    return false;
   htab->sgot = s;
 
   if (bed->want_got_plt)
@@ -177,7 +184,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 (s, bed->s->log_file_align))
-       return FALSE;
+       return false;
       htab->sgotplt = s;
     }
 
@@ -194,14 +201,14 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
                                       "_GLOBAL_OFFSET_TABLE_");
       elf_hash_table (info)->hgot = h;
       if (h == NULL)
-       return FALSE;
+       return false;
     }
 
-  return TRUE;
+  return true;
 }
 \f
 /* Create a strtab to hold the dynamic symbol names.  */
-static bfd_boolean
+static bool
 _bfd_elf_link_create_dynstrtab (bfd *abfd, struct bfd_link_info *info)
 {
   struct elf_link_hash_table *hash_table;
@@ -236,9 +243,9 @@ _bfd_elf_link_create_dynstrtab (bfd *abfd, struct bfd_link_info *info)
     {
       hash_table->dynstr = _bfd_elf_strtab_init ();
       if (hash_table->dynstr == NULL)
-       return FALSE;
+       return false;
     }
-  return TRUE;
+  return true;
 }
 
 /* Create some sections which will be filled in with dynamic linking
@@ -248,7 +255,7 @@ _bfd_elf_link_create_dynstrtab (bfd *abfd, struct bfd_link_info *info)
    addresses are assigned to the output sections.  We work out the
    actual contents and size of these sections later.  */
 
-bfd_boolean
+bool
 _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 {
   flagword flags;
@@ -257,13 +264,13 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   struct elf_link_hash_entry *h;
 
   if (! is_elf_hash_table (info->hash))
-    return FALSE;
+    return false;
 
   if (elf_hash_table (info)->dynamic_sections_created)
-    return TRUE;
+    return true;
 
   if (!_bfd_elf_link_create_dynstrtab (abfd, info))
-    return FALSE;
+    return false;
 
   abfd = elf_hash_table (info)->dynobj;
   bed = get_elf_backend_data (abfd);
@@ -277,7 +284,7 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
       s = bfd_make_section_anyway_with_flags (abfd, ".interp",
                                              flags | SEC_READONLY);
       if (s == NULL)
-       return FALSE;
+       return false;
     }
 
   /* Create sections to hold version informations.  These are removed
@@ -286,36 +293,36 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
                                          flags | SEC_READONLY);
   if (s == NULL
       || !bfd_set_section_alignment (s, bed->s->log_file_align))
-    return FALSE;
+    return false;
 
   s = bfd_make_section_anyway_with_flags (abfd, ".gnu.version",
                                          flags | SEC_READONLY);
   if (s == NULL
       || !bfd_set_section_alignment (s, 1))
-    return FALSE;
+    return false;
 
   s = bfd_make_section_anyway_with_flags (abfd, ".gnu.version_r",
                                          flags | SEC_READONLY);
   if (s == NULL
       || !bfd_set_section_alignment (s, bed->s->log_file_align))
-    return FALSE;
+    return false;
 
   s = bfd_make_section_anyway_with_flags (abfd, ".dynsym",
                                          flags | SEC_READONLY);
   if (s == NULL
       || !bfd_set_section_alignment (s, bed->s->log_file_align))
-    return FALSE;
+    return false;
   elf_hash_table (info)->dynsym = s;
 
   s = bfd_make_section_anyway_with_flags (abfd, ".dynstr",
                                          flags | SEC_READONLY);
   if (s == NULL)
-    return FALSE;
+    return false;
 
   s = bfd_make_section_anyway_with_flags (abfd, ".dynamic", flags);
   if (s == NULL
       || !bfd_set_section_alignment (s, bed->s->log_file_align))
-    return FALSE;
+    return false;
 
   /* The special symbol _DYNAMIC is always set to the start of the
      .dynamic section.  We could set _DYNAMIC in a linker script, but we
@@ -326,7 +333,7 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   h = _bfd_elf_define_linkage_sym (abfd, info, s, "_DYNAMIC");
   elf_hash_table (info)->hdynamic = h;
   if (h == NULL)
-    return FALSE;
+    return false;
 
   if (info->emit_hash)
     {
@@ -334,7 +341,7 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
                                              flags | SEC_READONLY);
       if (s == NULL
          || !bfd_set_section_alignment (s, bed->s->log_file_align))
-       return FALSE;
+       return false;
       elf_section_data (s)->this_hdr.sh_entsize = bed->s->sizeof_hash_entry;
     }
 
@@ -344,7 +351,7 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
                                              flags | SEC_READONLY);
       if (s == NULL
          || !bfd_set_section_alignment (s, bed->s->log_file_align))
-       return FALSE;
+       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
         variable count of 32-bit words.  */
@@ -359,16 +366,16 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
      the .got and .plt sections.  */
   if (bed->elf_backend_create_dynamic_sections == NULL
       || ! (*bed->elf_backend_create_dynamic_sections) (abfd, info))
-    return FALSE;
+    return false;
 
-  elf_hash_table (info)->dynamic_sections_created = TRUE;
+  elf_hash_table (info)->dynamic_sections_created = true;
 
-  return TRUE;
+  return true;
 }
 
 /* Create dynamic sections when linking against a dynamic object.  */
 
-bfd_boolean
+bool
 _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 {
   flagword flags, pltflags;
@@ -395,7 +402,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 (s, bed->plt_alignment))
-    return FALSE;
+    return false;
   htab->splt = s;
 
   /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
@@ -406,7 +413,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
                                       "_PROCEDURE_LINKAGE_TABLE_");
       elf_hash_table (info)->hplt = h;
       if (h == NULL)
-       return FALSE;
+       return false;
     }
 
   s = bfd_make_section_anyway_with_flags (abfd,
@@ -415,11 +422,11 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
                                          flags | SEC_READONLY);
   if (s == NULL
       || !bfd_set_section_alignment (s, bed->s->log_file_align))
-    return FALSE;
+    return false;
   htab->srelplt = s;
 
   if (! _bfd_elf_create_got_section (abfd, info))
-    return FALSE;
+    return false;
 
   if (bed->want_dynbss)
     {
@@ -432,7 +439,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
       s = bfd_make_section_anyway_with_flags (abfd, ".dynbss",
                                              SEC_ALLOC | SEC_LINKER_CREATED);
       if (s == NULL)
-       return FALSE;
+       return false;
       htab->sdynbss = s;
 
       if (bed->want_dynrelro)
@@ -443,7 +450,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
          s = bfd_make_section_anyway_with_flags (abfd, ".data.rel.ro",
                                                  flags);
          if (s == NULL)
-           return FALSE;
+           return false;
          htab->sdynrelro = s;
        }
 
@@ -466,7 +473,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
                                                  flags | SEC_READONLY);
          if (s == NULL
              || !bfd_set_section_alignment (s, bed->s->log_file_align))
-           return FALSE;
+           return false;
          htab->srelbss = s;
 
          if (bed->want_dynrelro)
@@ -477,13 +484,13 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
                    flags | SEC_READONLY));
              if (s == NULL
                  || !bfd_set_section_alignment (s, bed->s->log_file_align))
-               return FALSE;
+               return false;
              htab->sreldynrelro = s;
            }
        }
     }
 
-  return TRUE;
+  return true;
 }
 \f
 /* Record a new dynamic symbol.  We record the dynamic symbols as we
@@ -494,7 +501,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
    symbol should be in the dynamic symbol table, but only if there is
    one.  */
 
-bfd_boolean
+bool
 bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info,
                                    struct elf_link_hash_entry *h)
 {
@@ -505,6 +512,16 @@ bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info,
       const char *name;
       size_t indx;
 
+      if (h->root.type == bfd_link_hash_defined
+         || h->root.type == bfd_link_hash_defweak)
+       {
+         /* An IR symbol should not be made dynamic.  */
+         if (h->root.u.def.section != NULL
+             && h->root.u.def.section->owner != NULL
+             && (h->root.u.def.section->owner->flags & BFD_PLUGIN) != 0)
+           return true;
+       }
+
       /* XXX: The ABI draft says the linker must turn hidden and
         internal symbols into STB_LOCAL symbols when producing the
         DSO. However, if ld.so honors st_other in the dynamic table,
@@ -517,8 +534,15 @@ bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info,
              && h->root.type != bfd_link_hash_undefweak)
            {
              h->forced_local = 1;
-             if (!elf_hash_table (info)->is_relocatable_executable)
-               return TRUE;
+             if (!elf_hash_table (info)->is_relocatable_executable
+                 || ((h->root.type == bfd_link_hash_defined
+                      || h->root.type == bfd_link_hash_defweak)
+                     && h->root.u.def.section->owner != NULL
+                     && h->root.u.def.section->owner->no_export)
+                 || (h->root.type == bfd_link_hash_common
+                     && h->root.u.c.p->section->owner != NULL
+                     && h->root.u.c.p->section->owner->no_export))
+               return true;
            }
 
        default:
@@ -534,7 +558,7 @@ bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info,
          /* Create a strtab to hold the dynamic symbol names.  */
          elf_hash_table (info)->dynstr = dynstr = _bfd_elf_strtab_init ();
          if (dynstr == NULL)
-           return FALSE;
+           return false;
        }
 
       /* We don't put any version information in the dynamic string
@@ -555,11 +579,11 @@ bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info,
        *p = ELF_VER_CHR;
 
       if (indx == (size_t) -1)
-       return FALSE;
+       return false;
       h->dynstr_index = indx;
     }
 
-  return TRUE;
+  return true;
 }
 \f
 /* Mark a symbol dynamic.  */
@@ -595,22 +619,22 @@ bfd_elf_link_mark_dynamic_symbol (struct bfd_link_info *info,
 /* Record an assignment to a symbol made by a linker script.  We need
    this in case some dynamic object refers to this symbol.  */
 
-bfd_boolean
+bool
 bfd_elf_record_link_assignment (bfd *output_bfd,
                                struct bfd_link_info *info,
                                const char *name,
-                               bfd_boolean provide,
-                               bfd_boolean hidden)
+                               bool provide,
+                               bool hidden)
 {
   struct elf_link_hash_entry *h, *hv;
   struct elf_link_hash_table *htab;
   const struct elf_backend_data *bed;
 
   if (!is_elf_hash_table (info->hash))
-    return TRUE;
+    return true;
 
   htab = elf_hash_table (info);
-  h = elf_link_hash_lookup (htab, name, !provide, TRUE, FALSE);
+  h = elf_link_hash_lookup (htab, name, !provide, true, false);
   if (h == NULL)
     return provide;
 
@@ -672,7 +696,7 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
       break;
     default:
       BFD_FAIL ();
-      return FALSE;
+      return false;
     }
 
   /* If this symbol is being provided by the linker script, and it is
@@ -701,7 +725,7 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
       bed = get_elf_backend_data (output_bfd);
       if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
        h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
-      (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+      (*bed->elf_backend_hide_symbol) (info, h, true);
     }
 
   /* STV_HIDDEN and STV_INTERNAL symbols must be STB_LOCAL in shared objects
@@ -720,7 +744,7 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
       && h->dynindx == -1)
     {
       if (! bfd_elf_link_record_dynamic_symbol (info, h))
-       return FALSE;
+       return false;
 
       /* If this is a weak defined symbol, and we know a corresponding
         real symbol from the same dynamic object, make sure the real
@@ -731,11 +755,11 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
 
          if (def->dynindx == -1
              && !bfd_elf_link_record_dynamic_symbol (info, def))
-           return FALSE;
+           return false;
        }
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Record a new local dynamic symbol.  Returns 0 on failure, 1 on
@@ -747,7 +771,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;
@@ -805,7 +829,7 @@ bfd_elf_link_record_local_dynamic_symbol (struct bfd_link_info *info,
        return 0;
     }
 
-  dynstr_index = _bfd_elf_strtab_add (dynstr, name, FALSE);
+  dynstr_index = _bfd_elf_strtab_add (dynstr, name, false);
   if (dynstr_index == (size_t) -1)
     return 0;
   entry->isym.st_name = dynstr_index;
@@ -846,43 +870,43 @@ _bfd_elf_link_lookup_local_dynindx (struct bfd_link_info *info,
    them are removed because they are marked as local.  This is called
    via elf_link_hash_traverse.  */
 
-static bfd_boolean
+static bool
 elf_link_renumber_hash_table_dynsyms (struct elf_link_hash_entry *h,
                                      void *data)
 {
   size_t *count = (size_t *) data;
 
   if (h->forced_local)
-    return TRUE;
+    return true;
 
   if (h->dynindx != -1)
     h->dynindx = ++(*count);
 
-  return TRUE;
+  return true;
 }
 
 
 /* Like elf_link_renumber_hash_table_dynsyms, but just number symbols with
    STB_LOCAL binding.  */
 
-static bfd_boolean
+static bool
 elf_link_renumber_local_hash_table_dynsyms (struct elf_link_hash_entry *h,
                                            void *data)
 {
   size_t *count = (size_t *) data;
 
   if (!h->forced_local)
-    return TRUE;
+    return true;
 
   if (h->dynindx != -1)
     h->dynindx = ++(*count);
 
-  return TRUE;
+  return true;
 }
 
 /* Return true if the dynamic symbol for a given section should be
    omitted when creating a shared library.  */
-bfd_boolean
+bool
 _bfd_elf_omit_section_dynsym_default (bfd *output_bfd ATTRIBUTE_UNUSED,
                                      struct bfd_link_info *info,
                                      asection *p)
@@ -908,17 +932,17 @@ _bfd_elf_omit_section_dynsym_default (bfd *output_bfd ATTRIBUTE_UNUSED,
       /* There shouldn't be section relative relocations
         against any other section.  */
     default:
-      return TRUE;
+      return true;
     }
 }
 
-bfd_boolean
+bool
 _bfd_elf_omit_section_dynsym_all
     (bfd *output_bfd ATTRIBUTE_UNUSED,
      struct bfd_link_info *info ATTRIBUTE_UNUSED,
      asection *p ATTRIBUTE_UNUSED)
 {
-  return TRUE;
+  return true;
 }
 
 /* Assign dynsym indices.  In a shared library we generate a section
@@ -936,7 +960,7 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd,
                                unsigned long *section_sym_count)
 {
   unsigned long dynsymcount = 0;
-  bfd_boolean do_sec = section_sym_count != NULL;
+  bool do_sec = section_sym_count != NULL;
 
   if (bfd_link_pic (info)
       || elf_hash_table (info)->is_relocatable_executable)
@@ -989,20 +1013,20 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd,
 
 static void
 elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h,
-                   const Elf_Internal_Sym *isym, asection *sec,
-                   bfd_boolean definition, bfd_boolean dynamic)
+                   unsigned int st_other, asection *sec,
+                   bool definition, bool dynamic)
 {
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   /* If st_other has a processor-specific meaning, specific
      code might be needed here.  */
   if (bed->elf_backend_merge_symbol_attribute)
-    (*bed->elf_backend_merge_symbol_attribute) (h, isym, definition,
+    (*bed->elf_backend_merge_symbol_attribute) (h, st_other, definition,
                                                dynamic);
 
   if (!dynamic)
     {
-      unsigned symvis = ELF_ST_VISIBILITY (isym->st_other);
+      unsigned symvis = ELF_ST_VISIBILITY (st_other);
       unsigned hvis = ELF_ST_VISIBILITY (h->other);
 
       /* Keep the most constraining visibility.  Leave the remainder
@@ -1011,7 +1035,7 @@ elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h,
        h->other = symvis | (h->other & ~ELF_ST_VISIBILITY (-1));
     }
   else if (definition
-          && ELF_ST_VISIBILITY (isym->st_other) != STV_DEFAULT
+          && ELF_ST_VISIBILITY (st_other) != STV_DEFAULT
           && (sec->flags & SEC_READONLY) == 0)
     h->protected_def = 1;
 }
@@ -1029,7 +1053,7 @@ elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h,
    to change.  By OK to change, we mean that we shouldn't warn if the
    type or size does change.  */
 
-static bfd_boolean
+static bool
 _bfd_elf_merge_symbol (bfd *abfd,
                       struct bfd_link_info *info,
                       const char *name,
@@ -1038,13 +1062,13 @@ _bfd_elf_merge_symbol (bfd *abfd,
                       bfd_vma *pvalue,
                       struct elf_link_hash_entry **sym_hash,
                       bfd **poldbfd,
-                      bfd_boolean *pold_weak,
+                      bool *pold_weak,
                       unsigned int *pold_alignment,
-                      bfd_boolean *skip,
-                      bfd_boolean *override,
-                      bfd_boolean *type_change_ok,
-                      bfd_boolean *size_change_ok,
-                      bfd_boolean *matched)
+                      bool *skip,
+                      bfd **override,
+                      bool *type_change_ok,
+                      bool *size_change_ok,
+                      bool *matched)
 {
   asection *sec, *oldsec;
   struct elf_link_hash_entry *h;
@@ -1052,25 +1076,25 @@ _bfd_elf_merge_symbol (bfd *abfd,
   struct elf_link_hash_entry *flip;
   int bind;
   bfd *oldbfd;
-  bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
-  bfd_boolean newweak, oldweak, newfunc, oldfunc;
+  bool newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
+  bool newweak, oldweak, newfunc, oldfunc;
   const struct elf_backend_data *bed;
   char *new_version;
-  bfd_boolean default_sym = *matched;
+  bool default_sym = *matched;
 
-  *skip = FALSE;
-  *override = FALSE;
+  *skip = false;
+  *override = NULL;
 
   sec = *psec;
   bind = ELF_ST_BIND (sym->st_info);
 
   if (! bfd_is_und_section (sec))
-    h = elf_link_hash_lookup (elf_hash_table (info), name, TRUE, FALSE, FALSE);
+    h = elf_link_hash_lookup (elf_hash_table (info), name, true, false, false);
   else
     h = ((struct elf_link_hash_entry *)
-        bfd_wrapped_link_hash_lookup (abfd, info, name, TRUE, FALSE, FALSE));
+        bfd_wrapped_link_hash_lookup (abfd, info, name, true, false, false));
   if (h == NULL)
-    return FALSE;
+    return false;
   *sym_hash = h;
 
   bed = get_elf_backend_data (abfd);
@@ -1109,19 +1133,19 @@ _bfd_elf_merge_symbol (bfd *abfd,
   if (!*matched)
     {
       if (hi == h || h->root.type == bfd_link_hash_new)
-       *matched = TRUE;
+       *matched = true;
       else
        {
          /* OLD_HIDDEN is true if the existing symbol is only visible
             to the symbol with the same symbol version.  NEW_HIDDEN is
             true if the new symbol is only visible to the symbol with
             the same symbol version.  */
-         bfd_boolean old_hidden = h->versioned == versioned_hidden;
-         bfd_boolean new_hidden = hi->versioned == versioned_hidden;
+         bool old_hidden = h->versioned == versioned_hidden;
+         bool new_hidden = hi->versioned == versioned_hidden;
          if (!old_hidden && !new_hidden)
            /* The new symbol matches the existing symbol if both
               aren't hidden.  */
-           *matched = TRUE;
+           *matched = true;
          else
            {
              /* OLD_VERSION is the symbol version of the existing
@@ -1225,7 +1249,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
   if (h->root.type == bfd_link_hash_new)
     {
       h->non_elf = 0;
-      return TRUE;
+      return true;
     }
 
   /* In cases involving weak versioned symbols, we may wind up trying
@@ -1238,9 +1262,9 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && (newweak || oldweak)
       && ((abfd->flags & DYNAMIC) == 0
          || !h->def_regular))
-    return TRUE;
+    return true;
 
-  olddyn = FALSE;
+  olddyn = false;
   if (oldbfd != NULL)
     olddyn = (oldbfd->flags & DYNAMIC) != 0;
   else if (oldsec != NULL)
@@ -1256,8 +1280,8 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && (oldbfd->flags & BFD_PLUGIN) != (abfd->flags & BFD_PLUGIN)
       && newdyn != olddyn)
     {
-      h->root.non_ir_ref_dynamic = TRUE;
-      hi->root.non_ir_ref_dynamic = TRUE;
+      h->root.non_ir_ref_dynamic = true;
+      hi->root.non_ir_ref_dynamic = true;
     }
 
   /* NEWDEF and OLDDEF indicate whether the new or old symbol,
@@ -1293,8 +1317,8 @@ _bfd_elf_merge_symbol (bfd *abfd,
       if (newdyn
          && !olddyn)
        {
-         *skip = TRUE;
-         return TRUE;
+         *skip = true;
+         return true;
        }
 
       /* When adding a symbol from a regular object file after we have
@@ -1305,7 +1329,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
          && olddyn)
        {
          h = hi;
-         (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+         (*bed->elf_backend_hide_symbol) (info, h, true);
          h->forced_local = 0;
          h->ref_dynamic = 0;
          h->def_dynamic = 0;
@@ -1320,7 +1344,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
              h->root.type = bfd_link_hash_new;
              h->root.u.undef.abfd = NULL;
            }
-         return TRUE;
+         return true;
        }
     }
 
@@ -1334,7 +1358,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && (ELF_ST_TYPE (sym->st_info) == STT_TLS || h->type == STT_TLS))
     {
       bfd *ntbfd, *tbfd;
-      bfd_boolean ntdef, tdef;
+      bool ntdef, tdef;
       asection *ntsec, *tsec;
 
       if (h->type == STT_TLS)
@@ -1382,7 +1406,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
           h->root.root.string, tbfd, ntbfd, ntsec);
 
       bfd_set_error (bfd_error_bad_value);
-      return FALSE;
+      return false;
     }
 
   /* If the old symbol has non-default visibility, we ignore the new
@@ -1391,7 +1415,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
       && !bfd_is_und_section (sec))
     {
-      *skip = TRUE;
+      *skip = true;
       /* Make sure this symbol is dynamic.  */
       h->ref_dynamic = 1;
       hi->ref_dynamic = 1;
@@ -1402,7 +1426,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       if (ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
        return bfd_elf_link_record_dynamic_symbol (info, h);
       else
-       return TRUE;
+       return true;
     }
   else if (!newdyn
           && ELF_ST_VISIBILITY (sym->st_other) != STV_DEFAULT
@@ -1428,7 +1452,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
                {
                  /* If the new symbol is hidden or internal, completely undo
                     any dynamic link state.  */
-                 (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+                 (*bed->elf_backend_hide_symbol) (info, h, true);
                  h->forced_local = 0;
                  h->ref_dynamic = 0;
                }
@@ -1468,7 +1492,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
        {
          /* If the new symbol is hidden or internal, completely undo
             any dynamic link state.  */
-         (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+         (*bed->elf_backend_hide_symbol) (info, h, true);
          h->forced_local = 0;
          h->ref_dynamic = 0;
        }
@@ -1478,7 +1502,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       /* FIXME: Should we check type and size for protected symbol?  */
       h->size = 0;
       h->type = 0;
-      return TRUE;
+      return true;
     }
 
   /* If a new weak symbol definition comes from a regular file and the
@@ -1498,13 +1522,13 @@ _bfd_elf_merge_symbol (bfd *abfd,
      we warn properly when dynamic library symbols are overridden.  */
 
   if (newdef && !newdyn && (olddyn || h->root.ldscript_def))
-    newweak = FALSE;
+    newweak = false;
   if (olddef && newdyn)
-    oldweak = FALSE;
+    oldweak = false;
 
   /* Allow changes between different types of function symbol.  */
   if (newfunc && oldfunc)
-    *type_change_ok = TRUE;
+    *type_change_ok = true;
 
   /* It's OK to change the type if either the existing symbol or the
      new symbol is weak.  A type change is also OK if the old symbol
@@ -1514,14 +1538,14 @@ _bfd_elf_merge_symbol (bfd *abfd,
       || newweak
       || (newdef
          && h->root.type == bfd_link_hash_undefined))
-    *type_change_ok = TRUE;
+    *type_change_ok = true;
 
   /* It's OK to change the size if either the existing symbol or the
      new symbol is weak, or if the old symbol is undefined.  */
 
   if (*type_change_ok
       || h->root.type == bfd_link_hash_undefined)
-    *size_change_ok = TRUE;
+    *size_change_ok = true;
 
   /* NEWDYNCOMMON and OLDDYNCOMMON indicate whether the new or old
      symbol, respectively, appears to be a common symbol in a dynamic
@@ -1553,9 +1577,9 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && (sec->flags & SEC_LOAD) == 0
       && sym->st_size > 0
       && !newfunc)
-    newdyncommon = TRUE;
+    newdyncommon = true;
   else
-    newdyncommon = FALSE;
+    newdyncommon = false;
 
   if (olddyn
       && olddef
@@ -1565,16 +1589,16 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && (h->root.u.def.section->flags & SEC_LOAD) == 0
       && h->size > 0
       && !oldfunc)
-    olddyncommon = TRUE;
+    olddyncommon = true;
   else
-    olddyncommon = FALSE;
+    olddyncommon = false;
 
   /* We now know everything about the old and new symbols.  We ask the
      backend to check if we can merge them.  */
   if (bed->merge_symbol != NULL)
     {
       if (!bed->merge_symbol (h, sym, psec, newdef, olddef, oldbfd, oldsec))
-       return FALSE;
+       return false;
       sec = *psec;
     }
 
@@ -1589,8 +1613,8 @@ _bfd_elf_merge_symbol (bfd *abfd,
       /* Handle a multiple definition.  */
       (*info->callbacks->multiple_definition) (info, &h->root,
                                               abfd, sec, *pvalue);
-      *skip = TRUE;
-      return TRUE;
+      *skip = true;
+      return true;
     }
 
   /* If both the old and the new symbols look like common symbols in a
@@ -1612,7 +1636,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       if (sym->st_size > h->size)
        h->size = sym->st_size;
 
-      *size_change_ok = TRUE;
+      *size_change_ok = true;
     }
 
   /* If we are looking at a dynamic object, and we have found a
@@ -1635,12 +1659,12 @@ _bfd_elf_merge_symbol (bfd *abfd,
          || (h->root.type == bfd_link_hash_common
              && (newweak || newfunc))))
     {
-      *override = TRUE;
-      newdef = FALSE;
-      newdyncommon = FALSE;
+      *override = abfd;
+      newdef = false;
+      newdyncommon = false;
 
       *psec = sec = bfd_und_section_ptr;
-      *size_change_ok = TRUE;
+      *size_change_ok = true;
 
       /* If we get here when the old symbol is a common symbol, then
         we are explicitly letting it override a weak symbol or
@@ -1649,7 +1673,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
         change warning may still be appropriate.  */
 
       if (h->root.type == bfd_link_hash_common)
-       *type_change_ok = TRUE;
+       *type_change_ok = true;
     }
 
   /* Handle the special case of an old common symbol merging with a
@@ -1661,12 +1685,12 @@ _bfd_elf_merge_symbol (bfd *abfd,
   if (newdyncommon
       && h->root.type == bfd_link_hash_common)
     {
-      *override = TRUE;
-      newdef = FALSE;
-      newdyncommon = FALSE;
+      *override = oldbfd;
+      newdef = false;
+      newdyncommon = false;
       *pvalue = sym->st_size;
       *psec = sec = bed->common_section (oldsec);
-      *size_change_ok = TRUE;
+      *size_change_ok = true;
     }
 
   /* Skip weak definitions of symbols that are already defined.  */
@@ -1677,20 +1701,20 @@ _bfd_elf_merge_symbol (bfd *abfd,
            && (oldbfd->flags & BFD_PLUGIN) != 0
            && (abfd->flags & BFD_PLUGIN) == 0))
        {
-         newdef = FALSE;
-         *skip = TRUE;
+         newdef = false;
+         *skip = true;
        }
 
       /* Merge st_other.  If the symbol already has a dynamic index,
         but visibility says it should not be visible, turn it into a
         local symbol.  */
-      elf_merge_st_other (abfd, h, sym, sec, newdef, newdyn);
+      elf_merge_st_other (abfd, h, sym->st_other, sec, newdef, newdyn);
       if (h->dynindx != -1)
        switch (ELF_ST_VISIBILITY (h->other))
          {
          case STV_INTERNAL:
          case STV_HIDDEN:
-           (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+           (*bed->elf_backend_hide_symbol) (info, h, true);
            break;
          }
     }
@@ -1720,10 +1744,10 @@ _bfd_elf_merge_symbol (bfd *abfd,
 
       h->root.type = bfd_link_hash_undefined;
       h->root.u.undef.abfd = h->root.u.def.section->owner;
-      *size_change_ok = TRUE;
+      *size_change_ok = true;
 
-      olddef = FALSE;
-      olddyncommon = FALSE;
+      olddef = false;
+      olddyncommon = false;
 
       /* We again permit a type change when a common symbol may be
         overriding a function.  */
@@ -1738,7 +1762,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
              h->def_dynamic = 0;
              h->type = STT_NOTYPE;
            }
-         *type_change_ok = TRUE;
+         *type_change_ok = true;
        }
 
       if (hi->root.type == bfd_link_hash_indirect)
@@ -1777,14 +1801,14 @@ _bfd_elf_merge_symbol (bfd *abfd,
       BFD_ASSERT (pold_alignment);
       *pold_alignment = h->root.u.def.section->alignment_power;
 
-      olddef = FALSE;
-      olddyncommon = FALSE;
+      olddef = false;
+      olddyncommon = false;
 
       h->root.type = bfd_link_hash_undefined;
       h->root.u.undef.abfd = h->root.u.def.section->owner;
 
-      *size_change_ok = TRUE;
-      *type_change_ok = TRUE;
+      *size_change_ok = true;
+      *type_change_ok = true;
 
       if (hi->root.type == bfd_link_hash_indirect)
        flip = hi;
@@ -1809,7 +1833,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
        }
     }
 
-  return TRUE;
+  return true;
 }
 
 /* This function is called to create an indirect symbol from the
@@ -1817,7 +1841,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
    symbol is described by H, NAME, SYM, SEC, and VALUE.  We
    set DYNSYM if the new indirect symbol is dynamic.  */
 
-static bfd_boolean
+static bool
 _bfd_elf_add_default_symbol (bfd *abfd,
                             struct bfd_link_info *info,
                             struct elf_link_hash_entry *h,
@@ -1826,25 +1850,25 @@ _bfd_elf_add_default_symbol (bfd *abfd,
                             asection *sec,
                             bfd_vma value,
                             bfd **poldbfd,
-                            bfd_boolean *dynsym)
+                            bool *dynsym)
 {
-  bfd_boolean type_change_ok;
-  bfd_boolean size_change_ok;
-  bfd_boolean skip;
+  bool type_change_ok;
+  bool size_change_ok;
+  bool skip;
   char *shortname;
   struct elf_link_hash_entry *hi;
   struct bfd_link_hash_entry *bh;
   const struct elf_backend_data *bed;
-  bfd_boolean collect;
-  bfd_boolean dynamic;
-  bfd_boolean override;
+  bool collect;
+  bool dynamic;
+  bfd *override;
   char *p;
   size_t len, shortlen;
   asection *tmp_sec;
-  bfd_boolean matched;
+  bool matched;
 
   if (h->versioned == unversioned || h->versioned == versioned_hidden)
-    return TRUE;
+    return true;
 
   /* If this symbol has a version, and it is the default version, we
      create an indirect symbol from the default name to the fully
@@ -1856,14 +1880,14 @@ _bfd_elf_add_default_symbol (bfd *abfd,
       if (p == NULL)
        {
          h->versioned = unversioned;
-         return TRUE;
+         return true;
        }
       else
        {
          if (p[1] != ELF_VER_CHR)
            {
              h->versioned = versioned_hidden;
-             return TRUE;
+             return true;
            }
          else
            h->versioned = versioned;
@@ -1874,7 +1898,7 @@ _bfd_elf_add_default_symbol (bfd *abfd,
       /* PR ld/19073: We may see an unversioned definition after the
         default version.  */
       if (p == NULL)
-       return TRUE;
+       return true;
     }
 
   bed = get_elf_backend_data (abfd);
@@ -1884,7 +1908,7 @@ _bfd_elf_add_default_symbol (bfd *abfd,
   shortlen = p - name;
   shortname = (char *) bfd_hash_allocate (&info->hash->table, shortlen + 1);
   if (shortname == NULL)
-    return FALSE;
+    return false;
   memcpy (shortname, name, shortlen);
   shortname[shortlen] = '\0';
 
@@ -1892,19 +1916,19 @@ _bfd_elf_add_default_symbol (bfd *abfd,
      symbol with this name.  For the purposes of the merge, act as
      though we were defining the symbol we just defined, although we
      actually going to define an indirect symbol.  */
-  type_change_ok = FALSE;
-  size_change_ok = FALSE;
-  matched = TRUE;
+  type_change_ok = false;
+  size_change_ok = false;
+  matched = true;
   tmp_sec = sec;
   if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &tmp_sec, &value,
                              &hi, poldbfd, NULL, NULL, &skip, &override,
                              &type_change_ok, &size_change_ok, &matched))
-    return FALSE;
+    return false;
 
   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
@@ -1913,14 +1937,14 @@ _bfd_elf_add_default_symbol (bfd *abfd,
         command line rather than via --version-script.  */
       if (hi->verinfo.vertree == NULL && info->version_info != NULL)
        {
-         bfd_boolean hide;
+         bool hide;
 
          hi->verinfo.vertree
            = bfd_find_version_for_sym (info->version_info,
                                        hi->root.root.string, &hide);
          if (hi->verinfo.vertree != NULL && hide)
            {
-             (*bed->elf_backend_hide_symbol) (info, hi, TRUE);
+             (*bed->elf_backend_hide_symbol) (info, hi, true);
              goto nondefault;
            }
        }
@@ -1948,8 +1972,8 @@ _bfd_elf_add_default_symbol (bfd *abfd,
          if (! (_bfd_generic_link_add_one_symbol
                 (info, abfd, shortname, BSF_INDIRECT,
                  bfd_ind_section_ptr,
-                 0, name, FALSE, collect, &bh)))
-           return FALSE;
+                 0, name, false, collect, &bh)))
+           return false;
          hi = (struct elf_link_hash_entry *) bh;
        }
     }
@@ -1987,7 +2011,7 @@ _bfd_elf_add_default_symbol (bfd *abfd,
              || hi->def_regular)
            {
              if (! bfd_elf_link_record_dynamic_symbol (info, hi))
-               return FALSE;
+               return false;
            }
        }
 
@@ -2011,6 +2035,10 @@ _bfd_elf_add_default_symbol (bfd *abfd,
       ht = (struct elf_link_hash_entry *) hi->root.u.i.link;
       (*bed->elf_backend_copy_indirect_symbol) (info, ht, hi);
 
+      /* If we first saw a reference to SHORTNAME with non-default
+        visibility, merge that visibility to the @@VER symbol.  */
+      elf_merge_st_other (abfd, ht, hi->other, sec, true, dynamic);
+
       /* A reference to the SHORTNAME symbol from a dynamic library
         will be satisfied by the versioned symbol at runtime.  In
         effect, we have a reference to the versioned symbol.  */
@@ -2026,12 +2054,12 @@ _bfd_elf_add_default_symbol (bfd *abfd,
              if (! bfd_link_executable (info)
                  || hi->def_dynamic
                  || hi->ref_dynamic)
-               *dynsym = TRUE;
+               *dynsym = true;
            }
          else
            {
              if (hi->ref_regular)
-               *dynsym = TRUE;
+               *dynsym = true;
            }
        }
     }
@@ -2039,27 +2067,44 @@ _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)
-    return FALSE;
+    return false;
   memcpy (shortname, name, shortlen);
   memcpy (shortname + shortlen, p + 1, len - shortlen);
 
   /* Once again, merge with any existing symbol.  */
-  type_change_ok = FALSE;
-  size_change_ok = FALSE;
+  type_change_ok = false;
+  size_change_ok = false;
   tmp_sec = sec;
   if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &tmp_sec, &value,
                              &hi, poldbfd, NULL, NULL, &skip, &override,
                              &type_change_ok, &size_change_ok, &matched))
-    return FALSE;
+    return false;
 
   if (skip)
-    return TRUE;
-
-  if (override)
+    {
+      if (!dynamic
+         && h->root.type == bfd_link_hash_defweak
+         && hi->root.type == bfd_link_hash_defined)
+       {
+         /* We are handling a weak sym@@ver and attempting to define
+            a weak sym@ver, but _bfd_elf_merge_symbol said to skip the
+            new weak sym@ver because there is already a strong sym@ver.
+            However, sym@ver and sym@@ver are really the same symbol.
+            The existing strong sym@ver ought to override sym@@ver.  */
+         h->root.type = bfd_link_hash_defined;
+         h->root.u.def.section = hi->root.u.def.section;
+         h->root.u.def.value = hi->root.u.def.value;
+         hi->root.type = bfd_link_hash_indirect;
+         hi->root.u.i.link = &h->root;
+       }
+      else
+       return true;
+    }
+  else if (override)
     {
       /* Here SHORTNAME is a versioned name, so we don't expect to see
         the type of override we do in the case above unless it is
@@ -2070,63 +2115,68 @@ nondefault:
          /* xgettext:c-format */
          (_("%pB: unexpected redefinition of indirect versioned symbol `%s'"),
           abfd, shortname);
+      return true;
     }
   else
     {
       bh = &hi->root;
       if (! (_bfd_generic_link_add_one_symbol
             (info, abfd, shortname, BSF_INDIRECT,
-             bfd_ind_section_ptr, 0, name, FALSE, collect, &bh)))
-       return FALSE;
+             bfd_ind_section_ptr, 0, name, false, collect, &bh)))
+       return false;
       hi = (struct elf_link_hash_entry *) bh;
+    }
 
-      /* If there is a duplicate definition somewhere, then HI may not
-        point to an indirect symbol.  We will have reported an error
-        to the user in that case.  */
+  /* If there is a duplicate definition somewhere, then HI may not
+     point to an indirect symbol.  We will have reported an error
+     to the user in that case.  */
+  if (hi->root.type == bfd_link_hash_indirect)
+    {
+      (*bed->elf_backend_copy_indirect_symbol) (info, h, hi);
+      h->ref_dynamic_nonweak |= hi->ref_dynamic_nonweak;
+      hi->dynamic_def |= h->dynamic_def;
 
-      if (hi->root.type == bfd_link_hash_indirect)
-       {
-         (*bed->elf_backend_copy_indirect_symbol) (info, h, hi);
-         h->ref_dynamic_nonweak |= hi->ref_dynamic_nonweak;
-         hi->dynamic_def |= h->dynamic_def;
+      /* If we first saw a reference to @VER symbol with
+        non-default visibility, merge that visibility to the
+        @@VER symbol.  */
+      elf_merge_st_other (abfd, h, hi->other, sec, true, dynamic);
 
-         /* See if the new flags lead us to realize that the symbol
-            must be dynamic.  */
-         if (! *dynsym)
+      /* See if the new flags lead us to realize that the symbol
+        must be dynamic.  */
+      if (! *dynsym)
+       {
+         if (! dynamic)
            {
-             if (! dynamic)
-               {
-                 if (! bfd_link_executable (info)
-                     || hi->ref_dynamic)
-                   *dynsym = TRUE;
-               }
-             else
-               {
-                 if (hi->ref_regular)
-                   *dynsym = TRUE;
-               }
+             if (! bfd_link_executable (info)
+                 || hi->ref_dynamic)
+               *dynsym = true;
+           }
+         else
+           {
+             if (hi->ref_regular)
+               *dynsym = true;
            }
        }
     }
 
-  return TRUE;
+  return true;
 }
 \f
 /* This routine is used to export all defined symbols into the dynamic
    symbol table.  It is called via elf_link_hash_traverse.  */
 
-static bfd_boolean
+static bool
 _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
 {
   struct elf_info_failed *eif = (struct elf_info_failed *) data;
 
   /* Ignore indirect symbols.  These are added by the versioning code.  */
   if (h->root.type == bfd_link_hash_indirect)
-    return TRUE;
+    return true;
 
   /* Ignore this if we won't export it.  */
   if (!eif->info->export_dynamic && !h->dynamic)
-    return TRUE;
+    return true;
 
   if (h->dynindx == -1
       && (h->def_regular || h->ref_regular)
@@ -2135,12 +2185,12 @@ _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
     {
       if (! bfd_elf_link_record_dynamic_symbol (eif->info, h))
        {
-         eif->failed = TRUE;
-         return FALSE;
+         eif->failed = true;
+         return false;
        }
     }
 
-  return TRUE;
+  return true;
 }
 \f
 /* Look through the symbols which are defined in other shared
@@ -2148,14 +2198,14 @@ _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
    dependencies.  This will be put into the .gnu.version_r section.
    This function is called via elf_link_hash_traverse.  */
 
-static bfd_boolean
+static bool
 _bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h,
                                         void *data)
 {
   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.  */
@@ -2165,7 +2215,7 @@ _bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h,
       || h->verinfo.verdef == NULL
       || (elf_dyn_lib_class (h->verinfo.verdef->vd_bfd)
          & (DYN_AS_NEEDED | DYN_DT_NEEDED | DYN_NO_NEEDED)))
-    return TRUE;
+    return true;
 
   /* See if we already know about this version.  */
   for (t = elf_tdata (rinfo->info->output_bfd)->verref;
@@ -2177,7 +2227,7 @@ _bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h,
 
       for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
        if (a->vna_nodename == h->verinfo.verdef->vd_nodename)
-         return TRUE;
+         return true;
 
       break;
     }
@@ -2190,8 +2240,8 @@ _bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h,
       t = (Elf_Internal_Verneed *) bfd_zalloc (rinfo->info->output_bfd, amt);
       if (t == NULL)
        {
-         rinfo->failed = TRUE;
-         return FALSE;
+         rinfo->failed = true;
+         return false;
        }
 
       t->vn_bfd = h->verinfo.verdef->vd_bfd;
@@ -2203,8 +2253,8 @@ _bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h,
   a = (Elf_Internal_Vernaux *) bfd_zalloc (rinfo->info->output_bfd, amt);
   if (a == NULL)
     {
-      rinfo->failed = TRUE;
-      return FALSE;
+      rinfo->failed = true;
+      return false;
     }
 
   /* Note that we are copying a string pointer here, and testing it
@@ -2223,18 +2273,18 @@ _bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h,
 
   t->vn_auxptr = a;
 
-  return TRUE;
+  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
+static bool
 _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)
+                                    bool *hide)
 {
   struct bfd_elf_version_tree *t;
 
@@ -2250,14 +2300,14 @@ _bfd_elf_link_hide_versioned_symbol (struct bfd_link_info *info,
          len = version_p - h->root.root.string;
          alc = (char *) bfd_malloc (len);
          if (alc == NULL)
-           return FALSE;
+           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;
+         t->used = true;
          d = NULL;
 
          if (t->globals.list != NULL)
@@ -2271,7 +2321,7 @@ _bfd_elf_link_hide_versioned_symbol (struct bfd_link_info *info,
              if (d != NULL
                  && h->dynindx != -1
                  && ! info->export_dynamic)
-               *hide = TRUE;
+               *hide = true;
            }
 
          free (alc);
@@ -2281,23 +2331,23 @@ _bfd_elf_link_hide_versioned_symbol (struct bfd_link_info *info,
 
   *t_p = t;
 
-  return TRUE;
+  return true;
 }
 
 /* Return TRUE if the symbol H is hidden by version script.  */
 
-bfd_boolean
+bool
 _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;
+  bool 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;
+    return true;
 
   p = strchr (h->root.root.string, ELF_VER_CHR);
   if (p != NULL && h->verinfo.vertree == NULL)
@@ -2313,8 +2363,8 @@ _bfd_elf_link_hide_sym_by_version (struct bfd_link_info *info,
          && hide)
        {
          if (hide)
-           (*bed->elf_backend_hide_symbol) (info, h, TRUE);
-         return TRUE;
+           (*bed->elf_backend_hide_symbol) (info, h, true);
+         return true;
        }
     }
 
@@ -2327,12 +2377,12 @@ _bfd_elf_link_hide_sym_by_version (struct bfd_link_info *info,
                                    h->root.root.string, &hide);
       if (h->verinfo.vertree != NULL && hide)
        {
-         (*bed->elf_backend_hide_symbol) (info, h, TRUE);
-         return TRUE;
+         (*bed->elf_backend_hide_symbol) (info, h, true);
+         return true;
        }
     }
 
-  return FALSE;
+  return false;
 }
 
 /* Figure out appropriate versions for all the symbols.  We may not
@@ -2340,7 +2390,7 @@ _bfd_elf_link_hide_sym_by_version (struct bfd_link_info *info,
    files, so until that point we don't know which symbols should be
    local.  This function is called via elf_link_hash_traverse.  */
 
-static bfd_boolean
+static bool
 _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
 {
   struct elf_info_failed *sinfo;
@@ -2348,36 +2398,36 @@ _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;
+  bool hide;
 
   sinfo = (struct elf_info_failed *) data;
   info = sinfo->info;
 
   /* Fix the symbol flags.  */
-  eif.failed = FALSE;
+  eif.failed = false;
   eif.info = info;
   if (! _bfd_elf_fix_symbol_flags (h, &eif))
     {
       if (eif.failed)
-       sinfo->failed = TRUE;
-      return FALSE;
+       sinfo->failed = true;
+      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)
+  if (!h->def_regular && !ELF_COMMON_DEF_P (h))
     {
       /* Hide symbols defined in discarded input sections.  */
       if ((h->root.type == bfd_link_hash_defined
           || h->root.type == bfd_link_hash_defweak)
          && discarded_section (h->root.u.def.section))
-       (*bed->elf_backend_hide_symbol) (info, h, TRUE);
-      return TRUE;
+       (*bed->elf_backend_hide_symbol) (info, h, true);
+      return true;
     }
 
-  hide = FALSE;
+  hide = false;
   p = strchr (h->root.root.string, ELF_VER_CHR);
   if (p != NULL && h->verinfo.vertree == NULL)
     {
@@ -2389,16 +2439,16 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
 
       /* If there is no version string, we can just return out.  */
       if (*p == '\0')
-       return TRUE;
+       return true;
 
       if (!_bfd_elf_link_hide_versioned_symbol (info, h, p, &t, &hide))
        {
-         sinfo->failed = TRUE;
-         return FALSE;
+         sinfo->failed = true;
+         return false;
        }
 
       if (hide)
-       (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+       (*bed->elf_backend_hide_symbol) (info, h, true);
 
       /* If we are building an application, we need to create a
         version node for this version.  */
@@ -2410,19 +2460,19 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
          /* If we aren't going to export this symbol, we don't need
             to worry about it.  */
          if (h->dynindx == -1)
-           return TRUE;
+           return true;
 
          t = (struct bfd_elf_version_tree *) bfd_zalloc (info->output_bfd,
                                                          sizeof *t);
          if (t == NULL)
            {
-             sinfo->failed = TRUE;
-             return FALSE;
+             sinfo->failed = true;
+             return false;
            }
 
          t->name = p;
          t->name_indx = (unsigned int) -1;
-         t->used = TRUE;
+         t->used = true;
 
          version_index = 1;
          /* Don't count anonymous version tag.  */
@@ -2448,8 +2498,8 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
            (_("%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;
-         return FALSE;
+         sinfo->failed = true;
+         return false;
        }
     }
 
@@ -2463,10 +2513,10 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
        = bfd_find_version_for_sym (sinfo->info->version_info,
                                    h->root.root.string, &hide);
       if (h->verinfo.vertree != NULL && hide)
-       (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+       (*bed->elf_backend_hide_symbol) (info, h, true);
     }
 
-  return TRUE;
+  return true;
 }
 \f
 /* Read and swap the relocs from the section indicated by SHDR.  This
@@ -2478,7 +2528,7 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
 
    Returns FALSE if something goes wrong.  */
 
-static bfd_boolean
+static bool
 elf_link_read_relocs_from_section (bfd *abfd,
                                   asection *sec,
                                   Elf_Internal_Shdr *shdr,
@@ -2495,11 +2545,11 @@ elf_link_read_relocs_from_section (bfd *abfd,
 
   /* Position ourselves at the start of the section.  */
   if (bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0)
-    return FALSE;
+    return false;
 
   /* Read the relocations.  */
   if (bfd_bread (external_relocs, shdr->sh_size, abfd) != shdr->sh_size)
-    return FALSE;
+    return false;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   nsyms = NUM_SHDR_ENTRIES (symtab_hdr);
@@ -2514,7 +2564,7 @@ elf_link_read_relocs_from_section (bfd *abfd,
   else
     {
       bfd_set_error (bfd_error_wrong_format);
-      return FALSE;
+      return false;
     }
 
   erela = (const bfd_byte *) external_relocs;
@@ -2541,7 +2591,7 @@ elf_link_read_relocs_from_section (bfd *abfd,
                 abfd, (uint64_t) r_symndx, (unsigned long) nsyms,
                 (uint64_t) irela->r_offset, sec);
              bfd_set_error (bfd_error_bad_value);
-             return FALSE;
+             return false;
            }
        }
       else if (r_symndx != STN_UNDEF)
@@ -2554,13 +2604,13 @@ elf_link_read_relocs_from_section (bfd *abfd,
             abfd, (uint64_t) r_symndx,
             (uint64_t) irela->r_offset, sec);
          bfd_set_error (bfd_error_bad_value);
-         return FALSE;
+         return false;
        }
       irela += bed->s->int_rels_per_ext_rel;
       erela += shdr->sh_entsize;
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Read and swap the relocs for a section O.  They may have been
@@ -2578,7 +2628,7 @@ _bfd_elf_link_read_relocs (bfd *abfd,
                           asection *o,
                           void *external_relocs,
                           Elf_Internal_Rela *internal_relocs,
-                          bfd_boolean keep_memory)
+                          bool keep_memory)
 {
   void *alloc1 = NULL;
   Elf_Internal_Rela *alloc2 = NULL;
@@ -2643,8 +2693,7 @@ _bfd_elf_link_read_relocs (bfd *abfd,
   if (keep_memory)
     esdo->relocs = internal_relocs;
 
-  if (alloc1 != NULL)
-    free (alloc1);
+  free (alloc1);
 
   /* Don't free alloc2, since if it was allocated we are passing it
      back (under the name of internal_relocs).  */
@@ -2652,8 +2701,7 @@ _bfd_elf_link_read_relocs (bfd *abfd,
   return internal_relocs;
 
  error_return:
-  if (alloc1 != NULL)
-    free (alloc1);
+  free (alloc1);
   if (alloc2 != NULL)
     {
       if (keep_memory)
@@ -2667,7 +2715,7 @@ _bfd_elf_link_read_relocs (bfd *abfd,
 /* Compute the size of, and allocate space for, REL_HDR which is the
    section header for a section containing relocations for O.  */
 
-static bfd_boolean
+static bool
 _bfd_elf_link_size_reloc_section (bfd *abfd,
                                  struct bfd_elf_section_reloc_data *reldata)
 {
@@ -2682,7 +2730,7 @@ _bfd_elf_link_size_reloc_section (bfd *abfd,
      we zero the allocated space.  */
   rel_hdr->contents = (unsigned char *) bfd_zalloc (abfd, rel_hdr->sh_size);
   if (rel_hdr->contents == NULL && rel_hdr->sh_size != 0)
-    return FALSE;
+    return false;
 
   if (reldata->hashes == NULL && reldata->count)
     {
@@ -2691,19 +2739,19 @@ _bfd_elf_link_size_reloc_section (bfd *abfd,
       p = ((struct elf_link_hash_entry **)
           bfd_zmalloc (reldata->count * sizeof (*p)));
       if (p == NULL)
-       return FALSE;
+       return false;
 
       reldata->hashes = p;
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Copy the relocations indicated by the INTERNAL_RELOCS (which
    originated from the section given by INPUT_REL_HDR) to the
    OUTPUT_BFD.  */
 
-bfd_boolean
+bool
 _bfd_elf_link_output_relocs (bfd *output_bfd,
                             asection *input_section,
                             Elf_Internal_Shdr *input_rel_hdr,
@@ -2742,7 +2790,7 @@ _bfd_elf_link_output_relocs (bfd *output_bfd,
        (_("%pB: relocation size mismatch in %pB section %pA"),
         output_bfd, input_section->owner, input_section);
       bfd_set_error (bfd_error_wrong_format);
-      return FALSE;
+      return false;
     }
 
   erel = output_reldata->hdr->contents;
@@ -2761,12 +2809,12 @@ _bfd_elf_link_output_relocs (bfd *output_bfd,
      relocations.  */
   output_reldata->count += NUM_SHDR_ENTRIES (input_rel_hdr);
 
-  return TRUE;
+  return true;
 }
 \f
 /* Make weak undefined symbols in PIE dynamic.  */
 
-bfd_boolean
+bool
 _bfd_elf_link_hash_fixup_symbol (struct bfd_link_info *info,
                                 struct elf_link_hash_entry *h)
 {
@@ -2775,7 +2823,7 @@ _bfd_elf_link_hash_fixup_symbol (struct bfd_link_info *info,
       && h->root.type == bfd_link_hash_undefweak)
     return bfd_elf_link_record_dynamic_symbol (info, h);
 
-  return TRUE;
+  return true;
 }
 
 /* Fix up the flags for a symbol.  This handles various cases which
@@ -2784,7 +2832,7 @@ _bfd_elf_link_hash_fixup_symbol (struct bfd_link_info *info,
    assign_sym_version, which is unnecessary but perhaps more robust in
    the face of future changes.  */
 
-static bfd_boolean
+static bool
 _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
                           struct elf_info_failed *eif)
 {
@@ -2824,8 +2872,8 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
        {
          if (! bfd_elf_link_record_dynamic_symbol (eif->info, h))
            {
-             eif->failed = TRUE;
-             return FALSE;
+             eif->failed = true;
+             return false;
            }
        }
     }
@@ -2852,7 +2900,7 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
   bed = get_elf_backend_data (elf_hash_table (eif->info)->dynobj);
   if (bed->elf_backend_fixup_symbol
       && !(*bed->elf_backend_fixup_symbol) (eif->info, h))
-    return FALSE;
+    return false;
 
   /* If this is a final link, and the symbol was defined as a common
      symbol in a regular object file, and there was no definition in
@@ -2868,13 +2916,13 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
 
   /* 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);
+    (*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.  */
   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);
+    (*bed->elf_backend_hide_symbol) (eif->info, h, true);
 
   /* A hidden versioned symbol in executable should be forced local if
      it is is locally defined, not referenced by shared library and not
@@ -2885,7 +2933,7 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
           && !h->dynamic
           && !h->ref_dynamic
           && h->def_regular)
-    (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
+    (*bed->elf_backend_hide_symbol) (eif->info, h, true);
 
   /* If -Bsymbolic was used (which means to bind references to global
      symbols to the definition within the shared object), and this
@@ -2900,7 +2948,7 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
               || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
           && h->def_regular)
     {
-      bfd_boolean force_local;
+      bool force_local;
 
       force_local = (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
                     || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN);
@@ -2942,14 +2990,14 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
        }
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Make the backend pick a good value for a dynamic symbol.  This is
    called via elf_link_hash_traverse, and also calls itself
    recursively.  */
 
-static bfd_boolean
+static bool
 _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
 {
   struct elf_info_failed *eif = (struct elf_info_failed *) data;
@@ -2957,15 +3005,15 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
   const struct elf_backend_data *bed;
 
   if (! is_elf_hash_table (eif->info->hash))
-    return FALSE;
+    return false;
 
   /* Ignore indirect symbols.  These are added by the versioning code.  */
   if (h->root.type == bfd_link_hash_indirect)
-    return TRUE;
+    return true;
 
   /* Fix the symbol flags.  */
   if (! _bfd_elf_fix_symbol_flags (h, eif))
-    return FALSE;
+    return false;
 
   htab = elf_hash_table (eif->info);
   bed = get_elf_backend_data (htab->dynobj);
@@ -2973,7 +3021,7 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
   if (h->root.type == bfd_link_hash_undefweak)
     {
       if (eif->info->dynamic_undefined_weak == 0)
-       (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
+       (*bed->elf_backend_hide_symbol) (eif->info, h, true);
       else if (eif->info->dynamic_undefined_weak > 0
               && h->ref_regular
               && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
@@ -2982,8 +3030,8 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
        {
          if (!bfd_elf_link_record_dynamic_symbol (eif->info, h))
            {
-             eif->failed = TRUE;
-             return FALSE;
+             eif->failed = true;
+             return false;
            }
        }
     }
@@ -3003,13 +3051,13 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
              && (!h->is_weakalias || weakdef (h)->dynindx == -1))))
     {
       h->plt = elf_hash_table (eif->info)->init_plt_offset;
-      return TRUE;
+      return true;
     }
 
   /* If we've already adjusted this symbol, don't do it again.  This
      can happen via a recursive call.  */
   if (h->dynamic_adjusted)
-    return TRUE;
+    return true;
 
   /* Don't look at this symbol again.  Note that we must set this
      after checking the above conditions, because we may look at a
@@ -3056,7 +3104,7 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
       /* Ensure that the backend adjust_dynamic_symbol function sees
         the strong alias before H by recursively calling ourselves.  */
       if (!_bfd_elf_adjust_dynamic_symbol (def, eif))
-       return FALSE;
+       return false;
     }
 
   /* If a symbol has no type and no size and does not require a PLT
@@ -3073,17 +3121,17 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
 
   if (! (*bed->elf_backend_adjust_dynamic_symbol) (eif->info, h))
     {
-      eif->failed = TRUE;
-      return FALSE;
+      eif->failed = true;
+      return false;
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Adjust the dynamic symbol, H, for copy in the dynamic bss section,
    DYNBSS.  */
 
-bfd_boolean
+bool
 _bfd_elf_adjust_dynamic_copy (struct bfd_link_info *info,
                              struct elf_link_hash_entry *h,
                              asection *dynbss)
@@ -3109,7 +3157,7 @@ _bfd_elf_adjust_dynamic_copy (struct bfd_link_info *info,
     {
       /* Adjust the section alignment if needed.  */
       if (!bfd_set_section_alignment (dynbss, power_of_two))
-       return FALSE;
+       return false;
     }
 
   /* We make sure that the symbol will be aligned properly.  */
@@ -3131,13 +3179,13 @@ _bfd_elf_adjust_dynamic_copy (struct bfd_link_info *info,
       (_("%P: copy reloc against protected `%pT' is dangerous\n"),
        h->root.root.string);
 
-  return TRUE;
+  return true;
 }
 
 /* Adjust all external symbols pointing into SEC_MERGE sections
    to reflect the object merging within the sections.  */
 
-static bfd_boolean
+static bool
 _bfd_elf_link_sec_merge_syms (struct elf_link_hash_entry *h, void *data)
 {
   asection *sec;
@@ -3156,24 +3204,24 @@ _bfd_elf_link_sec_merge_syms (struct elf_link_hash_entry *h, void *data)
                                    h->root.u.def.value);
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Returns false if the symbol referred to by H should be considered
    to resolve local to the current module, and true if it should be
    considered to bind dynamically.  */
 
-bfd_boolean
+bool
 _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
                           struct bfd_link_info *info,
-                          bfd_boolean not_local_protected)
+                          bool not_local_protected)
 {
-  bfd_boolean binding_stays_local_p;
+  bool binding_stays_local_p;
   const struct elf_backend_data *bed;
   struct elf_link_hash_table *hash_table;
 
   if (h == NULL)
-    return FALSE;
+    return false;
 
   while (h->root.type == bfd_link_hash_indirect
         || h->root.type == bfd_link_hash_warning)
@@ -3181,9 +3229,9 @@ _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
 
   /* If it was forced local, then clearly it's not dynamic.  */
   if (h->dynindx == -1)
-    return FALSE;
+    return false;
   if (h->forced_local)
-    return FALSE;
+    return false;
 
   /* Identify the cases where name binding rules say that a
      visible symbol resolves locally.  */
@@ -3194,12 +3242,12 @@ _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
     {
     case STV_INTERNAL:
     case STV_HIDDEN:
-      return FALSE;
+      return false;
 
     case STV_PROTECTED:
       hash_table = elf_hash_table (info);
       if (!is_elf_hash_table (hash_table))
-       return FALSE;
+       return false;
 
       bed = get_elf_backend_data (hash_table->dynobj);
 
@@ -3207,7 +3255,7 @@ _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
         that these symbols perhaps be resolved dynamically, even though
         we should be resolving them to the current module.  */
       if (!not_local_protected || !bed->is_function_type (h->type))
-       binding_stays_local_p = TRUE;
+       binding_stays_local_p = true;
       break;
 
     default:
@@ -3216,7 +3264,7 @@ _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
 
   /* If it isn't defined locally, then clearly it's dynamic.  */
   if (!h->def_regular && !ELF_COMMON_DEF_P (h))
-    return TRUE;
+    return true;
 
   /* Otherwise, the symbol is dynamic if binding rules don't tell
      us that it remains local.  */
@@ -3236,26 +3284,26 @@ _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
    treatment of undefined weak symbols.  For those that do not make
    undefined weak symbols dynamic, both functions may return false.  */
 
-bfd_boolean
+bool
 _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h,
                              struct bfd_link_info *info,
-                             bfd_boolean local_protected)
+                             bool local_protected)
 {
   const struct elf_backend_data *bed;
   struct elf_link_hash_table *hash_table;
 
   /* If it's a local sym, of course we resolve locally.  */
   if (h == NULL)
-    return TRUE;
+    return true;
 
   /* STV_HIDDEN or STV_INTERNAL ones must be local.  */
   if (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
       || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)
-    return TRUE;
+    return true;
 
   /* Forced local symbols resolve locally.  */
   if (h->forced_local)
-    return TRUE;
+    return true;
 
   /* Common symbols that become definitions don't get the DEF_REGULAR
      flag set, so test it first, and don't bail out.  */
@@ -3264,26 +3312,26 @@ _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h,
   /* If we don't have a definition in a regular file, then we can't
      resolve locally.  The sym is either undefined or dynamic.  */
   else if (!h->def_regular)
-    return FALSE;
+    return false;
 
   /* Non-dynamic symbols resolve locally.  */
   if (h->dynindx == -1)
-    return TRUE;
+    return true;
 
   /* At this point, we know the symbol is defined and dynamic.  In an
      executable it must resolve locally, likewise when building symbolic
      shared libraries.  */
   if (bfd_link_executable (info) || SYMBOLIC_BIND (info, h))
-    return TRUE;
+    return true;
 
   /* Now deal with defined dynamic symbols in shared libraries.  Ones
      with default visibility might not resolve locally.  */
   if (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
-    return FALSE;
+    return false;
 
   hash_table = elf_hash_table (info);
   if (!is_elf_hash_table (hash_table))
-    return TRUE;
+    return true;
 
   bed = get_elf_backend_data (hash_table->dynobj);
 
@@ -3293,7 +3341,7 @@ _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h,
        || (info->extern_protected_data < 0
           && !bed->extern_protected_data))
       && !bed->is_function_type (h->type))
-    return TRUE;
+    return true;
 
   /* Function pointer equality tests may require that STV_PROTECTED
      symbols be treated as dynamic symbols.  If the address of a
@@ -3323,8 +3371,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;
 
@@ -3332,7 +3380,7 @@ _bfd_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
 }
 
 /* Return TRUE iff this is a non-common, definition of a non-function symbol.  */
-static bfd_boolean
+static bool
 is_global_data_symbol_definition (bfd *abfd ATTRIBUTE_UNUSED,
                                  Elf_Internal_Sym *sym)
 {
@@ -3341,21 +3389,21 @@ is_global_data_symbol_definition (bfd *abfd ATTRIBUTE_UNUSED,
   /* Local symbols do not count, but target specific ones might.  */
   if (ELF_ST_BIND (sym->st_info) != STB_GLOBAL
       && ELF_ST_BIND (sym->st_info) < STB_LOOS)
-    return FALSE;
+    return false;
 
   bed = get_elf_backend_data (abfd);
   /* Function symbols do not count.  */
   if (bed->is_function_type (ELF_ST_TYPE (sym->st_info)))
-    return FALSE;
+    return false;
 
   /* If the section is undefined, then so is the symbol.  */
   if (sym->st_shndx == SHN_UNDEF)
-    return FALSE;
+    return false;
 
   /* If the symbol is defined in the common section, then
      it is a common definition and so does not count.  */
   if (bed->common_definition (sym))
-    return FALSE;
+    return false;
 
   /* If the symbol is in a target specific section then we
      must rely upon the backend to tell us what it is.  */
@@ -3367,15 +3415,15 @@ is_global_data_symbol_definition (bfd *abfd ATTRIBUTE_UNUSED,
        Instead for now assume that the definition is not global,
        Even if this is wrong, at least the linker will behave
        in the same way that it used to do.  */
-    return FALSE;
+    return false;
 
-  return TRUE;
+  return true;
 }
 
 /* Search the symbol table of the archive element of the archive ABFD
    whose archive map contains a mention of SYMDEF, and determine if
    the symbol is defined in this element.  */
-static bfd_boolean
+static bool
 elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
 {
   Elf_Internal_Shdr * hdr;
@@ -3385,14 +3433,14 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
   Elf_Internal_Sym *isymbuf;
   Elf_Internal_Sym *isym;
   Elf_Internal_Sym *isymend;
-  bfd_boolean result;
+  bool result;
 
   abfd = _bfd_get_elt_at_filepos (abfd, symdef->file_offset);
   if (abfd == NULL)
-    return FALSE;
+    return false;
 
   if (! bfd_check_format (abfd, bfd_object))
-    return FALSE;
+    return false;
 
   /* Select the appropriate symbol table.  If we don't know if the
      object file is an IR object, give linker LTO plugin a chance to
@@ -3430,16 +3478,16 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
     }
 
   if (extsymcount == 0)
-    return FALSE;
+    return false;
 
   /* Read in the symbol table.  */
   isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff,
                                  NULL, NULL, NULL);
   if (isymbuf == NULL)
-    return FALSE;
+    return false;
 
   /* Scan the symbol table looking for SYMDEF.  */
-  result = FALSE;
+  result = false;
   for (isym = isymbuf, isymend = isymbuf + extsymcount; isym < isymend; isym++)
     {
       const char *name;
@@ -3463,7 +3511,7 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
 \f
 /* Add an entry to the .dynamic table.  */
 
-bfd_boolean
+bool
 _bfd_elf_add_dynamic_entry (struct bfd_link_info *info,
                            bfd_vma tag,
                            bfd_vma val)
@@ -3477,10 +3525,10 @@ _bfd_elf_add_dynamic_entry (struct bfd_link_info *info,
 
   hash_table = elf_hash_table (info);
   if (! is_elf_hash_table (hash_table))
-    return FALSE;
+    return false;
 
   if (tag == DT_RELA || tag == DT_REL)
-    hash_table->dynamic_relocs = TRUE;
+    hash_table->dynamic_relocs = true;
 
   bed = get_elf_backend_data (hash_table->dynobj);
   s = bfd_get_linker_section (hash_table->dynobj, ".dynamic");
@@ -3489,7 +3537,7 @@ _bfd_elf_add_dynamic_entry (struct bfd_link_info *info,
   newsize = s->size + bed->s->sizeof_dyn;
   newcontents = (bfd_byte *) bfd_realloc (s->contents, newsize);
   if (newcontents == NULL)
-    return FALSE;
+    return false;
 
   dyn.d_tag = tag;
   dyn.d_un.d_val = val;
@@ -3498,27 +3546,123 @@ _bfd_elf_add_dynamic_entry (struct bfd_link_info *info,
   s->size = newsize;
   s->contents = newcontents;
 
-  return TRUE;
+  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.  */
+
+bool
+_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 *);
+  bool strip_zero_sized;
+  bool 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);
-  strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, FALSE);
+  soname = elf_dt_name (abfd);
+  strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, false);
   if (strindex == (size_t) -1)
     return -1;
 
@@ -3547,17 +3691,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;
 }
@@ -3566,7 +3704,7 @@ elf_add_dt_needed_tag (bfd *abfd,
    (or the end of list if STOP is NULL), and needed by a library that
    will be loaded.  */
 
-static bfd_boolean
+static bool
 on_needed_list (const char *soname,
                struct bfd_link_needed_list *needed,
                struct bfd_link_needed_list *stop)
@@ -3582,51 +3720,84 @@ on_needed_list (const char *soname,
               the library.  Therefore search prior to the current
               LOOK, preventing possible infinite recursion.  */
            || on_needed_list (elf_dt_name (look->by), needed, look)))
-      return TRUE;
+      return true;
 
-  return FALSE;
+  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
    dynamic symbols.  This is called via elf_link_hash_traverse.  */
 
-static bfd_boolean
+static bool
 elf_adjust_dynstr_offsets (struct elf_link_hash_entry *h, void *data)
 {
   struct elf_strtab_hash *dynstr = (struct elf_strtab_hash *) data;
 
   if (h->dynindx != -1)
     h->dynstr_index = _bfd_elf_strtab_offset (dynstr, h->dynstr_index);
-  return TRUE;
+  return true;
 }
 
 /* Assign string offsets in .dynstr, update all structures referencing
    them.  */
 
-static bfd_boolean
+static bool
 elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info)
 {
   struct elf_link_hash_table *hash_table = elf_hash_table (info);
@@ -3641,6 +3812,11 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info)
   _bfd_elf_strtab_finalize (dynstr);
   size = _bfd_elf_strtab_size (dynstr);
 
+  /* Allow the linker to examine the dynsymtab now it's fully populated.  */
+
+  if (info->callbacks->examine_strtab)
+    info->callbacks->examine_strtab (dynstr);
+
   bed = get_elf_backend_data (dynobj);
   sdyn = bfd_get_linker_section (dynobj, ".dynamic");
   BFD_ASSERT (sdyn != NULL);
@@ -3748,14 +3924,14 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info)
       while (need.vn_next);
     }
 
-  return TRUE;
+  return true;
 }
 \f
 /* Return TRUE iff relocations for INPUT are compatible with OUTPUT.
    The default is to only match when the INPUT and OUTPUT are exactly
    the same target.  */
 
-bfd_boolean
+bool
 _bfd_elf_default_relocs_compatible (const bfd_target *input,
                                    const bfd_target *output)
 {
@@ -3766,20 +3942,20 @@ _bfd_elf_default_relocs_compatible (const bfd_target *input,
    This version is used when different targets for the same architecture
    are virtually identical.  */
 
-bfd_boolean
+bool
 _bfd_elf_relocs_compatible (const bfd_target *input,
                            const bfd_target *output)
 {
   const struct elf_backend_data *obed, *ibed;
 
   if (input == output)
-    return TRUE;
+    return true;
 
   ibed = xvec_get_elf_backend_data (input);
   obed = xvec_get_elf_backend_data (output);
 
   if (ibed->arch != obed->arch)
-    return FALSE;
+    return false;
 
   /* If both backends are using this function, deem them compatible.  */
   return ibed->relocs_compatible == obed->relocs_compatible;
@@ -3789,7 +3965,7 @@ _bfd_elf_relocs_compatible (const bfd_target *input,
    we are about to handle an as-needed lib, or have finished
    processing the lib.  */
 
-bfd_boolean
+bool
 _bfd_elf_notice_as_needed (bfd *ibfd,
                           struct bfd_link_info *info,
                           enum notice_asneeded_action act)
@@ -3799,7 +3975,7 @@ _bfd_elf_notice_as_needed (bfd *ibfd,
 
 /* Check relocations an ELF object file.  */
 
-bfd_boolean
+bool
 _bfd_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
 {
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
@@ -3833,10 +4009,18 @@ _bfd_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
       for (o = abfd->sections; o != NULL; o = o->next)
        {
          Elf_Internal_Rela *internal_relocs;
-         bfd_boolean ok;
-
-         /* Don't check relocations in excluded sections.  */
-         if ((o->flags & SEC_RELOC) == 0
+         bool ok;
+
+         /* Don't check relocations in excluded sections.  Don't do
+            anything special with non-loaded, non-alloced sections.
+            In particular, any relocs in such sections should not
+            affect GOT and PLT reference counting (ie.  we don't
+            allow them to create GOT or PLT entries), there's no
+            possibility or desire to optimize TLS relocs, and
+            there's not much point in propagating relocs to shared
+            libs that the dynamic linker won't relocate.  */
+         if ((o->flags & SEC_ALLOC) == 0
+             || (o->flags & SEC_RELOC) == 0
              || (o->flags & SEC_EXCLUDE) != 0
              || o->reloc_count == 0
              || ((info->strip == strip_all || info->strip == strip_debugger)
@@ -3847,7 +4031,7 @@ _bfd_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
          internal_relocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL,
                                                       info->keep_memory);
          if (internal_relocs == NULL)
-           return FALSE;
+           return false;
 
          ok = (*bed->check_relocs) (abfd, info, o, internal_relocs);
 
@@ -3855,16 +4039,16 @@ _bfd_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
            free (internal_relocs);
 
          if (! ok)
-           return FALSE;
+           return false;
        }
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Add symbols from an ELF object file to the linker hash table.  */
 
-static bfd_boolean
+static bool
 elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 {
   Elf_Internal_Ehdr *ehdr;
@@ -3873,7 +4057,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   size_t extsymcount;
   size_t extsymoff;
   struct elf_link_hash_entry **sym_hash;
-  bfd_boolean dynamic;
+  bool dynamic;
   Elf_External_Versym *extversym = NULL;
   Elf_External_Versym *extversym_end = NULL;
   Elf_External_Versym *ever;
@@ -3884,9 +4068,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   Elf_Internal_Sym *isym;
   Elf_Internal_Sym *isymend;
   const struct elf_backend_data *bed;
-  bfd_boolean add_needed;
+  bool 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;
@@ -3898,16 +4081,16 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   void *old_strtab = NULL;
   size_t tabsize = 0;
   asection *s;
-  bfd_boolean just_syms;
+  bool just_syms;
 
   htab = elf_hash_table (info);
   bed = get_elf_backend_data (abfd);
 
   if ((abfd->flags & DYNAMIC) == 0)
-    dynamic = FALSE;
+    dynamic = false;
   else
     {
-      dynamic = TRUE;
+      dynamic = true;
 
       /* You can't use -r against a dynamic object.  Also, there's no
         hope of using a dynamic object which does not exactly match
@@ -3946,7 +4129,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       const char *name;
 
       name = bfd_section_name (s);
-      if (CONST_STRNEQ (name, ".gnu.warning."))
+      if (startswith (name, ".gnu.warning."))
        {
          char *msg;
          bfd_size_type sz;
@@ -3966,7 +4149,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
            {
              struct elf_link_hash_entry *h;
 
-             h = elf_link_hash_lookup (htab, name, FALSE, FALSE, TRUE);
+             h = elf_link_hash_lookup (htab, name, false, false, true);
 
              /* FIXME: What about bfd_link_hash_common?  */
              if (h != NULL
@@ -3987,7 +4170,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 
          if (! (_bfd_generic_link_add_one_symbol
                 (info, abfd, name, BSF_WARNING, s, 0, msg,
-                 FALSE, bed->collect, NULL)))
+                 false, bed->collect, NULL)))
            goto error_return;
 
          if (bfd_link_executable (info))
@@ -4006,7 +4189,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   just_syms = ((s = abfd->sections) != NULL
               && s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS);
 
-  add_needed = TRUE;
+  add_needed = true;
   if (! dynamic)
     {
       /* If we are creating a shared library, create all the dynamic
@@ -4037,7 +4220,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.  */
@@ -4065,7 +4248,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;
            }
@@ -4094,8 +4277,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)
@@ -4117,8 +4300,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)
@@ -4143,8 +4326,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)
@@ -4194,10 +4377,14 @@ error_free_dyn:
        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;
          }
 
@@ -4226,15 +4413,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;
@@ -4278,8 +4472,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;
@@ -4298,17 +4491,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;
-         amt = versymhdr->sh_size;
-         extversym = (Elf_External_Versym *) bfd_malloc (amt);
+         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;
-         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));
+         extversym_end = extversym + amt / sizeof (*extversym);
        }
     }
 
@@ -4330,7 +4522,12 @@ error_free_dyn:
              h = (struct elf_link_hash_entry *) p;
              entsize += htab->root.table.entsize;
              if (h->root.type == bfd_link_hash_warning)
-               entsize += htab->root.table.entsize;
+               {
+                 entsize += htab->root.table.entsize;
+                 h = (struct elf_link_hash_entry *) h->root.u.i.link;
+               }
+             if (h->root.type == bfd_link_hash_common)
+               entsize += sizeof (*h->root.u.c.p);
            }
        }
 
@@ -4359,9 +4556,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++)
        {
@@ -4370,14 +4571,20 @@ error_free_dyn:
 
          for (p = htab->root.table.table[i]; p != NULL; p = p->next)
            {
-             memcpy (old_ent, p, htab->root.table.entsize);
-             old_ent = (char *) old_ent + htab->root.table.entsize;
              h = (struct elf_link_hash_entry *) p;
+             memcpy (old_ent, h, htab->root.table.entsize);
+             old_ent = (char *) old_ent + htab->root.table.entsize;
              if (h->root.type == bfd_link_hash_warning)
                {
-                 memcpy (old_ent, h->root.u.i.link, htab->root.table.entsize);
+                 h = (struct elf_link_hash_entry *) h->root.u.i.link;
+                 memcpy (old_ent, h, htab->root.table.entsize);
                  old_ent = (char *) old_ent + htab->root.table.entsize;
                }
+             if (h->root.type == bfd_link_hash_common)
+               {
+                 memcpy (old_ent, h->root.u.c.p, sizeof (*h->root.u.c.p));
+                 old_ent = (char *) old_ent + sizeof (*h->root.u.c.p);
+               }
            }
        }
     }
@@ -4415,20 +4622,20 @@ error_free_dyn:
       const char *name;
       struct elf_link_hash_entry *h;
       struct elf_link_hash_entry *hi;
-      bfd_boolean definition;
-      bfd_boolean size_change_ok;
-      bfd_boolean type_change_ok;
-      bfd_boolean new_weak;
-      bfd_boolean old_weak;
-      bfd_boolean override;
-      bfd_boolean common;
-      bfd_boolean discarded;
+      bool definition;
+      bool size_change_ok;
+      bool type_change_ok;
+      bool new_weak;
+      bool old_weak;
+      bfd *override;
+      bool common;
+      bool discarded;
       unsigned int old_alignment;
       unsigned int shindex;
       bfd *old_bfd;
-      bfd_boolean matched;
+      bool matched;
 
-      override = FALSE;
+      override = NULL;
 
       flags = BSF_NO_FLAGS;
       sec = NULL;
@@ -4438,9 +4645,9 @@ error_free_dyn:
        {
          /* Treat common symbol as undefined for --no-define-common.  */
          isym->st_shndx = SHN_UNDEF;
-         common = FALSE;
+         common = false;
        }
-      discarded = FALSE;
+      discarded = false;
 
       bind = ELF_ST_BIND (isym->st_info);
       switch (bind)
@@ -4509,7 +4716,7 @@ error_free_dyn:
              /* Symbols from discarded section are undefined.  We keep
                 its visibility.  */
              sec = bfd_und_section_ptr;
-             discarded = TRUE;
+             discarded = true;
              isym->st_shndx = SHN_UNDEF;
            }
          else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
@@ -4577,14 +4784,14 @@ error_free_dyn:
 
       if (bfd_is_und_section (sec)
          || bfd_is_com_section (sec))
-       definition = FALSE;
+       definition = false;
       else
-       definition = TRUE;
+       definition = true;
 
-      size_change_ok = FALSE;
+      size_change_ok = false;
       type_change_ok = bed->type_change_ok;
-      old_weak = FALSE;
-      matched = FALSE;
+      old_weak = false;
+      matched = false;
       old_alignment = 0;
       old_bfd = NULL;
       new_sec = sec;
@@ -4593,7 +4800,7 @@ error_free_dyn:
        {
          Elf_Internal_Versym iver;
          unsigned int vernum = 0;
-         bfd_boolean skip;
+         bool skip;
 
          if (ever == NULL)
            {
@@ -4734,7 +4941,7 @@ error_free_dyn:
          /* Override a definition only if the new symbol matches the
             existing one.  */
          if (override && matched)
-           definition = FALSE;
+           definition = false;
 
          h = *sym_hash;
          while (h->root.type == bfd_link_hash_indirect
@@ -4748,7 +4955,8 @@ error_free_dyn:
        }
 
       if (! (_bfd_generic_link_add_one_symbol
-            (info, abfd, name, flags, sec, value, NULL, FALSE, bed->collect,
+            (info, override ? override : abfd, name, flags, sec, value,
+             NULL, false, bed->collect,
              (struct bfd_link_hash_entry **) sym_hash)))
        goto error_free_vers;
 
@@ -4760,13 +4968,13 @@ error_free_dyn:
             || h->root.type == bfd_link_hash_warning)
        h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
+      *sym_hash = h;
+
       /* Setting the index to -3 tells elf_link_output_extsym that
         this symbol is defined in a discarded section.  */
-      if (discarded)
+      if (discarded && is_elf_hash_table (htab))
        h->indx = -3;
 
-      *sym_hash = h;
-
       new_weak = (flags & BSF_WEAK) != 0;
       if (dynamic
          && definition
@@ -4817,13 +5025,17 @@ error_free_dyn:
             reference or definition we just found.  A dynamic symbol
             is one which is referenced or defined by both a regular
             object and a shared object.  */
-         bfd_boolean dynsym = FALSE;
+         bool dynsym = false;
 
-         /* Plugin symbols aren't normal.  Don't set def_regular or
-            ref_regular for them, or make them dynamic.  */
+         /* Plugin symbols aren't normal.  Don't set def/ref flags.  */
          if ((abfd->flags & BFD_PLUGIN) != 0)
-           ;
-         else if (! dynamic)
+           {
+             /* Except for this flag to track nonweak references.  */
+             if (!definition
+                 && bind != STB_WEAK)
+               h->ref_ir_nonweak = 1;
+           }
+         else if (!dynamic)
            {
              if (! definition)
                {
@@ -4840,14 +5052,6 @@ error_free_dyn:
                      h->ref_dynamic = 1;
                    }
                }
-
-             /* If the indirect symbol has been forced local, don't
-                make the real symbol dynamic.  */
-             if ((h == hi || !hi->forced_local)
-                 && (bfd_link_dll (info)
-                     || h->def_dynamic
-                     || h->ref_dynamic))
-               dynsym = TRUE;
            }
          else
            {
@@ -4861,21 +5065,34 @@ error_free_dyn:
                  h->def_dynamic = 1;
                  hi->def_dynamic = 1;
                }
+           }
 
-             /* If the indirect symbol has been forced local, don't
-                make the real symbol dynamic.  */
-             if ((h == hi || !hi->forced_local)
-                 && (h->def_regular
-                     || h->ref_regular
-                     || (h->is_weakalias
-                         && weakdef (h)->dynindx != -1)))
-               dynsym = TRUE;
+         /* If an indirect symbol has been forced local, don't
+            make the real symbol dynamic.  */
+         if (h != hi && hi->forced_local)
+           ;
+         else if (!dynamic)
+           {
+             if (bfd_link_dll (info)
+                 || h->def_dynamic
+                 || h->ref_dynamic)
+               dynsym = true;
+           }
+         else
+           {
+             if (h->def_regular
+                 || h->ref_regular
+                 || (h->is_weakalias
+                     && weakdef (h)->dynindx != -1))
+               dynsym = true;
            }
 
          /* Check to see if we need to add an indirect symbol for
             the default name.  */
-         if (definition
-             || (!override && h->root.type == bfd_link_hash_common))
+         if ((definition
+              || (!override && h->root.type == bfd_link_hash_common))
+             && !(hi != h
+                  && hi->versioned == versioned_hidden))
            if (!_bfd_elf_add_default_symbol (abfd, info, h, name, isym,
                                              sec, value, &old_bfd, &dynsym))
              goto error_free_vers;
@@ -4996,17 +5213,18 @@ error_free_dyn:
            }
 
          /* Merge st_other field.  */
-         elf_merge_st_other (abfd, h, isym, sec, definition, dynamic);
+         elf_merge_st_other (abfd, h, isym->st_other, sec,
+                             definition, dynamic);
 
          /* We don't want to make debug symbol dynamic.  */
          if (definition
              && (sec->flags & SEC_DEBUGGING)
              && !bfd_link_relocatable (info))
-           dynsym = FALSE;
+           dynsym = false;
 
          /* Nor should we make plugin symbols dynamic.  */
          if ((abfd->flags & BFD_PLUGIN) != 0)
-           dynsym = FALSE;
+           dynsym = false;
 
          if (definition)
            {
@@ -5023,8 +5241,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)
@@ -5053,26 +5271,26 @@ error_free_dyn:
              {
              case STV_INTERNAL:
              case STV_HIDDEN:
-               (*bed->elf_backend_hide_symbol) (info, h, TRUE);
-               dynsym = FALSE;
+               (*bed->elf_backend_hide_symbol) (info, h, true);
+               dynsym = false;
                break;
              }
 
-         /* Don't add DT_NEEDED for references from the dummy bfd nor
-            for unmatched symbol.  */
          if (!add_needed
              && matched
              && definition
+             && h->root.type != bfd_link_hash_indirect
              && ((dynsym
-                  && h->ref_regular_nonweak
-                  && (old_bfd == NULL
-                      || (old_bfd->flags & BFD_PLUGIN) == 0))
+                  && h->ref_regular_nonweak)
+                 || (old_bfd != NULL
+                     && (old_bfd->flags & BFD_PLUGIN) != 0
+                     && h->ref_ir_nonweak
+                     && !info->lto_all_symbols_read)
                  || (h->ref_dynamic_nonweak
                      && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0
                      && !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,
@@ -5097,12 +5315,11 @@ error_free_dyn:
              elf_dyn_lib_class (abfd) = (enum dynamic_lib_link_class)
                (elf_dyn_lib_class (abfd) & ~DYN_AS_NEEDED);
 
-             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);
+             /* 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;
            }
        }
     }
@@ -5166,17 +5383,10 @@ error_free_dyn:
        }
     }
 
-  if (extversym != NULL)
-    {
-      free (extversym);
-      extversym = NULL;
-    }
-
-  if (isymbuf != NULL)
-    {
-      free (isymbuf);
-      isymbuf = NULL;
-    }
+  free (extversym);
+  extversym = NULL;
+  free (isymbuf);
+  isymbuf = NULL;
 
   if ((elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0)
     {
@@ -5192,56 +5402,39 @@ 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++)
        {
          struct bfd_hash_entry *p;
          struct elf_link_hash_entry *h;
-         bfd_size_type size;
-         unsigned int alignment_power;
          unsigned int non_ir_ref_dynamic;
 
          for (p = htab->root.table.table[i]; p != NULL; p = p->next)
            {
-             h = (struct elf_link_hash_entry *) p;
-             if (h->root.type == bfd_link_hash_warning)
-               h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
-             /* Preserve the maximum alignment and size for common
-                symbols even if this dynamic lib isn't on DT_NEEDED
-                since it can still be loaded at run time by another
-                dynamic lib.  */
-             if (h->root.type == bfd_link_hash_common)
-               {
-                 size = h->root.u.c.size;
-                 alignment_power = h->root.u.c.p->alignment_power;
-               }
-             else
-               {
-                 size = 0;
-                 alignment_power = 0;
-               }
              /* Preserve non_ir_ref_dynamic so that this symbol
                 will be exported when the dynamic lib becomes needed
                 in the second pass.  */
+             h = (struct elf_link_hash_entry *) p;
+             if (h->root.type == bfd_link_hash_warning)
+               h = (struct elf_link_hash_entry *) h->root.u.i.link;
              non_ir_ref_dynamic = h->root.non_ir_ref_dynamic;
-             memcpy (p, old_ent, htab->root.table.entsize);
-             old_ent = (char *) old_ent + htab->root.table.entsize;
+
              h = (struct elf_link_hash_entry *) p;
+             memcpy (h, old_ent, htab->root.table.entsize);
+             old_ent = (char *) old_ent + htab->root.table.entsize;
              if (h->root.type == bfd_link_hash_warning)
                {
-                 memcpy (h->root.u.i.link, old_ent, htab->root.table.entsize);
-                 old_ent = (char *) old_ent + htab->root.table.entsize;
                  h = (struct elf_link_hash_entry *) h->root.u.i.link;
+                 memcpy (h, old_ent, htab->root.table.entsize);
+                 old_ent = (char *) old_ent + htab->root.table.entsize;
                }
              if (h->root.type == bfd_link_hash_common)
                {
-                 if (size > h->root.u.c.size)
-                   h->root.u.c.size = size;
-                 if (alignment_power > h->root.u.c.p->alignment_power)
-                   h->root.u.c.p->alignment_power = alignment_power;
+                 memcpy (h->root.u.c.p, old_ent, sizeof (*h->root.u.c.p));
+                 old_ent = (char *) old_ent + sizeof (*h->root.u.c.p);
                }
              h->root.non_ir_ref_dynamic = non_ir_ref_dynamic;
            }
@@ -5255,9 +5448,8 @@ error_free_dyn:
       free (old_tab);
       objalloc_free_block ((struct objalloc *) htab->root.table.memory,
                           alloc_mark);
-      if (nondeflt_vers != NULL)
-       free (nondeflt_vers);
-      return TRUE;
+      free (nondeflt_vers);
+      return true;
     }
 
   if (old_tab != NULL)
@@ -5279,6 +5471,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
@@ -5295,13 +5488,13 @@ error_free_dyn:
 
          hi = (struct elf_link_hash_entry *)
               bfd_link_hash_lookup (&htab->root, shortname,
-                                    FALSE, FALSE, FALSE);
+                                    false, false, false);
          if (hi != NULL
              && hi->root.type == h->root.type
              && hi->root.u.def.value == h->root.u.def.value
              && hi->root.u.def.section == h->root.u.def.section)
            {
-             (*bed->elf_backend_hide_symbol) (info, hi, TRUE);
+             (*bed->elf_backend_hide_symbol) (info, hi, true);
              hi->root.type = bfd_link_hash_indirect;
              hi->root.u.i.link = (struct bfd_link_hash_entry *) h;
              (*bed->elf_backend_copy_indirect_symbol) (info, h, hi);
@@ -5339,14 +5532,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;
@@ -5366,8 +5558,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)
@@ -5484,7 +5675,7 @@ error_free_dyn:
 
   if (bed->check_directives
       && !(*bed->check_directives) (abfd, info))
-    return FALSE;
+    return false;
 
   /* If this is a non-traditional link, try to optimize the handling
      of the .stab/.stabstr sections.  */
@@ -5502,7 +5693,7 @@ error_free_dyn:
          asection *stab;
 
          for (stab = abfd->sections; stab; stab = stab->next)
-           if (CONST_STRNEQ (stab->name, ".stab")
+           if (startswith (stab->name, ".stab")
                && (!stab->name[5] ||
                    (stab->name[5] == '.' && ISDIGIT (stab->name[6])))
                && (stab->flags & SEC_MERGE) == 0
@@ -5521,7 +5712,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;
@@ -5530,26 +5721,24 @@ 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;
+  return true;
 
  error_free_vers:
-  if (old_tab != NULL)
-    free (old_tab);
-  if (old_strtab != NULL)
-    free (old_strtab);
-  if (nondeflt_vers != NULL)
-    free (nondeflt_vers);
-  if (extversym != NULL)
-    free (extversym);
+  free (old_tab);
+  free (old_strtab);
+  free (nondeflt_vers);
+  free (extversym);
  error_free_sym:
-  if (isymbuf != NULL)
-    free (isymbuf);
+  free (isymbuf);
  error_return:
-  return FALSE;
+  return false;
 }
 
 /* Return the linker hash table entry of a symbol that might be
@@ -5564,7 +5753,7 @@ _bfd_elf_archive_symbol_lookup (bfd *abfd,
   char *p, *copy;
   size_t len, first;
 
-  h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, TRUE);
+  h = elf_link_hash_lookup (elf_hash_table (info), name, false, false, true);
   if (h != NULL)
     return h;
 
@@ -5587,14 +5776,14 @@ _bfd_elf_archive_symbol_lookup (bfd *abfd,
   memcpy (copy, name, first);
   memcpy (copy + first, name + first + 1, len - first);
 
-  h = elf_link_hash_lookup (elf_hash_table (info), copy, FALSE, FALSE, TRUE);
+  h = elf_link_hash_lookup (elf_hash_table (info), copy, false, false, true);
   if (h == NULL)
     {
       /* We also need to check references to the symbol without the
         version.  */
       copy[first - 1] = '\0';
       h = elf_link_hash_lookup (elf_hash_table (info), copy,
-                               FALSE, FALSE, TRUE);
+                               false, false, true);
     }
 
   bfd_release (abfd, copy);
@@ -5614,14 +5803,14 @@ _bfd_elf_archive_symbol_lookup (bfd *abfd,
    Unfortunately, we do have to make multiple passes over the symbol
    table until nothing further is resolved.  */
 
-static bfd_boolean
+static bool
 elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
 {
   symindex c;
   unsigned char *included = NULL;
   carsym *symdefs;
-  bfd_boolean loop;
-  bfd_size_type amt;
+  bool loop;
+  size_t amt;
   const struct elf_backend_data *bed;
   struct elf_link_hash_entry * (*archive_symbol_lookup)
     (bfd *, struct bfd_link_info *, const char *);
@@ -5630,9 +5819,9 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
     {
       /* An empty archive is a special case.  */
       if (bfd_openr_next_archived_file (abfd, NULL) == NULL)
-       return TRUE;
+       return true;
       bfd_set_error (bfd_error_no_armap);
-      return FALSE;
+      return false;
     }
 
   /* Keep track of all symbols we know to be already defined, and all
@@ -5640,12 +5829,11 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
      second and subsequent passes.  */
   c = bfd_ardata (abfd)->symdef_count;
   if (c == 0)
-    return TRUE;
-  amt = c;
-  amt *= sizeof (*included);
+    return true;
+  amt = c * sizeof (*included);
   included = (unsigned char *) bfd_zmalloc (amt);
   if (included == NULL)
-    return FALSE;
+    return false;
 
   symdefs = bfd_ardata (abfd)->symdefs;
   bed = get_elf_backend_data (abfd);
@@ -5658,7 +5846,7 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
       carsym *symdef;
       carsym *symdefend;
 
-      loop = FALSE;
+      loop = false;
       last = -1;
 
       symdef = symdefs;
@@ -5674,7 +5862,7 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
            continue;
          if (symdef->file_offset == last)
            {
-             included[i] = TRUE;
+             included[i] = true;
              continue;
            }
 
@@ -5685,7 +5873,15 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
          if (h == NULL)
            continue;
 
-         if (h->root.type == bfd_link_hash_common)
+         if (h->root.type == bfd_link_hash_undefined)
+           {
+             /* If the archive element has already been loaded then one
+                of the symbols defined by that element might have been
+                made undefined due to being in a discarded section.  */
+             if (h->indx == -3)
+               continue;
+           }
+         else if (h->root.type == bfd_link_hash_common)
            {
              /* We currently have a common symbol.  The archive map contains
                 a reference to this symbol, so we may want to include it.  We
@@ -5702,11 +5898,11 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
              if (! elf_link_is_defined_archive_symbol (abfd, symdef))
                continue;
            }
-         else if (h->root.type != bfd_link_hash_undefined)
+         else
            {
              if (h->root.type != bfd_link_hash_undefweak)
                /* Symbol must be defined.  Don't check it again.  */
-               included[i] = TRUE;
+               included[i] = true;
              continue;
            }
 
@@ -5734,14 +5930,14 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
             does not require another pass.  This isn't a bug, but it
             does make the code less efficient than it could be.  */
          if (undefs_tail != info->hash->undefs_tail)
-           loop = TRUE;
+           loop = true;
 
          /* Look backward to mark all symbols from this object file
             which we have already seen in this pass.  */
          mark = i;
          do
            {
-             included[mark] = TRUE;
+             included[mark] = true;
              if (mark == 0)
                break;
              --mark;
@@ -5756,19 +5952,17 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
   while (loop);
 
   free (included);
-
-  return TRUE;
+  return true;
 
  error_return:
-  if (included != NULL)
-    free (included);
-  return FALSE;
+  free (included);
+  return false;
 }
 
 /* Given an ELF BFD, add symbols to the global hash table as
    appropriate.  */
 
-bfd_boolean
+bool
 bfd_elf_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
 {
   switch (bfd_get_format (abfd))
@@ -5779,20 +5973,20 @@ bfd_elf_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
       return elf_link_add_archive_symbols (abfd, info);
     default:
       bfd_set_error (bfd_error_wrong_format);
-      return FALSE;
+      return false;
     }
 }
 \f
 struct hash_codes_info
 {
   unsigned long *hashcodes;
-  bfd_boolean error;
+  bool error;
 };
 
 /* This function will be called though elf_link_hash_traverse to store
    all hash value of the exported symbols in an array.  */
 
-static bfd_boolean
+static bool
 elf_collect_hash_codes (struct elf_link_hash_entry *h, void *data)
 {
   struct hash_codes_info *inf = (struct hash_codes_info *) data;
@@ -5802,7 +5996,7 @@ elf_collect_hash_codes (struct elf_link_hash_entry *h, void *data)
 
   /* Ignore indirect symbols.  These are added by the versioning code.  */
   if (h->dynindx == -1)
-    return TRUE;
+    return true;
 
   name = h->root.root.string;
   if (h->versioned >= versioned)
@@ -5813,8 +6007,8 @@ elf_collect_hash_codes (struct elf_link_hash_entry *h, void *data)
          alc = (char *) bfd_malloc (p - name + 1);
          if (alc == NULL)
            {
-             inf->error = TRUE;
-             return FALSE;
+             inf->error = true;
+             return false;
            }
          memcpy (alc, name, p - name);
          alc[p - name] = '\0';
@@ -5832,10 +6026,8 @@ elf_collect_hash_codes (struct elf_link_hash_entry *h, void *data)
      later.  */
   h->u.elf_hash_value = ha;
 
-  if (alc != NULL)
-    free (alc);
-
-  return TRUE;
+  free (alc);
+  return true;
 }
 
 struct collect_gnu_hash_codes
@@ -5857,13 +6049,13 @@ struct collect_gnu_hash_codes
   long int local_indx;
   long int shift1, shift2;
   unsigned long int mask;
-  bfd_boolean error;
+  bool error;
 };
 
 /* This function will be called though elf_link_hash_traverse to store
    all hash value of the exported symbols in an array.  */
 
-static bfd_boolean
+static bool
 elf_collect_gnu_hash_codes (struct elf_link_hash_entry *h, void *data)
 {
   struct collect_gnu_hash_codes *s = (struct collect_gnu_hash_codes *) data;
@@ -5873,11 +6065,11 @@ elf_collect_gnu_hash_codes (struct elf_link_hash_entry *h, void *data)
 
   /* Ignore indirect symbols.  These are added by the versioning code.  */
   if (h->dynindx == -1)
-    return TRUE;
+    return true;
 
   /* Ignore also local symbols and undefined symbols.  */
   if (! (*s->bed->elf_hash_symbol) (h))
-    return TRUE;
+    return true;
 
   name = h->root.root.string;
   if (h->versioned >= versioned)
@@ -5888,8 +6080,8 @@ elf_collect_gnu_hash_codes (struct elf_link_hash_entry *h, void *data)
          alc = (char *) bfd_malloc (p - name + 1);
          if (alc == NULL)
            {
-             s->error = TRUE;
-             return FALSE;
+             s->error = true;
+             return false;
            }
          memcpy (alc, name, p - name);
          alc[p - name] = '\0';
@@ -5908,10 +6100,8 @@ elf_collect_gnu_hash_codes (struct elf_link_hash_entry *h, void *data)
   if (s->min_dynindx < 0 || s->min_dynindx > h->dynindx)
     s->min_dynindx = h->dynindx;
 
-  if (alc != NULL)
-    free (alc);
-
-  return TRUE;
+  free (alc);
+  return true;
 }
 
 /* This function will be called though elf_link_hash_traverse to do
@@ -5919,7 +6109,7 @@ elf_collect_gnu_hash_codes (struct elf_link_hash_entry *h, void *data)
    If using .MIPS.xhash, invoke record_xhash_symbol to add symbol index
    to the translation table.  */
 
-static bfd_boolean
+static bool
 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;
@@ -5928,7 +6118,7 @@ elf_gnu_hash_process_symidx (struct elf_link_hash_entry *h, void *data)
 
   /* Ignore indirect symbols.  */
   if (h->dynindx == -1)
-    return TRUE;
+    return true;
 
   /* Ignore also local symbols and undefined symbols.  */
   if (! (*s->bed->elf_hash_symbol) (h))
@@ -5943,7 +6133,7 @@ elf_gnu_hash_process_symidx (struct elf_link_hash_entry *h, void *data)
          else
            h->dynindx = s->local_indx++;
        }
-      return TRUE;
+      return true;
     }
 
   bucket = s->hashval[h->dynindx] % s->bucketcount;
@@ -5967,12 +6157,12 @@ elf_gnu_hash_process_symidx (struct elf_link_hash_entry *h, void *data)
     }
   else
     h->dynindx = s->indx[bucket]++;
-  return TRUE;
+  return true;
 }
 
 /* Return TRUE if symbol should be hashed in the `.gnu.hash' section.  */
 
-bfd_boolean
+bool
 _bfd_elf_hash_symbol (struct elf_link_hash_entry *h)
 {
   return !(h->forced_local
@@ -6142,7 +6332,7 @@ compute_bucket_count (struct bfd_link_info *info ATTRIBUTE_UNUSED,
 
 /* Size any SHT_GROUP section for ld -r.  */
 
-bfd_boolean
+bool
 _bfd_elf_size_group_sections (struct bfd_link_info *info)
 {
   bfd *ibfd;
@@ -6153,15 +6343,15 @@ _bfd_elf_size_group_sections (struct bfd_link_info *info)
        && (s = ibfd->sections) != NULL
        && s->sec_info_type != SEC_INFO_TYPE_JUST_SYMS
        && !_bfd_elf_fixup_group_sections (ibfd, bfd_abs_section_ptr))
-      return FALSE;
-  return TRUE;
+      return false;
+  return true;
 }
 
 /* Set a default stack segment size.  The value in INFO wins.  If it
    is unset, LEGACY_SYMBOL's value is used, and if that symbol is
    undefined it is initialized.  */
 
-bfd_boolean
+bool
 bfd_elf_stack_segment_size (bfd *output_bfd,
                            struct bfd_link_info *info,
                            const char *legacy_symbol,
@@ -6172,7 +6362,7 @@ bfd_elf_stack_segment_size (bfd *output_bfd,
   /* Look for legacy symbol.  */
   if (legacy_symbol)
     h = elf_link_hash_lookup (elf_hash_table (info), legacy_symbol,
-                             FALSE, FALSE, FALSE);
+                             false, false, false);
   if (h && (h->root.type == bfd_link_hash_defined
            || h->root.type == bfd_link_hash_defweak)
       && h->def_regular
@@ -6207,15 +6397,15 @@ bfd_elf_stack_segment_size (bfd *output_bfd,
            (info, output_bfd, legacy_symbol,
             BSF_GLOBAL, bfd_abs_section_ptr,
             info->stacksize >= 0 ? info->stacksize : 0,
-            NULL, FALSE, get_elf_backend_data (output_bfd)->collect, &bh)))
-       return FALSE;
+            NULL, false, get_elf_backend_data (output_bfd)->collect, &bh)))
+       return false;
 
       h = (struct elf_link_hash_entry *) bh;
       h->def_regular = 1;
       h->type = STT_OBJECT;
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Sweep symbols in swept sections.  Called via elf_link_hash_traverse.  */
@@ -6224,10 +6414,10 @@ struct elf_gc_sweep_symbol_info
 {
   struct bfd_link_info *info;
   void (*hide_symbol) (struct bfd_link_info *, struct elf_link_hash_entry *,
-                      bfd_boolean);
+                      bool);
 };
 
-static bfd_boolean
+static bool
 elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *data)
 {
   if (!h->mark
@@ -6241,13 +6431,13 @@ elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *data)
       struct elf_gc_sweep_symbol_info *inf;
 
       inf = (struct elf_gc_sweep_symbol_info *) data;
-      (*inf->hide_symbol) (inf->info, h, TRUE);
+      (*inf->hide_symbol) (inf->info, h, true);
       h->def_regular = 0;
       h->ref_regular = 0;
       h->ref_regular_nonweak = 0;
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Set up the sizes and contents of the ELF dynamic sections.  This is
@@ -6255,7 +6445,7 @@ elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *data)
    must set the sizes of the sections before the linker sets the
    addresses of the various sections.  */
 
-bfd_boolean
+bool
 bfd_elf_size_dynamic_sections (bfd *output_bfd,
                               const char *soname,
                               const char *rpath,
@@ -6272,7 +6462,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
   *sinterpptr = NULL;
 
   if (!is_elf_hash_table (info->hash))
-    return TRUE;
+    return true;
 
   dynobj = elf_hash_table (info)->dynobj;
 
@@ -6293,21 +6483,21 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          struct elf_info_failed eif;
 
          eif.info = info;
-         eif.failed = FALSE;
+         eif.failed = false;
          elf_link_hash_traverse (elf_hash_table (info),
                                  _bfd_elf_export_symbol,
                                  &eif);
          if (eif.failed)
-           return FALSE;
+           return false;
        }
 
       if (soname != NULL)
        {
          soname_indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                            soname, TRUE);
+                                            soname, true);
          if (soname_indx == (size_t) -1
              || !_bfd_elf_add_dynamic_entry (info, DT_SONAME, soname_indx))
-           return FALSE;
+           return false;
        }
       else
        soname_indx = (size_t) -1;
@@ -6331,7 +6521,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
              newname = (char *) bfd_malloc (newlen);
              if (newname == NULL)
-               return FALSE;
+               return false;
              newname[0] = leading_char;
              memcpy (newname + (leading_char != '\0'), name, namelen);
 
@@ -6340,8 +6530,8 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
              *p++ = ELF_VER_CHR;
              memcpy (p, verstr, verlen + 1);
              newh = elf_link_hash_lookup (elf_hash_table (info),
-                                          newname, FALSE, FALSE,
-                                          FALSE);
+                                          newname, false, false,
+                                          false);
              if (newh == NULL
                  || (newh->root.type != bfd_link_hash_defined
                      && newh->root.type != bfd_link_hash_defweak))
@@ -6350,8 +6540,8 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                  *p++ = ELF_VER_CHR;
                  memcpy (p, verstr, verlen + 1);
                  newh = elf_link_hash_lookup (elf_hash_table (info),
-                                              newname, FALSE, FALSE,
-                                              FALSE);
+                                              newname, false, false,
+                                              false);
                }
              free (newname);
 
@@ -6366,18 +6556,18 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
       /* Attach all the symbols to their version information.  */
       asvinfo.info = info;
-      asvinfo.failed = FALSE;
+      asvinfo.failed = false;
 
       elf_link_hash_traverse (elf_hash_table (info),
                              _bfd_elf_link_assign_sym_version,
                              &asvinfo);
       if (asvinfo.failed)
-       return FALSE;
+       return false;
 
       if (!info->allow_undefined_version)
        {
          /* Check if all global versions have a definition.  */
-         bfd_boolean all_defined = TRUE;
+         bool all_defined = true;
          for (t = info->version_info; t != NULL; t = t->next)
            for (d = t->globals.list; d != NULL; d = d->next)
              if (d->literal && !d->symver && !d->script)
@@ -6385,13 +6575,13 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                  _bfd_error_handler
                    (_("%s: undefined version: %s"),
                     d->pattern, t->name);
-                 all_defined = FALSE;
+                 all_defined = false;
                }
 
          if (!all_defined)
            {
              bfd_set_error (bfd_error_bad_value);
-             return FALSE;
+             return false;
            }
        }
 
@@ -6454,7 +6644,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          s->size = size;
          s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
          if (s->contents == NULL && s->size != 0)
-           return FALSE;
+           return false;
 
          /* Fill in the version definition section.  */
 
@@ -6488,12 +6678,12 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
            {
              size_t indx;
 
-             name = lbasename (output_bfd->filename);
+             name = lbasename (bfd_get_filename (output_bfd));
              def.vd_hash = bfd_elf_hash (name);
              indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                         name, FALSE);
+                                         name, false);
              if (indx == (size_t) -1)
-               return FALSE;
+               return false;
              defaux.vda_name = indx;
            }
          defaux.vda_next = 0;
@@ -6507,9 +6697,9 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
              bh = NULL;
              if (! (_bfd_generic_link_add_one_symbol
                     (info, dynobj, name, BSF_GLOBAL, bfd_abs_section_ptr,
-                     0, NULL, FALSE,
+                     0, NULL, false,
                      get_elf_backend_data (dynobj)->collect, &bh)))
-               return FALSE;
+               return false;
              h = (struct elf_link_hash_entry *) bh;
              h->non_elf = 0;
              h->def_regular = 1;
@@ -6517,7 +6707,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
              h->verinfo.vertree = NULL;
 
              if (! bfd_elf_link_record_dynamic_symbol (info, h))
-               return FALSE;
+               return false;
 
              /* Create a duplicate of the base version with the same
                 aux block, but different flags.  */
@@ -6554,9 +6744,9 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
              bh = NULL;
              if (! (_bfd_generic_link_add_one_symbol
                     (info, dynobj, t->name, BSF_GLOBAL, bfd_abs_section_ptr,
-                     0, NULL, FALSE,
+                     0, NULL, false,
                      get_elf_backend_data (dynobj)->collect, &bh)))
-               return FALSE;
+               return false;
              h = (struct elf_link_hash_entry *) bh;
              h->non_elf = 0;
              h->def_regular = 1;
@@ -6564,7 +6754,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
              h->verinfo.vertree = t;
 
              if (! bfd_elf_link_record_dynamic_symbol (info, h))
-               return FALSE;
+               return false;
 
              def.vd_version = VER_DEF_CURRENT;
              def.vd_flags = 0;
@@ -6660,13 +6850,13 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       sinfo.vers = elf_tdata (output_bfd)->cverdefs;
       if (sinfo.vers == 0)
        sinfo.vers = 1;
-      sinfo.failed = FALSE;
+      sinfo.failed = false;
 
       elf_link_hash_traverse (elf_hash_table (info),
                              _bfd_elf_link_find_version_dependencies,
                              &sinfo);
       if (sinfo.failed)
-       return FALSE;
+       return false;
 
       if (elf_tdata (output_bfd)->verref == NULL)
        s->flags |= SEC_EXCLUDE;
@@ -6695,7 +6885,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          s->size = size;
          s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
          if (s->contents == NULL)
-           return FALSE;
+           return false;
 
          p = s->contents;
          for (vn = elf_tdata (output_bfd)->verref;
@@ -6715,10 +6905,11 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
              indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
                                          elf_dt_name (vn->vn_bfd) != NULL
                                          ? elf_dt_name (vn->vn_bfd)
-                                         : lbasename (vn->vn_bfd->filename),
-                                         FALSE);
+                                         : lbasename (bfd_get_filename
+                                                      (vn->vn_bfd)),
+                                         false);
              if (indx == (size_t) -1)
-               return FALSE;
+               return false;
              vn->vn_file = indx;
              vn->vn_aux = sizeof (Elf_External_Verneed);
              if (vn->vn_nextref == NULL)
@@ -6735,9 +6926,9 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                {
                  a->vna_hash = bfd_elf_hash (a->vna_nodename);
                  indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                             a->vna_nodename, FALSE);
+                                             a->vna_nodename, false);
                  if (indx == (size_t) -1)
-                   return FALSE;
+                   return false;
                  a->vna_name = indx;
                  if (a->vna_nextptr == NULL)
                    a->vna_next = 0;
@@ -6763,13 +6954,13 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
   if (bfd_link_relocatable (info)
       && !_bfd_elf_size_group_sections (info))
-    return FALSE;
+    return false;
 
   /* The backend may have to create some sections regardless of whether
      we're dynamic or not.  */
   if (bed->elf_backend_always_size_sections
       && ! (*bed->elf_backend_always_size_sections) (output_bfd, info))
-    return FALSE;
+    return false;
 
   /* Determine any GNU_STACK segment requirements, after the backend
      has had a chance to set a default segment size.  */
@@ -6826,7 +7017,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       if (info->symbolic)
        {
          if (!_bfd_elf_add_dynamic_entry (info, DT_SYMBOLIC, 0))
-           return FALSE;
+           return false;
          info->flags |= DF_SYMBOLIC;
        }
 
@@ -6836,13 +7027,13 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          bfd_vma tag;
 
          indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, rpath,
-                                     TRUE);
+                                     true);
          if (indx == (size_t) -1)
-           return FALSE;
+           return false;
 
          tag = info->new_dtags ? DT_RUNPATH : DT_RPATH;
          if (!_bfd_elf_add_dynamic_entry (info, tag, indx))
-           return FALSE;
+           return false;
        }
 
       if (filter_shlib != NULL)
@@ -6850,10 +7041,10 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          size_t indx;
 
          indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                     filter_shlib, TRUE);
+                                     filter_shlib, true);
          if (indx == (size_t) -1
              || !_bfd_elf_add_dynamic_entry (info, DT_FILTER, indx))
-           return FALSE;
+           return false;
        }
 
       if (auxiliary_filters != NULL)
@@ -6865,10 +7056,10 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
              size_t indx;
 
              indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                         *p, TRUE);
+                                         *p, true);
              if (indx == (size_t) -1
                  || !_bfd_elf_add_dynamic_entry (info, DT_AUXILIARY, indx))
-               return FALSE;
+               return false;
            }
        }
 
@@ -6877,10 +7068,10 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          size_t indx;
 
          indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, audit,
-                                     TRUE);
+                                     true);
          if (indx == (size_t) -1
              || !_bfd_elf_add_dynamic_entry (info, DT_AUDIT, indx))
-           return FALSE;
+           return false;
        }
 
       if (depaudit != NULL)
@@ -6888,14 +7079,14 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          size_t indx;
 
          indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, depaudit,
-                                     TRUE);
+                                     true);
          if (indx == (size_t) -1
              || !_bfd_elf_add_dynamic_entry (info, DT_DEPAUDIT, indx))
-           return FALSE;
+           return false;
        }
 
       eif.info = info;
-      eif.failed = FALSE;
+      eif.failed = false;
 
       /* Find all symbols which were defined in a dynamic object and make
         the backend pick a reasonable value for them.  */
@@ -6903,7 +7094,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                              _bfd_elf_adjust_dynamic_symbol,
                              &eif);
       if (eif.failed)
-       return FALSE;
+       return false;
 
       /* Add some entries to the .dynamic section.  We fill in some of the
         values later, in bfd_elf_final_link, but we must add the entries
@@ -6913,27 +7104,27 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
         call then add the corresponding DT_INIT/DT_FINI entries.  */
       h = (info->init_function
           ? elf_link_hash_lookup (elf_hash_table (info),
-                                  info->init_function, FALSE,
-                                  FALSE, FALSE)
+                                  info->init_function, false,
+                                  false, false)
           : NULL);
       if (h != NULL
          && (h->ref_regular
              || h->def_regular))
        {
          if (!_bfd_elf_add_dynamic_entry (info, DT_INIT, 0))
-           return FALSE;
+           return false;
        }
       h = (info->fini_function
           ? elf_link_hash_lookup (elf_hash_table (info),
-                                  info->fini_function, FALSE,
-                                  FALSE, FALSE)
+                                  info->fini_function, false,
+                                  false, false)
           : NULL);
       if (h != NULL
          && (h->ref_regular
              || h->def_regular))
        {
          if (!_bfd_elf_add_dynamic_entry (info, DT_FINI, 0))
-           return FALSE;
+           return false;
        }
 
       s = bfd_get_section_by_name (output_bfd, ".preinit_array");
@@ -6960,26 +7151,26 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                      }
 
              bfd_set_error (bfd_error_nonrepresentable_section);
-             return FALSE;
+             return false;
            }
 
          if (!_bfd_elf_add_dynamic_entry (info, DT_PREINIT_ARRAY, 0)
              || !_bfd_elf_add_dynamic_entry (info, DT_PREINIT_ARRAYSZ, 0))
-           return FALSE;
+           return false;
        }
       s = bfd_get_section_by_name (output_bfd, ".init_array");
       if (s != NULL && s->linker_has_input)
        {
          if (!_bfd_elf_add_dynamic_entry (info, DT_INIT_ARRAY, 0)
              || !_bfd_elf_add_dynamic_entry (info, DT_INIT_ARRAYSZ, 0))
-           return FALSE;
+           return false;
        }
       s = bfd_get_section_by_name (output_bfd, ".fini_array");
       if (s != NULL && s->linker_has_input)
        {
          if (!_bfd_elf_add_dynamic_entry (info, DT_FINI_ARRAY, 0)
              || !_bfd_elf_add_dynamic_entry (info, DT_FINI_ARRAYSZ, 0))
-           return FALSE;
+           return false;
        }
 
       dynstr = bfd_get_linker_section (dynobj, ".dynstr");
@@ -7001,20 +7192,23 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
              || !_bfd_elf_add_dynamic_entry (info, DT_SYMTAB, 0)
              || !_bfd_elf_add_dynamic_entry (info, DT_STRSZ, strsize)
              || !_bfd_elf_add_dynamic_entry (info, DT_SYMENT,
-                                             bed->s->sizeof_sym))
-           return FALSE;
+                                             bed->s->sizeof_sym)
+             || (info->gnu_flags_1
+                 && !_bfd_elf_add_dynamic_entry (info, DT_GNU_FLAGS_1,
+                                                 info->gnu_flags_1)))
+           return false;
        }
     }
 
   if (! _bfd_elf_maybe_strip_eh_frame_hdr (info))
-    return FALSE;
+    return false;
 
   /* The backend must work out the sizes of all the other dynamic
      sections.  */
   if (dynobj != NULL
       && bed->elf_backend_size_dynamic_sections != NULL
       && ! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
-    return FALSE;
+    return false;
 
   if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
     {
@@ -7024,18 +7218,18 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
          if (!_bfd_elf_add_dynamic_entry (info, DT_VERDEF, 0)
              || !_bfd_elf_add_dynamic_entry (info, DT_VERDEFNUM, crefs))
-           return FALSE;
+           return false;
        }
 
       if ((info->new_dtags && info->flags) || (info->flags & DF_STATIC_TLS))
        {
          if (!_bfd_elf_add_dynamic_entry (info, DT_FLAGS, info->flags))
-           return FALSE;
+           return false;
        }
       else if (info->flags & DF_BIND_NOW)
        {
          if (!_bfd_elf_add_dynamic_entry (info, DT_BIND_NOW, 0))
-           return FALSE;
+           return false;
        }
 
       if (info->flags_1)
@@ -7045,7 +7239,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                                | DF_1_NODELETE
                                | DF_1_NOOPEN);
          if (!_bfd_elf_add_dynamic_entry (info, DT_FLAGS_1, info->flags_1))
-           return FALSE;
+           return false;
        }
 
       if (elf_tdata (output_bfd)->cverrefs)
@@ -7054,7 +7248,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
          if (!_bfd_elf_add_dynamic_entry (info, DT_VERNEED, 0)
              || !_bfd_elf_add_dynamic_entry (info, DT_VERNEEDNUM, crefs))
-           return FALSE;
+           return false;
        }
 
       if ((elf_tdata (output_bfd)->cverrefs == 0
@@ -7067,7 +7261,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          s->flags |= SEC_EXCLUDE;
        }
     }
-  return TRUE;
+  return true;
 }
 
 /* Find the first non-excluded output section.  We'll use its
@@ -7124,7 +7318,7 @@ _bfd_elf_init_2_index_sections (bfd *output_bfd, struct bfd_link_info *info)
 #define GNU_HASH_SECTION_NAME(bed)                         \
   (bed)->record_xhash_symbol != NULL ? ".MIPS.xhash" : ".gnu.hash"
 
-bfd_boolean
+bool
 bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
 {
   const struct elf_backend_data *bed;
@@ -7132,7 +7326,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
   bfd_size_type dynsymcount = 0;
 
   if (!is_elf_hash_table (info->hash))
-    return TRUE;
+    return true;
 
   bed = get_elf_backend_data (output_bfd);
   (*bed->elf_backend_init_index_section) (output_bfd, info);
@@ -7169,10 +7363,10 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
          s->size = dynsymcount * sizeof (Elf_External_Versym);
          s->contents = (unsigned char *) bfd_zalloc (output_bfd, s->size);
          if (s->contents == NULL)
-           return FALSE;
+           return false;
 
          if (!_bfd_elf_add_dynamic_entry (info, DT_VERSYM, 0))
-           return FALSE;
+           return false;
        }
 
       /* Set the size of the .dynsym and .hash sections.  We counted
@@ -7187,7 +7381,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
 
       s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
       if (s->contents == NULL)
-       return FALSE;
+       return false;
 
       /* The first entry in .dynsym is a dummy symbol.  Clear all the
         section syms, in case we don't output them all.  */
@@ -7213,9 +7407,9 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
          amt = dynsymcount * sizeof (unsigned long int);
          hashcodes = (unsigned long int *) bfd_malloc (amt);
          if (hashcodes == NULL)
-           return FALSE;
+           return false;
          hashinf.hashcodes = hashcodes;
-         hashinf.error = FALSE;
+         hashinf.error = false;
 
          /* Put all hash values in HASHCODES.  */
          elf_link_hash_traverse (elf_hash_table (info),
@@ -7223,7 +7417,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
          if (hashinf.error)
            {
              free (hashcodes);
-             return FALSE;
+             return false;
            }
 
          nsyms = hashinf.hashcodes - hashcodes;
@@ -7232,7 +7426,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
          free (hashcodes);
 
          if (bucketcount == 0 && nsyms > 0)
-           return FALSE;
+           return false;
 
          elf_hash_table (info)->bucketcount = bucketcount;
 
@@ -7242,7 +7436,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
          s->size = ((2 + bucketcount + dynsymcount) * hash_entry_size);
          s->contents = (unsigned char *) bfd_zalloc (output_bfd, s->size);
          if (s->contents == NULL)
-           return FALSE;
+           return false;
 
          bfd_put (8 * hash_entry_size, output_bfd, bucketcount, s->contents);
          bfd_put (8 * hash_entry_size, output_bfd, dynsymcount,
@@ -7265,7 +7459,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
          amt = dynsymcount * 2 * sizeof (unsigned long int);
          cinfo.hashcodes = (long unsigned int *) bfd_malloc (amt);
          if (cinfo.hashcodes == NULL)
-           return FALSE;
+           return false;
 
          cinfo.hashval = cinfo.hashcodes + dynsymcount;
          cinfo.min_dynindx = -1;
@@ -7278,7 +7472,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
          if (cinfo.error)
            {
              free (cinfo.hashcodes);
-             return FALSE;
+             return false;
            }
 
          bucketcount
@@ -7287,7 +7481,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
          if (bucketcount == 0)
            {
              free (cinfo.hashcodes);
-             return FALSE;
+             return false;
            }
 
          s = bfd_get_linker_section (dynobj, GNU_HASH_SECTION_NAME (bed));
@@ -7301,7 +7495,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
              s->size = 5 * 4 + bed->s->arch_size / 8;
              contents = (unsigned char *) bfd_zalloc (output_bfd, s->size);
              if (contents == NULL)
-               return FALSE;
+               return false;
              s->contents = contents;
              /* 1 empty bucket.  */
              bfd_put_32 (output_bfd, 1, contents);
@@ -7350,7 +7544,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
              if (cinfo.bitmask == NULL)
                {
                  free (cinfo.hashcodes);
-                 return FALSE;
+                 return false;
                }
 
              cinfo.counts = (long unsigned int *) (cinfo.bitmask + maskwords);
@@ -7382,7 +7576,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
                {
                  free (cinfo.bitmask);
                  free (cinfo.hashcodes);
-                 return FALSE;
+                 return false;
                }
 
              s->contents = contents;
@@ -7431,10 +7625,10 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
 
       for (dtagcount = 0; dtagcount <= info->spare_dynamic_tags; ++dtagcount)
        if (!_bfd_elf_add_dynamic_entry (info, DT_NULL, 0))
-         return FALSE;
+         return false;
     }
 
-  return TRUE;
+  return true;
 }
 \f
 /* Make sure sec_info_type is cleared if sec_info is cleared too.  */
@@ -7449,14 +7643,14 @@ merge_sections_remove_hook (bfd *abfd ATTRIBUTE_UNUSED,
 
 /* Finish SHF_MERGE section merging.  */
 
-bfd_boolean
+bool
 _bfd_elf_merge_sections (bfd *obfd, struct bfd_link_info *info)
 {
   bfd *ibfd;
   asection *sec;
 
   if (!is_elf_hash_table (info->hash))
-    return FALSE;
+    return false;
 
   for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
     if ((ibfd->flags & DYNAMIC) == 0
@@ -7473,7 +7667,7 @@ _bfd_elf_merge_sections (bfd *obfd, struct bfd_link_info *info)
            if (! _bfd_add_merge_section (obfd,
                                          &elf_hash_table (info)->merge_info,
                                          sec, &secdata->sec_info))
-             return FALSE;
+             return false;
            else if (secdata->sec_info)
              sec->sec_info_type = SEC_INFO_TYPE_MERGE;
          }
@@ -7481,7 +7675,7 @@ _bfd_elf_merge_sections (bfd *obfd, struct bfd_link_info *info)
   if (elf_hash_table (info)->merge_info != NULL)
     _bfd_merge_sections (obfd, info, elf_hash_table (info)->merge_info,
                         merge_sections_remove_hook);
-  return TRUE;
+  return true;
 }
 
 /* Create an entry in an ELF linker hash table.  */
@@ -7535,6 +7729,37 @@ _bfd_elf_link_hash_copy_indirect (struct bfd_link_info *info,
 {
   struct elf_link_hash_table *htab;
 
+  if (ind->dyn_relocs != NULL)
+    {
+      if (dir->dyn_relocs != NULL)
+       {
+         struct elf_dyn_relocs **pp;
+         struct elf_dyn_relocs *p;
+
+         /* Add reloc counts against the indirect sym to the direct sym
+            list.  Merge any entries against the same section.  */
+         for (pp = &ind->dyn_relocs; (p = *pp) != NULL; )
+           {
+             struct elf_dyn_relocs *q;
+
+             for (q = dir->dyn_relocs; q != NULL; q = q->next)
+               if (q->sec == p->sec)
+                 {
+                   q->pc_count += p->pc_count;
+                   q->count += p->count;
+                   *pp = p->next;
+                   break;
+                 }
+             if (q == NULL)
+               pp = &p->next;
+           }
+         *pp = dir->dyn_relocs;
+       }
+
+      dir->dyn_relocs = ind->dyn_relocs;
+      ind->dyn_relocs = NULL;
+    }
+
   /* Copy down any references that we may have already seen to the
      symbol which just became indirect.  */
 
@@ -7582,7 +7807,7 @@ _bfd_elf_link_hash_copy_indirect (struct bfd_link_info *info,
 void
 _bfd_elf_link_hash_hide_symbol (struct bfd_link_info *info,
                                struct elf_link_hash_entry *h,
-                               bfd_boolean force_local)
+                               bool force_local)
 {
   /* STT_GNU_IFUNC symbol must go through PLT.  */
   if (h->type != STT_GNU_IFUNC)
@@ -7616,7 +7841,7 @@ _bfd_elf_link_hide_symbol (bfd *output_bfd,
        = 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);
+      bed->elf_backend_hide_symbol (info, eh, true);
       eh->def_dynamic = 0;
       eh->ref_dynamic = 0;
       eh->dynamic_def = 0;
@@ -7626,7 +7851,7 @@ _bfd_elf_link_hide_symbol (bfd *output_bfd,
 /* Initialize an ELF linker hash table.  *TABLE has been zeroed by our
    caller.  */
 
-bfd_boolean
+bool
 _bfd_elf_link_hash_table_init
   (struct elf_link_hash_table *table,
    bfd *abfd,
@@ -7636,7 +7861,7 @@ _bfd_elf_link_hash_table_init
    unsigned int entsize,
    enum elf_target_id target_id)
 {
-  bfd_boolean ret;
+  bool ret;
   int can_refcount = get_elf_backend_data (abfd)->can_refcount;
 
   table->init_got_refcount.refcount = can_refcount - 1;
@@ -7650,6 +7875,7 @@ _bfd_elf_link_hash_table_init
 
   table->root.type = bfd_link_elf_hash_table;
   table->hash_table_id = target_id;
+  table->target_os = get_elf_backend_data (abfd)->target_os;
 
   return ret;
 }
@@ -7660,7 +7886,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)
@@ -7764,7 +7990,7 @@ bfd_elf_get_dt_soname (bfd *abfd)
 /* Get the list of DT_NEEDED entries from a BFD.  This is a hook for
    the ELF linker emulation code.  */
 
-bfd_boolean
+bool
 bfd_elf_get_bfd_needed_list (bfd *abfd,
                             struct bfd_link_needed_list **pneeded)
 {
@@ -7780,11 +8006,11 @@ bfd_elf_get_bfd_needed_list (bfd *abfd,
 
   if (bfd_get_flavour (abfd) != bfd_target_elf_flavour
       || bfd_get_format (abfd) != bfd_object)
-    return TRUE;
+    return true;
 
   s = bfd_get_section_by_name (abfd, ".dynamic");
   if (s == NULL || s->size == 0)
-    return TRUE;
+    return true;
 
   if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
     goto error_return;
@@ -7814,7 +8040,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)
@@ -7834,12 +8060,11 @@ bfd_elf_get_bfd_needed_list (bfd *abfd,
 
   free (dynbuf);
 
-  return TRUE;
+  return true;
 
  error_return:
-  if (dynbuf != NULL)
-    free (dynbuf);
-  return FALSE;
+  free (dynbuf);
+  return false;
 }
 
 struct elf_symbuf_symbol
@@ -7903,9 +8128,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;
 
@@ -7961,7 +8187,7 @@ elf_create_symbuf (size_t symcount, Elf_Internal_Sym *isymbuf)
 /* Check if 2 sections define the same set of local and global
    symbols.  */
 
-static bfd_boolean
+static bool
 bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
                                   struct bfd_link_info *info)
 {
@@ -7973,9 +8199,10 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
   struct elf_symbuf_head *ssymbuf1, *ssymbuf2;
   Elf_Internal_Sym *isym, *isymend;
   struct elf_symbol *symtable1 = NULL, *symtable2 = NULL;
-  size_t count1, count2, i;
+  size_t count1, count2, sec_count1, sec_count2, i;
   unsigned int shndx1, shndx2;
-  bfd_boolean result;
+  bool result;
+  bool ignore_section_symbol_p;
 
   bfd1 = sec1->owner;
   bfd2 = sec2->owner;
@@ -7983,15 +8210,15 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
   /* Both sections have to be in ELF.  */
   if (bfd_get_flavour (bfd1) != bfd_target_elf_flavour
       || bfd_get_flavour (bfd2) != bfd_target_elf_flavour)
-    return FALSE;
+    return false;
 
   if (elf_section_type (sec1) != elf_section_type (sec2))
-    return FALSE;
+    return false;
 
   shndx1 = _bfd_elf_section_from_bfd_section (bfd1, sec1);
   shndx2 = _bfd_elf_section_from_bfd_section (bfd2, sec2);
   if (shndx1 == SHN_BAD || shndx2 == SHN_BAD)
-    return FALSE;
+    return false;
 
   bed1 = get_elf_backend_data (bfd1);
   bed2 = get_elf_backend_data (bfd2);
@@ -8001,14 +8228,21 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
   symcount2 = hdr2->sh_size / bed2->s->sizeof_sym;
 
   if (symcount1 == 0 || symcount2 == 0)
-    return FALSE;
+    return false;
 
-  result = FALSE;
+  result = false;
   isymbuf1 = NULL;
   isymbuf2 = NULL;
   ssymbuf1 = (struct elf_symbuf_head *) elf_tdata (bfd1)->symbuf;
   ssymbuf2 = (struct elf_symbuf_head *) elf_tdata (bfd2)->symbuf;
 
+  /* Ignore section symbols only when matching non-debugging sections
+     or linkonce section with comdat section.  */
+  ignore_section_symbol_p
+    = ((sec1->flags & SEC_DEBUGGING) == 0
+       || ((elf_section_flags (sec1) & SHF_GROUP)
+          != (elf_section_flags (sec2) & SHF_GROUP)));
+
   if (ssymbuf1 == NULL)
     {
       isymbuf1 = bfd_elf_get_elf_syms (bfd1, hdr1, symcount1, 0,
@@ -8016,7 +8250,7 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
       if (isymbuf1 == NULL)
        goto done;
 
-      if (!info->reduce_memory_overheads)
+      if (info != NULL && !info->reduce_memory_overheads)
        {
          ssymbuf1 = elf_create_symbuf (symcount1, isymbuf1);
          elf_tdata (bfd1)->symbuf = ssymbuf1;
@@ -8030,7 +8264,7 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
       if (isymbuf2 == NULL)
        goto done;
 
-      if (ssymbuf1 != NULL && !info->reduce_memory_overheads)
+      if (ssymbuf1 != NULL && info != NULL && !info->reduce_memory_overheads)
        {
          ssymbuf2 = elf_create_symbuf (symcount2, isymbuf2);
          elf_tdata (bfd2)->symbuf = ssymbuf2;
@@ -8048,6 +8282,7 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
       hi = ssymbuf1->count;
       ssymbuf1++;
       count1 = 0;
+      sec_count1 = 0;
       while (lo < hi)
        {
          mid = (lo + hi) / 2;
@@ -8062,11 +8297,19 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
              break;
            }
        }
+      if (ignore_section_symbol_p)
+       {
+         for (i = 0; i < count1; i++)
+           if (ELF_ST_TYPE (ssymbuf1->ssym[i].st_info) == STT_SECTION)
+             sec_count1++;
+         count1 -= sec_count1;
+       }
 
       lo = 0;
       hi = ssymbuf2->count;
       ssymbuf2++;
       count2 = 0;
+      sec_count2 = 0;
       while (lo < hi)
        {
          mid = (lo + hi) / 2;
@@ -8081,6 +8324,13 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
              break;
            }
        }
+      if (ignore_section_symbol_p)
+       {
+         for (i = 0; i < count2; i++)
+           if (ELF_ST_TYPE (ssymbuf2->ssym[i].st_info) == STT_SECTION)
+             sec_count2++;
+         count2 -= sec_count2;
+       }
 
       if (count1 == 0 || count2 == 0 || count1 != count2)
        goto done;
@@ -8093,24 +8343,30 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
        goto done;
 
       symp = symtable1;
-      for (ssym = ssymbuf1->ssym, ssymend = ssym + count1;
-          ssym < ssymend; ssym++, symp++)
-       {
-         symp->u.ssym = ssym;
-         symp->name = bfd_elf_string_from_elf_section (bfd1,
-                                                       hdr1->sh_link,
-                                                       ssym->st_name);
-       }
+      for (ssym = ssymbuf1->ssym, ssymend = ssym + count1 + sec_count1;
+          ssym < ssymend; ssym++)
+       if (sec_count1 == 0
+           || ELF_ST_TYPE (ssym->st_info) != STT_SECTION)
+         {
+           symp->u.ssym = ssym;
+           symp->name = bfd_elf_string_from_elf_section (bfd1,
+                                                         hdr1->sh_link,
+                                                         ssym->st_name);
+           symp++;
+         }
 
       symp = symtable2;
-      for (ssym = ssymbuf2->ssym, ssymend = ssym + count2;
-          ssym < ssymend; ssym++, symp++)
-       {
-         symp->u.ssym = ssym;
-         symp->name = bfd_elf_string_from_elf_section (bfd2,
-                                                       hdr2->sh_link,
-                                                       ssym->st_name);
-       }
+      for (ssym = ssymbuf2->ssym, ssymend = ssym + count2 + sec_count2;
+          ssym < ssymend; ssym++)
+       if (sec_count2 == 0
+           || ELF_ST_TYPE (ssym->st_info) != STT_SECTION)
+         {
+           symp->u.ssym = ssym;
+           symp->name = bfd_elf_string_from_elf_section (bfd2,
+                                                         hdr2->sh_link,
+                                                         ssym->st_name);
+           symp++;
+         }
 
       /* Sort symbol by name.  */
       qsort (symtable1, count1, sizeof (struct elf_symbol),
@@ -8125,7 +8381,7 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
            || strcmp (symtable1 [i].name, symtable2 [i].name) != 0)
          goto done;
 
-      result = TRUE;
+      result = true;
       goto done;
     }
 
@@ -8139,12 +8395,16 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
   /* Count definitions in the section.  */
   count1 = 0;
   for (isym = isymbuf1, isymend = isym + symcount1; isym < isymend; isym++)
-    if (isym->st_shndx == shndx1)
+    if (isym->st_shndx == shndx1
+       && (!ignore_section_symbol_p
+           || ELF_ST_TYPE (isym->st_info) != STT_SECTION))
       symtable1[count1++].u.isym = isym;
 
   count2 = 0;
   for (isym = isymbuf2, isymend = isym + symcount2; isym < isymend; isym++)
-    if (isym->st_shndx == shndx2)
+    if (isym->st_shndx == shndx2
+       && (!ignore_section_symbol_p
+           || ELF_ST_TYPE (isym->st_info) != STT_SECTION))
       symtable2[count2++].u.isym = isym;
 
   if (count1 == 0 || count2 == 0 || count1 != count2)
@@ -8173,24 +8433,20 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
        || strcmp (symtable1 [i].name, symtable2 [i].name) != 0)
       goto done;
 
-  result = TRUE;
+  result = true;
 
-done:
-  if (symtable1)
-    free (symtable1);
-  if (symtable2)
-    free (symtable2);
-  if (isymbuf1)
-    free (isymbuf1);
-  if (isymbuf2)
-    free (isymbuf2);
+ done:
+  free (symtable1);
+  free (symtable2);
+  free (isymbuf1);
+  free (isymbuf2);
 
   return result;
 }
 
 /* Return TRUE if 2 section types are compatible.  */
 
-bfd_boolean
+bool
 _bfd_elf_match_sections_by_type (bfd *abfd, const asection *asec,
                                 bfd *bbfd, const asection *bsec)
 {
@@ -8198,7 +8454,7 @@ _bfd_elf_match_sections_by_type (bfd *abfd, const asection *asec,
       || bsec == NULL
       || abfd->xvec->flavour != bfd_target_elf_flavour
       || bbfd->xvec->flavour != bfd_target_elf_flavour)
-    return TRUE;
+    return true;
 
   return elf_section_type (asec) == elf_section_type (bsec);
 }
@@ -8243,15 +8499,56 @@ struct elf_final_link_info
   Elf_External_Sym_Shndx *symshndxbuf;
   /* Number of STT_FILE syms seen.  */
   size_t filesym_count;
+  /* Local symbol hash table.  */
+  struct bfd_hash_table local_hash_table;
 };
 
+struct local_hash_entry
+{
+  /* Base hash table entry structure.  */
+  struct bfd_hash_entry root;
+  /* Size of the local symbol name.  */
+  size_t size;
+  /* Number of the duplicated local symbol names.  */
+  long count;
+};
+
+/* Create an entry in the local symbol hash table.  */
+
+static struct bfd_hash_entry *
+local_hash_newfunc (struct bfd_hash_entry *entry,
+                   struct bfd_hash_table *table,
+                   const char *string)
+{
+
+  /* Allocate the structure if it has not already been allocated by a
+     subclass.  */
+  if (entry == NULL)
+    {
+      entry = bfd_hash_allocate (table,
+                                sizeof (struct local_hash_entry));
+      if (entry == NULL)
+        return entry;
+    }
+
+  /* Call the allocation method of the superclass.  */
+  entry = bfd_hash_newfunc (entry, table, string);
+  if (entry != NULL)
+    {
+      ((struct local_hash_entry *) entry)->count = 0;
+      ((struct local_hash_entry *) entry)->size = 0;
+    }
+
+  return entry;
+}
+
 /* This struct is used to pass information to elf_link_output_extsym.  */
 
 struct elf_outext_info
 {
-  bfd_boolean failed;
-  bfd_boolean localsyms;
-  bfd_boolean file_sym_done;
+  bool failed;
+  bool localsyms;
+  bool file_sym_done;
   struct elf_final_link_info *flinfo;
 };
 
@@ -8262,12 +8559,12 @@ struct elf_outext_info
    implementation of them consists of two parts: complex symbols, and the
    relocations themselves.
 
-   The relocations are use a reserved elf-wide relocation type code (R_RELC
+   The relocations use a reserved elf-wide relocation type code (R_RELC
    external / BFD_RELOC_RELC internal) and an encoding of relocation field
    information (start bit, end bit, word width, etc) into the addend.  This
    information is extracted from CGEN-generated operand tables within gas.
 
-   Complex symbols are mangled symbols (BSF_RELC external / STT_RELC
+   Complex symbols are mangled symbols (STT_RELC external / BSF_RELC
    internal) representing prefix-notation expressions, including but not
    limited to those sorts of expressions normally encoded as addends in the
    addend field.  The symbol mangling format is:
@@ -8326,7 +8623,7 @@ set_symbol_value (bfd *bfd_with_globals,
   h->root.u.def.section = bfd_abs_section_ptr;
 }
 
-static bfd_boolean
+static bool
 resolve_symbol (const char *name,
                bfd *input_bfd,
                struct elf_final_link_info *flinfo,
@@ -8366,15 +8663,15 @@ resolve_symbol (const char *name,
          printf ("Found symbol with value %8.8lx\n",
                  (unsigned long) *result);
 #endif
-         return TRUE;
+         return true;
        }
     }
 
   /* Hmm, haven't found it yet. perhaps it is a global.  */
   global_entry = bfd_link_hash_lookup (flinfo->info->hash, name,
-                                      FALSE, FALSE, TRUE);
+                                      false, false, true);
   if (!global_entry)
-    return FALSE;
+    return false;
 
   if (global_entry->type == bfd_link_hash_defined
       || global_entry->type == bfd_link_hash_defweak)
@@ -8386,17 +8683,17 @@ resolve_symbol (const char *name,
       printf ("Found GLOBAL symbol '%s' with value %8.8lx\n",
              global_entry->root.string, (unsigned long) *result);
 #endif
-      return TRUE;
+      return true;
     }
 
-  return FALSE;
+  return false;
 }
 
 /* Looks up NAME in SECTIONS.  If found sets RESULT to NAME's address (in
    bytes) and returns TRUE, otherwise returns FALSE.  Accepts pseudo-section
    names like "foo.end" which is the end address of section "foo".  */
 
-static bfd_boolean
+static bool
 resolve_section (const char *name,
                 asection *sections,
                 bfd_vma *result,
@@ -8409,7 +8706,7 @@ resolve_section (const char *name,
     if (strcmp (curr->name, name) == 0)
       {
        *result = curr->vma;
-       return TRUE;
+       return true;
       }
 
   /* Hmm. still haven't found it. try pseudo-section names.  */
@@ -8422,17 +8719,18 @@ resolve_section (const char *name,
 
       if (strncmp (curr->name, name, len) == 0)
        {
-         if (strncmp (".end", name + len, 4) == 0)
+         if (startswith (name + len, ".end"))
            {
-             *result = curr->vma + curr->size / bfd_octets_per_byte (abfd);
-             return TRUE;
+             *result = (curr->vma
+                        + curr->size / bfd_octets_per_byte (abfd, curr));
+             return true;
            }
 
          /* Insert more pseudo-section names here, if you like.  */
        }
     }
 
-  return FALSE;
+  return false;
 }
 
 static void
@@ -8441,9 +8739,10 @@ undefined_reference (const char *reftype, const char *name)
   /* xgettext:c-format */
   _bfd_error_handler (_("undefined %s reference in complex symbol: %s"),
                      reftype, name);
+  bfd_set_error (bfd_error_bad_value);
 }
 
-static bfd_boolean
+static bool
 eval_symbol (bfd_vma *result,
             const char **symp,
             bfd *input_bfd,
@@ -8460,7 +8759,7 @@ eval_symbol (bfd_vma *result,
   char symbuf[4096];
   const char *sym = *symp;
   const char *symend;
-  bfd_boolean symbol_is_section = FALSE;
+  bool symbol_is_section = false;
 
   len = strlen (sym);
   symend = sym + len;
@@ -8468,7 +8767,7 @@ eval_symbol (bfd_vma *result,
   if (len < 1 || len > sizeof (symbuf))
     {
       bfd_set_error (bfd_error_invalid_operation);
-      return FALSE;
+      return false;
     }
 
   switch (* sym)
@@ -8476,15 +8775,15 @@ eval_symbol (bfd_vma *result,
     case '.':
       *result = dot;
       *symp = sym + 1;
-      return TRUE;
+      return true;
 
     case '#':
       ++sym;
       *result = strtoul (sym, (char **) symp, 16);
-      return TRUE;
+      return true;
 
     case 'S':
-      symbol_is_section = TRUE;
+      symbol_is_section = true;
       /* Fall through.  */
     case 's':
       ++sym;
@@ -8494,7 +8793,7 @@ eval_symbol (bfd_vma *result,
       if (symend < sym || symlen + 1 > sizeof (symbuf))
        {
          bfd_set_error (bfd_error_invalid_operation);
-         return FALSE;
+         return false;
        }
 
       memcpy (symbuf, sym, symlen);
@@ -8513,7 +8812,7 @@ eval_symbol (bfd_vma *result,
                                  isymbuf, locsymcount))
            {
              undefined_reference ("section", symbuf);
-             return FALSE;
+             return false;
            }
        }
       else
@@ -8524,16 +8823,16 @@ eval_symbol (bfd_vma *result,
                                   result, input_bfd))
            {
              undefined_reference ("symbol", symbuf);
-             return FALSE;
+             return false;
            }
        }
 
-      return TRUE;
+      return true;
 
       /* All that remains are operators.  */
 
 #define UNARY_OP(op)                                           \
-  if (strncmp (sym, #op, strlen (#op)) == 0)                   \
+  if (startswith (sym, #op))                                   \
     {                                                          \
       sym += strlen (#op);                                     \
       if (*sym == ':')                                         \
@@ -8541,16 +8840,16 @@ eval_symbol (bfd_vma *result,
       *symp = sym;                                             \
       if (!eval_symbol (&a, symp, input_bfd, flinfo, dot,      \
                        isymbuf, locsymcount, signed_p))        \
-       return FALSE;                                           \
+       return false;                                           \
       if (signed_p)                                            \
        *result = op ((bfd_signed_vma) a);                      \
       else                                                     \
        *result = op a;                                         \
-      return TRUE;                                             \
+      return true;                                             \
     }
 
-#define BINARY_OP(op)                                          \
-  if (strncmp (sym, #op, strlen (#op)) == 0)                   \
+#define BINARY_OP_HEAD(op)                                     \
+  if (startswith (sym, #op))                                   \
     {                                                          \
       sym += strlen (#op);                                     \
       if (*sym == ':')                                         \
@@ -8558,22 +8857,37 @@ eval_symbol (bfd_vma *result,
       *symp = sym;                                             \
       if (!eval_symbol (&a, symp, input_bfd, flinfo, dot,      \
                        isymbuf, locsymcount, signed_p))        \
-       return FALSE;                                           \
+       return false;                                           \
       ++*symp;                                                 \
       if (!eval_symbol (&b, symp, input_bfd, flinfo, dot,      \
                        isymbuf, locsymcount, signed_p))        \
-       return FALSE;                                           \
+       return false;
+#define BINARY_OP_TAIL(op)                                     \
       if (signed_p)                                            \
        *result = ((bfd_signed_vma) a) op ((bfd_signed_vma) b); \
       else                                                     \
        *result = a op b;                                       \
-      return TRUE;                                             \
+      return true;                                             \
     }
+#define BINARY_OP(op) BINARY_OP_HEAD(op) BINARY_OP_TAIL(op)
 
     default:
       UNARY_OP  (0-);
-      BINARY_OP (<<);
-      BINARY_OP (>>);
+      BINARY_OP_HEAD (<<);
+      if (b >= sizeof (a) * CHAR_BIT)
+       {
+         *result = 0;
+         return true;
+       }
+      signed_p = 0;
+      BINARY_OP_TAIL (<<);
+      BINARY_OP_HEAD (>>);
+      if (b >= sizeof (a) * CHAR_BIT)
+       {
+         *result = signed_p && (bfd_signed_vma) a < 0 ? -1 : 0;
+         return true;
+       }
+      BINARY_OP_TAIL (>>);
       BINARY_OP (==);
       BINARY_OP (!=);
       BINARY_OP (<=);
@@ -8583,8 +8897,22 @@ eval_symbol (bfd_vma *result,
       UNARY_OP  (~);
       UNARY_OP  (!);
       BINARY_OP (*);
-      BINARY_OP (/);
-      BINARY_OP (%);
+      BINARY_OP_HEAD (/);
+      if (b == 0)
+       {
+         _bfd_error_handler (_("division by zero"));
+         bfd_set_error (bfd_error_bad_value);
+         return false;
+       }
+      BINARY_OP_TAIL (/);
+      BINARY_OP_HEAD (%);
+      if (b == 0)
+       {
+         _bfd_error_handler (_("division by zero"));
+         bfd_set_error (bfd_error_bad_value);
+         return false;
+       }
+      BINARY_OP_TAIL (%);
       BINARY_OP (^);
       BINARY_OP (|);
       BINARY_OP (&);
@@ -8596,7 +8924,7 @@ eval_symbol (bfd_vma *result,
 #undef BINARY_OP
       _bfd_error_handler (_("unknown operator '%c' in complex symbol"), * sym);
       bfd_set_error (bfd_error_invalid_operation);
-      return FALSE;
+      return false;
     }
 }
 
@@ -8719,7 +9047,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)
@@ -8727,6 +9055,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
@@ -8745,8 +9074,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: "
@@ -8778,8 +9107,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;
 }
 
@@ -8874,11 +9202,11 @@ ext64b_r_offset (const void *p)
    referenced must be updated.  Update all the relocations found in
    RELDATA.  */
 
-static bfd_boolean
+static bool
 elf_link_adjust_relocs (bfd *abfd,
                        asection *sec,
                        struct bfd_elf_section_reloc_data *reldata,
-                       bfd_boolean sort,
+                       bool sort,
                        struct bfd_link_info *info)
 {
   unsigned int i;
@@ -8938,7 +9266,7 @@ elf_link_adjust_relocs (bfd *abfd,
          _bfd_error_handler (_("%pB:%pA: error: try relinking with --gc-keep-exported enabled"),
                              abfd, sec);
          bfd_set_error (bfd_error_invalid_operation);
-         return FALSE;
+         return false;
        }
       BFD_ASSERT ((*rel_hash)->indx >= 0);
 
@@ -9040,7 +9368,7 @@ elf_link_adjust_relocs (bfd *abfd,
                {
                  buf = bfd_malloc (buf_size);
                  if (buf == NULL)
-                   return FALSE;
+                   return false;
                }
              if (runlen < sortlen)
                {
@@ -9062,7 +9390,7 @@ elf_link_adjust_relocs (bfd *abfd,
       reldata->hashes = NULL;
       free (buf);
     }
-  return TRUE;
+  return true;
 }
 
 struct elf_link_sort_rela
@@ -9143,12 +9471,12 @@ 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;
   bfd_vma r_sym_mask;
-  bfd_boolean use_rela;
+  bool use_rela;
 
   /* Find a dynamic reloc section.  */
   rela_dyn = bfd_get_section_by_name (abfd, ".rela.dyn");
@@ -9156,11 +9484,11 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
   if (rela_dyn != NULL && rela_dyn->size > 0
       && rel_dyn != NULL && rel_dyn->size > 0)
     {
-      bfd_boolean use_rela_initialised = FALSE;
+      bool use_rela_initialised = false;
 
       /* This is just here to stop gcc from complaining.
         Its initialization checking code is not perfect.  */
-      use_rela = TRUE;
+      use_rela = true;
 
       /* Both sections are present.  Examine the sizes
         of the indirect sections to help us choose.  */
@@ -9188,8 +9516,8 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
                      }
                    else
                      {
-                       use_rela = TRUE;
-                       use_rela_initialised = TRUE;
+                       use_rela = true;
+                       use_rela_initialised = true;
                      }
                  }
              }
@@ -9206,8 +9534,8 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
                  }
                else
                  {
-                   use_rela = FALSE;
-                   use_rela_initialised = TRUE;
+                   use_rela = false;
+                   use_rela_initialised = true;
                  }
              }
            else
@@ -9245,8 +9573,8 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
                      }
                    else
                      {
-                       use_rela = TRUE;
-                       use_rela_initialised = TRUE;
+                       use_rela = true;
+                       use_rela_initialised = true;
                      }
                  }
              }
@@ -9263,8 +9591,8 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
                  }
                else
                  {
-                   use_rela = FALSE;
-                   use_rela_initialised = TRUE;
+                   use_rela = false;
+                   use_rela_initialised = true;
                  }
              }
            else
@@ -9280,12 +9608,12 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
 
       if (! use_rela_initialised)
        /* Make a guess.  */
-       use_rela = TRUE;
+       use_rela = true;
     }
   else if (rela_dyn != NULL && rela_dyn->size > 0)
-    use_rela = TRUE;
+    use_rela = true;
   else if (rel_dyn != NULL && rel_dyn->size > 0)
-    use_rela = FALSE;
+    use_rela = false;
   else
     return 0;
 
@@ -9439,12 +9767,13 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
 /* Add a symbol to the output symbol string table.  */
 
 static int
-elf_link_output_symstrtab (struct elf_final_link_info *flinfo,
+elf_link_output_symstrtab (void *finf,
                           const char *name,
                           Elf_Internal_Sym *elfsym,
                           asection *input_sec,
                           struct elf_link_hash_entry *h)
 {
+  struct elf_final_link_info *flinfo = finf;
   int (*output_symbol_hook)
     (struct bfd_link_info *, const char *, Elf_Internal_Sym *, asection *,
      struct elf_link_hash_entry *);
@@ -9476,9 +9805,72 @@ elf_link_output_symstrtab (struct elf_final_link_info *flinfo,
     {
       /* Call _bfd_elf_strtab_offset after _bfd_elf_strtab_finalize
         to get the final offset for st_name.  */
+      char *versioned_name = (char *) name;
+      if (h != NULL)
+       {
+         if (h->versioned == versioned && h->def_dynamic)
+           {
+             /* Keep only one '@' for versioned symbols defined in
+                shared objects.  */
+             char *version = strrchr (name, ELF_VER_CHR);
+             char *base_end = strchr (name, ELF_VER_CHR);
+             if (version != base_end)
+               {
+                 size_t base_len;
+                 size_t len = strlen (name);
+                 versioned_name = bfd_alloc (flinfo->output_bfd, len);
+                 if (versioned_name == NULL)
+                   return 0;
+                 base_len = base_end - name;
+                 memcpy (versioned_name, name, base_len);
+                 memcpy (versioned_name + base_len, version,
+                         len - base_len);
+               }
+           }
+       }
+      else if (flinfo->info->unique_symbol
+              && ELF_ST_BIND (elfsym->st_info) == STB_LOCAL)
+       {
+         struct local_hash_entry *lh;
+         switch (ELF_ST_TYPE (elfsym->st_info))
+           {
+           case STT_FILE:
+           case STT_SECTION:
+             break;
+           default:
+             lh = (struct local_hash_entry *) bfd_hash_lookup
+                    (&flinfo->local_hash_table, name, true, false);
+             if (lh == NULL)
+               return 0;
+             if (lh->count)
+               {
+                 /* Append ".COUNT" to duplicated local symbols.  */
+                 size_t count_len;
+                 size_t base_len = lh->size;
+                 char buf[30];
+                 sprintf (buf, "%lx", lh->count);
+                 if (!base_len)
+                   {
+                     base_len = strlen (name);
+                     lh->size = base_len;
+                   }
+                 count_len = strlen (buf);
+                 versioned_name = bfd_alloc (flinfo->output_bfd,
+                                             base_len + count_len + 2);
+                 if (versioned_name == NULL)
+                   return 0;
+                 memcpy (versioned_name, name, base_len);
+                 versioned_name[base_len] = '.';
+                 memcpy (versioned_name + base_len + 1, buf,
+                         count_len + 1);
+               }
+             lh->count++;
+             break;
+           }
+       }
       elfsym->st_name
        = (unsigned long) _bfd_elf_strtab_add (flinfo->symstrtab,
-                                              name, FALSE);
+                                              versioned_name, false);
       if (elfsym->st_name == (unsigned long) -1)
        return 0;
     }
@@ -9511,20 +9903,20 @@ elf_link_output_symstrtab (struct elf_final_link_info *flinfo,
 /* Swap symbols out to the symbol table and flush the output symbols to
    the file.  */
 
-static bfd_boolean
+static bool
 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;
   Elf_Internal_Shdr *hdr;
   file_ptr pos;
-  bfd_boolean ret;
+  bool ret;
 
   if (!hash_table->strtabcount)
-    return TRUE;
+    return true;
 
   BFD_ASSERT (elf_onesymtab (flinfo->output_bfd));
 
@@ -9533,7 +9925,7 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo)
   amt = bed->s->sizeof_sym * hash_table->strtabcount;
   symbuf = (bfd_byte *) bfd_malloc (amt);
   if (symbuf == NULL)
-    return FALSE;
+    return false;
 
   if (flinfo->symshndxbuf)
     {
@@ -9543,10 +9935,11 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo)
       if (flinfo->symshndxbuf == NULL)
        {
          free (symbuf);
-         return FALSE;
+         return false;
        }
     }
 
+  /* Now swap out the symbols.  */
   for (i = 0; i < hash_table->strtabcount; i++)
     {
       struct elf_sym_strtab *elfsym = &hash_table->strtab[i];
@@ -9556,6 +9949,13 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo)
        elfsym->sym.st_name
          = (unsigned long) _bfd_elf_strtab_offset (flinfo->symstrtab,
                                                    elfsym->sym.st_name);
+
+      /* Inform the linker of the addition of this symbol.  */
+
+      if (flinfo->info->callbacks->ctf_new_symbol)
+       flinfo->info->callbacks->ctf_new_symbol (elfsym->dest_index,
+                                                &elfsym->sym);
+
       bed->s->swap_symbol_out (flinfo->output_bfd, &elfsym->sym,
                               ((bfd_byte *) symbuf
                                + (elfsym->dest_index
@@ -9564,14 +9964,6 @@ 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;
@@ -9579,10 +9971,10 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo)
       && bfd_bwrite (symbuf, amt, flinfo->output_bfd) == amt)
     {
       hdr->sh_size += amt;
-      ret = TRUE;
+      ret = true;
     }
   else
-    ret = FALSE;
+    ret = false;
 
   free (symbuf);
 
@@ -9594,7 +9986,7 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo)
 
 /* Return TRUE if the dynamic symbol SYM in ABFD is supported.  */
 
-static bfd_boolean
+static bool
 check_dynsym (bfd *abfd, Elf_Internal_Sym *sym)
 {
   if (sym->st_shndx >= (SHN_LORESERVE & 0xffff)
@@ -9607,9 +9999,9 @@ check_dynsym (bfd *abfd, Elf_Internal_Sym *sym)
        (_("%pB: too many sections: %d (>= %d)"),
         abfd, bfd_count_sections (abfd), SHN_LORESERVE & 0xffff);
       bfd_set_error (bfd_error_nonrepresentable_section);
-      return FALSE;
+      return false;
     }
-  return TRUE;
+  return true;
 }
 
 /* For DSOs loaded in via a DT_NEEDED entry, emulate ld.so in
@@ -9618,7 +10010,7 @@ check_dynsym (bfd *abfd, Elf_Internal_Sym *sym)
    We also handle the case that a DSO references a hidden symbol
    which may be satisfied by a versioned symbol in another DSO.  */
 
-static bfd_boolean
+static bool
 elf_link_check_versioned_symbol (struct bfd_link_info *info,
                                 const struct elf_backend_data *bed,
                                 struct elf_link_hash_entry *h)
@@ -9627,7 +10019,7 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
   struct elf_link_loaded_list *loaded;
 
   if (!is_elf_hash_table (info->hash))
-    return FALSE;
+    return false;
 
   /* Check indirect symbol.  */
   while (h->root.type == bfd_link_hash_indirect)
@@ -9645,7 +10037,7 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
       if (abfd == NULL
          || (abfd->flags & DYNAMIC) == 0
          || (elf_dyn_lib_class (abfd) & DYN_DT_NEEDED) == 0)
-       return FALSE;
+       return false;
       break;
 
     case bfd_link_hash_defined:
@@ -9659,7 +10051,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)
     {
@@ -9679,7 +10071,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;
 
@@ -9703,22 +10094,17 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
       isymbuf = bfd_elf_get_elf_syms (input, hdr, extsymcount, extsymoff,
                                      NULL, NULL, NULL);
       if (isymbuf == NULL)
-       return FALSE;
+       return false;
 
       /* 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;
+         return false;
        }
 
       ever = extversym + extsymoff;
@@ -9758,7 +10144,7 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
              /* This is the base or first version.  We can use it.  */
              free (extversym);
              free (isymbuf);
-             return TRUE;
+             return true;
            }
        }
 
@@ -9766,7 +10152,7 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
       free (isymbuf);
     }
 
-  return FALSE;
+  return false;
 }
 
 /* Convert ELF common symbol TYPE.  */
@@ -9798,13 +10184,13 @@ elf_link_convert_common_type (struct bfd_link_info *info, int type)
    script.  The second time we output the symbols that are still
    global symbols.  */
 
-static bfd_boolean
+static bool
 elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
 {
   struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) bh;
   struct elf_outext_info *eoinfo = (struct elf_outext_info *) data;
   struct elf_final_link_info *flinfo = eoinfo->flinfo;
-  bfd_boolean strip;
+  bool strip;
   Elf_Internal_Sym sym;
   asection *input_sec;
   const struct elf_backend_data *bed;
@@ -9816,19 +10202,19 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
     {
       h = (struct elf_link_hash_entry *) h->root.u.i.link;
       if (h->root.type == bfd_link_hash_new)
-       return TRUE;
+       return true;
     }
 
   /* Decide whether to output this symbol in this pass.  */
   if (eoinfo->localsyms)
     {
       if (!h->forced_local)
-       return TRUE;
+       return true;
     }
   else
     {
       if (h->forced_local)
-       return TRUE;
+       return true;
     }
 
   bed = get_elf_backend_data (flinfo->output_bfd);
@@ -9840,7 +10226,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
         references in regular files have already been handled unless
         they are in unreferenced sections which are removed by garbage
         collection).  */
-      bfd_boolean ignore_undef = FALSE;
+      bool ignore_undef = false;
 
       /* Some symbols may be special in that the fact that they're
         undefined can be safely ignored - let backend determine that.  */
@@ -9853,15 +10239,17 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
          && (!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)
-       return TRUE;
+       return true;
     }
 
   /* We should also warn if a forced local symbol is referenced from
@@ -9897,15 +10285,15 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
       _bfd_error_handler (msg, flinfo->output_bfd,
                          h->root.root.string, def_bfd);
       bfd_set_error (bfd_error_bad_value);
-      eoinfo->failed = TRUE;
-      return FALSE;
+      eoinfo->failed = true;
+      return false;
     }
 
   /* We don't want to output symbols that have never been mentioned by
      a regular file, or that we have been told to strip.  However, if
      h->indx is set to -2, the symbol is used by a reloc and we must
      output it.  */
-  strip = FALSE;
+  strip = false;
   if (h->indx == -2)
     ;
   else if ((h->def_dynamic
@@ -9913,13 +10301,13 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
            || h->root.type == bfd_link_hash_new)
           && !h->def_regular
           && !h->ref_regular)
-    strip = TRUE;
+    strip = true;
   else if (flinfo->info->strip == strip_all)
-    strip = TRUE;
+    strip = true;
   else if (flinfo->info->strip == strip_some
           && bfd_hash_lookup (flinfo->info->keep_hash,
-                              h->root.root.string, FALSE, FALSE) == NULL)
-    strip = TRUE;
+                              h->root.root.string, false, false) == NULL)
+    strip = true;
   else if ((h->root.type == bfd_link_hash_defined
            || h->root.type == bfd_link_hash_defweak)
           && ((flinfo->info->strip_discarded
@@ -9927,12 +10315,12 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
               || ((h->root.u.def.section->flags & SEC_LINKER_CREATED) == 0
                   && h->root.u.def.section->owner != NULL
                   && (h->root.u.def.section->owner->flags & BFD_PLUGIN) != 0)))
-    strip = TRUE;
+    strip = true;
   else if ((h->root.type == bfd_link_hash_undefined
            || h->root.type == bfd_link_hash_undefweak)
           && h->root.u.undef.abfd != NULL
           && (h->root.u.undef.abfd->flags & BFD_PLUGIN) != 0)
-    strip = TRUE;
+    strip = true;
 
   type = h->type;
 
@@ -9944,7 +10332,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
       && h->dynindx == -1
       && type != STT_GNU_IFUNC
       && !h->forced_local)
-    return TRUE;
+    return true;
 
   sym.st_value = 0;
   sym.st_size = h->size;
@@ -9955,7 +10343,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
     case bfd_link_hash_new:
     case bfd_link_hash_warning:
       abort ();
-      return FALSE;
+      return false;
 
     case bfd_link_hash_undefined:
     case bfd_link_hash_undefweak:
@@ -9979,8 +10367,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
                  (_("%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;
-               return FALSE;
+               eoinfo->failed = true;
+               return false;
              }
 
            /* ELF symbols in relocatable files are section relative,
@@ -10021,7 +10409,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
         foo is used with no version, then we add an indirect symbol
         foo which points to foo@@GNU_1.2.  We ignore these symbols,
         since the indirected symbol is already in the hash table.  */
-      return TRUE;
+      return true;
     }
 
   if (type == STT_COMMON || type == STT_OBJECT)
@@ -10079,8 +10467,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
       if (! ((*bed->elf_backend_finish_dynamic_symbol)
             (flinfo->output_bfd, flinfo->info, h, &sym)))
        {
-         eoinfo->failed = TRUE;
-         return FALSE;
+         eoinfo->failed = true;
+         return false;
        }
     }
 
@@ -10139,8 +10527,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
        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;
-      return FALSE;
+      eoinfo->failed = true;
+      return false;
     }
 
   /* If this symbol should be put in the .dynsym section, then put it
@@ -10170,8 +10558,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
                /* xgettext:c-format */
                (_("%pB: no symbol version section for versioned symbol `%s'"),
                 flinfo->output_bfd, h->root.root.string);
-             eoinfo->failed = TRUE;
-             return FALSE;
+             eoinfo->failed = true;
+             return false;
            }
        }
 
@@ -10180,9 +10568,15 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
              + h->dynindx * bed->s->sizeof_sym);
       if (!check_dynsym (flinfo->output_bfd, &sym))
        {
-         eoinfo->failed = TRUE;
-         return FALSE;
+         eoinfo->failed = true;
+         return false;
        }
+
+      /* Inform the linker of the addition of this symbol.  */
+
+      if (flinfo->info->callbacks->ctf_new_dynsym)
+       flinfo->info->callbacks->ctf_new_dynsym (h->dynindx, &sym);
+
       bed->s->swap_symbol_out (flinfo->output_bfd, &sym, esym, 0);
 
       if (flinfo->hash_sec != NULL)
@@ -10213,12 +10607,12 @@ 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)
                      & (DYN_AS_NEEDED | DYN_DT_NEEDED | DYN_NO_NEEDED)))
-               iversym.vs_vers = 0;
+               iversym.vs_vers = 1;
              else
                iversym.vs_vers = h->verinfo.verdef->vd_exp_refno + 1;
            }
@@ -10251,14 +10645,14 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
           /* PR 22319 Do not strip global undefined symbols marked as being needed.  */
           && (h->mark != 1 || ELF_ST_BIND (sym.st_info) != STB_GLOBAL)
           && !bfd_link_relocatable (flinfo->info))
-    return TRUE;
+    return true;
 
   /* Also strip others that we couldn't earlier due to dynamic symbol
      processing.  */
   if (strip)
-    return TRUE;
+    return true;
   if ((input_sec->flags & SEC_EXCLUDE) != 0)
-    return TRUE;
+    return true;
 
   /* Output a FILE symbol so that following locals are not associated
      with the wrong input file.  We need one for forced local symbols
@@ -10278,9 +10672,9 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
       fsym.st_shndx = SHN_ABS;
       if (!elf_link_output_symstrtab (eoinfo->flinfo, NULL, &fsym,
                                      bfd_und_section_ptr, NULL))
-       return FALSE;
+       return false;
 
-      eoinfo->file_sym_done = TRUE;
+      eoinfo->file_sym_done = true;
     }
 
   indx = bfd_get_symcount (flinfo->output_bfd);
@@ -10288,21 +10682,21 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
                                   input_sec, h);
   if (ret == 0)
     {
-      eoinfo->failed = TRUE;
-      return FALSE;
+      eoinfo->failed = true;
+      return false;
     }
   else if (ret == 1)
     h->indx = indx;
   else if (h->indx == -2)
     abort();
 
-  return TRUE;
+  return true;
 }
 
 /* Return TRUE if special handling is done for relocs in SEC against
    symbols defined in discarded sections.  */
 
-static bfd_boolean
+static bool
 elf_section_ignore_discarded_relocs (asection *sec)
 {
   const struct elf_backend_data *bed;
@@ -10312,7 +10706,7 @@ elf_section_ignore_discarded_relocs (asection *sec)
     case SEC_INFO_TYPE_STABS:
     case SEC_INFO_TYPE_EH_FRAME:
     case SEC_INFO_TYPE_EH_FRAME_ENTRY:
-      return TRUE;
+      return true;
     default:
       break;
     }
@@ -10320,9 +10714,9 @@ elf_section_ignore_discarded_relocs (asection *sec)
   bed = get_elf_backend_data (sec->owner);
   if (bed->elf_backend_ignore_discarded_relocs != NULL
       && (*bed->elf_backend_ignore_discarded_relocs) (sec))
-    return TRUE;
+    return true;
 
-  return FALSE;
+  return false;
 }
 
 /* Return a mask saying how ld should treat relocations in SEC against
@@ -10385,10 +10779,21 @@ _bfd_elf_check_kept_section (asection *sec, struct bfd_link_info *info)
     {
       if ((kept->flags & SEC_GROUP) != 0)
        kept = match_group_member (sec, kept, info);
-      if (kept != NULL
-         && ((sec->rawsize != 0 ? sec->rawsize : sec->size)
-             != (kept->rawsize != 0 ? kept->rawsize : kept->size)))
-       kept = NULL;
+      if (kept != NULL)
+       {
+         if ((sec->rawsize != 0 ? sec->rawsize : sec->size)
+             != (kept->rawsize != 0 ? kept->rawsize : kept->size))
+           kept = NULL;
+         else
+           {
+             /* Get the real kept section.  */
+             asection *next;
+             for (next = kept->kept_section;
+                  next != NULL;
+                  next = next->kept_section)
+               kept = next;
+           }
+       }
       sec->kept_section = kept;
     }
   return kept;
@@ -10399,7 +10804,7 @@ _bfd_elf_check_kept_section (asection *sec, struct bfd_link_info *info)
    This is so that we only have to read the local symbols once, and
    don't have to keep them in memory.  */
 
-static bfd_boolean
+static bool
 elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 {
   int (*relocate_section)
@@ -10420,7 +10825,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
   bfd_size_type address_size;
   bfd_vma r_type_mask;
   int r_sym_shift;
-  bfd_boolean have_file_sym = FALSE;
+  bool have_file_sym = false;
 
   output_bfd = flinfo->output_bfd;
   bed = get_elf_backend_data (output_bfd);
@@ -10430,7 +10835,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
      we don't want the local symbols, and we don't want the section
      contents.  */
   if ((input_bfd->flags & DYNAMIC) != 0)
-    return TRUE;
+    return true;
 
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   if (elf_bad_symtab (input_bfd))
@@ -10444,6 +10849,16 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
       extsymoff = symtab_hdr->sh_info;
     }
 
+  /* Enable GNU OSABI features in the output BFD that are used in the input
+     BFD.  */
+  if (bed->elf_osabi == ELFOSABI_NONE
+      || bed->elf_osabi == ELFOSABI_GNU
+      || bed->elf_osabi == ELFOSABI_FREEBSD)
+    elf_tdata (output_bfd)->has_gnu_osabi
+      |= (elf_tdata (input_bfd)->has_gnu_osabi
+         & (bfd_link_relocatable (flinfo->info)
+            ? -1 : ~elf_gnu_osabi_retain));
+
   /* Read the local symbols.  */
   isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
   if (isymbuf == NULL && locsymcount != 0)
@@ -10453,7 +10868,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                                      flinfo->external_syms,
                                      flinfo->locsym_shndx);
       if (isymbuf == NULL)
-       return FALSE;
+       return false;
     }
 
   /* Find local symbol sections and adjust values of symbols in
@@ -10534,6 +10949,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, bfd_get_filename (isec->owner));
+         continue;
+       }
+
       if (isym->st_shndx != SHN_UNDEF
          && isym->st_shndx < SHN_LORESERVE
          && bfd_section_removed_from_list (output_bfd,
@@ -10544,11 +10971,11 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
       name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link,
                                              isym->st_name);
       if (name == NULL)
-       return FALSE;
+       return false;
 
       /* See if we are discarding symbols with this name.  */
       if ((flinfo->info->strip == strip_some
-          && (bfd_hash_lookup (flinfo->info->keep_hash, name, FALSE, FALSE)
+          && (bfd_hash_lookup (flinfo->info->keep_hash, name, false, false)
               == NULL))
          || (((flinfo->info->discard == discard_sec_merge
                && (isec->flags & SEC_MERGE)
@@ -10563,7 +10990,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
            /* -flto puts a temp file name here.  This means builds
               are not reproducible.  Discard the symbol.  */
            continue;
-         have_file_sym = TRUE;
+         have_file_sym = true;
          flinfo->filesym_count += 1;
        }
       if (!have_file_sym)
@@ -10574,17 +11001,19 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
             files lack such, so that their symbols won't be
             associated with a previous input file.  It's not the
             source file, but the best we can do.  */
-         have_file_sym = TRUE;
+         const char *filename;
+         have_file_sym = true;
          flinfo->filesym_count += 1;
          memset (&osym, 0, sizeof (osym));
          osym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
          osym.st_shndx = SHN_ABS;
-         if (!elf_link_output_symstrtab (flinfo,
-                                         (input_bfd->lto_output ? NULL
-                                          : input_bfd->filename),
-                                         &osym, bfd_abs_section_ptr,
-                                         NULL))
-           return FALSE;
+         if (input_bfd->lto_output)
+           filename = NULL;
+         else
+           filename = lbasename (bfd_get_filename (input_bfd));
+         if (!elf_link_output_symstrtab (flinfo, filename, &osym,
+                                         bfd_abs_section_ptr, NULL))
+           return false;
        }
 
       osym = *isym;
@@ -10593,7 +11022,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
       osym.st_shndx = _bfd_elf_section_from_bfd_section (output_bfd,
                                                         isec->output_section);
       if (osym.st_shndx == SHN_BAD)
-       return FALSE;
+       return false;
 
       /* ELF symbols in relocatable files are section relative, but
         in executable files they are virtual addresses.  Note that
@@ -10620,7 +11049,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
       indx = bfd_get_symcount (output_bfd);
       ret = elf_link_output_symstrtab (flinfo, name, &osym, isec, NULL);
       if (ret == 0)
-       return FALSE;
+       return false;
       else if (ret == 1)
        *pindex = indx;
     }
@@ -10692,12 +11121,12 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                                                          symtab_hdr->sh_link,
                                                          sym.st_name);
                  if (name == NULL)
-                   return FALSE;
+                   return false;
 
                  sym.st_shndx = _bfd_elf_section_from_bfd_section (output_bfd,
                                                                    sec);
                  if (sym.st_shndx == SHN_BAD)
-                   return FALSE;
+                   return false;
 
                  sym.st_value += o->output_offset;
 
@@ -10705,7 +11134,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                  ret = elf_link_output_symstrtab (flinfo, name, &sym, o,
                                                   NULL);
                  if (ret == 0)
-                   return FALSE;
+                   return false;
                  else if (ret == 1)
                    flinfo->indices[symndx] = indx;
                  else
@@ -10746,7 +11175,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
        {
          contents = flinfo->contents;
          if (! bfd_get_full_section_contents (input_bfd, o, &contents))
-           return FALSE;
+           return false;
        }
 
       if ((o->flags & SEC_RELOC) != 0)
@@ -10759,18 +11188,18 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
          /* Get the swapped relocs.  */
          internal_relocs
            = _bfd_elf_link_read_relocs (input_bfd, o, flinfo->external_relocs,
-                                        flinfo->internal_relocs, FALSE);
+                                        flinfo->internal_relocs, false);
          if (internal_relocs == NULL
              && o->reloc_count > 0)
-           return FALSE;
+           return false;
 
          /* We need to reverse-copy input .ctors/.dtors sections if
             they are placed in .init_array/.finit_array for output.  */
          if (o->size > address_size
-             && ((strncmp (o->name, ".ctors", 6) == 0
+             && ((startswith (o->name, ".ctors")
                   && strcmp (o->output_section->name,
                              ".init_array") == 0)
-                 || (strncmp (o->name, ".dtors", 6) == 0
+                 || (startswith (o->name, ".dtors")
                      && strcmp (o->output_section->name,
                                 ".fini_array") == 0))
              && (o->name[6] == 0 || o->name[6] == '.'))
@@ -10784,7 +11213,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                       "multiple of address size"),
                     input_bfd, o);
                  bfd_set_error (bfd_error_bad_value);
-                 return FALSE;
+                 return false;
                }
              o->flags |= SEC_ELF_REVERSE_COPY;
            }
@@ -10829,7 +11258,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                           "that references a non-existent global symbol"),
                         input_bfd, (uint64_t) rel->r_info, o);
                      bfd_set_error (bfd_error_bad_value);
-                     return FALSE;
+                     return false;
                    }
 
                  while (h->root.type == bfd_link_hash_indirect
@@ -10883,7 +11312,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 #ifdef DEBUG
                  printf ("Encountered a complex symbol!");
                  printf (" (input_bfd %s, section %s, reloc %ld\n",
-                         input_bfd->filename, o->name,
+                         bfd_get_filename (input_bfd), o->name,
                          (long) (rel - internal_relocs));
                  printf (" symbol: idx  %8.8lx, name %s\n",
                          r_symndx, sym_name);
@@ -10893,7 +11322,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 #endif
                  if (!eval_symbol (&val, &sym_name, input_bfd, flinfo, dot,
                                    isymbuf, locsymcount, s_type == STT_SRELC))
-                   return FALSE;
+                   return false;
 
                  /* Symbol evaluated OK.  Update to absolute value.  */
                  set_symbol_value (input_bfd, isymbuf, locsymcount,
@@ -10963,7 +11392,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                                     isymbuf,
                                     flinfo->sections);
          if (!ret)
-           return FALSE;
+           return false;
 
          if (ret == 2
              || bfd_link_relocatable (flinfo->info)
@@ -10976,12 +11405,12 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
              struct elf_link_hash_entry **rel_hash_list, **rela_hash_list;
              Elf_Internal_Shdr *input_rel_hdr, *input_rela_hdr;
              unsigned int next_erel;
-             bfd_boolean rela_normal;
+             bool rela_normal;
              struct bfd_elf_section_data *esdi, *esdo;
 
              esdi = elf_section_data (o);
              esdo = elf_section_data (o->output_section);
-             rela_normal = FALSE;
+             rela_normal = false;
 
              /* Adjust the reloc addresses and symbol indices.  */
 
@@ -11092,7 +11521,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                      else if (sec == NULL || sec->owner == NULL)
                        {
                          bfd_set_error (bfd_error_bad_value);
-                         return FALSE;
+                         return false;
                        }
                      else
                        {
@@ -11144,7 +11573,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                            {
                              /* You can't do ld -r -s.  */
                              bfd_set_error (bfd_error_invalid_operation);
-                             return FALSE;
+                             return false;
                            }
 
                          /* This symbol was skipped earlier, but
@@ -11154,14 +11583,14 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                          name = (bfd_elf_string_from_elf_section
                                  (input_bfd, shlink, sym.st_name));
                          if (name == NULL)
-                           return FALSE;
+                           return false;
 
                          osec = sec->output_section;
                          sym.st_shndx =
                            _bfd_elf_section_from_bfd_section (output_bfd,
                                                               osec);
                          if (sym.st_shndx == SHN_BAD)
-                           return FALSE;
+                           return false;
 
                          sym.st_value += sec->output_offset;
                          if (!bfd_link_relocatable (flinfo->info))
@@ -11188,7 +11617,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                                                           &sym, sec,
                                                           NULL);
                          if (ret == 0)
-                           return FALSE;
+                           return false;
                          else if (ret == 1)
                            flinfo->indices[r_symndx] = indx;
                          else
@@ -11210,7 +11639,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                                                     input_rel_hdr,
                                                     internal_relocs,
                                                     rel_hash_list))
-                   return FALSE;
+                   return false;
                  internal_relocs += (NUM_SHDR_ENTRIES (input_rel_hdr)
                                      * bed->s->int_rels_per_ext_rel);
                  rel_hash_list += NUM_SHDR_ENTRIES (input_rel_hdr);
@@ -11223,7 +11652,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                                                     input_rela_hdr,
                                                     internal_relocs,
                                                     rela_hash_list))
-                   return FALSE;
+                   return false;
                }
            }
        }
@@ -11242,18 +11671,18 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                 (output_bfd,
                  &elf_hash_table (flinfo->info)->stab_info,
                  o, &elf_section_data (o)->sec_info, contents)))
-           return FALSE;
+           return false;
          break;
        case SEC_INFO_TYPE_MERGE:
          if (! _bfd_write_merged_section (output_bfd, o,
                                           elf_section_data (o)->sec_info))
-           return FALSE;
+           return false;
          break;
        case SEC_INFO_TYPE_EH_FRAME:
          {
            if (! _bfd_elf_write_section_eh_frame (output_bfd, flinfo->info,
                                                   o, contents))
-             return FALSE;
+             return false;
          }
          break;
        case SEC_INFO_TYPE_EH_FRAME_ENTRY:
@@ -11261,7 +11690,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
            if (! _bfd_elf_write_section_eh_frame_entry (output_bfd,
                                                         flinfo->info,
                                                         o, contents))
-             return FALSE;
+             return false;
          }
          break;
        default:
@@ -11271,7 +11700,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))
                  {
@@ -11284,7 +11713,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                                                        contents + todo,
                                                        offset,
                                                        address_size))
-                         return FALSE;
+                         return false;
                        if (todo == 0)
                          break;
                        offset += address_size;
@@ -11295,14 +11724,14 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                                                     o->output_section,
                                                     contents,
                                                     offset, todo))
-                 return FALSE;
+                 return false;
              }
          }
          break;
        }
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Generate a reloc when linking an ELF file.  This is a reloc
@@ -11310,7 +11739,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
    is used to build constructor and destructor tables when linking
    with -Ur.  */
 
-static bfd_boolean
+static bool
 elf_reloc_link_order (bfd *output_bfd,
                      struct bfd_link_info *info,
                      asection *output_section,
@@ -11333,7 +11762,7 @@ elf_reloc_link_order (bfd *output_bfd,
   if (howto == NULL)
     {
       bfd_set_error (bfd_error_bad_value);
-      return FALSE;
+      return false;
     }
 
   addend = link_order->u.reloc.p->addend;
@@ -11365,7 +11794,7 @@ elf_reloc_link_order (bfd *output_bfd,
       h = ((struct elf_link_hash_entry *)
           bfd_wrapped_link_hash_lookup (output_bfd, info,
                                         link_order->u.reloc.p->u.name,
-                                        FALSE, FALSE, TRUE));
+                                        false, false, true));
       if (h != NULL
          && (h->root.type == bfd_link_hash_defined
              || h->root.type == bfd_link_hash_defweak))
@@ -11403,13 +11832,14 @@ elf_reloc_link_order (bfd *output_bfd,
       bfd_size_type size;
       bfd_reloc_status_type rstat;
       bfd_byte *buf;
-      bfd_boolean ok;
+      bool ok;
       const char *sym_name;
+      bfd_size_type octets;
 
       size = (bfd_size_type) bfd_get_reloc_size (howto);
       buf = (bfd_byte *) bfd_zmalloc (size);
       if (buf == NULL && size != 0)
-       return FALSE;
+       return false;
       rstat = _bfd_relocate_contents (howto, output_bfd, addend, buf);
       switch (rstat)
        {
@@ -11431,13 +11861,13 @@ 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;
+       return false;
     }
 
   /* The address of a reloc is relative to the section in a
@@ -11474,149 +11904,16 @@ elf_reloc_link_order (bfd *output_bfd,
 
   ++reldata->count;
 
-  return TRUE;
-}
-
-
-/* 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)
-{
-  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;
-
-  /* If they are both zero size then they almost certainly have the same
-     VMA and thus are not ordered with respect to each other.  Test VMA
-     anyway, and fall back to id to make the result reproducible across
-     qsort implementations.  */
-  apos = asec->output_section->vma + asec->output_offset;
-  bpos = bsec->output_section->vma + bsec->output_offset;
-  if (apos < bpos)
-    return -1;
-  if (apos > bpos)
-    return 1;
-
-  return asec->id - bsec->id;
-}
-
-
-/* Looks for sections with SHF_LINK_ORDER set.  Rearranges them into the same
-   order as their linked sections.  Returns false if this could not be done
-   because an output section includes both ordered and unordered
-   sections.  Ideally we'd do this in the linker proper.  */
-
-static bfd_boolean
-elf_fixup_link_order (bfd *abfd, asection *o)
-{
-  size_t seen_linkorder;
-  size_t seen_other;
-  size_t n;
-  struct bfd_link_order *p;
-  bfd *sub;
-  struct bfd_link_order **sections;
-  asection *s, *other_sec, *linkorder_sec;
-  bfd_vma offset;
-
-  other_sec = NULL;
-  linkorder_sec = NULL;
-  seen_other = 0;
-  seen_linkorder = 0;
-  for (p = o->map_head.link_order; p != NULL; p = p->next)
-    {
-      if (p->type == bfd_indirect_link_order)
-       {
-         s = p->u.indirect.section;
-         sub = s->owner;
-         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;
-           }
-         else
-           {
-             seen_other++;
-             other_sec = s;
-           }
-       }
-      else
-       seen_other++;
-
-      if (seen_other && seen_linkorder)
-       {
-         if (other_sec && linkorder_sec)
-           _bfd_error_handler
-             /* xgettext:c-format */
-             (_("%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
-             (_("%pA has both ordered and unordered sections"), o);
-         bfd_set_error (bfd_error_bad_value);
-         return FALSE;
-       }
-    }
-
-  if (!seen_linkorder)
-    return TRUE;
-
-  sections = bfd_malloc (seen_linkorder * sizeof (*sections));
-  if (sections == NULL)
-    return FALSE;
-
-  seen_linkorder = 0;
-  for (p = o->map_head.link_order; p != NULL; p = p->next)
-    sections[seen_linkorder++] = p;
-
-  /* Sort the input sections in the order of their linked section.  */
-  qsort (sections, seen_linkorder, sizeof (*sections), compare_link_order);
-
-  /* Change the offsets of the sections.  */
-  offset = 0;
-  for (n = 0; n < seen_linkorder; n++)
-    {
-      bfd_vma mask;
-      s = sections[n]->u.indirect.section;
-      mask = ~(bfd_vma) 0 << s->alignment_power;
-      offset = (offset + ~mask) & mask;
-      s->output_offset = offset / bfd_octets_per_byte (abfd);
-      sections[n]->offset = offset;
-      offset += sections[n]->size;
-    }
-
-  free (sections);
-  return TRUE;
+  return true;
 }
 
 /* Generate an import library in INFO->implib_bfd from symbols in ABFD.
    Returns TRUE upon success, FALSE otherwise.  */
 
-static bfd_boolean
+static bool
 elf_output_implib (bfd *abfd, struct bfd_link_info *info)
 {
-  bfd_boolean ret = FALSE;
+  bool ret = false;
   bfd *implib_bfd;
   const struct elf_backend_data *bed;
   flagword flags;
@@ -11627,19 +11924,20 @@ 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);
 
   if (!bfd_set_format (implib_bfd, bfd_object))
-    return FALSE;
+    return false;
 
   /* Use flag from executable but make it a relocatable object.  */
   flags = bfd_get_file_flags (abfd);
   flags &= ~HAS_RELOC;
   if (!bfd_set_start_address (implib_bfd, 0)
       || !bfd_set_file_flags (implib_bfd, flags & ~EXEC_P))
-    return FALSE;
+    return false;
 
   /* Copy architecture of output file to import library file.  */
   arch = bfd_get_arch (abfd);
@@ -11647,17 +11945,17 @@ elf_output_implib (bfd *abfd, struct bfd_link_info *info)
   if (!bfd_set_arch_mach (implib_bfd, arch, mach)
       && (abfd->target_defaulted
          || bfd_get_arch (abfd) != bfd_get_arch (implib_bfd)))
-    return FALSE;
+    return false;
 
   /* Get symbol table size.  */
   symsize = bfd_get_symtab_upper_bound (abfd);
   if (symsize < 0)
-    return FALSE;
+    return false;
 
   /* Read in the symbol table.  */
   sympp = (asymbol **) bfd_malloc (symsize);
   if (sympp == NULL)
-    return FALSE;
+    return false;
 
   symcount = bfd_canonicalize_symtab (abfd, sympp);
   if (symcount < 0)
@@ -11684,8 +11982,8 @@ 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;
 
@@ -11712,9 +12010,9 @@ elf_output_implib (bfd *abfd, struct bfd_link_info *info)
   if (!bfd_close (implib_bfd))
     goto free_sym_buf;
 
-  ret = TRUE;
+  ret = true;
 
-free_sym_buf:
+ free_sym_buf:
   free (sympp);
   return ret;
 }
@@ -11726,42 +12024,31 @@ elf_final_link_free (bfd *obfd, struct elf_final_link_info *flinfo)
 
   if (flinfo->symstrtab != NULL)
     _bfd_elf_strtab_free (flinfo->symstrtab);
-  if (flinfo->contents != NULL)
-    free (flinfo->contents);
-  if (flinfo->external_relocs != NULL)
-    free (flinfo->external_relocs);
-  if (flinfo->internal_relocs != NULL)
-    free (flinfo->internal_relocs);
-  if (flinfo->external_syms != NULL)
-    free (flinfo->external_syms);
-  if (flinfo->locsym_shndx != NULL)
-    free (flinfo->locsym_shndx);
-  if (flinfo->internal_syms != NULL)
-    free (flinfo->internal_syms);
-  if (flinfo->indices != NULL)
-    free (flinfo->indices);
-  if (flinfo->sections != NULL)
-    free (flinfo->sections);
-  if (flinfo->symshndxbuf != NULL
-      && flinfo->symshndxbuf != (Elf_External_Sym_Shndx *) -1)
+  free (flinfo->contents);
+  free (flinfo->external_relocs);
+  free (flinfo->internal_relocs);
+  free (flinfo->external_syms);
+  free (flinfo->locsym_shndx);
+  free (flinfo->internal_syms);
+  free (flinfo->indices);
+  free (flinfo->sections);
+  if (flinfo->symshndxbuf != (Elf_External_Sym_Shndx *) -1)
     free (flinfo->symshndxbuf);
   for (o = obfd->sections; o != NULL; o = o->next)
     {
       struct bfd_elf_section_data *esdo = elf_section_data (o);
-      if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL)
-       free (esdo->rel.hashes);
-      if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL)
-       free (esdo->rela.hashes);
+      free (esdo->rel.hashes);
+      free (esdo->rela.hashes);
     }
 }
 
 /* Do the final step of an ELF link.  */
 
-bfd_boolean
+bool
 bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 {
-  bfd_boolean dynamic;
-  bfd_boolean emit_relocs;
+  bool dynamic;
+  bool emit_relocs;
   bfd *dynobj;
   struct elf_final_link_info flinfo;
   asection *o;
@@ -11778,7 +12065,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   Elf_Internal_Shdr *symtab_shndx_hdr;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   struct elf_outext_info eoinfo;
-  bfd_boolean merged;
+  bool merged;
   size_t relativecount = 0;
   asection *reldyn = 0;
   bfd_size_type amt;
@@ -11786,9 +12073,11 @@ 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);
+  bool sections_removed;
+  bool ret;
 
   if (!is_elf_hash_table (htab))
-    return FALSE;
+    return false;
 
   if (bfd_link_pic (info))
     abfd->flags |= DYNAMIC;
@@ -11799,11 +12088,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   emit_relocs = (bfd_link_relocatable (info)
                 || info->emitrelocations);
 
+  memset (&flinfo, 0, sizeof (flinfo));
   flinfo.info = info;
   flinfo.output_bfd = abfd;
   flinfo.symstrtab = _bfd_elf_strtab_init ();
   if (flinfo.symstrtab == NULL)
-    return FALSE;
+    return false;
 
   if (! dynamic)
     {
@@ -11818,24 +12108,20 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       /* Note that it is OK if symver_sec is NULL.  */
     }
 
-  flinfo.contents = NULL;
-  flinfo.external_relocs = NULL;
-  flinfo.internal_relocs = NULL;
-  flinfo.external_syms = NULL;
-  flinfo.locsym_shndx = NULL;
-  flinfo.internal_syms = NULL;
-  flinfo.indices = NULL;
-  flinfo.sections = NULL;
-  flinfo.symshndxbuf = NULL;
-  flinfo.filesym_count = 0;
+  if (info->unique_symbol
+      && !bfd_hash_table_init (&flinfo.local_hash_table,
+                              local_hash_newfunc,
+                              sizeof (struct local_hash_entry)))
+    return false;
 
   /* The object attributes have been merged.  Remove the input
      sections from the link, and set the contents of the output
      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;
+      bool remove_section = false;
 
       if ((std_attrs_section && strcmp (o->name, std_attrs_section) == 0)
          || strcmp (o->name, ".gnu.attributes") == 0)
@@ -11859,20 +12145,23 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
          if (attr_size)
            attr_section = o;
          else
-           remove_section = TRUE;
+           remove_section = true;
        }
       else if ((o->flags & SEC_GROUP) != 0 && o->size == 0)
        {
          /* Remove empty group section from linker output.  */
-         remove_section = TRUE;
+         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
@@ -11882,7 +12171,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   max_internal_reloc_count = 0;
   max_sym_count = 0;
   max_sym_shndx_count = 0;
-  merged = FALSE;
+  merged = false;
   for (o = abfd->sections; o != NULL; o = o->next)
     {
       struct bfd_elf_section_data *esdo = elf_section_data (o);
@@ -11907,10 +12196,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                 link.  This will normally be every section.  We need
                 to do this so that we can identify any sections which
                 the linker has decided to not include.  */
-             sec->linker_mark = TRUE;
+             sec->linker_mark = true;
 
              if (sec->flags & SEC_MERGE)
-               merged = TRUE;
+               merged = true;
 
              if (sec->rawsize > max_contents_size)
                max_contents_size = sec->rawsize;
@@ -12105,7 +12394,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
     {
       file_ptr off = elf_next_file_pos (abfd);
 
-      _bfd_elf_assign_file_position_for_section (symtab_hdr, off, TRUE);
+      _bfd_elf_assign_file_position_for_section (symtab_hdr, off, true);
 
       /* Note that at this point elf_next_file_pos (abfd) is
         incorrect.  We do not yet know the size of the .symtab section.
@@ -12123,33 +12412,49 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                                     bfd_und_section_ptr, NULL) != 1)
        goto error_return;
 
-      /* Output a symbol for each section.  We output these even if we are
-        discarding local symbols, since they are used for relocs.  These
-        symbols have no names.  We store the index of each one in the
-        index field of the section, so that we can find it again when
-        outputting relocs.  */
+      /* Output a symbol for each section if asked or they are used for
+        relocs.  These symbols usually have no names.  We store the
+        index of each one in the index field of the section, so that
+        we can find it again when outputting relocs.  */
 
-      elfsym.st_size = 0;
-      elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
-      elfsym.st_other = 0;
-      elfsym.st_value = 0;
-      elfsym.st_target_internal = 0;
-      for (i = 1; i < elf_numsections (abfd); i++)
+      if (bfd_keep_unused_section_symbols (abfd) || emit_relocs)
        {
-         o = bfd_section_from_elf_index (abfd, i);
-         if (o != NULL)
+         bool name_local_sections
+           = (bed->elf_backend_name_local_section_symbols
+              && bed->elf_backend_name_local_section_symbols (abfd));
+         const char *name = NULL;
+
+         elfsym.st_size = 0;
+         elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
+         elfsym.st_other = 0;
+         elfsym.st_value = 0;
+         elfsym.st_target_internal = 0;
+         for (i = 1; i < elf_numsections (abfd); i++)
            {
-             o->target_index = bfd_get_symcount (abfd);
-             elfsym.st_shndx = i;
-             if (!bfd_link_relocatable (info))
-               elfsym.st_value = o->vma;
-             if (elf_link_output_symstrtab (&flinfo, NULL, &elfsym, o,
-                                            NULL) != 1)
-               goto error_return;
+             o = bfd_section_from_elf_index (abfd, i);
+             if (o != NULL)
+               {
+                 o->target_index = bfd_get_symcount (abfd);
+                 elfsym.st_shndx = i;
+                 if (!bfd_link_relocatable (info))
+                   elfsym.st_value = o->vma;
+                 if (name_local_sections)
+                   name = o->name;
+                 if (elf_link_output_symstrtab (&flinfo, name, &elfsym, o,
+                                                NULL) != 1)
+                   goto error_return;
+               }
            }
        }
     }
 
+  /* On some targets like Irix 5 the symbol split between local and global
+     ones recorded in the sh_info field needs to be done between section
+     and all other symbols.  */
+  if (bed->elf_backend_elfsym_local_is_section
+      && bed->elf_backend_elfsym_local_is_section (abfd))
+    symtab_hdr->sh_info = bfd_get_symcount (abfd);
+
   /* Allocate some memory to hold information read in from the input
      files.  */
   if (max_contents_size != 0)
@@ -12207,7 +12512,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;
@@ -12215,6 +12520,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)
@@ -12222,9 +12528,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
@@ -12234,15 +12540,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       htab->tls_size = end - base;
     }
 
-  /* Reorder SHF_LINK_ORDER sections.  */
-  for (o = abfd->sections; o != NULL; o = o->next)
-    {
-      if (!elf_fixup_link_order (abfd, o))
-       return FALSE;
-    }
-
   if (!_bfd_elf_fixup_eh_frame_hdr (info))
-    return FALSE;
+    return false;
 
   /* Since ELF permits relocations to be against local symbols, we
      must have the local symbols available when we do the relocations.
@@ -12265,7 +12564,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
      know how bad the memory loss will be.  */
 
   for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
-    sub->output_has_begun = FALSE;
+    sub->output_has_begun = false;
   for (o = abfd->sections; o != NULL; o = o->next)
     {
       for (p = o->map_head.link_order; p != NULL; p = p->next)
@@ -12279,7 +12578,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                {
                  if (! elf_link_input_bfd (&flinfo, sub))
                    goto error_return;
-                 sub->output_has_begun = TRUE;
+                 sub->output_has_begun = true;
                }
            }
          else if (p->type == bfd_section_reloc_link_order
@@ -12333,41 +12632,43 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   if (!info->reduce_memory_overheads)
     {
       for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
-       if (bfd_get_flavour (sub) == bfd_target_elf_flavour
-           && elf_tdata (sub)->symbuf)
+       if (bfd_get_flavour (sub) == bfd_target_elf_flavour)
          {
            free (elf_tdata (sub)->symbuf);
            elf_tdata (sub)->symbuf = NULL;
          }
     }
 
+  ret = true;
+
   /* Output any global symbols that got converted to local in a
      version script or due to symbol visibility.  We do this in a
      separate step since ELF requires all local symbols to appear
      prior to any global symbols.  FIXME: We should only do this if
      some global symbols were, in fact, converted to become local.
      FIXME: Will this work correctly with the Irix 5 linker?  */
-  eoinfo.failed = FALSE;
+  eoinfo.failed = false;
   eoinfo.flinfo = &flinfo;
-  eoinfo.localsyms = TRUE;
-  eoinfo.file_sym_done = FALSE;
+  eoinfo.localsyms = true;
+  eoinfo.file_sym_done = false;
   bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo);
   if (eoinfo.failed)
-    return FALSE;
+    {
+      ret = false;
+      goto return_local_hash_table;
+    }
 
   /* If backend needs to output some local symbols not present in the hash
      table, do it now.  */
   if (bed->elf_backend_output_arch_local_syms
       && (info->strip != strip_all || emit_relocs))
     {
-      typedef int (*out_sym_func)
-       (void *, const char *, Elf_Internal_Sym *, asection *,
-        struct elf_link_hash_entry *);
-
       if (! ((*bed->elf_backend_output_arch_local_syms)
-            (abfd, info, &flinfo,
-             (out_sym_func) elf_link_output_symstrtab)))
-       return FALSE;
+            (abfd, info, &flinfo, elf_link_output_symstrtab)))
+       {
+         ret = false;
+         goto return_local_hash_table;
+       }
     }
 
   /* That wrote out all the local symbols.  Finish up the symbol table
@@ -12376,7 +12677,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
      converted to local in a version script.  */
 
   /* The sh_info field records the index of the first non local symbol.  */
-  symtab_hdr->sh_info = bfd_get_symcount (abfd);
+  if (!symtab_hdr->sh_info)
+    symtab_hdr->sh_info = bfd_get_symcount (abfd);
 
   if (dynamic
       && htab->dynsym != NULL
@@ -12413,9 +12715,18 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
              BFD_ASSERT (indx > 0);
              sym.st_shndx = indx;
              if (! check_dynsym (abfd, &sym))
-               return FALSE;
+               {
+                 ret = false;
+                 goto return_local_hash_table;
+               }
              sym.st_value = s->vma;
              dest = dynsym + dynindx * bed->s->sizeof_sym;
+
+             /* Inform the linker of the addition of this symbol.  */
+
+             if (info->callbacks->ctf_new_dynsym)
+               info->callbacks->ctf_new_dynsym (dynindx, &sym);
+
              bed->s->swap_symbol_out (abfd, &sym, dest, 0);
            }
        }
@@ -12434,20 +12745,31 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                 the original st_name with the dynstr_index.  */
              sym = e->isym;
              sym.st_other &= ~ELF_ST_VISIBILITY (-1);
+             sym.st_shndx = SHN_UNDEF;
 
              s = bfd_section_from_elf_index (e->input_bfd,
                                              e->isym.st_shndx);
-             if (s != NULL)
+             if (s != NULL
+                 && s->output_section != NULL
+                 && elf_section_data (s->output_section) != NULL)
                {
                  sym.st_shndx =
                    elf_section_data (s->output_section)->this_idx;
                  if (! check_dynsym (abfd, &sym))
-                   return FALSE;
+                   {
+                     ret = false;
+                     goto return_local_hash_table;
+                   }
                  sym.st_value = (s->output_section->vma
                                  + s->output_offset
                                  + e->isym.st_value);
                }
 
+             /* Inform the linker of the addition of this symbol.  */
+
+             if (info->callbacks->ctf_new_dynsym)
+               info->callbacks->ctf_new_dynsym (e->dynindx, &sym);
+
              dest = dynsym + e->dynindx * bed->s->sizeof_sym;
              bed->s->swap_symbol_out (abfd, &sym, dest, 0);
            }
@@ -12455,26 +12777,27 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
     }
 
   /* We get the global symbols from the hash table.  */
-  eoinfo.failed = FALSE;
-  eoinfo.localsyms = FALSE;
+  eoinfo.failed = false;
+  eoinfo.localsyms = false;
   eoinfo.flinfo = &flinfo;
   bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo);
   if (eoinfo.failed)
-    return FALSE;
+    {
+      ret = false;
+      goto return_local_hash_table;
+    }
 
   /* If backend needs to output some symbols not present in the hash
      table, do it now.  */
   if (bed->elf_backend_output_arch_syms
       && (info->strip != strip_all || emit_relocs))
     {
-      typedef int (*out_sym_func)
-       (void *, const char *, Elf_Internal_Sym *, asection *,
-        struct elf_link_hash_entry *);
-
       if (! ((*bed->elf_backend_output_arch_syms)
-            (abfd, info, &flinfo,
-             (out_sym_func) elf_link_output_symstrtab)))
-       return FALSE;
+            (abfd, info, &flinfo, elf_link_output_symstrtab)))
+       {
+         ret = false;
+         goto return_local_hash_table;
+       }
     }
 
   /* Finalize the .strtab section.  */
@@ -12482,7 +12805,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
   /* Swap out the .strtab section. */
   if (!elf_link_swap_symbols_out (&flinfo))
-    return FALSE;
+    {
+      ret = false;
+      goto return_local_hash_table;
+    }
 
   /* Now we know the size of the symtab section.  */
   if (bfd_get_symcount (abfd) > 0)
@@ -12505,11 +12831,14 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
              symtab_shndx_hdr->sh_size = amt;
 
              off = _bfd_elf_assign_file_position_for_section (symtab_shndx_hdr,
-                                                              off, TRUE);
+                                                              off, true);
 
              if (bfd_seek (abfd, symtab_shndx_hdr->sh_offset, SEEK_SET) != 0
                  || (bfd_bwrite (flinfo.symshndxbuf, amt, abfd) != amt))
-               return FALSE;
+               {
+                 ret = false;
+                 goto return_local_hash_table;
+               }
            }
        }
 
@@ -12526,26 +12855,30 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       symstrtab_hdr->sh_addralign = 1;
 
       off = _bfd_elf_assign_file_position_for_section (symstrtab_hdr,
-                                                      off, TRUE);
+                                                      off, true);
       elf_next_file_pos (abfd) = off;
 
       if (bfd_seek (abfd, symstrtab_hdr->sh_offset, SEEK_SET) != 0
          || ! _bfd_elf_strtab_emit (abfd, flinfo.symstrtab))
-       return FALSE;
+       {
+         ret = false;
+         goto return_local_hash_table;
+       }
     }
 
   if (info->out_implib_bfd && !elf_output_implib (abfd, info))
     {
       _bfd_error_handler (_("%pB: failed to generate import library"),
                          info->out_implib_bfd);
-      return FALSE;
+      ret = false;
+      goto return_local_hash_table;
     }
 
   /* Adjust the relocs to have the correct symbol indices.  */
   for (o = abfd->sections; o != NULL; o = o->next)
     {
       struct bfd_elf_section_data *esdo = elf_section_data (o);
-      bfd_boolean sort;
+      bool sort;
 
       if ((o->flags & SEC_RELOC) == 0)
        continue;
@@ -12553,10 +12886,16 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       sort = bed->sort_relocs_p == NULL || (*bed->sort_relocs_p) (o);
       if (esdo->rel.hdr != NULL
          && !elf_link_adjust_relocs (abfd, o, &esdo->rel, sort, info))
-       return FALSE;
+       {
+         ret = false;
+         goto return_local_hash_table;
+       }
       if (esdo->rela.hdr != NULL
          && !elf_link_adjust_relocs (abfd, o, &esdo->rela, sort, info))
-       return FALSE;
+       {
+         ret = false;
+         goto return_local_hash_table;
+       }
 
       /* Set the reloc_count field to 0 to prevent write_relocs from
         trying to swap the relocs out itself.  */
@@ -12616,7 +12955,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
              {
                struct elf_link_hash_entry *h;
 
-               h = elf_link_hash_lookup (htab, name, FALSE, FALSE, TRUE);
+               h = elf_link_hash_lookup (htab, name, false, false, true);
                if (h != NULL
                    && (h->root.type == bfd_link_hash_defined
                        || h->root.type == bfd_link_hash_defweak))
@@ -12737,6 +13076,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;
@@ -12756,7 +13097,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;
                }
 
@@ -12777,8 +13118,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
        goto error_return;
 
       /* Check for DT_TEXTREL (late, in case the backend removes it).  */
-      if (((info->warn_shared_textrel && bfd_link_pic (info))
-          || info->error_textrel)
+      if (bfd_link_textrel_check (info)
          && (o = bfd_get_linker_section (dynobj, ".dynamic")) != NULL)
        {
          bfd_byte *dyncon, *dynconend;
@@ -12793,12 +13133,15 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
              if (dyn.d_tag == DT_TEXTREL)
                {
-                 if (info->error_textrel)
+                 if (info->textrel_check == textrel_check_error)
                    info->callbacks->einfo
                      (_("%P%X: read-only segment has dynamic relocations\n"));
+                 else if (bfd_link_dll (info))
+                   info->callbacks->einfo
+                     (_("%P: warning: creating DT_TEXTREL in a shared object\n"));
                  else
                    info->callbacks->einfo
-                     (_("%P: warning: creating a DT_TEXTREL in a shared object\n"));
+                     (_("%P: warning: creating DT_TEXTREL in a PIE\n"));
                  break;
                }
            }
@@ -12822,11 +13165,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
@@ -12845,7 +13187,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
   if (!info->resolve_section_groups)
     {
-      bfd_boolean failed = FALSE;
+      bool failed = false;
 
       BFD_ASSERT (bfd_link_relocatable (info));
       bfd_map_over_sections (abfd, bfd_elf_set_group_contents, &failed);
@@ -12872,22 +13214,30 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
     {
       bfd_byte *contents = (bfd_byte *) bfd_malloc (attr_size);
       if (contents == NULL)
-       return FALSE;   /* Bail out and fail.  */
+       {
+         /* Bail out and fail.  */
+         ret = false;
+         goto return_local_hash_table;
+       }
       bfd_elf_set_obj_attr_contents (abfd, contents, attr_size);
       bfd_set_section_contents (abfd, attr_section, contents, 0, attr_size);
       free (contents);
     }
 
-  return TRUE;
+ return_local_hash_table:
+  if (info->unique_symbol)
+    bfd_hash_table_free (&flinfo.local_hash_table);
+  return ret;
 
  error_return:
   elf_final_link_free (abfd, &flinfo);
-  return FALSE;
+  ret = false;
+  goto return_local_hash_table;
 }
 \f
 /* Initialize COOKIE for input bfd ABFD.  */
 
-static bfd_boolean
+static bool
 init_reloc_cookie (struct elf_reloc_cookie *cookie,
                   struct bfd_link_info *info, bfd *abfd)
 {
@@ -12925,12 +13275,12 @@ init_reloc_cookie (struct elf_reloc_cookie *cookie,
       if (cookie->locsyms == NULL)
        {
          info->callbacks->einfo (_("%P%X: can not read symbols: %E\n"));
-         return FALSE;
+         return false;
        }
       if (info->keep_memory)
        symtab_hdr->contents = (bfd_byte *) cookie->locsyms;
     }
-  return TRUE;
+  return true;
 }
 
 /* Free the memory allocated by init_reloc_cookie, if appropriate.  */
@@ -12941,15 +13291,14 @@ fini_reloc_cookie (struct elf_reloc_cookie *cookie, bfd *abfd)
   Elf_Internal_Shdr *symtab_hdr;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  if (cookie->locsyms != NULL
-      && symtab_hdr->contents != (unsigned char *) cookie->locsyms)
+  if (symtab_hdr->contents != (unsigned char *) cookie->locsyms)
     free (cookie->locsyms);
 }
 
 /* Initialize the relocation information in COOKIE for input section SEC
    of input bfd ABFD.  */
 
-static bfd_boolean
+static bool
 init_reloc_cookie_rels (struct elf_reloc_cookie *cookie,
                        struct bfd_link_info *info, bfd *abfd,
                        asection *sec)
@@ -12964,12 +13313,12 @@ init_reloc_cookie_rels (struct elf_reloc_cookie *cookie,
       cookie->rels = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
                                                info->keep_memory);
       if (cookie->rels == NULL)
-       return FALSE;
+       return false;
       cookie->rel = cookie->rels;
       cookie->relend = cookie->rels + sec->reloc_count;
     }
   cookie->rel = cookie->rels;
-  return TRUE;
+  return true;
 }
 
 /* Free the memory allocated by init_reloc_cookie_rels,
@@ -12979,13 +13328,13 @@ static void
 fini_reloc_cookie_rels (struct elf_reloc_cookie *cookie,
                        asection *sec)
 {
-  if (cookie->rels && elf_section_data (sec)->relocs != cookie->rels)
+  if (elf_section_data (sec)->relocs != cookie->rels)
     free (cookie->rels);
 }
 
 /* Initialize the whole of COOKIE for input section SEC.  */
 
-static bfd_boolean
+static bool
 init_reloc_cookie_for_section (struct elf_reloc_cookie *cookie,
                               struct bfd_link_info *info,
                               asection *sec)
@@ -12994,12 +13343,12 @@ init_reloc_cookie_for_section (struct elf_reloc_cookie *cookie,
     goto error1;
   if (!init_reloc_cookie_rels (cookie, info, sec->owner, sec))
     goto error2;
-  return TRUE;
+  return true;
 
  error2:
   fini_reloc_cookie (cookie, sec->owner);
  error1:
-  return FALSE;
+  return false;
 }
 
 /* Free the memory allocated by init_reloc_cookie_for_section,
@@ -13082,10 +13431,10 @@ asection *
 _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
                       elf_gc_mark_hook_fn gc_mark_hook,
                       struct elf_reloc_cookie *cookie,
-                      bfd_boolean *start_stop)
+                      bool *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)
@@ -13094,6 +13443,8 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
   if (r_symndx >= cookie->locsymcount
       || ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL)
     {
+      bool was_marked;
+
       h = cookie->sym_hashes[r_symndx - cookie->extsymoff];
       if (h == NULL)
        {
@@ -13104,23 +13455,32 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
       while (h->root.type == bfd_link_hash_indirect
             || h->root.type == bfd_link_hash_warning)
        h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+      was_marked = h->mark;
       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)
+      if (!was_marked && h->start_stop && !h->root.ldscript_def)
        {
+         if (info->start_stop_gc)
+           return NULL;
+
          /* To work around a glibc bug, mark XXX input sections
             when there is a reference to __start_XXX or __stop_XXX
             symbols.  */
-         if (h->start_stop)
+         else if (start_stop != NULL)
            {
              asection *s = h->u2.start_stop_section;
-             *start_stop = !s->gc_mark;
+             *start_stop = true;
              return s;
            }
        }
@@ -13136,14 +13496,14 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
    a section we've decided to keep.  Mark the section that contains
    the relocation symbol.  */
 
-bfd_boolean
+bool
 _bfd_elf_gc_mark_reloc (struct bfd_link_info *info,
                        asection *sec,
                        elf_gc_mark_hook_fn gc_mark_hook,
                        struct elf_reloc_cookie *cookie)
 {
   asection *rsec;
-  bfd_boolean start_stop = FALSE;
+  bool start_stop = false;
 
   rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie, &start_stop);
   while (rsec != NULL)
@@ -13154,25 +13514,25 @@ _bfd_elf_gc_mark_reloc (struct bfd_link_info *info,
              || (rsec->owner->flags & DYNAMIC) != 0)
            rsec->gc_mark = 1;
          else if (!_bfd_elf_gc_mark (info, rsec, gc_mark_hook))
-           return FALSE;
+           return false;
        }
       if (!start_stop)
        break;
       rsec = bfd_get_next_section_by_name (rsec->owner, rsec);
     }
-  return TRUE;
+  return true;
 }
 
 /* The mark phase of garbage collection.  For a given section, mark
    it and any sections in this section's group, and all the sections
    which define symbols to which it refers.  */
 
-bfd_boolean
+bool
 _bfd_elf_gc_mark (struct bfd_link_info *info,
                  asection *sec,
                  elf_gc_mark_hook_fn gc_mark_hook)
 {
-  bfd_boolean ret;
+  bool ret;
   asection *group_sec, *eh_frame;
 
   sec->gc_mark = 1;
@@ -13181,10 +13541,10 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
   group_sec = elf_section_data (sec)->next_in_group;
   if (group_sec && !group_sec->gc_mark)
     if (!_bfd_elf_gc_mark (info, group_sec, gc_mark_hook))
-      return FALSE;
+      return false;
 
   /* Look through the section relocs.  */
-  ret = TRUE;
+  ret = true;
   eh_frame = elf_eh_frame_section (sec->owner);
   if ((sec->flags & SEC_RELOC) != 0
       && sec->reloc_count > 0
@@ -13193,13 +13553,13 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
       struct elf_reloc_cookie cookie;
 
       if (!init_reloc_cookie_for_section (&cookie, info, sec))
-       ret = FALSE;
+       ret = false;
       else
        {
          for (; cookie.rel < cookie.relend; cookie.rel++)
            if (!_bfd_elf_gc_mark_reloc (info, sec, gc_mark_hook, &cookie))
              {
-               ret = FALSE;
+               ret = false;
                break;
              }
          fini_reloc_cookie_for_section (&cookie, sec);
@@ -13211,12 +13571,12 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
       struct elf_reloc_cookie cookie;
 
       if (!init_reloc_cookie_for_section (&cookie, info, eh_frame))
-       ret = FALSE;
+       ret = false;
       else
        {
          if (!_bfd_elf_gc_mark_fdes (info, sec, eh_frame,
                                      gc_mark_hook, &cookie))
-           ret = FALSE;
+           ret = false;
          fini_reloc_cookie_for_section (&cookie, eh_frame);
        }
     }
@@ -13224,7 +13584,7 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
   eh_frame = elf_section_eh_frame_entry (sec);
   if (ret && eh_frame && !eh_frame->gc_mark)
     if (!_bfd_elf_gc_mark (info, eh_frame, gc_mark_hook))
-      ret = FALSE;
+      ret = false;
 
   return ret;
 }
@@ -13239,8 +13599,8 @@ _bfd_elf_gc_mark_debug_special_section_group (asection *grp)
   /* Used to iterate the section group.  */
   asection *msec;
 
-  bfd_boolean is_special_grp = TRUE;
-  bfd_boolean is_debug_grp = TRUE;
+  bool is_special_grp = true;
+  bool is_debug_grp = true;
 
   /* First scan to see if group contains any section other than debug
      and special section.  */
@@ -13248,10 +13608,10 @@ _bfd_elf_gc_mark_debug_special_section_group (asection *grp)
   do
     {
       if ((msec->flags & SEC_DEBUGGING) == 0)
-       is_debug_grp = FALSE;
+       is_debug_grp = false;
 
       if ((msec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) != 0)
-       is_special_grp = FALSE;
+       is_special_grp = false;
 
       msec = elf_next_in_group (msec);
     }
@@ -13272,18 +13632,18 @@ _bfd_elf_gc_mark_debug_special_section_group (asection *grp)
 
 /* Keep debug and special sections.  */
 
-bfd_boolean
+bool
 _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;
 
   for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
     {
       asection *isec;
-      bfd_boolean some_kept;
-      bfd_boolean debug_frag_seen;
-      bfd_boolean has_kept_debug_info;
+      bool some_kept;
+      bool debug_frag_seen;
+      bool has_kept_debug_info;
 
       if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
        continue;
@@ -13294,7 +13654,7 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
       /* Ensure all linker created sections are kept,
         see if any other section is already marked,
         and note if we have any fragmented debug sections.  */
-      debug_frag_seen = some_kept = has_kept_debug_info = FALSE;
+      debug_frag_seen = some_kept = has_kept_debug_info = false;
       for (isec = ibfd->sections; isec != NULL; isec = isec->next)
        {
          if ((isec->flags & SEC_LINKER_CREATED) != 0)
@@ -13302,12 +13662,42 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
          else if (isec->gc_mark
                   && (isec->flags & SEC_ALLOC) != 0
                   && elf_section_type (isec) != SHT_NOTE)
-           some_kept = TRUE;
+           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;
+             for (linked_to_sec = elf_linked_to_section (isec);
+                  linked_to_sec != NULL && !linked_to_sec->linker_mark;
+                  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;
+                   }
+                 linked_to_sec->linker_mark = 1;
+               }
+             for (linked_to_sec = elf_linked_to_section (isec);
+                  linked_to_sec != NULL && linked_to_sec->linker_mark;
+                  linked_to_sec = elf_linked_to_section (linked_to_sec))
+               linked_to_sec->linker_mark = 0;
+           }
 
          if (!debug_frag_seen
              && (isec->flags & SEC_DEBUGGING)
-             && CONST_STRNEQ (isec->name, ".debug_line."))
-           debug_frag_seen = TRUE;
+             && startswith (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
@@ -13317,17 +13707,19 @@ _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;
+           has_kept_debug_info = true;
        }
 
       /* Look for CODE sections which are going to be discarded,
@@ -13371,12 +13763,12 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
              && (isec->flags & SEC_DEBUGGING) != 0)
            if (!_bfd_elf_gc_mark (info, isec,
                                   elf_gc_mark_debug_section))
-             return FALSE;
+             return false;
     }
-  return TRUE;
+  return true;
 }
 
-static bfd_boolean
+static bool
 elf_gc_sweep (bfd *abfd, struct bfd_link_info *info)
 {
   bfd *sub;
@@ -13424,28 +13816,28 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info)
        }
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Propagate collected vtable information.  This is called through
    elf_link_hash_traverse.  */
 
-static bfd_boolean
+static bool
 elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
 {
   /* Those that are not vtables.  */
   if (h->start_stop
       || h->u2.vtable == NULL
       || h->u2.vtable->parent == NULL)
-    return TRUE;
+    return true;
 
   /* Those vtables that do not have parents, we cannot merge.  */
   if (h->u2.vtable->parent == (struct elf_link_hash_entry *) -1)
-    return TRUE;
+    return true;
 
   /* If we've already been done, exit.  */
   if (h->u2.vtable->used && h->u2.vtable->used[-1])
-    return TRUE;
+    return true;
 
   /* Make sure the parent's table is up to date.  */
   elf_gc_propagate_vtable_entries_used (h->u2.vtable->parent, okp);
@@ -13460,11 +13852,11 @@ elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
   else
     {
       size_t n;
-      bfd_boolean *cu, *pu;
+      bool *cu, *pu;
 
       /* Or the parent's entries into ours.  */
       cu = h->u2.vtable->used;
-      cu[-1] = TRUE;
+      cu[-1] = true;
       pu = h->u2.vtable->parent->u2.vtable->used;
       if (pu != NULL)
        {
@@ -13477,17 +13869,17 @@ elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
          while (n--)
            {
              if (*pu)
-               *cu = TRUE;
+               *cu = true;
              pu++;
              cu++;
            }
        }
     }
 
-  return TRUE;
+  return true;
 }
 
-static bfd_boolean
+static bool
 elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
 {
   asection *sec;
@@ -13501,7 +13893,7 @@ elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
   if (h->start_stop
       || h->u2.vtable == NULL
       || h->u2.vtable->parent == NULL)
-    return TRUE;
+    return true;
 
   BFD_ASSERT (h->root.type == bfd_link_hash_defined
              || h->root.type == bfd_link_hash_defweak);
@@ -13510,9 +13902,9 @@ elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
   hstart = h->root.u.def.value;
   hend = hstart + h->size;
 
-  relstart = _bfd_elf_link_read_relocs (sec->owner, sec, NULL, NULL, TRUE);
+  relstart = _bfd_elf_link_read_relocs (sec->owner, sec, NULL, NULL, true);
   if (!relstart)
-    return *(bfd_boolean *) okp = FALSE;
+    return *(bool *) okp = false;
   bed = get_elf_backend_data (sec->owner);
   log_file_align = bed->s->log_file_align;
 
@@ -13533,14 +13925,14 @@ elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
        rel->r_offset = rel->r_info = rel->r_addend = 0;
       }
 
-  return TRUE;
+  return true;
 }
 
 /* Mark sections containing dynamically referenced symbols.  When
    building shared libraries, we must assume that any visible symbol is
    referenced.  */
 
-bfd_boolean
+bool
 bfd_elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h, void *inf)
 {
   struct bfd_link_info *info = (struct bfd_link_info *) inf;
@@ -13548,6 +13940,9 @@ 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->start_stop
+         || h->root.ldscript_def
+         || !info->start_stop_gc)
       && ((h->ref_dynamic && !h->forced_local)
          || ((h->def_regular || ELF_COMMON_DEF_P (h))
              && ELF_ST_VISIBILITY (h->other) != STV_INTERNAL
@@ -13563,7 +13958,7 @@ bfd_elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h, void *inf)
                                               h->root.root.string)))))
     h->root.u.def.section->flags |= SEC_KEEP;
 
-  return TRUE;
+  return true;
 }
 
 /* Keep all sections containing symbols undefined on the command-line,
@@ -13579,18 +13974,17 @@ _bfd_elf_gc_keep (struct bfd_link_info *info)
       struct elf_link_hash_entry *h;
 
       h = elf_link_hash_lookup (elf_hash_table (info), sym->name,
-                               FALSE, FALSE, FALSE);
+                               false, false, false);
 
       if (h != NULL
          && (h->root.type == bfd_link_hash_defined
              || h->root.type == bfd_link_hash_defweak)
-         && !bfd_is_abs_section (h->root.u.def.section)
-         && !bfd_is_und_section (h->root.u.def.section))
+         && !bfd_is_const_section (h->root.u.def.section))
        h->root.u.def.section->flags |= SEC_KEEP;
     }
 }
 
-bfd_boolean
+bool
 bfd_elf_parse_eh_frame_entries (bfd *abfd ATTRIBUTE_UNUSED,
                                struct bfd_link_info *info)
 {
@@ -13608,11 +14002,11 @@ bfd_elf_parse_eh_frame_entries (bfd *abfd ATTRIBUTE_UNUSED,
        continue;
 
       if (!init_reloc_cookie (&cookie, info, ibfd))
-       return FALSE;
+       return false;
 
       for (sec = ibfd->sections; sec; sec = sec->next)
        {
-         if (CONST_STRNEQ (bfd_section_name (sec), ".eh_frame_entry")
+         if (startswith (bfd_section_name (sec), ".eh_frame_entry")
              && init_reloc_cookie_rels (&cookie, info, ibfd, sec))
            {
              _bfd_elf_parse_eh_frame_entry (info, sec, &cookie);
@@ -13620,15 +14014,15 @@ bfd_elf_parse_eh_frame_entries (bfd *abfd ATTRIBUTE_UNUSED,
            }
        }
     }
-  return TRUE;
+  return true;
 }
 
 /* Do mark and sweep of unused sections.  */
 
-bfd_boolean
+bool
 bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
 {
-  bfd_boolean ok = TRUE;
+  bool ok = true;
   bfd *sub;
   elf_gc_mark_hook_fn gc_mark_hook;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
@@ -13638,7 +14032,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
       || !is_elf_hash_table (info->hash))
     {
       _bfd_error_handler(_("warning: gc-sections option ignored"));
-      return TRUE;
+      return true;
     }
 
   bed->gc_keep (info);
@@ -13671,12 +14065,12 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
   /* Apply transitive closure to the vtable entry usage info.  */
   elf_link_hash_traverse (htab, elf_gc_propagate_vtable_entries_used, &ok);
   if (!ok)
-    return FALSE;
+    return false;
 
   /* Kill the vtable relocations that were not used.  */
   elf_link_hash_traverse (htab, elf_gc_smash_unused_vtentry_relocs, &ok);
   if (!ok)
-    return FALSE;
+    return false;
 
   /* Mark dynamically referenced symbols.  */
   if (htab->dynamic_sections_created || info->gc_keep_exported)
@@ -13713,10 +14107,13 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
                        || (elf_section_data (o)->this_hdr.sh_type
                            == SHT_FINI_ARRAY)))
                || (elf_section_data (o)->this_hdr.sh_type == SHT_NOTE
-                   && elf_next_in_group (o) == NULL )))
+                   && elf_next_in_group (o) == NULL
+                   && elf_linked_to_section (o) == NULL)
+               || ((elf_tdata (sub)->has_gnu_osabi & elf_gnu_osabi_retain)
+                   && (elf_section_flags (o) & SHF_GNU_RETAIN))))
          {
            if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
-             return FALSE;
+             return false;
          }
     }
 
@@ -13729,7 +14126,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
 \f
 /* Called from check_relocs to record the existence of a VTINHERIT reloc.  */
 
-bfd_boolean
+bool
 bfd_elf_gc_record_vtinherit (bfd *abfd,
                             asection *sec,
                             struct elf_link_hash_entry *h,
@@ -13766,7 +14163,7 @@ bfd_elf_gc_record_vtinherit (bfd *abfd,
   _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;
+  return false;
 
  win:
   if (!child->u2.vtable)
@@ -13774,7 +14171,7 @@ bfd_elf_gc_record_vtinherit (bfd *abfd,
       child->u2.vtable = ((struct elf_link_virtual_table_entry *)
                          bfd_zalloc (abfd, sizeof (*child->u2.vtable)));
       if (!child->u2.vtable)
-       return FALSE;
+       return false;
     }
   if (!h)
     {
@@ -13788,12 +14185,12 @@ bfd_elf_gc_record_vtinherit (bfd *abfd,
   else
     child->u2.vtable->parent = h;
 
-  return TRUE;
+  return true;
 }
 
 /* Called from check_relocs to record the existence of a VTENTRY reloc.  */
 
-bfd_boolean
+bool
 bfd_elf_gc_record_vtentry (bfd *abfd, asection *sec,
                           struct elf_link_hash_entry *h,
                           bfd_vma addend)
@@ -13807,7 +14204,7 @@ bfd_elf_gc_record_vtentry (bfd *abfd, asection *sec,
       _bfd_error_handler (_("%pB: section '%pA': corrupt VTENTRY entry"),
                          abfd, sec);
       bfd_set_error (bfd_error_bad_value);
-      return FALSE;
+      return false;
     }
 
   if (!h->u2.vtable)
@@ -13815,13 +14212,13 @@ bfd_elf_gc_record_vtentry (bfd *abfd, asection *sec,
       h->u2.vtable = ((struct elf_link_virtual_table_entry *)
                      bfd_zalloc (abfd, sizeof (*h->u2.vtable)));
       if (!h->u2.vtable)
-       return FALSE;
+       return false;
     }
 
   if (addend >= h->u2.vtable->size)
     {
       size_t size, bytes, file_align;
-      bfd_boolean *ptr = h->u2.vtable->used;
+      bool *ptr = h->u2.vtable->used;
 
       /* While the symbol is undefined, we have to be prepared to handle
         a zero size.  */
@@ -13842,35 +14239,35 @@ bfd_elf_gc_record_vtentry (bfd *abfd, asection *sec,
 
       /* Allocate one extra entry for use as a "done" flag for the
         consolidation pass.  */
-      bytes = ((size >> log_file_align) + 1) * sizeof (bfd_boolean);
+      bytes = ((size >> log_file_align) + 1) * sizeof (bool);
 
       if (ptr)
        {
-         ptr = (bfd_boolean *) bfd_realloc (ptr - 1, bytes);
+         ptr = (bool *) bfd_realloc (ptr - 1, bytes);
 
          if (ptr != NULL)
            {
              size_t oldbytes;
 
              oldbytes = (((h->u2.vtable->size >> log_file_align) + 1)
-                         * sizeof (bfd_boolean));
+                         * sizeof (bool));
              memset (((char *) ptr) + oldbytes, 0, bytes - oldbytes);
            }
        }
       else
-       ptr = (bfd_boolean *) bfd_zmalloc (bytes);
+       ptr = (bool *) bfd_zmalloc (bytes);
 
       if (ptr == NULL)
-       return FALSE;
+       return false;
 
       /* And arrange for that done flag to be at index -1.  */
       h->u2.vtable->used = ptr + 1;
       h->u2.vtable->size = size;
     }
 
-  h->u2.vtable->used[addend >> log_file_align] = TRUE;
+  h->u2.vtable->used[addend >> log_file_align] = true;
 
-  return TRUE;
+  return true;
 }
 
 /* Map an ELF section header flag to its corresponding string.  */
@@ -13880,7 +14277,7 @@ typedef struct
   flagword flag_value;
 } elf_flags_to_name_table;
 
-static elf_flags_to_name_table elf_flags_to_names [] =
+static const elf_flags_to_name_table elf_flags_to_names [] =
 {
   { "SHF_WRITE", SHF_WRITE },
   { "SHF_ALLOC", SHF_ALLOC },
@@ -13897,7 +14294,7 @@ static elf_flags_to_name_table elf_flags_to_names [] =
 };
 
 /* Returns TRUE if the section is to be included, otherwise FALSE.  */
-bfd_boolean
+bool
 bfd_elf_lookup_section_flags (struct bfd_link_info *info,
                              struct flag_info *flaginfo,
                              asection *section)
@@ -13928,7 +14325,7 @@ bfd_elf_lookup_section_flags (struct bfd_link_info *info,
                    with_hex |= hexval;
                  else if (tf->with == without_flags)
                    without_hex |= hexval;
-                 tf->valid = TRUE;
+                 tf->valid = true;
                  continue;
                }
            }
@@ -13940,7 +14337,7 @@ bfd_elf_lookup_section_flags (struct bfd_link_info *info,
                    with_hex |= elf_flags_to_names[i].flag_value;
                  else if (tf->with == without_flags)
                    without_hex |= elf_flags_to_names[i].flag_value;
-                 tf->valid = TRUE;
+                 tf->valid = true;
                  break;
                }
            }
@@ -13948,21 +14345,21 @@ bfd_elf_lookup_section_flags (struct bfd_link_info *info,
            {
              info->callbacks->einfo
                (_("unrecognized INPUT_SECTION_FLAG %s\n"), tf->name);
-             return FALSE;
+             return false;
            }
        }
-      flaginfo->flags_initialized = TRUE;
+      flaginfo->flags_initialized = true;
       flaginfo->only_with_flags |= with_hex;
       flaginfo->not_with_flags |= without_hex;
     }
 
   if ((flaginfo->only_with_flags & sh_flags) != flaginfo->only_with_flags)
-    return FALSE;
+    return false;
 
   if ((flaginfo->not_with_flags & sh_flags) != 0)
-    return FALSE;
+    return false;
 
-  return TRUE;
+  return true;
 }
 
 struct alloc_got_off_arg {
@@ -13973,7 +14370,7 @@ struct alloc_got_off_arg {
 /* We need a special top-level link routine to convert got reference counts
    to real got offsets.  */
 
-static bfd_boolean
+static bool
 elf_gc_allocate_got_offsets (struct elf_link_hash_entry *h, void *arg)
 {
   struct alloc_got_off_arg *gofarg = (struct alloc_got_off_arg *) arg;
@@ -13988,13 +14385,13 @@ elf_gc_allocate_got_offsets (struct elf_link_hash_entry *h, void *arg)
   else
     h->got.offset = (bfd_vma) -1;
 
-  return TRUE;
+  return true;
 }
 
 /* And an accompanying bit to work out final got entry offsets once
    we're done.  Should be called from final_link.  */
 
-bfd_boolean
+bool
 bfd_elf_gc_common_finalize_got_offsets (bfd *abfd,
                                        struct bfd_link_info *info)
 {
@@ -14006,7 +14403,7 @@ bfd_elf_gc_common_finalize_got_offsets (bfd *abfd,
   BFD_ASSERT (abfd == info->output_bfd);
 
   if (! is_elf_hash_table (info->hash))
-    return FALSE;
+    return false;
 
   /* The GOT offset is relative to the .got section, but the GOT header is
      put into the .got.plt section, if the backend uses it.  */
@@ -14054,23 +14451,23 @@ bfd_elf_gc_common_finalize_got_offsets (bfd *abfd,
   elf_link_hash_traverse (elf_hash_table (info),
                          elf_gc_allocate_got_offsets,
                          &gofarg);
-  return TRUE;
+  return true;
 }
 
 /* Many folk need no more in the way of final link than this, once
    got entry reference counting is enabled.  */
 
-bfd_boolean
+bool
 bfd_elf_gc_common_final_link (bfd *abfd, struct bfd_link_info *info)
 {
   if (!bfd_elf_gc_common_finalize_got_offsets (abfd, info))
-    return FALSE;
+    return false;
 
   /* Invoke the regular ELF backend linker to do all the work.  */
   return bfd_elf_final_link (abfd, info);
 }
 
-bfd_boolean
+bool
 bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
 {
   struct elf_reloc_cookie *rcookie = (struct elf_reloc_cookie *) cookie;
@@ -14084,13 +14481,13 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
 
       if (! rcookie->bad_symtab)
        if (rcookie->rel->r_offset > offset)
-         return FALSE;
+         return false;
       if (rcookie->rel->r_offset != offset)
        continue;
 
       r_symndx = rcookie->rel->r_info >> rcookie->r_sym_shift;
       if (r_symndx == STN_UNDEF)
-       return TRUE;
+       return true;
 
       if (r_symndx >= rcookie->locsymcount
          || ELF_ST_BIND (rcookie->locsyms[r_symndx].st_info) != STB_LOCAL)
@@ -14108,7 +14505,7 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
              && (h->root.u.def.section->owner != rcookie->abfd
                  || h->root.u.def.section->kept_section != NULL
                  || discarded_section (h->root.u.def.section)))
-           return TRUE;
+           return true;
        }
       else
        {
@@ -14124,11 +14521,11 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
          if (isec != NULL
              && (isec->kept_section != NULL
                  || discarded_section (isec)))
-           return TRUE;
+           return true;
        }
-      return FALSE;
+      return false;
     }
-  return FALSE;
+  return false;
 }
 
 /* Discard unneeded references to discarded sections.
@@ -14184,7 +14581,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)
        {
@@ -14211,7 +14608,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)
@@ -14281,7 +14679,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
   return changed;
 }
 
-bfd_boolean
+bool
 _bfd_elf_section_already_linked (bfd *abfd,
                                 asection *sec,
                                 struct bfd_link_info *info)
@@ -14292,19 +14690,19 @@ _bfd_elf_section_already_linked (bfd *abfd,
   struct bfd_section_already_linked_hash_entry *already_linked_list;
 
   if (sec->output_section == bfd_abs_section_ptr)
-    return FALSE;
+    return false;
 
   flags = sec->flags;
 
   /* Return if it isn't a linkonce section.  A comdat group section
      also has SEC_LINK_ONCE set.  */
   if ((flags & SEC_LINK_ONCE) == 0)
-    return FALSE;
+    return false;
 
   /* Don't put group member sections on our list of already linked
      sections.  They are handled as a group via their group section.  */
   if (elf_sec_group (sec) != NULL)
-    return FALSE;
+    return false;
 
   /* For a SHT_GROUP section, use the group signature as the key.  */
   name = sec->name;
@@ -14315,7 +14713,7 @@ _bfd_elf_section_already_linked (bfd *abfd,
   else
     {
       /* Otherwise we should have a .gnu.linkonce.<type>.<key> section.  */
-      if (CONST_STRNEQ (name, ".gnu.linkonce.")
+      if (startswith (name, ".gnu.linkonce.")
          && (key = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL)
        key++;
       else
@@ -14338,12 +14736,13 @@ _bfd_elf_section_already_linked (bfd *abfd,
       if (((flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP)
           && ((flags & SEC_GROUP) != 0
               || strcmp (name, l->sec->name) == 0))
-         || (l->sec->owner->flags & BFD_PLUGIN) != 0)
+         || (l->sec->owner->flags & BFD_PLUGIN) != 0
+         || (sec->owner->flags & BFD_PLUGIN) != 0)
        {
          /* The section has already been linked.  See if we should
             issue a warning.  */
          if (!_bfd_handle_already_linked (sec, l, info))
-           return FALSE;
+           return false;
 
          if (flags & SEC_GROUP)
            {
@@ -14362,7 +14761,7 @@ _bfd_elf_section_already_linked (bfd *abfd,
                }
            }
 
-         return TRUE;
+         return true;
        }
     }
 
@@ -14413,10 +14812,10 @@ _bfd_elf_section_already_linked (bfd *abfd,
      `.gnu.linkonce.r.F' section.  The order of sections in a bfd does not
      matter as here were are looking only for cross-bfd sections.  */
 
-  if ((flags & SEC_GROUP) == 0 && CONST_STRNEQ (name, ".gnu.linkonce.r."))
+  if ((flags & SEC_GROUP) == 0 && startswith (name, ".gnu.linkonce.r."))
     for (l = already_linked_list->entry; l != NULL; l = l->next)
       if ((l->sec->flags & SEC_GROUP) == 0
-         && CONST_STRNEQ (l->sec->name, ".gnu.linkonce.t."))
+         && startswith (l->sec->name, ".gnu.linkonce.t."))
        {
          if (abfd != l->sec->owner)
            sec->output_section = bfd_abs_section_ptr;
@@ -14429,7 +14828,7 @@ _bfd_elf_section_already_linked (bfd *abfd,
   return sec->output_section == bfd_abs_section_ptr;
 }
 
-bfd_boolean
+bool
 _bfd_elf_common_definition (Elf_Internal_Sym *sym)
 {
   return sym->st_shndx == SHN_COMMON;
@@ -14465,7 +14864,7 @@ _bfd_elf_default_got_elt_size (bfd *abfd,
 static const char *
 get_dynamic_reloc_section_name (bfd *       abfd,
                                asection *  sec,
-                               bfd_boolean is_rela)
+                               bool is_rela)
 {
   char *name;
   const char *old_name = bfd_section_name (sec);
@@ -14486,15 +14885,15 @@ get_dynamic_reloc_section_name (bfd *       abfd,
    of IS_RELA.  */
 
 asection *
-_bfd_elf_get_dynamic_reloc_section (bfd *       abfd,
-                                   asection *  sec,
-                                   bfd_boolean is_rela)
+_bfd_elf_get_dynamic_reloc_section (bfd *abfd,
+                                   asection *sec,
+                                   bool is_rela)
 {
-  asection * reloc_sec = elf_section_data (sec)->sreloc;
+  asection *reloc_sec = elf_section_data (sec)->sreloc;
 
   if (reloc_sec == NULL)
     {
-      const char * name = get_dynamic_reloc_section_name (abfd, sec, is_rela);
+      const char *name = get_dynamic_reloc_section_name (abfd, sec, is_rela);
 
       if (name != NULL)
        {
@@ -14523,7 +14922,7 @@ _bfd_elf_make_dynamic_reloc_section (asection *sec,
                                     bfd *dynobj,
                                     unsigned int alignment,
                                     bfd *abfd,
-                                    bfd_boolean is_rela)
+                                    bool is_rela)
 {
   asection * reloc_sec = elf_section_data (sec)->sreloc;
 
@@ -14579,7 +14978,7 @@ _bfd_elf_copy_link_hash_symbol_type (bfd *abfd,
   ehdest->target_internal = ehsrc->target_internal;
 
   isym.st_other = ehsrc->other;
-  elf_merge_st_other (abfd, ehdest, &isym, NULL, TRUE, FALSE);
+  elf_merge_st_other (abfd, ehdest, isym.st_other, NULL, true, false);
 }
 
 /* Append a RELA relocation REL to section S in BFD.  */
@@ -14613,13 +15012,18 @@ bfd_elf_define_start_stop (struct bfd_link_info *info,
   struct elf_link_hash_entry *h;
 
   h = elf_link_hash_lookup (elf_hash_table (info), symbol,
-                           FALSE, FALSE, TRUE);
+                           false, false, true);
+  /* NB: Common symbols will be turned into definition later.  */
   if (h != NULL
+      && !h->root.ldscript_def
       && (h->root.type == bfd_link_hash_undefined
          || h->root.type == bfd_link_hash_undefweak
-         || ((h->ref_regular || h->def_dynamic) && !h->def_regular)))
+         || ((h->ref_regular || h->def_dynamic)
+             && !h->def_regular
+             && h->root.type != bfd_link_hash_common)))
     {
-      bfd_boolean was_dynamic = h->ref_dynamic || h->def_dynamic;
+      bool was_dynamic = h->ref_dynamic || h->def_dynamic;
+      h->verinfo.verdef = NULL;
       h->root.type = bfd_link_hash_defined;
       h->root.u.def.section = sec;
       h->root.u.def.value = 0;
@@ -14632,12 +15036,13 @@ bfd_elf_define_start_stop (struct bfd_link_info *info,
          /* .startof. and .sizeof. symbols are local.  */
          const struct elf_backend_data *bed;
          bed = get_elf_backend_data (info->output_bfd);
-         (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+         (*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;
+           h->other = ((h->other & ~ELF_ST_VISIBILITY (-1))
+                       | info->start_stop_visibility);
          if (was_dynamic)
            bfd_elf_link_record_dynamic_symbol (info, h);
        }
@@ -14645,3 +15050,147 @@ bfd_elf_define_start_stop (struct bfd_link_info *info,
     }
   return NULL;
 }
+
+/* Find dynamic relocs for H that apply to read-only sections.  */
+
+asection *
+_bfd_elf_readonly_dynrelocs (struct elf_link_hash_entry *h)
+{
+  struct elf_dyn_relocs *p;
+
+  for (p = h->dyn_relocs; p != NULL; p = p->next)
+    {
+      asection *s = p->sec->output_section;
+
+      if (s != NULL && (s->flags & SEC_READONLY) != 0)
+       return p->sec;
+    }
+  return NULL;
+}
+
+/* Set DF_TEXTREL if we find any dynamic relocs that apply to
+   read-only sections.  */
+
+bool
+_bfd_elf_maybe_set_textrel (struct elf_link_hash_entry *h, void *inf)
+{
+  asection *sec;
+
+  if (h->root.type == bfd_link_hash_indirect)
+    return true;
+
+  sec = _bfd_elf_readonly_dynrelocs (h);
+  if (sec != NULL)
+    {
+      struct bfd_link_info *info = (struct bfd_link_info *) inf;
+
+      info->flags |= DF_TEXTREL;
+      /* xgettext:c-format */
+      info->callbacks->minfo (_("%pB: dynamic relocation against `%pT' "
+                               "in read-only section `%pA'\n"),
+                             sec->owner, h->root.root.string, sec);
+
+      if (bfd_link_textrel_check (info))
+       /* xgettext:c-format */
+       info->callbacks->einfo (_("%P: %pB: warning: relocation against `%s' "
+                                 "in read-only section `%pA'\n"),
+                               sec->owner, h->root.root.string, sec);
+
+      /* Not an error, just cut short the traversal.  */
+      return false;
+    }
+  return true;
+}
+
+/* Add dynamic tags.  */
+
+bool
+_bfd_elf_add_dynamic_tags (bfd *output_bfd, struct bfd_link_info *info,
+                          bool need_dynamic_reloc)
+{
+  struct elf_link_hash_table *htab = elf_hash_table (info);
+
+  if (htab->dynamic_sections_created)
+    {
+      /* Add some entries to the .dynamic section.  We fill in the
+        values later, in finish_dynamic_sections, but we must add
+        the entries now so that we get the correct size for the
+        .dynamic section.  The DT_DEBUG entry is filled in by the
+        dynamic linker and used by the debugger.  */
+#define add_dynamic_entry(TAG, VAL) \
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
+
+      const struct elf_backend_data *bed
+       = get_elf_backend_data (output_bfd);
+
+      if (bfd_link_executable (info))
+       {
+         if (!add_dynamic_entry (DT_DEBUG, 0))
+           return false;
+       }
+
+      if (htab->dt_pltgot_required || htab->splt->size != 0)
+       {
+         /* DT_PLTGOT is used by prelink even if there is no PLT
+            relocation.  */
+         if (!add_dynamic_entry (DT_PLTGOT, 0))
+           return false;
+       }
+
+      if (htab->dt_jmprel_required || htab->srelplt->size != 0)
+       {
+         if (!add_dynamic_entry (DT_PLTRELSZ, 0)
+             || !add_dynamic_entry (DT_PLTREL,
+                                    (bed->rela_plts_and_copies_p
+                                     ? DT_RELA : DT_REL))
+             || !add_dynamic_entry (DT_JMPREL, 0))
+           return false;
+       }
+
+      if (htab->tlsdesc_plt
+         && (!add_dynamic_entry (DT_TLSDESC_PLT, 0)
+             || !add_dynamic_entry (DT_TLSDESC_GOT, 0)))
+       return false;
+
+      if (need_dynamic_reloc)
+       {
+         if (bed->rela_plts_and_copies_p)
+           {
+             if (!add_dynamic_entry (DT_RELA, 0)
+                 || !add_dynamic_entry (DT_RELASZ, 0)
+                 || !add_dynamic_entry (DT_RELAENT,
+                                        bed->s->sizeof_rela))
+               return false;
+           }
+         else
+           {
+             if (!add_dynamic_entry (DT_REL, 0)
+                 || !add_dynamic_entry (DT_RELSZ, 0)
+                 || !add_dynamic_entry (DT_RELENT,
+                                        bed->s->sizeof_rel))
+               return false;
+           }
+
+         /* If any dynamic relocs apply to a read-only section,
+            then we need a DT_TEXTREL entry.  */
+         if ((info->flags & DF_TEXTREL) == 0)
+           elf_link_hash_traverse (htab, _bfd_elf_maybe_set_textrel,
+                                   info);
+
+         if ((info->flags & DF_TEXTREL) != 0)
+           {
+             if (htab->ifunc_resolvers)
+               info->callbacks->einfo
+                 (_("%P: warning: GNU indirect functions with DT_TEXTREL "
+                    "may result in a segfault at runtime; recompile with %s\n"),
+                  bfd_link_dll (info) ? "-fPIC" : "-fPIE");
+
+             if (!add_dynamic_entry (DT_TEXTREL, 0))
+               return false;
+           }
+       }
+    }
+#undef add_dynamic_entry
+
+  return true;
+}