This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


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

A patch for DT_NEEDED [Re: The DT_AUXILIARY patch]


On Tue, Jul 18, 2000 at 05:41:05PM +0200, Mark Kettenis wrote:
>    >    That is true. The isse is we need to find a way to make the references
>    >    to those exported symbols in libgcc.so dynamic. That is what libgcc.so
>    >    is used for. How about we teach ld to check DT_AUXILIARY? It will
>    >    be treated as DT_NEEDED for that purpose. ld won't wont propagate
>    >    DT_AUXILIARY to anything else.
>    > 
>    > Argh!  No!  The current behaviour of ld to walk the DT_NEEDED list
>    > when resolving symbols from shared libraries has its problems and is
>    > incompatible with at least the Solaris linker.  See
>    > <http://sources.redhat.com/ml/binutils/1999-11/msg00037.html> for a
> 
>    I didn't find the original message. Is the original problem solved?
>    I ran into a similar problem with OpenGL. One OpenGL implmenentation
>    is multi-threaded. But it has to work with single thread applications.
>    That means the OpenGL implmenentation has to make sure libpthread.so
>    is always available even if it is used with a single thread application.
>    I had to fix a bug in glibc to make things to work for them. I can ask
>    them to see how they solved the problem.
> 
> Here is link to the message with details about the origional problem:
> 
> http://x40.deja.com/getdoc.xp?AN=545891503&CONTEXT=958448712.1788280849&hitnum=29
> 
> The "bug" isn't fixed.  It's one of those "BUG IN DYNAMIC LINKER"
> cases where there's a corrupt/inconsistent binary.  The dynamic linker
> is complaining about the fact that there is a version dependency for a
> library that's not in the applications DT_NEEDED list, and it has
> every right to do so.
> 
> The right fix is to stop the static linker from walking the DT_NEEDED
> list (at least when recording versioning information, but in principle
> altogether).  The old behaviour should probably still be available,
> when activated by a special switch.
> 

I like the new bebavior. It can even catch some symbol version mismatch
errors which otherwise can only be caught at the run-time. It is also
convenient to do

# gcc .... -lGL

and I don't have to worry about how my OpenGL is implemented since my
OpenGL code do not make any calls to X libraries directly. Anyway,
here is a patch for the DT_NEEDED handling. At present, we don't add
files from DT_NEEDED to the DT_NEEDED list in the resulting binary.
That causes the problem if the resulting binary references the symbols
in files from DT_NEEDED and they are not passed to the linker at the
comand line. This patch tries to add those files to the DT_NEEDED list
if they are used by the regular files during the link. Ian, what do
you think?



H.J.
----
2000-07-18  H.J. Lu  <hjl@gnu.org>

	* bfd-in.h (bfd_elf_set_dt_needed_soname): New.
	* bfd-in2.h: Rebuild.

	* elf-bfd.h (elf_obj_tdata): Add dt_soname.
	(elf_dt_soname): New.

	* elf.c (bfd_elf_set_dt_needed_soname): New.

	* elflink.h (elf_link_add_object_symbols): Add the DT_NEEDED
	entry if the shared object loaded by DT_NEEDED is used to
	resolve the reference in a regular object.

Index: bfd/bfd-in.h
===================================================================
RCS file: /work/cvs/gnu/binutils/bfd/bfd-in.h,v
retrieving revision 1.11
diff -u -p -r1.11 bfd-in.h
--- bfd/bfd-in.h	2000/07/13 16:00:33	1.11
+++ bfd/bfd-in.h	2000/07/18 19:32:33
@@ -627,6 +627,7 @@ extern boolean bfd_elf64_size_dynamic_se
 	   const char * const *, struct bfd_link_info *, struct sec **,
 	   struct bfd_elf_version_tree *));
 extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *));
+extern void bfd_elf_set_dt_needed_soname PARAMS ((bfd *, const char *));
 extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
 
 /* Return an upper bound on the number of bytes required to store a
Index: bfd/bfd-in2.h
===================================================================
RCS file: /work/cvs/gnu/binutils/bfd/bfd-in2.h,v
retrieving revision 1.35
diff -u -p -r1.35 bfd-in2.h
--- bfd/bfd-in2.h	2000/07/13 16:00:33	1.35
+++ bfd/bfd-in2.h	2000/07/18 19:34:06
@@ -627,6 +627,7 @@ extern boolean bfd_elf64_size_dynamic_se
 	   const char * const *, struct bfd_link_info *, struct sec **,
 	   struct bfd_elf_version_tree *));
 extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *));
+extern void bfd_elf_set_dt_needed_soname PARAMS ((bfd *, const char *));
 extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
 
 /* Return an upper bound on the number of bytes required to store a
Index: bfd/elf-bfd.h
===================================================================
RCS file: /work/cvs/gnu/binutils/bfd/elf-bfd.h,v
retrieving revision 1.1.1.15
diff -u -p -r1.1.1.15 elf-bfd.h
--- bfd/elf-bfd.h	2000/07/09 23:37:28	1.1.1.15
+++ bfd/elf-bfd.h	2000/07/18 21:13:49
@@ -838,6 +838,14 @@ struct elf_obj_tdata
      one.  */
   const char *dt_name;
 
+  /* When a reference in a regular object is resolved by a shared
+     object is loaded into via the DT_NEEDED entries by the linker
+     ELF emulation code, we need to add the shared object to the
+     DT_NEEDED list of the resulting binary to indicate the dependency
+     as if the -l option is passed to the linker. This field holds the
+     name of the loaded shared object. */
+  const char *dt_soname;
+
   /* Irix 5 often screws up the symbol table, sorting local symbols
      after global symbols.  This flag is set if the symbol table in
      this BFD appears to be screwed up.  If it is, we ignore the
@@ -915,6 +923,7 @@ struct elf_obj_tdata
 #define elf_local_got_offsets(bfd) (elf_tdata(bfd) -> local_got.offsets)
 #define elf_local_ptr_offsets(bfd) (elf_tdata(bfd) -> linker_section_pointers)
 #define elf_dt_name(bfd)	(elf_tdata(bfd) -> dt_name)
+#define elf_dt_soname(bfd)	(elf_tdata(bfd) -> dt_soname)
 #define elf_bad_symtab(bfd)	(elf_tdata(bfd) -> bad_symtab)
 #define elf_flags_init(bfd)	(elf_tdata(bfd) -> flags_init)
 #define elf_linker_section(bfd,n) (elf_tdata(bfd) -> linker_section[(int)n])
Index: bfd/elf.c
===================================================================
RCS file: /work/cvs/gnu/binutils/bfd/elf.c,v
retrieving revision 1.23
diff -u -p -r1.23 elf.c
--- bfd/elf.c	2000/07/13 16:00:33	1.23
+++ bfd/elf.c	2000/07/18 20:26:45
@@ -1023,6 +1023,16 @@ bfd_elf_set_dt_needed_name (abfd, name)
     elf_dt_name (abfd) = name;
 }
 
+void
+bfd_elf_set_dt_needed_soname (abfd, name)
+     bfd *abfd;
+     const char *name;
+{
+  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+      && bfd_get_format (abfd) == bfd_object)
+    elf_dt_soname (abfd) = name;
+}
+
 /* Get the list of DT_NEEDED entries for a link.  This is a hook for
    the linker ELF emulation code.  */
 
Index: bfd/elflink.h
===================================================================
RCS file: /work/cvs/gnu/binutils/bfd/elflink.h,v
retrieving revision 1.33
diff -u -p -r1.33 elflink.h
--- bfd/elflink.h	2000/06/20 17:47:42	1.33
+++ bfd/elflink.h	2000/07/18 20:56:34
@@ -890,6 +890,7 @@ elf_link_add_object_symbols (abfd, info)
   Elf_External_Sym *esym;
   Elf_External_Sym *esymend;
   struct elf_backend_data *bed;
+  boolean dt_needed;
 
   bed = get_elf_backend_data (abfd);
   add_symbol_hook = bed->elf_add_symbol_hook;
@@ -1049,6 +1050,8 @@ elf_link_add_object_symbols (abfd, info)
     goto error_return;
   elf_sym_hashes (abfd) = sym_hash;
 
+  dt_needed = false;
+
   if (! dynamic)
     {
       /* If we are creating a shared library, create all the dynamic
@@ -1085,7 +1088,12 @@ elf_link_add_object_symbols (abfd, info)
 	{
 	  name = elf_dt_name (abfd);
 	  if (*name == '\0')
-	    add_needed = false;
+	    {
+	      if (elf_dt_soname (abfd) != NULL)
+	        dt_needed = true;
+
+	      add_needed = false;
+	    }
 	}
       s = bfd_get_section_by_name (abfd, ".dynamic");
       if (s != NULL)
@@ -1863,6 +1871,52 @@ elf_link_add_object_symbols (abfd, info)
 		(*bed->elf_backend_hide_symbol) (info, h);
 		break;
 	      }
+
+	  if (dynamic && dt_needed && definition
+	      && (h->elf_link_hash_flags
+		  & ELF_LINK_HASH_REF_REGULAR) != 0)
+	    {
+	      bfd_size_type oldsize;
+	      bfd_size_type strindex;
+
+	      /* The symbol from a DT_NEEDED object is referenced from
+	         the regular object to create a dynamic executable. We
+		 have to make sure there is a DT_NEEDED entry for it. */
+
+	      oldsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
+	      strindex = _bfd_stringtab_add (elf_hash_table (info)->dynstr,
+	      				     elf_dt_soname (abfd),
+					     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;
+
+		  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);
+		      BFD_ASSERT (dyn.d_tag != DT_NEEDED ||
+				  dyn.d_un.d_val != strindex);
+		    }
+		}
+
+	      if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex))
+		goto error_return;
+	    }
 	}
     }
 
2000-07-18  H.J. Lu  <hjl@gnu.org>

	* emultempl/elf32.em (gld${EMULATION_NAME}_try_needed): Call
	bfd_elf_set_dt_needed_soname ().

Index: ld/emultempl/elf32.em
===================================================================
RCS file: /work/cvs/gnu/binutils/ld/emultempl/elf32.em,v
retrieving revision 1.17
diff -u -p -r1.17 elf32.em
--- ld/emultempl/elf32.em	2000/07/13 16:00:36	1.17
+++ ld/emultempl/elf32.em	2000/07/18 21:13:41
@@ -532,6 +532,18 @@ cat >>e${EMULATION_NAME}.c <<EOF
      DT_NEEDED entry for this file.  */
   bfd_elf_set_dt_needed_name (abfd, "");
 
+  /* First strip off everything before the last '/'.  */
+  name = strrchr (abfd->filename, '/');
+  if (name)
+    name++;
+  else
+    name = abfd->filename;
+
+  /* Tell the ELF backend that the output file needs a DT_NEEDED
+     entry for this file if it is used to resolve the reference in
+     a regular object.  */
+  bfd_elf_set_dt_needed_soname (abfd, name);
+
   /* Add this file into the symbol table.  */
   if (! bfd_link_add_symbols (abfd, &link_info))
     einfo ("%F%B: could not read symbols: %E\n", abfd);

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