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

H.J. Lu hjl.tools@gmail.com
Thu Nov 27 15:56:00 GMT 2014


On Thu, Nov 27, 2014 at 12:16 AM, Alan Modra <amodra@gmail.com> wrote:
> This is a fix for
> Inconsistency detected by ld.so: 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 liba.so that has a dependency on libb.so where "f" is
> defined as a versioned symbol.  A later revision of liba.so defines
> "f" itself, without the version, and doesn't link against libb.so.
> A further revision of liba.so doesn't link against libb.so and also
> doesn't define "f".
>
> cat > lib.c <<EOF
> int f (void) { return 1; }
> EOF
> cat > lib.map <<EOF
> FOO { global: f; };
> EOF
> cat > main.c <<EOF
> int f (void) __attribute__ ((weak));
> int main (void) { return f ? f() : 0; }
> EOF
> cat > empty.c <<EOF
> EOF
> gcc -o libb.so -shared -fPIC -Wl,-soname,libb.so,--version-script,lib.map lib.c
> gcc -o liba.so.1 -shared -fPIC -Wl,--no-as-needed,-soname,liba.so -L. -lb
> gcc -o liba.so.2 -shared -fPIC -Wl,-soname,liba.so lib.c
> gcc -o liba.so.3 -shared -fPIC -Wl,-soname,liba.so empty.c
> ln -sfn liba.so.1 liba.so
> gcc -o pr16452 -fPIC main.c -Wl,--no-as-needed,--rpath,. -L. -la
> ./pr16452
> echo $?
> ln -sfn liba.so.2 liba.so
> ./pr16452
> echo $?
> ln -sfn liba.so.3 liba.so
> ./pr16452
> echo $?
>
> Currently the script output is
> 1
> Inconsistency detected by ld.so: dl-version.c: 224: _dl_check_map_versions: Assertion `needed != ((void *)0)' failed!
> 127
> Inconsistency detected by ld.so: dl-version.c: 224: _dl_check_map_versions: Assertion `needed != ((void *)0)' failed!
> 127
>
> 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 libb.so is not listed as
> DT_NEEDED in the executable.  However, a version FOO from libb.so *is*
> added to the executable, specifying that it came from libb.so.  When
> we use rev 2 or 3 of liba.so, no libb.so is loaded and the version
> check fails to find the required library.
>
> You could argue that it's wrong for ld.so to complain about a weak
> symbol version, but the ld.so check isn't being done against symbols.
> ld.so 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 liba.so is a
> user library without any versioning and in rev 2, liba.so 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 "./libb.so: 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.
>

Such a change needs a testcase to show what it does and make
sure that there is no regression in the future.



-- 
H.J.



More information about the Binutils mailing list