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]

Re: Fix uninitialized data in .dynsym


On Tue, Jul 10, 2007 at 09:28:13AM +0930, Alan Modra wrote:
> On Mon, Jul 09, 2007 at 04:25:29PM -0700, H.J. Lu wrote:
> > I don't think it is right. When you do
> > 
> > ld -shared -o b.so --defsym foo=0 a.so --version-script a.ver -E
> > 
> > shouldn't foo be dynamic?
> 
> Yes, it should.  So should the following, but I wasn't going to reject
> Joseph's patch just because he didn't fix all the bugs involved.
> 
> ld -shared -o b.so --defsym foo=0 -E empty.o

I don't feel comfortable for patches without a testcase. We may break
it aganst later.

Here is a patch to linker defined symbols with version.

I also noticed a bug. In _bfd_elf_merge_symbol, there are

      h->root.type = bfd_link_hash_indirect;
      h->root.u.i.link = (struct bfd_link_hash_entry *) flip; 
      (*bed->elf_backend_copy_indirect_symbol) (info, flip, h);
      flip->root.u.undef.abfd = h->root.u.undef.abfd;

The problem is 

      h->root.u.i.link = (struct bfd_link_hash_entry *) flip; 

will update h->root.u.undef.abfd since it is a union. I think we
should copy h->root.u.undef.abfd before updating h->root.u.i.link.


H.J.
---
2007-07-09  H.J. Lu  <hongjiu.lu@intel.com>

	* elflink.c (bfd_elf_record_link_assignment): Handle indirect
	symbol.
	(_bfd_elf_merge_symbol): Properly update normal symbol when
	overriding the versioned symbol from a dynamic library.

--- bfd/elflink.c.bad	2007-07-09 15:39:46.000000000 -0700
+++ bfd/elflink.c	2007-07-09 17:31:59.000000000 -0700
@@ -489,8 +489,9 @@ bfd_elf_record_link_assignment (bfd *out
 				bfd_boolean provide,
 				bfd_boolean hidden)
 {
-  struct elf_link_hash_entry *h;
+  struct elf_link_hash_entry *h, *hv;
   struct elf_link_hash_table *htab;
+  const struct elf_backend_data *bed;
 
   if (!is_elf_hash_table (info->hash))
     return TRUE;
@@ -500,21 +501,43 @@ bfd_elf_record_link_assignment (bfd *out
   if (h == NULL)
     return provide;
 
-  /* Since we're defining the symbol, don't let it seem to have not
-     been defined.  record_dynamic_symbol and size_dynamic_sections
-     may depend on this.  */
-  if (h->root.type == bfd_link_hash_undefweak
-      || h->root.type == bfd_link_hash_undefined)
+  switch (h->root.type)
     {
+    case bfd_link_hash_defined:
+    case bfd_link_hash_defweak:
+    case bfd_link_hash_common:
+      break;
+    case bfd_link_hash_undefweak:
+    case bfd_link_hash_undefined:
+      /* Since we're defining the symbol, don't let it seem to have not
+	 been defined.  record_dynamic_symbol and size_dynamic_sections
+	 may depend on this.  */
       h->root.type = bfd_link_hash_new;
       if (h->root.u.undef.next != NULL || htab->root.undefs_tail == &h->root)
 	bfd_link_repair_undef_list (&htab->root);
-    }
-
-  if (h->root.type == bfd_link_hash_new)
-    {
+      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
+         the versioned symbol point to this one.  */
+      bed = get_elf_backend_data (output_bfd);
+      hv = h;
+      while (hv->root.type == bfd_link_hash_indirect
+	     || hv->root.type == bfd_link_hash_warning)
+	hv = (struct elf_link_hash_entry *) hv->root.u.i.link;
+      /* We don't need to update h->root.u since linker will set them
+	 later.  */
+      h->root.type = bfd_link_hash_undefined;
+      hv->root.type = bfd_link_hash_indirect;
+      hv->root.u.i.link = (struct bfd_link_hash_entry *) h;
+      (*bed->elf_backend_copy_indirect_symbol) (info, h, hv);
+      break;
+    case bfd_link_hash_warning:
+      abort ();
+      break;
     }
 
   /* If this symbol is being provided by the linker script, and it is
@@ -1456,10 +1479,10 @@ _bfd_elf_merge_symbol (bfd *abfd,
 	 case, we make the versioned symbol point to the normal one.  */
       const struct elf_backend_data *bed = get_elf_backend_data (abfd);
       flip->root.type = h->root.type;
+      flip->root.u.undef.abfd = h->root.u.undef.abfd;
       h->root.type = bfd_link_hash_indirect;
       h->root.u.i.link = (struct bfd_link_hash_entry *) flip;
       (*bed->elf_backend_copy_indirect_symbol) (info, flip, h);
-      flip->root.u.undef.abfd = h->root.u.undef.abfd;
       if (h->def_dynamic)
 	{
 	  h->def_dynamic = 0;


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