This is the mail archive of the binutils@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]

PR ld/12649 and --as-needed cleanup


This is a fix for a case involving versioned symbols where --as-needed
libraries (that aren't needed) can result in new dynamic symbols being
added that previously didn't exist in the symbol hash table.  If that
happens then the string table entries for those symbols won't be
deleted when restoring the old symbol hash table.  See
http://sourceware.org/bugzilla/show_bug.cgi?id=12549#c2 and
http://sourceware.org/bugzilla/show_bug.cgi?id=14862.  The testcase
involved weak symbols and a new behaviour for --as-needed, but I think
it may be possible to trigger the same problem without weak symbols.

	PR ld/12549
	* elf-bfd.h (_bfd_elf_strtab_clear_refs): Declare.
	(_bfd_elf_strtab_clear_all_refs): Define.
	* elf-strtab.c (_bfd_elf_strtab_clear_refs): New function.
	(_bfd_elf_strtab_clear_all_refs): Delete.
	* elflink.c (elf_link_add_object_symbols): Clear out added
	strtab refs.  Correct handling of warning common symbols.

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.352
diff -u -p -r1.352 elf-bfd.h
--- bfd/elf-bfd.h	10 Jan 2013 09:49:08 -0000	1.352
+++ bfd/elf-bfd.h	11 Jan 2013 13:05:56 -0000
@@ -1938,8 +1938,10 @@ extern void _bfd_elf_strtab_addref
   (struct elf_strtab_hash *, bfd_size_type);
 extern void _bfd_elf_strtab_delref
   (struct elf_strtab_hash *, bfd_size_type);
-extern void _bfd_elf_strtab_clear_all_refs
-  (struct elf_strtab_hash *);
+extern void _bfd_elf_strtab_clear_refs
+  (struct elf_strtab_hash *, bfd_size_type);
+#define _bfd_elf_strtab_clear_all_refs(tab) \
+  do { _bfd_elf_strtab_clear_refs (tab, 1); } while (0)
 extern bfd_size_type _bfd_elf_strtab_size
   (struct elf_strtab_hash *);
 extern bfd_size_type _bfd_elf_strtab_offset
Index: bfd/elf-strtab.c
===================================================================
RCS file: /cvs/src/src/bfd/elf-strtab.c,v
retrieving revision 1.16
diff -u -p -r1.16 elf-strtab.c
--- bfd/elf-strtab.c	9 Sep 2009 21:38:57 -0000	1.16
+++ bfd/elf-strtab.c	11 Jan 2013 13:05:56 -0000
@@ -202,12 +202,10 @@ _bfd_elf_strtab_delref (struct elf_strta
 }
 
 void
-_bfd_elf_strtab_clear_all_refs (struct elf_strtab_hash *tab)
+_bfd_elf_strtab_clear_refs (struct elf_strtab_hash *tab, bfd_size_type idx)
 {
-  bfd_size_type idx;
-
-  for (idx = 1; idx < tab->size; ++idx)
-    tab->array[idx]->refcount = 0;
+  while (idx < tab->size)
+    tab->array[idx++]->refcount = 0;
 }
 
 bfd_size_type
Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.460
diff -u -p -r1.460 elflink.c
--- bfd/elflink.c	10 Jan 2013 20:03:54 -0000	1.460
+++ bfd/elflink.c	11 Jan 2013 13:05:57 -0000
@@ -3385,6 +3385,7 @@ elf_link_add_object_symbols (bfd *abfd, 
   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;
   size_t tabsize = 0;
   size_t hashsize = 0;
 
@@ -3834,6 +3835,7 @@ error_free_dyn:
       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);
 
       for (i = 0; i < htab->root.table.size; i++)
 	{
@@ -4566,6 +4568,7 @@ error_free_dyn:
       memcpy (sym_hash, old_hash, hashsize);
       htab->root.undefs = old_undefs;
       htab->root.undefs_tail = old_undefs_tail;
+      _bfd_elf_strtab_clear_refs (htab->dynstr, old_dynstr_size);
       for (i = 0; i < htab->root.table.size; i++)
 	{
 	  struct bfd_hash_entry *p;
@@ -4578,12 +4581,13 @@ 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)
+	      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
-		 since it can still be loaded at the run-time by another
+		 since it can still be loaded at run time by another
 		 dynamic lib.  */
 	      if (h->root.type == bfd_link_hash_common)
 		{
@@ -4602,8 +4606,9 @@ error_free_dyn:
 		{
 		  memcpy (h->root.u.i.link, old_ent, htab->root.table.entsize);
 		  old_ent = (char *) old_ent + htab->root.table.entsize;
+		  h = (struct elf_link_hash_entry *) h->root.u.i.link;
 		}
-	      else if (h->root.type == bfd_link_hash_common)
+	      if (h->root.type == bfd_link_hash_common)
 		{
 		  if (size > h->root.u.c.size)
 		    h->root.u.c.size = size;

-- 
Alan Modra
Australia Development Lab, IBM


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