This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb/binutils-2_29-branch] PR22150, ld keeps a version reference for gc'd symbols


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=c01ee74d3ad56a25272dfd5607ce4a807223e7e5

commit c01ee74d3ad56a25272dfd5607ce4a807223e7e5
Author: Alan Modra <amodra@gmail.com>
Date:   Tue Sep 19 11:59:30 2017 +0930

    PR22150, ld keeps a version reference for gc'd symbols
    
    elf_gc_sweep_symbol should run after verdefs are calculated, since
    the verdef code creates symbols for the versions.  However,
    elf_gc_sweep_symbol needs to run before verrefs so as to not emit
    useless verrefs for symbols that are gc'd.
    
    I've also removed a _bfd_elf_link_renumber_dynsyms calls added by
    Maciej after I fussed about it when reviewing.  On further examination
    the call appears to be unnecessary.  Looking at renumber_dynsyms also
    made me realize that the test to exclude .gnu.version has been wrong
    since 2016-04-26 (git commit d5486c4372), so fix that too.
    
    	PR 22150
    	* elflink.c (bfd_elf_size_dynamic_sections): Garbage collect
    	symbols before calculating verrefs.  Don't renumber dynsyms
    	after gc.  Exclude .gnu.version when zero or one dynsym.
    	Localize some vars and reindent.
    
    (cherry picked from commit 3d13f3e9bda5aada68915f5d958f731ae79ed41d)

Diff:
---
 bfd/ChangeLog |   8 +++
 bfd/elflink.c | 227 ++++++++++++++++++++++++++++------------------------------
 2 files changed, 118 insertions(+), 117 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 6dce8cc..fac3150 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,11 @@
+2017-09-19  Alan Modra  <amodra@gmail.com>
+
+	PR 22150
+	* elflink.c (bfd_elf_size_dynamic_sections): Garbage collect
+	symbols before calculating verrefs.  Don't renumber dynsyms
+	after gc.  Exclude .gnu.version when zero or one dynsym.
+	Localize some vars and reindent.
+
 2017-08-31  Alan Modra  <amodra@gmail.com>
 
 	* elf-eh-frame.c (_bfd_elf_parse_eh_frame): Don't exit early
diff --git a/bfd/elflink.c b/bfd/elflink.c
index e852762..02713a5 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -6000,19 +6000,18 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       struct elf_info_failed asvinfo;
       struct bfd_elf_version_tree *t;
       struct bfd_elf_version_expr *d;
-      struct elf_info_failed eif;
-      bfd_boolean all_defined;
       asection *s;
       size_t soname_indx;
 
-      eif.info = info;
-      eif.failed = FALSE;
-
       /* If we are supposed to export all symbols into the dynamic symbol
 	 table (this is not the normal case), then do so.  */
       if (info->export_dynamic
 	  || (bfd_link_executable (info) && info->dynamic))
 	{
+	  struct elf_info_failed eif;
+
+	  eif.info = info;
+	  eif.failed = FALSE;
 	  elf_link_hash_traverse (elf_hash_table (info),
 				  _bfd_elf_export_symbol,
 				  &eif);
@@ -6096,7 +6095,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       if (!info->allow_undefined_version)
 	{
 	  /* Check if all global versions have a definition.  */
-	  all_defined = TRUE;
+	  bfd_boolean all_defined = TRUE;
 	  for (t = info->version_info; t != NULL; t = t->next)
 	    for (d = t->globals.list; d != NULL; d = d->next)
 	      if (d->literal && !d->symver && !d->script)
@@ -6349,134 +6348,128 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
 	  elf_tdata (output_bfd)->cverdefs = cdefs;
 	}
+    }
+
+  bed = get_elf_backend_data (output_bfd);
+
+  if (info->gc_sections && bed->can_gc_sections)
+    {
+      struct elf_gc_sweep_symbol_info sweep_info;
+
+      /* Remove the symbols that were in the swept sections from the
+	 dynamic symbol table.  */
+      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);
+    }
+
+  if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
+    {
+      asection *s;
+      struct elf_find_verdep_info sinfo;
 
       /* 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;
+      sinfo.info = info;
+      sinfo.vers = elf_tdata (output_bfd)->cverdefs;
+      if (sinfo.vers == 0)
+	sinfo.vers = 1;
+      sinfo.failed = 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;
+      elf_link_hash_traverse (elf_hash_table (info),
+			      _bfd_elf_link_find_version_dependencies,
+			      &sinfo);
+      if (sinfo.failed)
+	return FALSE;
 
-		size += sizeof (Elf_External_Verneed);
-		++crefs;
-		for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
-		  size += sizeof (Elf_External_Vernaux);
-	      }
+      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;
 
-	    s->size = size;
-	    s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
-	    if (s->contents == NULL)
-	      return FALSE;
+	  /* 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;
 
-	    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));
+	      size += sizeof (Elf_External_Verneed);
+	      ++crefs;
+	      for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
+		size += sizeof (Elf_External_Vernaux);
+	    }
 
-		_bfd_elf_swap_verneed_out (output_bfd, vn,
-					   (Elf_External_Verneed *) p);
-		p += sizeof (Elf_External_Verneed);
+	  s->size = size;
+	  s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
+	  if (s->contents == NULL)
+	    return FALSE;
 
-		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);
+	  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;
 
-		    _bfd_elf_swap_vernaux_out (output_bfd, a,
-					       (Elf_External_Vernaux *) p);
-		    p += sizeof (Elf_External_Vernaux);
-		  }
-	      }
+	      caux = 0;
+	      for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
+		++caux;
 
-	    elf_tdata (output_bfd)->cverrefs = crefs;
-	  }
-      }
-    }
+	      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));
 
-  bed = get_elf_backend_data (output_bfd);
+	      _bfd_elf_swap_verneed_out (output_bfd, vn,
+					 (Elf_External_Verneed *) p);
+	      p += sizeof (Elf_External_Verneed);
 
-  if (info->gc_sections && bed->can_gc_sections)
-    {
-      struct elf_gc_sweep_symbol_info sweep_info;
-      unsigned long section_sym_count;
+	      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);
 
-      /* 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_swap_vernaux_out (output_bfd, a,
+					     (Elf_External_Vernaux *) p);
+		  p += sizeof (Elf_External_Vernaux);
+		}
+	    }
 
-      /* 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);
+	  elf_tdata (output_bfd)->cverrefs = crefs;
+	}
     }
 
   /* Any syms created from now on start with -1 in
@@ -6786,7 +6779,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       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)
+					     &section_sym_count) <= 1)
 	{
 	  asection *s;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]