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

Re: Bug in dynamic linker


On Thu, Jul 20, 2000 at 11:04:16AM -0700, H . J . Lu wrote:
> On Thu, Jul 20, 2000 at 07:56:08PM +0200, Mark Kettenis wrote:
> > 
> > Here it is (thanks for including the shar target :-)).  By the way,
> 
> Sure.
> 
> > looks like there's something wrong with the linker.  I get the
> 
> Yes, I fixed it and checked my fix into CVS :-). BTW, that is the
> one we are discussing now.
> 
> > following output (with glibc 2.1.3):
> > 
> > delius:~/tmp/needed$ make
> > for f in threadtest test; do echo "Running: $f"; ./$f; \
> >   if [ $? != 0 ]; then echo Failed; fi; done
> > Running: threadtest
> > BUG IN DYNAMIC LINKER ld.so: dynamic-link.h: 57: elf_get_dynamic_info: Assertion `! "bad dynamic tag"' failed!
> > Failed
> > Running: test
> > ./test: error in loading shared libraries: libthreadlib.so: cannot open shared object file: No such file or directory
> > Failed
> > for f in threadtest test; do echo "Running: ldd $f"; ldd ./$f; \
> >   if [ $? != 0 ]; then echo Failed; fi; done
> > Running: ldd threadtest
> > BUG IN DYNAMIC LINKER ld.so: dynamic-link.h: 57: elf_get_dynamic_info: Assertion `! "bad dynamic tag"' failed!
> > ldd: /lib/ld-linux.so.2 exited with unknown exit code (127)
> > Failed
> > Running: ldd test
> >        libthreadlib.so => not found
> >        libc.so.6 => /lib/libc.so.6 (0x40015000)
> >        libpthread.so.0 => /lib/libpthread.so.0 (0x400f8000)
> >        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
> > delius:~/tmp/needed$ make
> > 
> 
> With the current linker from CVS,
> 
> # make
> ....
> Running: ldd threadtest
>         libthreadlib.so => ./libthreadlib.so (0x40019000)
>         libc.so.6 => /lib/libc.so.6 (0x4002a000)
>         libpthread.so.0 => /lib/libpthread.so.0 (0x4013e000)
>         /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
> Running: ldd test
>         libthreadlib.so => not found
>         libc.so.6 => /lib/libc.so.6 (0x40028000)
>         /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
> 
> If you think there still is a problem, please send me a testcase
> to show it.
> 

I did find a problem under glibc 2.1.3 since close is not weak in
libpthread.so. In glibc 2.2, close is weak in libpthread.so. Here
is a patch for that case. Any comments?

BTW, this patch has some interesting impacts on the testcase. I don't
know for sure if it will break anything although I think it is ok.

Thanks.


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

	* elflink.h (elf_merge_symbol): Take one more argument,
	dt_needed, to indicate if the symbol comes from a DT_NEEDED
	entry. Don't overide the existing weak definition if dt_needed
	is true.
	(elf_link_add_object_symbols): Pass dt_needed to
	elf_merge_symbol ().

--- /home/is/sourceware/src/bfd/elflink.h	Thu Jul 20 14:15:05 2000
+++ elflink.h	Thu Jul 20 15:08:35 2000
@@ -35,7 +35,7 @@ static boolean elf_link_add_archive_symb
 static boolean elf_merge_symbol
   PARAMS ((bfd *, struct bfd_link_info *, const char *, Elf_Internal_Sym *,
 	   asection **, bfd_vma *, struct elf_link_hash_entry **,
-	   boolean *, boolean *, boolean *));
+	   boolean *, boolean *, boolean *, boolean));
 static boolean elf_export_symbol
   PARAMS ((struct elf_link_hash_entry *, PTR));
 static boolean elf_fix_symbol_flags
@@ -433,11 +433,12 @@ elf_link_add_archive_symbols (abfd, info
    TYPE_CHANGE_OK if it is OK for the type to change.  We set
    SIZE_CHANGE_OK if it is OK for the size to change.  By OK to
    change, we mean that we shouldn't warn if the type or size does
-   change.  */
+   change. DT_NEEDED indicates if it comes from a DT_NEEDED entry of
+   a shared object.  */
 
 static boolean
 elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
-		  override, type_change_ok, size_change_ok)
+		  override, type_change_ok, size_change_ok, dt_needed)
      bfd *abfd;
      struct bfd_link_info *info;
      const char *name;
@@ -448,6 +449,7 @@ elf_merge_symbol (abfd, info, name, sym,
      boolean *override;
      boolean *type_change_ok;
      boolean *size_change_ok;
+     boolean dt_needed;
 {
   asection *sec;
   struct elf_link_hash_entry *h;
@@ -624,9 +626,11 @@ elf_merge_symbol (abfd, info, name, sym,
     olddyncommon = false;
 
   /* It's OK to change the type if either the existing symbol or the
-     new symbol is weak.  */
+     new symbol is weak unless it comes from a DT_NEEDED entry of
+     a shared object, in which case, the DT_NEEDED entry may not be
+     required at the run time. */
 
-  if (h->root.type == bfd_link_hash_defweak
+  if ((! dt_needed && h->root.type == bfd_link_hash_defweak)
       || h->root.type == bfd_link_hash_undefweak
       || bind == STB_WEAK)
     *type_change_ok = true;
@@ -678,7 +682,9 @@ elf_merge_symbol (abfd, info, name, sym,
      object to override a weak symbol in a shared object.
 
      We prefer a non-weak definition in a shared library to a weak
-     definition in the executable.  */
+     definition in the executable unless it comes from a DT_NEEDED
+     entry of a shared object, in which case, the DT_NEEDED entry
+     may not be required at the run time. */
 
   if (newdyn
       && newdef
@@ -686,7 +692,8 @@ elf_merge_symbol (abfd, info, name, sym,
 	  || (h->root.type == bfd_link_hash_common
 	      && (bind == STB_WEAK
 		  || ELF_ST_TYPE (sym->st_info) == STT_FUNC)))
-      && (h->root.type != bfd_link_hash_defweak
+      && (h->root.type != bfd_link_hash_defweak 
+	  || dt_needed
 	  || bind == STB_WEAK))
     {
       *override = true;
@@ -821,8 +828,11 @@ elf_merge_symbol (abfd, info, name, sym,
 
   /* Handle the special case of a weak definition in a regular object
      followed by a non-weak definition in a shared object.  In this
-     case, we prefer the definition in the shared object.  */
+     case, we prefer the definition in the shared object unless it
+     comes from a DT_NEEDED entry of a shared object, in which case,
+     the DT_NEEDED entry may not be required at the run time. */
   if (olddef
+      && ! dt_needed
       && h->root.type == bfd_link_hash_defweak
       && newdef
       && newdyn
@@ -1465,7 +1475,7 @@ elf_link_add_object_symbols (abfd, info)
 
 	  if (! elf_merge_symbol (abfd, info, name, &sym, &sec, &value,
 				  sym_hash, &override, &type_change_ok,
-				  &size_change_ok))
+				  &size_change_ok, dt_needed))
 	    goto error_return;
 
 	  if (override)
@@ -1668,7 +1678,8 @@ elf_link_add_object_symbols (abfd, info)
 		  size_change_ok = false;
 		  if (! elf_merge_symbol (abfd, info, shortname, &sym, &sec,
 					  &value, &hi, &override,
-					  &type_change_ok, &size_change_ok))
+					  &type_change_ok,
+					  &size_change_ok, dt_needed))
 		    goto error_return;
 
 		  if (! override)
@@ -1785,7 +1796,8 @@ elf_link_add_object_symbols (abfd, info)
 		  size_change_ok = false;
 		  if (! elf_merge_symbol (abfd, info, shortname, &sym, &sec,
 					  &value, &hi, &override,
-					  &type_change_ok, &size_change_ok))
+					  &type_change_ok,
+					  &size_change_ok, dt_needed))
 		    goto error_return;
 
 		  if (override)

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