How to fix the ELF linker?

Ian Lance Taylor ian@cygnus.com
Fri Mar 17 08:50:00 GMT 1995


   From: hjl@nynexst.com (H.J. Lu)
   Date: Thu, 16 Mar 95 22:35:08 EST

   When you do

   # gcc foo.c -lc

   the ELF linker will load libc.so twice. But the dynamic linker will
   only map libc.so into the address space once. The prolem comes
   up if the ELF linker uses both instances of libc.so to resolve
   the references. 

I don't see how this can happen.  The symbols are loaded the first
time, and the second time around the symbols should just be ignored.
I can't recreate this problem at all.

I can detect exactly one symptom from linking a dynamic object in more
than once: two DT_NEEDED entries are created.  Since that is
undesirable, since it may force the runtime loader to do extra work,
this patch will avoid the problem.  It will probably also fix whatever
problem you are encountering.

Ian

Index: elfcode.h
===================================================================
RCS file: /rel/cvsfiles/devo/bfd/elfcode.h,v
retrieving revision 1.179
diff -p -r1.179 elfcode.h
*** elfcode.h	1995/03/13 21:55:57	1.179
--- elfcode.h	1995/03/17 16:45:58
*************** elf_link_add_object_symbols (abfd, info)
*** 4215,4220 ****
--- 4215,4221 ----
      {
        asection *s;
        const char *name;
+       bfd_size_type oldsize;
        bfd_size_type strindex;
  
        dynamic = true;
*************** elf_link_add_object_symbols (abfd, info)
*** 4301,4310 ****
--- 4302,4344 ----
  	}
  
        /* Add a DT_NEEDED entry for this dynamic object.  */
+       oldsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
        strindex = _bfd_stringtab_add (elf_hash_table (info)->dynstr, name,
  				     true, false);
        if (strindex == (bfd_size_type) -1)
  	goto error_return;
+ 
+       if (oldsize == _bfd_stringtab_size (elf_hash_table (info)->dynstr))
+ 	{
+ 	  asection *sdyn;
+ 	  Elf_External_Dyn *dyncon, *dynconend;
+ 
+ 	  /* The hash table size did not change, which means that the
+              dynamic object name was already entered.  If we have
+              already included this dynamic object in the link, just
+              ignore it.  There is no reason to include a particular
+              dynamic object more than once.  */
+ 	  sdyn = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
+ 					  ".dynamic");
+ 	  BFD_ASSERT (sdyn != NULL);
+ 
+ 	  dyncon = (Elf_External_Dyn *) sdyn->contents;
+ 	  dynconend = (Elf_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+ 	  for (; dyncon < dynconend; dyncon++)
+ 	    {
+ 	      Elf_Internal_Dyn dyn;
+ 
+ 	      elf_swap_dyn_in (elf_hash_table (info)->dynobj, dyncon, &dyn);
+ 	      if (dyn.d_tag == DT_NEEDED
+ 		  && dyn.d_un.d_val == strindex)
+ 		{
+ 		  if (buf != NULL)
+ 		    free (buf);
+ 		  return true;
+ 		}
+ 	    }
+ 	}
+ 
        if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex))
  	goto error_return;
      }




More information about the Gas2 mailing list