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_26-branch] Revert PR16467 change


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

commit bdf48af13cdaccdcbcc0aca9c41ae376038508fd
Author: Alan Modra <amodra@gmail.com>
Date:   Mon May 30 09:43:44 2016 +0930

    Revert PR16467 change
    
    This reverts the pr16467 change, which was incorrect due to faulty
    analysis of the pr16467 testcase.  The failure was not due to a
    mismatch in symbol type (ifunc/non-ifunc) but due to a symbol loop
    being set up.
    
    See https://sourceware.org/ml/binutils/2016-06/msg00013.html for some
    rambling on versioned symbols and ELF shared library symbol overriding
    that explain this patch.
    
    bfd/
    	PR ld/20159
    	PR ld/16467
    	* elflink.c (_bfd_elf_merge_symbol): Revert PR16467 change.
    	(_bfd_elf_add_default_symbol): Don't indirect to/from defined
    	symbol given a version by a script different to the version
    	of the symbol being added.
    	(elf_link_add_object_symbols): Use _bfd_elf_strtab_save and
    	_bfd_elf_strtab_restore.  Don't fudge dynstr references.
    	* elf-strtab.c (_bfd_elf_strtab_restore_size): Delete.
    	(struct strtab_save): New.
    	(_bfd_elf_strtab_save, _bfd_elf_strtab_restore): New functions.
    	* elf-bfd.h (_bfd_elf_strtab_restore_size): Delete.
    	(_bfd_elf_strtab_save, _bfd_elf_strtab_restore): Declare.

Diff:
---
 bfd/ChangeLog    | 16 ++++++++++++++
 bfd/elf-bfd.h    |  8 ++++---
 bfd/elf-strtab.c | 41 ++++++++++++++++++++++++++++++------
 bfd/elflink.c    | 63 +++++++++++++++++++++++++++++++++++++++-----------------
 4 files changed, 100 insertions(+), 28 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index fbb8753..6d70417 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,19 @@
+2016-06-09  Alan Modra  <amodra@gmail.com>
+
+	PR ld/20159
+	PR ld/16467
+	* elflink.c (_bfd_elf_merge_symbol): Revert PR16467 change.
+	(_bfd_elf_add_default_symbol): Don't indirect to/from defined
+	symbol given a version by a script different to the version
+	of the symbol being added.
+	(elf_link_add_object_symbols): Use _bfd_elf_strtab_save and
+	_bfd_elf_strtab_restore.  Don't fudge dynstr references.
+	* elf-strtab.c (_bfd_elf_strtab_restore_size): Delete.
+	(struct strtab_save): New.
+	(_bfd_elf_strtab_save, _bfd_elf_strtab_restore): New functions.
+	* elf-bfd.h (_bfd_elf_strtab_restore_size): Delete.
+	(_bfd_elf_strtab_save, _bfd_elf_strtab_restore): Declare.
+
 2016-05-20  H.J. Lu  <hongjiu.lu@intel.com>
 
 	Backport from master
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 70e3327..f36b945 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2039,9 +2039,11 @@ extern void _bfd_elf_strtab_delref
 extern unsigned int _bfd_elf_strtab_refcount
   (struct elf_strtab_hash *, bfd_size_type);
 extern void _bfd_elf_strtab_clear_all_refs
-  (struct elf_strtab_hash *tab);
-extern void _bfd_elf_strtab_restore_size
-  (struct elf_strtab_hash *, bfd_size_type);
+  (struct elf_strtab_hash *);
+extern void *_bfd_elf_strtab_save
+  (struct elf_strtab_hash *);
+extern void _bfd_elf_strtab_restore
+  (struct elf_strtab_hash *, void *);
 extern bfd_size_type _bfd_elf_strtab_size
   (struct elf_strtab_hash *);
 extern bfd_size_type _bfd_elf_strtab_offset
diff --git a/bfd/elf-strtab.c b/bfd/elf-strtab.c
index 4d38e04..e7de973 100644
--- a/bfd/elf-strtab.c
+++ b/bfd/elf-strtab.c
@@ -215,16 +215,45 @@ _bfd_elf_strtab_clear_all_refs (struct elf_strtab_hash *tab)
     tab->array[idx]->refcount = 0;
 }
 
-/* Downsizes strtab.  Entries from IDX up to the current size are
-   removed from the array.  */
+/* Save strtab refcounts prior to adding --as-needed library.  */
+
+struct strtab_save
+{
+  bfd_size_type size;
+  unsigned int refcount[1];
+};
+
+void *
+_bfd_elf_strtab_save (struct elf_strtab_hash *tab)
+{
+  struct strtab_save *save;
+  bfd_size_type idx, size;
+
+  size = sizeof (*save) + (tab->size - 1) * sizeof (save->refcount[0]);
+  save = bfd_malloc (size);
+  if (save == NULL)
+    return save;
+
+  save->size = tab->size;
+  for (idx = 1; idx < tab->size; idx++)
+    save->refcount[idx] = tab->array[idx]->refcount;
+  return save;
+}
+
+/* Restore strtab refcounts on finding --as-needed library not needed.  */
+
 void
-_bfd_elf_strtab_restore_size (struct elf_strtab_hash *tab, bfd_size_type idx)
+_bfd_elf_strtab_restore (struct elf_strtab_hash *tab, void *buf)
 {
-  bfd_size_type curr_size = tab->size;
+  bfd_size_type idx, curr_size = tab->size;
+  struct strtab_save *save = (struct strtab_save *) buf;
 
   BFD_ASSERT (tab->sec_size == 0);
-  BFD_ASSERT (idx <= curr_size);
-  tab->size = idx;
+  BFD_ASSERT (save->size <= curr_size);
+  tab->size = save->size;
+  for (idx = 1; idx < save->size; ++idx)
+    tab->array[idx]->refcount = save->refcount[idx];
+
   for (; idx < curr_size; ++idx)
     {
       /* We don't remove entries from the hash table, just set their
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 842e85b..4e7de0c 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -1184,21 +1184,20 @@ _bfd_elf_merge_symbol (bfd *abfd,
   oldfunc = (h->type != STT_NOTYPE
 	     && bed->is_function_type (h->type));
 
-  /* When we try to create a default indirect symbol from the dynamic
-     definition with the default version, we skip it if its type and
-     the type of existing regular definition mismatch.  */
+  /* 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)
-	   && ELF_ST_TYPE (sym->st_info) != h->type
-	   && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
-	   && h->type != STT_NOTYPE
-	   && !(newfunc && oldfunc))
-	  || (olddef
-	      && ((h->type == STT_GNU_IFUNC)
-		  != (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)))))
+      && (olddef || h->root.type == bfd_link_hash_common)
+      && ELF_ST_TYPE (sym->st_info) != h->type
+      && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
+      && h->type != STT_NOTYPE
+      && !(newfunc && oldfunc))
     {
       *skip = TRUE;
       return TRUE;
@@ -1766,6 +1765,31 @@ _bfd_elf_add_default_symbol (bfd *abfd,
   if (skip)
     goto nondefault;
 
+  if (hi->def_regular)
+    {
+      /* If the undecorated symbol will have a version added by a
+	 script different to H, then don't indirect to/from the
+	 undecorated symbol.  This isn't ideal because we may not yet
+	 have seen symbol versions, if given by a script on the
+	 command line rather than via --version-script.  */
+      if (hi->verinfo.vertree == NULL && info->version_info != NULL)
+	{
+	  bfd_boolean hide;
+
+	  hi->verinfo.vertree
+	    = bfd_find_version_for_sym (info->version_info,
+					hi->root.root.string, &hide);
+	  if (hi->verinfo.vertree != NULL && hide)
+	    {
+	      (*bed->elf_backend_hide_symbol) (info, hi, TRUE);
+	      goto nondefault;
+	    }
+	}
+      if (hi->verinfo.vertree != NULL
+	  && strcmp (p + 1 + (p[1] == '@'), hi->verinfo.vertree->name) != 0)
+	goto nondefault;
+    }
+
   if (! override)
     {
       /* Add the default symbol if not performing a relocatable link.  */
@@ -3497,8 +3521,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   void *old_ent;
   struct bfd_link_hash_entry *old_undefs = NULL;
   struct bfd_link_hash_entry *old_undefs_tail = NULL;
-  long old_dynsymcount = 0;
-  bfd_size_type old_dynstr_size = 0;
+  void *old_strtab = NULL;
   size_t tabsize = 0;
   asection *s;
   bfd_boolean just_syms;
@@ -3939,8 +3962,9 @@ error_free_dyn:
       old_table = htab->root.table.table;
       old_size = htab->root.table.size;
       old_count = htab->root.table.count;
-      old_dynsymcount = htab->dynsymcount;
-      old_dynstr_size = _bfd_elf_strtab_size (htab->dynstr);
+      old_strtab = _bfd_elf_strtab_save (htab->dynstr);
+      if (old_strtab == NULL)
+	goto error_free_vers;
 
       for (i = 0; i < htab->root.table.size; i++)
 	{
@@ -4651,7 +4675,9 @@ error_free_dyn:
       memcpy (htab->root.table.table, old_tab, tabsize);
       htab->root.undefs = old_undefs;
       htab->root.undefs_tail = old_undefs_tail;
-      _bfd_elf_strtab_restore_size (htab->dynstr, old_dynstr_size);
+      _bfd_elf_strtab_restore (htab->dynstr, old_strtab);
+      free (old_strtab);
+      old_strtab = NULL;
       for (i = 0; i < htab->root.table.size; i++)
 	{
 	  struct bfd_hash_entry *p;
@@ -4664,9 +4690,6 @@ error_free_dyn:
 	      h = (struct elf_link_hash_entry *) p;
 	      if (h->root.type == bfd_link_hash_warning)
 		h = (struct elf_link_hash_entry *) h->root.u.i.link;
-	      if (h->dynindx >= old_dynsymcount
-		  && h->dynstr_index < old_dynstr_size)
-		_bfd_elf_strtab_delref (htab->dynstr, h->dynstr_index);
 
 	      /* Preserve the maximum alignment and size for common
 		 symbols even if this dynamic lib isn't on DT_NEEDED
@@ -5036,6 +5059,8 @@ error_free_dyn:
  error_free_vers:
   if (old_tab != NULL)
     free (old_tab);
+  if (old_strtab != NULL)
+    free (old_strtab);
   if (nondeflt_vers != NULL)
     free (nondeflt_vers);
   if (extversym != NULL)


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