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

RFC: Don't output symbol version requirement for non-DT_NEEDED libs

This is a fix for
Inconsistency detected by dl-version.c: 224: _dl_check_map_versions: Assertion `needed != ((void *)0)' failed!
a situation that can arise with weak references to versioned symbols
in dependent libraries.

Consider this testcase, a main that calls a weak "f", linked against a
shared library that has a dependency on where "f" is
defined as a versioned symbol.  A later revision of defines
"f" itself, without the version, and doesn't link against
A further revision of doesn't link against and also
doesn't define "f".

cat > lib.c <<EOF
int f (void) { return 1; }
cat > <<EOF
FOO { global: f; };
cat > main.c <<EOF
int f (void) __attribute__ ((weak));
int main (void) { return f ? f() : 0; }
cat > empty.c <<EOF
gcc -o -shared -fPIC -Wl,-soname,,--version-script, lib.c
gcc -o -shared -fPIC -Wl,--no-as-needed,-soname, -L. -lb
gcc -o -shared -fPIC -Wl,-soname, lib.c
gcc -o -shared -fPIC -Wl,-soname, empty.c
ln -sfn
gcc -o pr16452 -fPIC main.c -Wl,--no-as-needed,--rpath,. -L. -la
echo $?
ln -sfn
echo $?
ln -sfn
echo $?

Currently the script output is
Inconsistency detected by dl-version.c: 224: _dl_check_map_versions: Assertion `needed != ((void *)0)' failed!
Inconsistency detected by dl-version.c: 224: _dl_check_map_versions: Assertion `needed != ((void *)0)' failed!

The problem here is that since binutils-2.22 we've defaulted to
--no-copy-dt-needed-entries (which was a good change despite the
number of bugreports it has generated).  So is not listed as
DT_NEEDED in the executable.  However, a version FOO from *is*
added to the executable, specifying that it came from  When
we use rev 2 or 3 of, no is loaded and the version
check fails to find the required library.

You could argue that it's wrong for to complain about a weak
symbol version, but the check isn't being done against symbols. is looking at .gnu.version_r, the version requirements
themselves, each possibly used by multiple symbols..

You might also argue that it's a user problem that f lost its version
in rev 2 of the testcase.  However this might be because is a
user library without any versioning and in rev 2, was linked
against a static libb.  (Typical libb in real life is libpthread.)

So, absent someone implementing a glibc fix, how about we just drop
the symbol versioning for weak symbols, when their defining library
won't be in DT_NEEDED?  Note that if "f" above was a strong symbol,
ld will still complain with "./ error adding symbols: DSO
missing from command line".

	PR 16452
	* elflink.c (_bfd_elf_link_find_version_dependencies): Exclude
	symbols from libraries that won't be listed in DT_NEEDED.
	(elf_link_output_extsym): Don't output verdefs for such symbols.

diff --git a/bfd/elflink.c b/bfd/elflink.c
index c8068c0..c964a98 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -1832,7 +1832,9 @@ _bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h,
   if (!h->def_dynamic
       || h->def_regular
       || h->dynindx == -1
-      || h->verinfo.verdef == NULL)
+      || h->verinfo.verdef == NULL
+      || (elf_dyn_lib_class (h->verinfo.verdef->vd_bfd)
     return TRUE;
   /* See if we already know about this version.  */
@@ -9050,7 +9052,9 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
 	  if (!h->def_regular)
-	      if (h->verinfo.verdef == NULL)
+	      if (h->verinfo.verdef == NULL
+		  || (elf_dyn_lib_class (h->verinfo.verdef->vd_bfd)
 		iversym.vs_vers = 0;
 		iversym.vs_vers = h->verinfo.verdef->vd_exp_refno + 1;

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]