[ARC] ARC_PC32 dynamic reloc incorrectly generated.
[deliverable/binutils-gdb.git] / bfd / elflink.c
index d7ed8ce6b4646a9397cad11c7ffdbb641da51513..1b447bb785081844b2d577f364586d67c81328ce 100644 (file)
@@ -119,15 +119,18 @@ _bfd_elf_define_linkage_sym (bfd *abfd,
         defined in shared libraries can't be overridden, because we
         lose the link to the bfd which is via the symbol section.  */
       h->root.type = bfd_link_hash_new;
+      bh = &h->root;
     }
+  else
+    bh = NULL;
 
-  bh = &h->root;
   bed = get_elf_backend_data (abfd);
   if (!_bfd_generic_link_add_one_symbol (info, abfd, name, BSF_GLOBAL,
                                         sec, 0, NULL, FALSE, bed->collect,
                                         &bh))
     return NULL;
   h = (struct elf_link_hash_entry *) bh;
+  BFD_ASSERT (h != NULL);
   h->def_regular = 1;
   h->non_elf = 0;
   h->root.linker_def = 1;
@@ -424,7 +427,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
         initialize them at run time.  The linker script puts the .dynbss
         section into the .bss section of the final image.  */
       s = bfd_make_section_anyway_with_flags (abfd, ".dynbss",
-                                             (SEC_ALLOC | SEC_LINKER_CREATED));
+                                             SEC_ALLOC | SEC_LINKER_CREATED);
       if (s == NULL)
        return FALSE;
       htab->sdynbss = s;
@@ -432,11 +435,10 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
       if (bed->want_dynrelro)
        {
          /* Similarly, but for symbols that were originally in read-only
-            sections.  */
+            sections.  This section doesn't really need to have contents,
+            but make it like other .data.rel.ro sections.  */
          s = bfd_make_section_anyway_with_flags (abfd, ".data.rel.ro",
-                                                 (SEC_ALLOC | SEC_READONLY
-                                                  | SEC_HAS_CONTENTS
-                                                  | SEC_LINKER_CREATED));
+                                                 flags);
          if (s == NULL)
            return FALSE;
          htab->sdynrelro = s;
@@ -578,7 +580,7 @@ bfd_elf_link_mark_dynamic_symbol (struct bfd_link_info *info,
               && (ELF_ST_TYPE (sym->st_info) == STT_OBJECT
                   || ELF_ST_TYPE (sym->st_info) == STT_COMMON))))
       || (d != NULL
-         && h->root.type == bfd_link_hash_new
+         && h->non_elf
          && (*d->match) (&d->head, NULL, h->root.root.string)))
     h->dynamic = 1;
 }
@@ -621,6 +623,14 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
        }
     }
 
+  /* Symbols defined in a linker script but not referenced anywhere
+     else will have non_elf set.  */
+  if (h->non_elf)
+    {
+      bfd_elf_link_mark_dynamic_symbol (info, h, NULL);
+      h->non_elf = 0;
+    }
+
   switch (h->root.type)
     {
     case bfd_link_hash_defined:
@@ -637,8 +647,6 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
        bfd_link_repair_undef_list (&htab->root);
       break;
     case bfd_link_hash_new:
-      bfd_elf_link_mark_dynamic_symbol (info, h, NULL);
-      h->non_elf = 0;
       break;
     case bfd_link_hash_indirect:
       /* We had a versioned symbol in a dynamic library.  We make the
@@ -671,17 +679,15 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
 
   /* If this symbol is not being provided by the linker script, and it is
      currently defined by a dynamic object, but not by a regular object,
-     then undo any forced local marking that may have been set by input
-     section garbage collection and clear out any version information
-     because the symbol will not be associated with the dynamic object
-     any more.  */
+     then clear out any version information because the symbol will not be
+     associated with the dynamic object any more.  */
   if (!provide
       && h->def_dynamic
       && !h->def_regular)
-    {
-      h->forced_local = 0;
-      h->verinfo.verdef = NULL;
-    }
+    h->verinfo.verdef = NULL;
+
+  /* Make sure this symbol is not garbage collected.  */
+  h->mark = 1;
 
   h->def_regular = 1;
 
@@ -1242,23 +1248,50 @@ _bfd_elf_merge_symbol (bfd *abfd,
   oldfunc = (h->type != STT_NOTYPE
             && bed->is_function_type (h->type));
 
-  /* If creating a default indirect symbol ("foo" or "foo@") from a
-     dynamic versioned definition ("foo@@") skip doing so if there is
-     an existing regular definition with a different type.  We don't
-     want, for example, a "time" variable in the executable overriding
-     a "time" function in a shared library.  */
-  if (pold_alignment == NULL
-      && newdyn
-      && newdef
-      && !olddyn
-      && (olddef || h->root.type == bfd_link_hash_common)
+  if (!(newfunc && oldfunc)
       && ELF_ST_TYPE (sym->st_info) != h->type
       && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
       && h->type != STT_NOTYPE
-      && !(newfunc && oldfunc))
+      && (newdef || bfd_is_com_section (sec))
+      && (olddef || h->root.type == bfd_link_hash_common))
     {
-      *skip = TRUE;
-      return TRUE;
+      /* If creating a default indirect symbol ("foo" or "foo@") from
+        a dynamic versioned definition ("foo@@") skip doing so if
+        there is an existing regular definition with a different
+        type.  We don't want, for example, a "time" variable in the
+        executable overriding a "time" function in a shared library.  */
+      if (newdyn
+         && !olddyn)
+       {
+         *skip = TRUE;
+         return TRUE;
+       }
+
+      /* When adding a symbol from a regular object file after we have
+        created indirect symbols, undo the indirection and any
+        dynamic state.  */
+      if (hi != h
+         && !newdyn
+         && olddyn)
+       {
+         h = hi;
+         (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+         h->forced_local = 0;
+         h->ref_dynamic = 0;
+         h->def_dynamic = 0;
+         h->dynamic_def = 0;
+         if (h->root.u.undef.next || info->hash->undefs_tail == &h->root)
+           {
+             h->root.type = bfd_link_hash_undefined;
+             h->root.u.undef.abfd = abfd;
+           }
+         else
+           {
+             h->root.type = bfd_link_hash_new;
+             h->root.u.undef.abfd = NULL;
+           }
+         return TRUE;
+       }
     }
 
   /* Check TLS symbols.  We don't check undefined symbols introduced
@@ -1298,25 +1331,25 @@ _bfd_elf_merge_symbol (bfd *abfd,
          /* xgettext:c-format */
          (_("%s: TLS definition in %B section %A "
             "mismatches non-TLS definition in %B section %A"),
-          tbfd, tsec, ntbfd, ntsec, h->root.root.string);
+          h->root.root.string, tbfd, tsec, ntbfd, ntsec);
       else if (!tdef && !ntdef)
        _bfd_error_handler
          /* xgettext:c-format */
          (_("%s: TLS reference in %B "
             "mismatches non-TLS reference in %B"),
-          tbfd, ntbfd, h->root.root.string);
+          h->root.root.string, tbfd, ntbfd);
       else if (tdef)
        _bfd_error_handler
          /* xgettext:c-format */
          (_("%s: TLS definition in %B section %A "
             "mismatches non-TLS reference in %B"),
-          tbfd, tsec, ntbfd, h->root.root.string);
+          h->root.root.string, tbfd, tsec, ntbfd);
       else
        _bfd_error_handler
          /* xgettext:c-format */
          (_("%s: TLS reference in %B "
             "mismatches non-TLS definition in %B section %A"),
-          tbfd, ntbfd, ntsec, h->root.root.string);
+          h->root.root.string, tbfd, ntbfd, ntsec);
 
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
@@ -1544,16 +1577,13 @@ _bfd_elf_merge_symbol (bfd *abfd,
      represent variables; this can cause confusion in principle, but
      any such confusion would seem to indicate an erroneous program or
      shared library.  We also permit a common symbol in a regular
-     object to override a weak symbol in a shared object.  A common
-     symbol in executable also overrides a symbol in a shared object.  */
+     object to override a weak symbol in a shared object.  */
 
   if (newdyn
       && newdef
       && (olddef
          || (h->root.type == bfd_link_hash_common
-             && (newweak
-                 || newfunc
-                 || (!olddyn && bfd_link_executable (info))))))
+             && (newweak || newfunc))))
     {
       *override = TRUE;
       newdef = FALSE;
@@ -2362,8 +2392,8 @@ elf_link_read_relocs_from_section (bfd *abfd,
                /* xgettext:c-format */
                (_("%B: bad reloc symbol index (0x%lx >= 0x%lx)"
                   " for offset 0x%lx in section `%A'"),
-                abfd, sec,
-                (unsigned long) r_symndx, (unsigned long) nsyms, irela->r_offset);
+                abfd, (unsigned long) r_symndx, (unsigned long) nsyms,
+                irela->r_offset, sec);
              bfd_set_error (bfd_error_bad_value);
              return FALSE;
            }
@@ -2372,10 +2402,11 @@ elf_link_read_relocs_from_section (bfd *abfd,
        {
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B: non-zero symbol index (0x%lx) for offset 0x%lx in section `%A'"
+           (_("%B: non-zero symbol index (0x%lx)"
+              " for offset 0x%lx in section `%A'"
               " when the object file has no symbol table"),
-            abfd, sec,
-            (unsigned long) r_symndx, (unsigned long) nsyms, irela->r_offset);
+            abfd, (unsigned long) r_symndx, (unsigned long) nsyms,
+            irela->r_offset, sec);
          bfd_set_error (bfd_error_bad_value);
          return FALSE;
        }
@@ -2419,8 +2450,7 @@ _bfd_elf_link_read_relocs (bfd *abfd,
     {
       bfd_size_type size;
 
-      size = o->reloc_count;
-      size *= bed->s->int_rels_per_ext_rel * sizeof (Elf_Internal_Rela);
+      size = (bfd_size_type) o->reloc_count * sizeof (Elf_Internal_Rela);
       if (keep_memory)
        internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_alloc (abfd, size);
       else
@@ -2778,6 +2808,24 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
   if (! _bfd_elf_fix_symbol_flags (h, eif))
     return FALSE;
 
+  if (h->root.type == bfd_link_hash_undefweak)
+    {
+      if (eif->info->dynamic_undefined_weak == 0)
+       _bfd_elf_link_hash_hide_symbol (eif->info, h, TRUE);
+      else if (eif->info->dynamic_undefined_weak > 0
+              && h->ref_regular
+              && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+              && !bfd_hide_sym_by_version (eif->info->version_info,
+                                           h->root.root.string))
+       {
+         if (!bfd_elf_link_record_dynamic_symbol (eif->info, h))
+           {
+             eif->failed = TRUE;
+             return FALSE;
+           }
+       }
+    }
+
   /* If this symbol does not require a PLT entry, and it is not
      defined by a dynamic object, or is not referenced by a regular
      object, ignore it.  We do have to handle a weak defined symbol,
@@ -3020,10 +3068,10 @@ _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
    to resolve local to the current module, and false otherwise.  Differs
    from (the inverse of) _bfd_elf_dynamic_symbol_p in the treatment of
    undefined symbols.  The two functions are virtually identical except
-   for the place where forced_local and dynindx == -1 are tested.  If
-   either of those tests are true, _bfd_elf_dynamic_symbol_p will say
-   the symbol is local, while _bfd_elf_symbol_refs_local_p will say
-   the symbol is local only for defined symbols.
+   for the place where dynindx == -1 is tested.  If that test is true,
+   _bfd_elf_dynamic_symbol_p will say the symbol is local, while
+   _bfd_elf_symbol_refs_local_p will say the symbol is local only for
+   defined symbols.
    It might seem that _bfd_elf_dynamic_symbol_p could be rewritten as
    !_bfd_elf_symbol_refs_local_p, except that targets differ in their
    treatment of undefined weak symbols.  For those that do not make
@@ -3046,6 +3094,10 @@ _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h,
       || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)
     return TRUE;
 
+  /* Forced local symbols resolve locally.  */
+  if (h->forced_local)
+    return TRUE;
+
   /* Common symbols that become definitions don't get the DEF_REGULAR
      flag set, so test it first, and don't bail out.  */
   if (ELF_COMMON_DEF_P (h))
@@ -3055,11 +3107,7 @@ _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h,
   else if (!h->def_regular)
     return FALSE;
 
-  /* Forced local symbols resolve locally.  */
-  if (h->forced_local)
-    return TRUE;
-
-  /* As do non-dynamic symbols.  */
+  /* Non-dynamic symbols resolve locally.  */
   if (h->dynindx == -1)
     return TRUE;
 
@@ -3808,6 +3856,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       if (!just_syms
          && (bfd_link_pic (info)
              || (!bfd_link_relocatable (info)
+                 && info->nointerp
                  && (info->export_dynamic || info->dynamic)))
          && is_elf_hash_table (htab)
          && info->output_bfd->xvec == abfd->xvec
@@ -4676,15 +4725,15 @@ error_free_dyn:
                      /* xgettext:c-format */
                      (_("Warning: alignment %u of common symbol `%s' in %B is"
                         " greater than the alignment (%u) of its section %A"),
-                      common_bfd, h->root.u.def.section,
-                      1 << common_align, name, 1 << normal_align);
+                      1 << common_align, name, common_bfd,
+                      1 << normal_align, h->root.u.def.section);
                  else
                    _bfd_error_handler
                      /* xgettext:c-format */
                      (_("Warning: alignment %u of symbol `%s' in %B"
                         " is smaller than %u in %B"),
-                      normal_bfd, common_bfd,
-                      1 << normal_align, name, 1 << common_align);
+                      1 << normal_align, name, normal_bfd,
+                      1 << common_align, common_bfd);
                }
            }
 
@@ -4700,9 +4749,8 @@ error_free_dyn:
                  /* xgettext:c-format */
                  (_("Warning: size of symbol `%s' changed"
                     " from %lu in %B to %lu in %B"),
-                  old_bfd, abfd,
-                  name, (unsigned long) h->size,
-                  (unsigned long) isym->st_size);
+                  name, (unsigned long) h->size, old_bfd,
+                  (unsigned long) isym->st_size, abfd);
 
              h->size = isym->st_size;
            }
@@ -4736,7 +4784,7 @@ error_free_dyn:
                    _bfd_error_handler
                      (_("Warning: type of symbol `%s' changed"
                         " from %d to %d in %B"),
-                      abfd, name, h->type, type);
+                      name, h->type, type, abfd);
 
                  h->type = type;
                }
@@ -4890,6 +4938,7 @@ error_free_dyn:
          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)
            {
@@ -4911,6 +4960,10 @@ error_free_dyn:
                  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.  */
+             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;
@@ -4927,6 +4980,7 @@ error_free_dyn:
                  if (alignment_power > h->root.u.c.p->alignment_power)
                    h->root.u.c.p->alignment_power = alignment_power;
                }
+             h->root.non_ir_ref_dynamic = non_ir_ref_dynamic;
            }
        }
 
@@ -5876,6 +5930,38 @@ bfd_elf_stack_segment_size (bfd *output_bfd,
   return TRUE;
 }
 
+/* Sweep symbols in swept sections.  Called via elf_link_hash_traverse.  */
+
+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);
+};
+
+static bfd_boolean
+elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *data)
+{
+  if (!h->mark
+      && (((h->root.type == bfd_link_hash_defined
+           || h->root.type == bfd_link_hash_defweak)
+          && !((h->def_regular || ELF_COMMON_DEF_P (h))
+               && h->root.u.def.section->gc_mark))
+         || h->root.type == bfd_link_hash_undefined
+         || h->root.type == bfd_link_hash_undefweak))
+    {
+      struct elf_gc_sweep_symbol_info *inf;
+
+      inf = (struct elf_gc_sweep_symbol_info *) data;
+      (*inf->hide_symbol) (inf->info, h, TRUE);
+      h->def_regular = 0;
+      h->ref_regular = 0;
+      h->ref_regular_nonweak = 0;
+    }
+
+  return TRUE;
+}
+
 /* Set up the sizes and contents of the ELF dynamic sections.  This is
    called by the ELF linker emulation before_allocation routine.  We
    must set the sizes of the sections before the linker sets the
@@ -5892,169 +5978,26 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                               struct bfd_link_info *info,
                               asection **sinterpptr)
 {
-  size_t soname_indx;
   bfd *dynobj;
   const struct elf_backend_data *bed;
-  struct elf_info_failed asvinfo;
 
   *sinterpptr = NULL;
 
-  soname_indx = (size_t) -1;
-
   if (!is_elf_hash_table (info->hash))
     return TRUE;
 
-  bed = get_elf_backend_data (output_bfd);
-
-  /* Any syms created from now on start with -1 in
-     got.refcount/offset and plt.refcount/offset.  */
-  elf_hash_table (info)->init_got_refcount
-    = elf_hash_table (info)->init_got_offset;
-  elf_hash_table (info)->init_plt_refcount
-    = elf_hash_table (info)->init_plt_offset;
-
-  if (bfd_link_relocatable (info)
-      && !_bfd_elf_size_group_sections (info))
-    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;
-
-  /* Determine any GNU_STACK segment requirements, after the backend
-     has had a chance to set a default segment size.  */
-  if (info->execstack)
-    elf_stack_flags (output_bfd) = PF_R | PF_W | PF_X;
-  else if (info->noexecstack)
-    elf_stack_flags (output_bfd) = PF_R | PF_W;
-  else
-    {
-      bfd *inputobj;
-      asection *notesec = NULL;
-      int exec = 0;
-
-      for (inputobj = info->input_bfds;
-          inputobj;
-          inputobj = inputobj->link.next)
-       {
-         asection *s;
-
-         if (inputobj->flags
-             & (DYNAMIC | EXEC_P | BFD_PLUGIN | BFD_LINKER_CREATED))
-           continue;
-         s = bfd_get_section_by_name (inputobj, ".note.GNU-stack");
-         if (s)
-           {
-             if (s->flags & SEC_CODE)
-               exec = PF_X;
-             notesec = s;
-           }
-         else if (bed->default_execstack)
-           exec = PF_X;
-       }
-      if (notesec || info->stacksize > 0)
-       elf_stack_flags (output_bfd) = PF_R | PF_W | exec;
-      if (notesec && exec && bfd_link_relocatable (info)
-         && notesec->output_section != bfd_abs_section_ptr)
-       notesec->output_section->flags |= SEC_CODE;
-    }
-
   dynobj = elf_hash_table (info)->dynobj;
 
   if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
     {
-      struct elf_info_failed eif;
-      struct elf_link_hash_entry *h;
-      asection *dynstr;
+      struct bfd_elf_version_tree *verdefs;
+      struct elf_info_failed asvinfo;
       struct bfd_elf_version_tree *t;
       struct bfd_elf_version_expr *d;
-      asection *s;
+      struct elf_info_failed eif;
       bfd_boolean all_defined;
-
-      *sinterpptr = bfd_get_linker_section (dynobj, ".interp");
-      BFD_ASSERT (*sinterpptr != NULL || !bfd_link_executable (info) || info->nointerp);
-
-      if (soname != NULL)
-       {
-         soname_indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                            soname, TRUE);
-         if (soname_indx == (size_t) -1
-             || !_bfd_elf_add_dynamic_entry (info, DT_SONAME, soname_indx))
-           return FALSE;
-       }
-
-      if (info->symbolic)
-       {
-         if (!_bfd_elf_add_dynamic_entry (info, DT_SYMBOLIC, 0))
-           return FALSE;
-         info->flags |= DF_SYMBOLIC;
-       }
-
-      if (rpath != NULL)
-       {
-         size_t indx;
-         bfd_vma tag;
-
-         indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, rpath,
-                                     TRUE);
-         if (indx == (size_t) -1)
-           return FALSE;
-
-         tag = info->new_dtags ? DT_RUNPATH : DT_RPATH;
-         if (!_bfd_elf_add_dynamic_entry (info, tag, indx))
-           return FALSE;
-       }
-
-      if (filter_shlib != NULL)
-       {
-         size_t indx;
-
-         indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                     filter_shlib, TRUE);
-         if (indx == (size_t) -1
-             || !_bfd_elf_add_dynamic_entry (info, DT_FILTER, indx))
-           return FALSE;
-       }
-
-      if (auxiliary_filters != NULL)
-       {
-         const char * const *p;
-
-         for (p = auxiliary_filters; *p != NULL; p++)
-           {
-             size_t indx;
-
-             indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                         *p, TRUE);
-             if (indx == (size_t) -1
-                 || !_bfd_elf_add_dynamic_entry (info, DT_AUXILIARY, indx))
-               return FALSE;
-           }
-       }
-
-      if (audit != NULL)
-       {
-         size_t indx;
-
-         indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, audit,
-                                     TRUE);
-         if (indx == (size_t) -1
-             || !_bfd_elf_add_dynamic_entry (info, DT_AUDIT, indx))
-           return FALSE;
-       }
-
-      if (depaudit != NULL)
-       {
-         size_t indx;
-
-         indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, depaudit,
-                                     TRUE);
-         if (indx == (size_t) -1
-             || !_bfd_elf_add_dynamic_entry (info, DT_DEPAUDIT, indx))
-           return FALSE;
-       }
+      asection *s;
+      size_t soname_indx;
 
       eif.info = info;
       eif.failed = FALSE;
@@ -6071,6 +6014,17 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
            return FALSE;
        }
 
+      if (soname != NULL)
+       {
+         soname_indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                            soname, TRUE);
+         if (soname_indx == (size_t) -1
+             || !_bfd_elf_add_dynamic_entry (info, DT_SONAME, soname_indx))
+           return FALSE;
+       }
+      else
+       soname_indx = (size_t) -1;
+
       /* Make all global versions with definition.  */
       for (t = info->version_info; t != NULL; t = t->next)
        for (d = t->globals.list; d != NULL; d = d->next)
@@ -6154,136 +6108,13 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
            }
        }
 
-      /* Find all symbols which were defined in a dynamic object and make
-        the backend pick a reasonable value for them.  */
-      elf_link_hash_traverse (elf_hash_table (info),
-                             _bfd_elf_adjust_dynamic_symbol,
-                             &eif);
-      if (eif.failed)
-       return FALSE;
+      /* Set up the version definition section.  */
+      s = bfd_get_linker_section (dynobj, ".gnu.version_d");
+      BFD_ASSERT (s != NULL);
 
-      /* 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
-        now so that we know the final size of the .dynamic section.  */
-
-      /* If there are initialization and/or finalization functions to
-        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)
-          : NULL);
-      if (h != NULL
-         && (h->ref_regular
-             || h->def_regular))
-       {
-         if (!_bfd_elf_add_dynamic_entry (info, DT_INIT, 0))
-           return FALSE;
-       }
-      h = (info->fini_function
-          ? elf_link_hash_lookup (elf_hash_table (info),
-                                  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;
-       }
-
-      s = bfd_get_section_by_name (output_bfd, ".preinit_array");
-      if (s != NULL && s->linker_has_input)
-       {
-         /* DT_PREINIT_ARRAY is not allowed in shared library.  */
-         if (! bfd_link_executable (info))
-           {
-             bfd *sub;
-             asection *o;
-
-             for (sub = info->input_bfds; sub != NULL;
-                  sub = sub->link.next)
-               if (bfd_get_flavour (sub) == bfd_target_elf_flavour)
-                 for (o = sub->sections; o != NULL; o = o->next)
-                   if (elf_section_data (o)->this_hdr.sh_type
-                       == SHT_PREINIT_ARRAY)
-                     {
-                       _bfd_error_handler
-                         (_("%B: .preinit_array section is not allowed in DSO"),
-                          sub);
-                       break;
-                     }
-
-             bfd_set_error (bfd_error_nonrepresentable_section);
-             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;
-       }
-      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;
-       }
-      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;
-       }
-
-      dynstr = bfd_get_linker_section (dynobj, ".dynstr");
-      /* If .dynstr is excluded from the link, we don't want any of
-        these tags.  Strictly, we should be checking each section
-        individually;  This quick check covers for the case where
-        someone does a /DISCARD/ : { *(*) }.  */
-      if (dynstr != NULL && dynstr->output_section != bfd_abs_section_ptr)
-       {
-         bfd_size_type strsize;
-
-         strsize = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
-         if ((info->emit_hash
-              && !_bfd_elf_add_dynamic_entry (info, DT_HASH, 0))
-             || (info->emit_gnu_hash
-                 && !_bfd_elf_add_dynamic_entry (info, DT_GNU_HASH, 0))
-             || !_bfd_elf_add_dynamic_entry (info, DT_STRTAB, 0)
-             || !_bfd_elf_add_dynamic_entry (info, DT_SYMTAB, 0)
-             || !_bfd_elf_add_dynamic_entry (info, DT_STRSZ, strsize)
-             || !_bfd_elf_add_dynamic_entry (info, DT_SYMENT,
-                                             bed->s->sizeof_sym))
-           return FALSE;
-       }
-    }
-
-  if (! _bfd_elf_maybe_strip_eh_frame_hdr (info))
-    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;
-
-  if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
-    {
-      unsigned long section_sym_count;
-      struct bfd_elf_version_tree *verdefs;
-      asection *s;
-
-      /* Set up the version definition section.  */
-      s = bfd_get_linker_section (dynobj, ".gnu.version_d");
-      BFD_ASSERT (s != NULL);
-
-      /* We may have created additional version definitions if we are
-        just linking a regular application.  */
-      verdefs = info->version_info;
+      /* We may have created additional version definitions if we are
+        just linking a regular application.  */
+      verdefs = info->version_info;
 
       /* Skip anonymous version tag.  */
       if (verdefs != NULL && verdefs->vernum == 0)
@@ -6295,7 +6126,6 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
        {
          unsigned int cdefs;
          bfd_size_type size;
-         struct bfd_elf_version_tree *t;
          bfd_byte *p;
          Elf_Internal_Verdef def;
          Elf_Internal_Verdaux defaux;
@@ -6466,56 +6296,450 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
              if (t->next != NULL && t->next->vernum == 0)
                BFD_ASSERT (t->next->next == NULL);
 
-             if (t->next != NULL && t->next->vernum != 0)
-               def.vd_next = (sizeof (Elf_External_Verdef)
-                              + (cdeps + 1) * sizeof (Elf_External_Verdaux));
+             if (t->next != NULL && t->next->vernum != 0)
+               def.vd_next = (sizeof (Elf_External_Verdef)
+                              + (cdeps + 1) * sizeof (Elf_External_Verdaux));
+
+             _bfd_elf_swap_verdef_out (output_bfd, &def,
+                                       (Elf_External_Verdef *) p);
+             p += sizeof (Elf_External_Verdef);
+
+             defaux.vda_name = h->dynstr_index;
+             _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr,
+                                     h->dynstr_index);
+             defaux.vda_next = 0;
+             if (t->deps != NULL)
+               defaux.vda_next = sizeof (Elf_External_Verdaux);
+             t->name_indx = defaux.vda_name;
+
+             _bfd_elf_swap_verdaux_out (output_bfd, &defaux,
+                                        (Elf_External_Verdaux *) p);
+             p += sizeof (Elf_External_Verdaux);
+
+             for (n = t->deps; n != NULL; n = n->next)
+               {
+                 if (n->version_needed == NULL)
+                   {
+                     /* This can happen if there was an error in the
+                        version script.  */
+                     defaux.vda_name = 0;
+                   }
+                 else
+                   {
+                     defaux.vda_name = n->version_needed->name_indx;
+                     _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr,
+                                             defaux.vda_name);
+                   }
+                 if (n->next == NULL)
+                   defaux.vda_next = 0;
+                 else
+                   defaux.vda_next = sizeof (Elf_External_Verdaux);
+
+                 _bfd_elf_swap_verdaux_out (output_bfd, &defaux,
+                                            (Elf_External_Verdaux *) p);
+                 p += sizeof (Elf_External_Verdaux);
+               }
+           }
+
+         elf_tdata (output_bfd)->cverdefs = cdefs;
+       }
+
+      /* Work out the size of the version reference section.  */
+
+      s = bfd_get_linker_section (dynobj, ".gnu.version_r");
+      BFD_ASSERT (s != NULL);
+      {
+       struct elf_find_verdep_info sinfo;
+
+       sinfo.info = info;
+       sinfo.vers = elf_tdata (output_bfd)->cverdefs;
+       if (sinfo.vers == 0)
+         sinfo.vers = 1;
+       sinfo.failed = FALSE;
+
+       elf_link_hash_traverse (elf_hash_table (info),
+                               _bfd_elf_link_find_version_dependencies,
+                               &sinfo);
+       if (sinfo.failed)
+         return FALSE;
+
+       if (elf_tdata (output_bfd)->verref == NULL)
+         s->flags |= SEC_EXCLUDE;
+       else
+         {
+           Elf_Internal_Verneed *vn;
+           unsigned int size;
+           unsigned int crefs;
+           bfd_byte *p;
+
+           /* Build the version dependency section.  */
+           size = 0;
+           crefs = 0;
+           for (vn = elf_tdata (output_bfd)->verref;
+                vn != NULL;
+                vn = vn->vn_nextref)
+             {
+               Elf_Internal_Vernaux *a;
+
+               size += sizeof (Elf_External_Verneed);
+               ++crefs;
+               for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
+                 size += sizeof (Elf_External_Vernaux);
+             }
+
+           s->size = size;
+           s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
+           if (s->contents == NULL)
+             return FALSE;
+
+           p = s->contents;
+           for (vn = elf_tdata (output_bfd)->verref;
+                vn != NULL;
+                vn = vn->vn_nextref)
+             {
+               unsigned int caux;
+               Elf_Internal_Vernaux *a;
+               size_t indx;
+
+               caux = 0;
+               for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
+                 ++caux;
+
+               vn->vn_version = VER_NEED_CURRENT;
+               vn->vn_cnt = caux;
+               indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                           elf_dt_name (vn->vn_bfd) != NULL
+                                           ? elf_dt_name (vn->vn_bfd)
+                                           : lbasename (vn->vn_bfd->filename),
+                                           FALSE);
+               if (indx == (size_t) -1)
+                 return FALSE;
+               vn->vn_file = indx;
+               vn->vn_aux = sizeof (Elf_External_Verneed);
+               if (vn->vn_nextref == NULL)
+                 vn->vn_next = 0;
+               else
+                 vn->vn_next = (sizeof (Elf_External_Verneed)
+                               + caux * sizeof (Elf_External_Vernaux));
+
+               _bfd_elf_swap_verneed_out (output_bfd, vn,
+                                          (Elf_External_Verneed *) p);
+               p += sizeof (Elf_External_Verneed);
+
+               for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
+                 {
+                   a->vna_hash = bfd_elf_hash (a->vna_nodename);
+                   indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                               a->vna_nodename, FALSE);
+                   if (indx == (size_t) -1)
+                     return FALSE;
+                   a->vna_name = indx;
+                   if (a->vna_nextptr == NULL)
+                     a->vna_next = 0;
+                   else
+                     a->vna_next = sizeof (Elf_External_Vernaux);
+
+                   _bfd_elf_swap_vernaux_out (output_bfd, a,
+                                              (Elf_External_Vernaux *) p);
+                   p += sizeof (Elf_External_Vernaux);
+                 }
+             }
+
+           elf_tdata (output_bfd)->cverrefs = crefs;
+         }
+      }
+    }
+
+  bed = get_elf_backend_data (output_bfd);
+
+  if (info->gc_sections && bed->can_gc_sections)
+    {
+      struct elf_gc_sweep_symbol_info sweep_info;
+      unsigned long section_sym_count;
+
+      /* Remove the symbols that were in the swept sections from the
+        dynamic symbol table.  GCFIXME: Anyone know how to get them
+        out of the static symbol table as well?  */
+      sweep_info.info = info;
+      sweep_info.hide_symbol = bed->elf_backend_hide_symbol;
+      elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
+                             &sweep_info);
+
+      /* We need to reassign dynsym indices now that symbols may have
+        been removed.  See the call in `bfd_elf_size_dynsym_hash_dynstr'
+        for the details of the conditions used here.  */
+      if (elf_hash_table (info)->dynamic_sections_created
+         || bed->always_renumber_dynsyms)
+       _bfd_elf_link_renumber_dynsyms (output_bfd, info, &section_sym_count);
+    }
+
+  /* Any syms created from now on start with -1 in
+     got.refcount/offset and plt.refcount/offset.  */
+  elf_hash_table (info)->init_got_refcount
+    = elf_hash_table (info)->init_got_offset;
+  elf_hash_table (info)->init_plt_refcount
+    = elf_hash_table (info)->init_plt_offset;
+
+  if (bfd_link_relocatable (info)
+      && !_bfd_elf_size_group_sections (info))
+    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;
+
+  /* Determine any GNU_STACK segment requirements, after the backend
+     has had a chance to set a default segment size.  */
+  if (info->execstack)
+    elf_stack_flags (output_bfd) = PF_R | PF_W | PF_X;
+  else if (info->noexecstack)
+    elf_stack_flags (output_bfd) = PF_R | PF_W;
+  else
+    {
+      bfd *inputobj;
+      asection *notesec = NULL;
+      int exec = 0;
+
+      for (inputobj = info->input_bfds;
+          inputobj;
+          inputobj = inputobj->link.next)
+       {
+         asection *s;
+
+         if (inputobj->flags
+             & (DYNAMIC | EXEC_P | BFD_PLUGIN | BFD_LINKER_CREATED))
+           continue;
+         s = bfd_get_section_by_name (inputobj, ".note.GNU-stack");
+         if (s)
+           {
+             if (s->flags & SEC_CODE)
+               exec = PF_X;
+             notesec = s;
+           }
+         else if (bed->default_execstack)
+           exec = PF_X;
+       }
+      if (notesec || info->stacksize > 0)
+       elf_stack_flags (output_bfd) = PF_R | PF_W | exec;
+      if (notesec && exec && bfd_link_relocatable (info)
+         && notesec->output_section != bfd_abs_section_ptr)
+       notesec->output_section->flags |= SEC_CODE;
+    }
+
+  if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
+    {
+      struct elf_info_failed eif;
+      struct elf_link_hash_entry *h;
+      asection *dynstr;
+      asection *s;
+
+      *sinterpptr = bfd_get_linker_section (dynobj, ".interp");
+      BFD_ASSERT (*sinterpptr != NULL || !bfd_link_executable (info) || info->nointerp);
+
+      if (info->symbolic)
+       {
+         if (!_bfd_elf_add_dynamic_entry (info, DT_SYMBOLIC, 0))
+           return FALSE;
+         info->flags |= DF_SYMBOLIC;
+       }
+
+      if (rpath != NULL)
+       {
+         size_t indx;
+         bfd_vma tag;
+
+         indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, rpath,
+                                     TRUE);
+         if (indx == (size_t) -1)
+           return FALSE;
+
+         tag = info->new_dtags ? DT_RUNPATH : DT_RPATH;
+         if (!_bfd_elf_add_dynamic_entry (info, tag, indx))
+           return FALSE;
+       }
+
+      if (filter_shlib != NULL)
+       {
+         size_t indx;
+
+         indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                     filter_shlib, TRUE);
+         if (indx == (size_t) -1
+             || !_bfd_elf_add_dynamic_entry (info, DT_FILTER, indx))
+           return FALSE;
+       }
+
+      if (auxiliary_filters != NULL)
+       {
+         const char * const *p;
+
+         for (p = auxiliary_filters; *p != NULL; p++)
+           {
+             size_t indx;
+
+             indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                         *p, TRUE);
+             if (indx == (size_t) -1
+                 || !_bfd_elf_add_dynamic_entry (info, DT_AUXILIARY, indx))
+               return FALSE;
+           }
+       }
+
+      if (audit != NULL)
+       {
+         size_t indx;
+
+         indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, audit,
+                                     TRUE);
+         if (indx == (size_t) -1
+             || !_bfd_elf_add_dynamic_entry (info, DT_AUDIT, indx))
+           return FALSE;
+       }
+
+      if (depaudit != NULL)
+       {
+         size_t indx;
+
+         indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, depaudit,
+                                     TRUE);
+         if (indx == (size_t) -1
+             || !_bfd_elf_add_dynamic_entry (info, DT_DEPAUDIT, indx))
+           return FALSE;
+       }
+
+      eif.info = info;
+      eif.failed = FALSE;
+
+      /* Find all symbols which were defined in a dynamic object and make
+        the backend pick a reasonable value for them.  */
+      elf_link_hash_traverse (elf_hash_table (info),
+                             _bfd_elf_adjust_dynamic_symbol,
+                             &eif);
+      if (eif.failed)
+       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
+        now so that we know the final size of the .dynamic section.  */
+
+      /* If there are initialization and/or finalization functions to
+        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)
+          : NULL);
+      if (h != NULL
+         && (h->ref_regular
+             || h->def_regular))
+       {
+         if (!_bfd_elf_add_dynamic_entry (info, DT_INIT, 0))
+           return FALSE;
+       }
+      h = (info->fini_function
+          ? elf_link_hash_lookup (elf_hash_table (info),
+                                  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;
+       }
+
+      s = bfd_get_section_by_name (output_bfd, ".preinit_array");
+      if (s != NULL && s->linker_has_input)
+       {
+         /* DT_PREINIT_ARRAY is not allowed in shared library.  */
+         if (! bfd_link_executable (info))
+           {
+             bfd *sub;
+             asection *o;
+
+             for (sub = info->input_bfds; sub != NULL;
+                  sub = sub->link.next)
+               if (bfd_get_flavour (sub) == bfd_target_elf_flavour)
+                 for (o = sub->sections; o != NULL; o = o->next)
+                   if (elf_section_data (o)->this_hdr.sh_type
+                       == SHT_PREINIT_ARRAY)
+                     {
+                       _bfd_error_handler
+                         (_("%B: .preinit_array section is not allowed in DSO"),
+                          sub);
+                       break;
+                     }
+
+             bfd_set_error (bfd_error_nonrepresentable_section);
+             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;
+       }
+      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;
+       }
+      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;
+       }
+
+      dynstr = bfd_get_linker_section (dynobj, ".dynstr");
+      /* If .dynstr is excluded from the link, we don't want any of
+        these tags.  Strictly, we should be checking each section
+        individually;  This quick check covers for the case where
+        someone does a /DISCARD/ : { *(*) }.  */
+      if (dynstr != NULL && dynstr->output_section != bfd_abs_section_ptr)
+       {
+         bfd_size_type strsize;
 
-             _bfd_elf_swap_verdef_out (output_bfd, &def,
-                                       (Elf_External_Verdef *) p);
-             p += sizeof (Elf_External_Verdef);
+         strsize = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
+         if ((info->emit_hash
+              && !_bfd_elf_add_dynamic_entry (info, DT_HASH, 0))
+             || (info->emit_gnu_hash
+                 && !_bfd_elf_add_dynamic_entry (info, DT_GNU_HASH, 0))
+             || !_bfd_elf_add_dynamic_entry (info, DT_STRTAB, 0)
+             || !_bfd_elf_add_dynamic_entry (info, DT_SYMTAB, 0)
+             || !_bfd_elf_add_dynamic_entry (info, DT_STRSZ, strsize)
+             || !_bfd_elf_add_dynamic_entry (info, DT_SYMENT,
+                                             bed->s->sizeof_sym))
+           return FALSE;
+       }
+    }
 
-             defaux.vda_name = h->dynstr_index;
-             _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr,
-                                     h->dynstr_index);
-             defaux.vda_next = 0;
-             if (t->deps != NULL)
-               defaux.vda_next = sizeof (Elf_External_Verdaux);
-             t->name_indx = defaux.vda_name;
+  if (! _bfd_elf_maybe_strip_eh_frame_hdr (info))
+    return FALSE;
 
-             _bfd_elf_swap_verdaux_out (output_bfd, &defaux,
-                                        (Elf_External_Verdaux *) p);
-             p += sizeof (Elf_External_Verdaux);
+  /* 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;
 
-             for (n = t->deps; n != NULL; n = n->next)
-               {
-                 if (n->version_needed == NULL)
-                   {
-                     /* This can happen if there was an error in the
-                        version script.  */
-                     defaux.vda_name = 0;
-                   }
-                 else
-                   {
-                     defaux.vda_name = n->version_needed->name_indx;
-                     _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr,
-                                             defaux.vda_name);
-                   }
-                 if (n->next == NULL)
-                   defaux.vda_next = 0;
-                 else
-                   defaux.vda_next = sizeof (Elf_External_Verdaux);
+  if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
+    {
+      unsigned long section_sym_count;
 
-                 _bfd_elf_swap_verdaux_out (output_bfd, &defaux,
-                                            (Elf_External_Verdaux *) p);
-                 p += sizeof (Elf_External_Verdaux);
-               }
-           }
+      if (elf_tdata (output_bfd)->cverdefs)
+       {
+         unsigned int crefs = elf_tdata (output_bfd)->cverdefs;
 
          if (!_bfd_elf_add_dynamic_entry (info, DT_VERDEF, 0)
-             || !_bfd_elf_add_dynamic_entry (info, DT_VERDEFNUM, cdefs))
+             || !_bfd_elf_add_dynamic_entry (info, DT_VERDEFNUM, crefs))
            return FALSE;
-
-         elf_tdata (output_bfd)->cverdefs = cdefs;
        }
 
       if ((info->new_dtags && info->flags) || (info->flags & DF_STATIC_TLS))
@@ -6539,120 +6763,22 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
            return FALSE;
        }
 
-      /* Work out the size of the version reference section.  */
-
-      s = bfd_get_linker_section (dynobj, ".gnu.version_r");
-      BFD_ASSERT (s != NULL);
-      {
-       struct elf_find_verdep_info sinfo;
-
-       sinfo.info = info;
-       sinfo.vers = elf_tdata (output_bfd)->cverdefs;
-       if (sinfo.vers == 0)
-         sinfo.vers = 1;
-       sinfo.failed = FALSE;
-
-       elf_link_hash_traverse (elf_hash_table (info),
-                               _bfd_elf_link_find_version_dependencies,
-                               &sinfo);
-       if (sinfo.failed)
-         return FALSE;
-
-       if (elf_tdata (output_bfd)->verref == NULL)
-         s->flags |= SEC_EXCLUDE;
-       else
-         {
-           Elf_Internal_Verneed *t;
-           unsigned int size;
-           unsigned int crefs;
-           bfd_byte *p;
-
-           /* Build the version dependency section.  */
-           size = 0;
-           crefs = 0;
-           for (t = elf_tdata (output_bfd)->verref;
-                t != NULL;
-                t = t->vn_nextref)
-             {
-               Elf_Internal_Vernaux *a;
-
-               size += sizeof (Elf_External_Verneed);
-               ++crefs;
-               for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
-                 size += sizeof (Elf_External_Vernaux);
-             }
-
-           s->size = size;
-           s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
-           if (s->contents == NULL)
-             return FALSE;
-
-           p = s->contents;
-           for (t = elf_tdata (output_bfd)->verref;
-                t != NULL;
-                t = t->vn_nextref)
-             {
-               unsigned int caux;
-               Elf_Internal_Vernaux *a;
-               size_t indx;
-
-               caux = 0;
-               for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
-                 ++caux;
-
-               t->vn_version = VER_NEED_CURRENT;
-               t->vn_cnt = caux;
-               indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                           elf_dt_name (t->vn_bfd) != NULL
-                                           ? elf_dt_name (t->vn_bfd)
-                                           : lbasename (t->vn_bfd->filename),
-                                           FALSE);
-               if (indx == (size_t) -1)
-                 return FALSE;
-               t->vn_file = indx;
-               t->vn_aux = sizeof (Elf_External_Verneed);
-               if (t->vn_nextref == NULL)
-                 t->vn_next = 0;
-               else
-                 t->vn_next = (sizeof (Elf_External_Verneed)
-                               + caux * sizeof (Elf_External_Vernaux));
-
-               _bfd_elf_swap_verneed_out (output_bfd, t,
-                                          (Elf_External_Verneed *) p);
-               p += sizeof (Elf_External_Verneed);
-
-               for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
-                 {
-                   a->vna_hash = bfd_elf_hash (a->vna_nodename);
-                   indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                               a->vna_nodename, FALSE);
-                   if (indx == (size_t) -1)
-                     return FALSE;
-                   a->vna_name = indx;
-                   if (a->vna_nextptr == NULL)
-                     a->vna_next = 0;
-                   else
-                     a->vna_next = sizeof (Elf_External_Vernaux);
-
-                   _bfd_elf_swap_vernaux_out (output_bfd, a,
-                                              (Elf_External_Vernaux *) p);
-                   p += sizeof (Elf_External_Vernaux);
-                 }
-             }
-
-           if (!_bfd_elf_add_dynamic_entry (info, DT_VERNEED, 0)
-               || !_bfd_elf_add_dynamic_entry (info, DT_VERNEEDNUM, crefs))
-             return FALSE;
+      if (elf_tdata (output_bfd)->cverrefs)
+       {
+         unsigned int crefs = elf_tdata (output_bfd)->cverrefs;
 
-           elf_tdata (output_bfd)->cverrefs = crefs;
-         }
-      }
+         if (!_bfd_elf_add_dynamic_entry (info, DT_VERNEED, 0)
+             || !_bfd_elf_add_dynamic_entry (info, DT_VERNEEDNUM, crefs))
+           return FALSE;
+       }
 
       if ((elf_tdata (output_bfd)->cverrefs == 0
           && elf_tdata (output_bfd)->cverdefs == 0)
          || _bfd_elf_link_renumber_dynsyms (output_bfd, info,
                                             &section_sym_count) == 0)
        {
+         asection *s;
+
          s = bfd_get_linker_section (dynobj, ".gnu.version");
          s->flags |= SEC_EXCLUDE;
        }
@@ -6711,6 +6837,8 @@ bfd_boolean
 bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
 {
   const struct elf_backend_data *bed;
+  unsigned long section_sym_count;
+  bfd_size_type dynsymcount;
 
   if (!is_elf_hash_table (info->hash))
     return TRUE;
@@ -6718,24 +6846,30 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
   bed = get_elf_backend_data (output_bfd);
   (*bed->elf_backend_init_index_section) (output_bfd, info);
 
+  /* Assign dynsym indices.  In a shared library we generate a section
+     symbol for each output section, which come first.  Next come all
+     of the back-end allocated local dynamic syms, followed by the rest
+     of the global symbols.
+
+     This is usually not needed for static binaries, however backends
+     can request to always do it, e.g. the MIPS backend uses dynamic
+     symbol counts to lay out GOT, which will be produced in the
+     presence of GOT relocations even in static binaries (holding fixed
+     data in that case, to satisfy those relocations).  */
+
+  if (elf_hash_table (info)->dynamic_sections_created
+      || bed->always_renumber_dynsyms)
+    dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info,
+                                                 &section_sym_count);
+
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       bfd *dynobj;
       asection *s;
-      bfd_size_type dynsymcount;
-      unsigned long section_sym_count;
       unsigned int dtagcount;
 
       dynobj = elf_hash_table (info)->dynobj;
 
-      /* Assign dynsym indicies.  In a shared library we generate a
-        section symbol for each output section, which come first.
-        Next come all of the back-end allocated local dynamic syms,
-        followed by the rest of the global symbols.  */
-
-      dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info,
-                                                   &section_sym_count);
-
       /* Work out the size of the symbol version section.  */
       s = bfd_get_linker_section (dynobj, ".gnu.version");
       BFD_ASSERT (s != NULL);
@@ -7166,9 +7300,10 @@ _bfd_elf_link_hash_hide_symbol (struct bfd_link_info *info,
       h->forced_local = 1;
       if (h->dynindx != -1)
        {
-         h->dynindx = -1;
          _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
                                  h->dynstr_index);
+         h->dynindx = -1;
+         h->dynstr_index = 0;
        }
     }
 }
@@ -8689,7 +8824,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
                else
                  {
                    /* Section size is only divisible by rela.  */
-                   if (use_rela_initialised && (use_rela == FALSE))
+                   if (use_rela_initialised && !use_rela)
                      {
                        _bfd_error_handler (_("%B: Unable to sort relocs - "
                                              "they are in more than one size"),
@@ -8707,7 +8842,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
            else if ((o->size % bed->s->sizeof_rel) == 0)
              {
                /* Section size is only divisible by rel.  */
-               if (use_rela_initialised && (use_rela == TRUE))
+               if (use_rela_initialised && use_rela)
                  {
                    _bfd_error_handler (_("%B: Unable to sort relocs - "
                                          "they are in more than one size"),
@@ -8746,7 +8881,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
                else
                  {
                    /* Section size is only divisible by rela.  */
-                   if (use_rela_initialised && (use_rela == FALSE))
+                   if (use_rela_initialised && !use_rela)
                      {
                        _bfd_error_handler (_("%B: Unable to sort relocs - "
                                              "they are in more than one size"),
@@ -8764,7 +8899,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
            else if ((o->size % bed->s->sizeof_rel) == 0)
              {
                /* Section size is only divisible by rel.  */
-               if (use_rela_initialised && (use_rela == TRUE))
+               if (use_rela_initialised && use_rela)
                  {
                    _bfd_error_handler (_("%B: Unable to sort relocs - "
                                          "they are in more than one size"),
@@ -9392,8 +9527,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
       def_bfd = flinfo->output_bfd;
       if (hi->root.u.def.section != bfd_abs_section_ptr)
        def_bfd = hi->root.u.def.section->owner;
-      _bfd_error_handler (msg, flinfo->output_bfd, def_bfd,
-                         h->root.root.string);
+      _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;
@@ -10142,7 +10277,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
          continue;
        }
 
-      if (bfd_link_relocatable (flinfo->info)
+      if (!flinfo->info->resolve_section_groups
          && (o->flags & (SEC_LINKER_CREATED | SEC_GROUP)) == SEC_GROUP)
        {
          /* Deal with the group signature symbol.  */
@@ -10150,6 +10285,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
          unsigned long symndx = sec_data->this_hdr.sh_info;
          asection *osec = o->output_section;
 
+         BFD_ASSERT (bfd_link_relocatable (flinfo->info));
          if (symndx >= locsymcount
              || (elf_bad_symtab (input_bfd)
                  && flinfo->sections[symndx] == NULL))
@@ -10266,7 +10402,8 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                                 ".fini_array") == 0))
              && (o->name[6] == 0 || o->name[6] == '.'))
            {
-             if (o->size != o->reloc_count * address_size)
+             if (o->size * bed->s->int_rels_per_ext_rel
+                 != o->reloc_count * address_size)
                {
                  _bfd_error_handler
                    /* xgettext:c-format */
@@ -10290,7 +10427,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
             relocs against removed link-once sections.  */
 
          rel = internal_relocs;
-         relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
+         relend = rel + o->reloc_count;
          for ( ; rel < relend; rel++)
            {
              unsigned long r_symndx = rel->r_info >> r_sym_shift;
@@ -10320,7 +10457,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                        /* xgettext:c-format */
                        (_("error: %B contains a reloc (0x%s) for section %A "
                           "that references a non-existent global symbol"),
-                        input_bfd, o, buffer);
+                        input_bfd, buffer, o);
                      bfd_set_error (bfd_error_bad_value);
                      return FALSE;
                    }
@@ -10336,7 +10473,8 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                     linker may attach linker created dynamic sections
                     to the plugin bfd.  Symbols defined in linker
                     created sections are not plugin symbols.  */
-                 if (h->root.non_ir_ref
+                 if ((h->root.non_ir_ref_regular
+                      || h->root.non_ir_ref_dynamic)
                      && (h->root.type == bfd_link_hash_defined
                          || h->root.type == bfd_link_hash_defweak)
                      && (h->root.u.def.section->flags
@@ -10478,7 +10616,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
              /* Adjust the reloc addresses and symbol indices.  */
 
              irela = internal_relocs;
-             irelaend = irela + o->reloc_count * bed->s->int_rels_per_ext_rel;
+             irelaend = irela + o->reloc_count;
              rel_hash = esdo->rel.hashes + esdo->rel.count;
              /* We start processing the REL relocs, if any.  When we reach
                 IRELAMID in the loop, we switch to the RELA relocs.  */
@@ -11075,9 +11213,8 @@ elf_fixup_link_order (bfd *abfd, asection *o)
              /* xgettext:c-format */
              (_("%A has both ordered [`%A' in %B] "
                 "and unordered [`%A' in %B] sections"),
-              o, linkorder_sec,
-              linkorder_sec->owner, other_sec,
-              other_sec->owner);
+              o, linkorder_sec, linkorder_sec->owner,
+              other_sec, other_sec->owner);
          else
            _bfd_error_handler
              (_("%A has both ordered and unordered sections"), o);
@@ -11142,10 +11279,11 @@ elf_output_implib (bfd *abfd, struct bfd_link_info *info)
   if (!bfd_set_format (implib_bfd, bfd_object))
     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))
+      || !bfd_set_file_flags (implib_bfd, flags & ~EXEC_P))
     return FALSE;
 
   /* Copy architecture of output file to import library file.  */
@@ -11652,8 +11790,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
   if (max_internal_reloc_count != 0)
     {
-      amt = max_internal_reloc_count * bed->s->int_rels_per_ext_rel;
-      amt *= sizeof (Elf_Internal_Rela);
+      amt = max_internal_reloc_count * sizeof (Elf_Internal_Rela);
       flinfo.internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt);
       if (flinfo.internal_relocs == NULL)
        goto error_return;
@@ -11974,24 +12111,28 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
     {
       /* Finish up and write out the symbol string table (.strtab)
         section.  */
-      Elf_Internal_Shdr *symstrtab_hdr;
+      Elf_Internal_Shdr *symstrtab_hdr = NULL;
       file_ptr off = symtab_hdr->sh_offset + symtab_hdr->sh_size;
 
-      symtab_shndx_hdr = & elf_symtab_shndx_list (abfd)->hdr;
-      if (symtab_shndx_hdr != NULL && symtab_shndx_hdr->sh_name != 0)
+      if (elf_symtab_shndx_list (abfd))
        {
-         symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
-         symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
-         symtab_shndx_hdr->sh_addralign = sizeof (Elf_External_Sym_Shndx);
-         amt = bfd_get_symcount (abfd) * sizeof (Elf_External_Sym_Shndx);
-         symtab_shndx_hdr->sh_size = amt;
+         symtab_shndx_hdr = & elf_symtab_shndx_list (abfd)->hdr;
+
+         if (symtab_shndx_hdr != NULL && symtab_shndx_hdr->sh_name != 0)
+           {
+             symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
+             symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
+             symtab_shndx_hdr->sh_addralign = sizeof (Elf_External_Sym_Shndx);
+             amt = bfd_get_symcount (abfd) * sizeof (Elf_External_Sym_Shndx);
+             symtab_shndx_hdr->sh_size = amt;
 
-         off = _bfd_elf_assign_file_position_for_section (symtab_shndx_hdr,
-                                                          off, TRUE);
+             off = _bfd_elf_assign_file_position_for_section (symtab_shndx_hdr,
+                                                              off, TRUE);
 
-         if (bfd_seek (abfd, symtab_shndx_hdr->sh_offset, SEEK_SET) != 0
-             || (bfd_bwrite (flinfo.symshndxbuf, amt, abfd) != amt))
-           return FALSE;
+             if (bfd_seek (abfd, symtab_shndx_hdr->sh_offset, SEEK_SET) != 0
+                 || (bfd_bwrite (flinfo.symshndxbuf, amt, abfd) != amt))
+               return FALSE;
+           }
        }
 
       symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
@@ -12063,6 +12204,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
          Elf_Internal_Dyn dyn;
          const char *name;
          unsigned int type;
+         bfd_size_type sh_size;
+         bfd_vma sh_addr;
 
          bed->s->swap_dyn_in (dynobj, dyncon, &dyn);
 
@@ -12196,8 +12339,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                type = SHT_REL;
              else
                type = SHT_RELA;
-             dyn.d_un.d_val = 0;
-             dyn.d_un.d_ptr = 0;
+             sh_size = 0;
+             sh_addr = 0;
              for (i = 1; i < elf_numsections (abfd); i++)
                {
                  Elf_Internal_Shdr *hdr;
@@ -12206,28 +12349,42 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                  if (hdr->sh_type == type
                      && (hdr->sh_flags & SHF_ALLOC) != 0)
                    {
-                     if (dyn.d_tag == DT_RELSZ || dyn.d_tag == DT_RELASZ)
-                       dyn.d_un.d_val += hdr->sh_size;
-                     else
-                       {
-                         if (dyn.d_un.d_ptr == 0
-                             || hdr->sh_addr < dyn.d_un.d_ptr)
-                           dyn.d_un.d_ptr = hdr->sh_addr;
-                       }
+                     sh_size += hdr->sh_size;
+                     if (sh_addr == 0
+                         || sh_addr > hdr->sh_addr)
+                       sh_addr = hdr->sh_addr;
                    }
                }
+
              if (bed->dtrel_excludes_plt && htab->srelplt != NULL)
                {
                  /* Don't count procedure linkage table relocs in the
                     overall reloc count.  */
-                 if (dyn.d_tag == DT_RELSZ || dyn.d_tag == DT_RELASZ)
-                   dyn.d_un.d_val -= htab->srelplt->size;
+                 sh_size -= htab->srelplt->size;
+                 if (sh_size == 0)
+                   /* If the size is zero, make the address zero too.
+                      This is to avoid a glibc bug.  If the backend
+                      emits DT_RELA/DT_RELASZ even when DT_RELASZ is
+                      zero, then we'll put DT_RELA at the end of
+                      DT_JMPREL.  glibc will interpret the end of
+                      DT_RELA matching the end of DT_JMPREL as the
+                      case where DT_RELA includes DT_JMPREL, and for
+                      LD_BIND_NOW will decide that processing DT_RELA
+                      will process the PLT relocs too.  Net result:
+                      No PLT relocs applied.  */
+                   sh_addr = 0;
+
                  /* If .rela.plt is the first .rela section, exclude
                     it from DT_RELA.  */
-                 else if (dyn.d_un.d_ptr == (htab->srelplt->output_section->vma
-                                             + htab->srelplt->output_offset))
-                   dyn.d_un.d_ptr += htab->srelplt->size;
+                 else if (sh_addr == (htab->srelplt->output_section->vma
+                                      + htab->srelplt->output_offset))
+                   sh_addr += htab->srelplt->size;
                }
+
+             if (dyn.d_tag == DT_RELSZ || dyn.d_tag == DT_RELASZ)
+               dyn.d_un.d_val = sh_size;
+             else
+               dyn.d_un.d_ptr = sh_addr;
              break;
            }
          bed->s->swap_dyn_out (dynobj, &dyn, dyncon);
@@ -12307,10 +12464,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
        }
     }
 
-  if (bfd_link_relocatable (info))
+  if (!info->resolve_section_groups)
     {
       bfd_boolean failed = FALSE;
 
+      BFD_ASSERT (bfd_link_relocatable (info));
       bfd_map_over_sections (abfd, bfd_elf_set_group_contents, &failed);
       if (failed)
        goto error_return;
@@ -12416,8 +12574,6 @@ init_reloc_cookie_rels (struct elf_reloc_cookie *cookie,
                        struct bfd_link_info *info, bfd *abfd,
                        asection *sec)
 {
-  const struct elf_backend_data *bed;
-
   if (sec->reloc_count == 0)
     {
       cookie->rels = NULL;
@@ -12425,15 +12581,12 @@ init_reloc_cookie_rels (struct elf_reloc_cookie *cookie,
     }
   else
     {
-      bed = get_elf_backend_data (abfd);
-
       cookie->rels = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
                                                info->keep_memory);
       if (cookie->rels == NULL)
        return FALSE;
       cookie->rel = cookie->rels;
-      cookie->relend = (cookie->rels
-                       + sec->reloc_count * bed->s->int_rels_per_ext_rel);
+      cookie->relend = cookie->rels + sec->reloc_count;
     }
   cookie->rel = cookie->rels;
   return TRUE;
@@ -12512,6 +12665,24 @@ _bfd_elf_gc_mark_hook (asection *sec,
   return NULL;
 }
 
+/* Return the global debug definition section.  */
+
+static asection *
+elf_gc_mark_debug_section (asection *sec ATTRIBUTE_UNUSED,
+                          struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                          Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
+                          struct elf_link_hash_entry *h,
+                          Elf_Internal_Sym *sym ATTRIBUTE_UNUSED)
+{
+  if (h != NULL
+      && (h->root.type == bfd_link_hash_defined
+         || h->root.type == bfd_link_hash_defweak)
+      && (h->root.u.def.section->flags & SEC_DEBUGGING) != 0)
+    return h->root.u.def.section;
+
+  return NULL;
+}
+
 /* For undefined __start_<name> and __stop_<name> symbols, return the
    first input section matching <name>.  Return NULL otherwise.  */
 
@@ -12773,6 +12944,7 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
       asection *isec;
       bfd_boolean some_kept;
       bfd_boolean debug_frag_seen;
+      bfd_boolean has_kept_debug_info;
 
       if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
        continue;
@@ -12780,22 +12952,24 @@ _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 = 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)
            isec->gc_mark = 1;
-         else if (isec->gc_mark)
+         else if (isec->gc_mark
+                  && (isec->flags & SEC_ALLOC) != 0
+                  && elf_section_type (isec) != SHT_NOTE)
            some_kept = TRUE;
 
-         if (debug_frag_seen == FALSE
+         if (!debug_frag_seen
              && (isec->flags & SEC_DEBUGGING)
              && CONST_STRNEQ (isec->name, ".debug_line."))
            debug_frag_seen = TRUE;
        }
 
-      /* If no section in this file will be kept, then we can
-        toss out the debug and special sections.  */
+      /* If no non-note alloc section in this file will be kept, then
+        we can toss out the debug and special sections.  */
       if (!some_kept)
        continue;
 
@@ -12810,78 +12984,53 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
                    || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)
                   && elf_next_in_group (isec) == NULL)
            isec->gc_mark = 1;
+         if (isec->gc_mark && (isec->flags & SEC_DEBUGGING) != 0)
+           has_kept_debug_info = TRUE;
        }
 
-      if (! debug_frag_seen)
-       continue;
-
       /* Look for CODE sections which are going to be discarded,
         and find and discard any fragmented debug sections which
         are associated with that code section.  */
-      for (isec = ibfd->sections; isec != NULL; isec = isec->next)
-       if ((isec->flags & SEC_CODE) != 0
-           && isec->gc_mark == 0)
-         {
-           unsigned int ilen;
-           asection *dsec;
+      if (debug_frag_seen)
+       for (isec = ibfd->sections; isec != NULL; isec = isec->next)
+         if ((isec->flags & SEC_CODE) != 0
+             && isec->gc_mark == 0)
+           {
+             unsigned int ilen;
+             asection *dsec;
 
-           ilen = strlen (isec->name);
+             ilen = strlen (isec->name);
 
-           /* Association is determined by the name of the debug section
-              containing the name of the code section as a suffix.  For
-              example .debug_line.text.foo is a debug section associated
-              with .text.foo.  */
-           for (dsec = ibfd->sections; dsec != NULL; dsec = dsec->next)
-             {
-               unsigned int dlen;
+             /* Association is determined by the name of the debug
+                section containing the name of the code section as
+                a suffix.  For example .debug_line.text.foo is a
+                debug section associated with .text.foo.  */
+             for (dsec = ibfd->sections; dsec != NULL; dsec = dsec->next)
+               {
+                 unsigned int dlen;
 
-               if (dsec->gc_mark == 0
-                   || (dsec->flags & SEC_DEBUGGING) == 0)
-                 continue;
+                 if (dsec->gc_mark == 0
+                     || (dsec->flags & SEC_DEBUGGING) == 0)
+                   continue;
 
-               dlen = strlen (dsec->name);
+                 dlen = strlen (dsec->name);
 
-               if (dlen > ilen
-                   && strncmp (dsec->name + (dlen - ilen),
-                               isec->name, ilen) == 0)
-                 {
+                 if (dlen > ilen
+                     && strncmp (dsec->name + (dlen - ilen),
+                                 isec->name, ilen) == 0)
                    dsec->gc_mark = 0;
-                 }
-             }
+               }
          }
-    }
-  return TRUE;
-}
-
-/* Sweep symbols in swept sections.  Called via elf_link_hash_traverse.  */
-
-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);
-};
-
-static bfd_boolean
-elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *data)
-{
-  if (!h->mark
-      && (((h->root.type == bfd_link_hash_defined
-           || h->root.type == bfd_link_hash_defweak)
-          && !((h->def_regular || ELF_COMMON_DEF_P (h))
-               && h->root.u.def.section->gc_mark))
-         || h->root.type == bfd_link_hash_undefined
-         || h->root.type == bfd_link_hash_undefweak))
-    {
-      struct elf_gc_sweep_symbol_info *inf;
 
-      inf = (struct elf_gc_sweep_symbol_info *) data;
-      (*inf->hide_symbol) (inf->info, h, TRUE);
-      h->def_regular = 0;
-      h->ref_regular = 0;
-      h->ref_regular_nonweak = 0;
+      /* Mark debug sections referenced by kept debug sections.  */
+      if (has_kept_debug_info)
+       for (isec = ibfd->sections; isec != NULL; isec = isec->next)
+         if (isec->gc_mark
+             && (isec->flags & SEC_DEBUGGING) != 0)
+           if (!_bfd_elf_gc_mark (info, isec,
+                                  elf_gc_mark_debug_section))
+             return FALSE;
     }
-
   return TRUE;
 }
 
@@ -12896,8 +13045,6 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info)
   bfd *sub;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   gc_sweep_hook_fn gc_sweep_hook = bed->gc_sweep_hook;
-  unsigned long section_sym_count;
-  struct elf_gc_sweep_symbol_info sweep_info;
 
   for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
     {
@@ -12932,7 +13079,8 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info)
 
          if (info->print_gc_sections && o->size != 0)
            /* xgettext:c-format */
-           _bfd_error_handler (_("Removing unused section '%s' in file '%B'"), sub, o->name);
+           _bfd_error_handler (_("Removing unused section '%A' in file '%B'"),
+                               o, sub);
 
          /* But we also have to update some of the relocation
             info we collected before.  */
@@ -12963,15 +13111,6 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info)
        }
     }
 
-  /* Remove the symbols that were in the swept sections from the dynamic
-     symbol table.  GCFIXME: Anyone know how to get them out of the
-     static symbol table as well?  */
-  sweep_info.info = info;
-  sweep_info.hide_symbol = bed->elf_backend_hide_symbol;
-  elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
-                         &sweep_info);
-
-  _bfd_elf_link_renumber_dynsyms (abfd, info, &section_sym_count);
   return TRUE;
 }
 
@@ -13060,7 +13199,7 @@ elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
   bed = get_elf_backend_data (sec->owner);
   log_file_align = bed->s->log_file_align;
 
-  relend = relstart + sec->reloc_count * bed->s->int_rels_per_ext_rel;
+  relend = relstart + sec->reloc_count;
 
   for (rel = relstart; rel < relend; ++rel)
     if (rel->r_offset >= hstart && rel->r_offset < hend)
@@ -13700,6 +13839,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
   if (o != NULL)
     {
       asection *i;
+      int eh_changed = 0;
 
       for (i = o->map_head.s; i != NULL; i = i->map_head.s)
        {
@@ -13717,10 +13857,17 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
          if (_bfd_elf_discard_section_eh_frame (abfd, info, i,
                                                 bfd_elf_reloc_symbol_deleted_p,
                                                 &cookie))
-           changed = 1;
+           {
+             eh_changed = 1;
+             if (i->size != i->rawsize)
+               changed = 1;
+           }
 
          fini_reloc_cookie_for_section (&cookie, i);
        }
+      if (eh_changed)
+       elf_link_hash_traverse (elf_hash_table (info),
+                               _bfd_elf_adjust_eh_frame_global_symbol, NULL);
     }
 
   for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
This page took 0.048666 seconds and 4 git commands to generate.