Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 9728e29feaf82745358bd4ab4a59fae56d3268a8..027ce83ce1f4b40b6c225def377cd19058298719 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF linking support for BFD.
-   Copyright (C) 1995-2016 Free Software Foundation, Inc.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -429,6 +429,19 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
        return FALSE;
       htab->sdynbss = s;
 
+      if (bed->want_dynrelro)
+       {
+         /* Similarly, but for symbols that were originally in read-only
+            sections.  */
+         s = bfd_make_section_anyway_with_flags (abfd, ".data.rel.ro",
+                                                 (SEC_ALLOC | SEC_READONLY
+                                                  | SEC_HAS_CONTENTS
+                                                  | SEC_LINKER_CREATED));
+         if (s == NULL)
+           return FALSE;
+         htab->sdynrelro = s;
+       }
+
       /* The .rel[a].bss section holds copy relocs.  This section is not
         normally needed.  We need to create it here, though, so that the
         linker will map it to an output section.  We can't just create it
@@ -450,6 +463,19 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
              || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
            return FALSE;
          htab->srelbss = s;
+
+         if (bed->want_dynrelro)
+           {
+             s = (bfd_make_section_anyway_with_flags
+                  (abfd, (bed->rela_plts_and_copies_p
+                          ? ".rela.data.rel.ro" : ".rel.data.rel.ro"),
+                   flags | SEC_READONLY));
+             if (s == NULL
+                 || ! bfd_set_section_alignment (abfd, s,
+                                                 bed->s->log_file_align))
+               return FALSE;
+             htab->sreldynrelro = s;
+           }
        }
     }
 
@@ -652,6 +678,9 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
       && !h->def_regular)
     h->verinfo.verdef = NULL;
 
+  /* Make sure this symbol is not garbage collected.  */
+  h->mark = 1;
+
   h->def_regular = 1;
 
   if (hidden)
@@ -3793,6 +3822,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       const char *soname = NULL;
       char *audit = NULL;
       struct bfd_link_needed_list *rpath = NULL, *runpath = NULL;
+      const Elf_Internal_Phdr *phdr;
       int ret;
 
       /* ld --just-symbols and dynamic objects don't mix very well.
@@ -3942,6 +3972,21 @@ error_free_dyn:
          *pn = rpath;
        }
 
+      /* If we have a PT_GNU_RELRO program header, mark as read-only
+        all sections contained fully therein.  This makes relro
+        shared library sections appear as they will at run-time.  */
+      phdr = elf_tdata (abfd)->phdr + elf_elfheader (abfd)->e_phnum;
+      while (--phdr >= elf_tdata (abfd)->phdr)
+       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;
+           break;
+         }
+
       /* We do not want to include any of the sections in a dynamic
         object in the output file.  We hack by simply clobbering the
         list of sections in the BFD.  This could be handled more
@@ -5829,6 +5874,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
@@ -5848,7 +5925,6 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
   size_t soname_indx;
   bfd *dynobj;
   const struct elf_backend_data *bed;
-  struct elf_info_failed asvinfo;
 
   *sinterpptr = NULL;
 
@@ -5857,157 +5933,17 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
   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;
 
       eif.info = info;
       eif.failed = FALSE;
@@ -6107,154 +6043,30 @@ 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.  */
+      /* We may have created additional version definitions if we are
+        just linking a regular application.  */
+      verdefs = info->version_info;
 
-      /* 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;
-       }
+      /* Skip anonymous version tag.  */
+      if (verdefs != NULL && verdefs->vernum == 0)
+       verdefs = verdefs->next;
 
-      s = bfd_get_section_by_name (output_bfd, ".preinit_array");
-      if (s != NULL && s->linker_has_input)
+      if (verdefs == NULL && !info->create_default_symver)
+       s->flags |= SEC_EXCLUDE;
+      else
        {
-         /* 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;
-
-      /* Skip anonymous version tag.  */
-      if (verdefs != NULL && verdefs->vernum == 0)
-       verdefs = verdefs->next;
-
-      if (verdefs == NULL && !info->create_default_symver)
-       s->flags |= SEC_EXCLUDE;
-      else
-       {
-         unsigned int cdefs;
-         bfd_size_type size;
-         struct bfd_elf_version_tree *t;
-         bfd_byte *p;
-         Elf_Internal_Verdef def;
-         Elf_Internal_Verdaux defaux;
-         struct bfd_link_hash_entry *bh;
-         struct elf_link_hash_entry *h;
-         const char *name;
+         unsigned int cdefs;
+         bfd_size_type size;
+         bfd_byte *p;
+         Elf_Internal_Verdef def;
+         Elf_Internal_Verdaux defaux;
+         struct bfd_link_hash_entry *bh;
+         struct elf_link_hash_entry *h;
+         const char *name;
 
          cdefs = 0;
          size = 0;
@@ -6399,76 +6211,474 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
              h->type = STT_OBJECT;
              h->verinfo.vertree = t;
 
-             if (! bfd_elf_link_record_dynamic_symbol (info, h))
-               return FALSE;
+             if (! bfd_elf_link_record_dynamic_symbol (info, h))
+               return FALSE;
+
+             def.vd_version = VER_DEF_CURRENT;
+             def.vd_flags = 0;
+             if (t->globals.list == NULL
+                 && t->locals.list == NULL
+                 && ! t->used)
+               def.vd_flags |= VER_FLG_WEAK;
+             def.vd_ndx = t->vernum + (info->create_default_symver ? 2 : 1);
+             def.vd_cnt = cdeps + 1;
+             def.vd_hash = bfd_elf_hash (t->name);
+             def.vd_aux = sizeof (Elf_External_Verdef);
+             def.vd_next = 0;
+
+             /* If a basever node is next, it *must* be the last node in
+                the chain, otherwise Verdef construction breaks.  */
+             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));
+
+             _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);
+
+      _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 (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;
+       }
+
+      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;
+                     }
 
-             def.vd_version = VER_DEF_CURRENT;
-             def.vd_flags = 0;
-             if (t->globals.list == NULL
-                 && t->locals.list == NULL
-                 && ! t->used)
-               def.vd_flags |= VER_FLG_WEAK;
-             def.vd_ndx = t->vernum + (info->create_default_symver ? 2 : 1);
-             def.vd_cnt = cdeps + 1;
-             def.vd_hash = bfd_elf_hash (t->name);
-             def.vd_aux = sizeof (Elf_External_Verdef);
-             def.vd_next = 0;
+             bfd_set_error (bfd_error_nonrepresentable_section);
+             return FALSE;
+           }
 
-             /* If a basever node is next, it *must* be the last node in
-                the chain, otherwise Verdef construction breaks.  */
-             if (t->next != NULL && t->next->vernum == 0)
-               BFD_ASSERT (t->next->next == NULL);
+         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;
+       }
 
-             if (t->next != NULL && t->next->vernum != 0)
-               def.vd_next = (sizeof (Elf_External_Verdef)
-                              + (cdeps + 1) * sizeof (Elf_External_Verdaux));
+      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))
@@ -6492,120 +6702,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;
        }
@@ -7060,18 +7172,15 @@ _bfd_elf_link_hash_copy_indirect (struct bfd_link_info *info,
   struct elf_link_hash_table *htab;
 
   /* Copy down any references that we may have already seen to the
-     symbol which just became indirect if DIR isn't a hidden versioned
-     symbol.  */
+     symbol which just became indirect.  */
 
   if (dir->versioned != versioned_hidden)
-    {
-      dir->ref_dynamic |= ind->ref_dynamic;
-      dir->ref_regular |= ind->ref_regular;
-      dir->ref_regular_nonweak |= ind->ref_regular_nonweak;
-      dir->non_got_ref |= ind->non_got_ref;
-      dir->needs_plt |= ind->needs_plt;
-      dir->pointer_equality_needed |= ind->pointer_equality_needed;
-    }
+    dir->ref_dynamic |= ind->ref_dynamic;
+  dir->ref_regular |= ind->ref_regular;
+  dir->ref_regular_nonweak |= ind->ref_regular_nonweak;
+  dir->non_got_ref |= ind->non_got_ref;
+  dir->needs_plt |= ind->needs_plt;
+  dir->pointer_equality_needed |= ind->pointer_equality_needed;
 
   if (ind->root.type != bfd_link_hash_indirect)
     return;
@@ -12019,6 +12128,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);
 
@@ -12152,8 +12263,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;
@@ -12162,28 +12273,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);
@@ -12809,38 +12934,6 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
   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;
-}
-
 /* The sweep phase of garbage collection.  Remove all garbage sections.  */
 
 typedef bfd_boolean (*gc_sweep_hook_fn)
@@ -12852,8 +12945,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)
     {
@@ -12888,7 +12979,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 '%s' in file '%B'"),
+                               sub, o->name);
 
          /* But we also have to update some of the relocation
             info we collected before.  */
@@ -12919,15 +13011,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;
 }
 
This page took 0.040153 seconds and 4 git commands to generate.