[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#136707: Proposal: Debian should use symbol versions for libdb2, libdb3, libbdb4





I propose that Debian attach a symbol version to all symbols in the
db2, db3, and db4 libraries and that a distinct version be used for
db2, db3 and db4.

I additionally propose that significant libraries that link against db
be relinked to include the symbol versions.  In particual, I propose
that at least libsasl, libnss-db, and libpam be rebuilt.  I'm not
actually sure it matters for libpam but it probably couldn't hurt.

I will describe the advantages and disadvantages of this proposal  and
then describe the tests I made to confirm these advantages  and
disadvantages.

Ben discussed some ideas involving both weak symbols and symbol
versions.  I don't think these would be useful because I don't think
that the arguments for weak aliases apply in this case.  A weak alias
is useful when you have some symbol that the application may want to
redefine and you want to avoid duplicate symbol warnings.  Libc does
this to be pedantically correct with regard to the C spec as I
understand it.




			      Advantages

1) It works to solve external symbol collisions as defined earlier in
   this bug.  An application linked against symbol versioned  libdb3
   will always call the db3 symbols even if an library  linked
   against a versioned db2 is linked in.

2)  It mostly works even if we don't relink the applications.  If an
    application was linked against an unversioned libdb3 then the
    symbols it gets  will depend on link order, but any libraries it
    calls that have been relinked will work correctly.  That is, to
    solve our problem, we need to relink all the db versions and
    relink any base libraries that use them.  We do not need to relink
    our all applications that use db.

3) The solution seems likely to work in the long term.  We can
   continue to make our packages work even  if the upstream adopts
   symbol versions.  Symbol versions can inherit from each other so we
   could fix both the upstream and our versions to work.

4)  Easy to implement.  You create a 4-5 line version script and pass
			    it in on the ld command line

			    Disadvantages

1) Symbol versions are somewhat complex to understand 

2)  Symbol versions only work if you rebuild all the libraries
    involved.  An unversioned symbol takes precidence over any
    versioned symbol .  So we are depending on  anyone who might
    generate a symbol conflicting with DB to version their symbol.  We
    implicitly also depend on future versions of db to be have
    versioned symbols.


3) A solution like Solaris's -Bgroup would really be simpler and have
   more contained semantics.  Of course the glibc elf interpreter
   doesn't support it, so it's not like we could actually use that
   solution.


4) Debian binaries will be incompatible at an ABI level with other
   distributions.  Because Debian binaries will be looking for
   versioned symbols, they will give warnings if run on other
   distributions.  For db2 and db3 this is a non-issue because there
   are already ABI compatibility issues.  I think willy is looking to
   preserve the upstream ABI for db4.  If he wants to do that, he
   could install two libraries in the libdb4-dev ; one for other
   debian packages to link against  and one for people who care about
   upstream ABI to use.


5)  This solution is specific to the glibc elf interpreter.  I note
    that Solaris and potentially other elf platforms treat  versions
    differently.

Despite these disadvantages, I believe this proposal is the only
solution that is likely to work.

			   Acknowledgements

During my exploration of shared libraries, many people have
contributed useful advice, explanations and listened to me rant.  I'd
like to thank Ben Collins, Mark Eichin, Ted Ts'o, Nathan Williams.
I'm beginning to believe I'd like to anti-thank the Elf format.



				Tests

My set of test cases can be found at
http://www.meepzorp.org/~hartmans/elf-libtest.tar.gz.  Note that these
are distributed under a non-free license that forbids redistribution.
I'm doing this because I'd like to keep a handle on them until I write
better documentation.  If you have need for the test cases to be under
a free software license, let me know and I can relicense.


The tests consist of a set of functions that call each other.  Each
function prints out the name  of the library it is in when it is
called.

There is an application called main which calls foo_a, foo_b and
foo_c.  Foo_a can be thought of as a routine in libsasl that accesses
db2.  foo_b can be thought of as a symbol shared between db2 and db3.
We can ignore foo_c and foo_d for this discussion, they are used to
prove that -Bsymbolic works, but since that doesn't matter for this
proposal we don't care.

There is a library libfoo1 which roughly represents libsasl.  It
defines  foo_a and links to libfoo2.  Libfoo2 represents libdb2 and
defines foo_b.

The library libfoo3 can be thought of as libdb3.  It also defines
foo_b.

The application main links to libfoo3 and libfoo1.

The Makefile in the tests builds at least two versions of everything.
IT builds a version that uses symbol versions placed into the
elf-libtest directory and a version that does not use symbols in the
the elf-libtest/noversion directory.

I present the application main_foo1ns as an example of proof that I
have a solution to the problem described in this bug under the
standard of proof I proposed earlier:

* Binutils and libc version:
ii  libc6          2.2.5-3        GNU C Library: Shared libraries and
Timezone

ii  binutils       2.11.93.0.2-1  The GNU assembler, linker and binary
utiliti


* The symbol  foo_b is a symbol shared between libfoo2 and libfoo3

* The application main_foo1ns calls the symbol foo_b desiring the
  version in libfoo3
* The library libfoo1 calls  foo_b expecting the one from libfoo2

* If the wrong symbol is called the incorrect consequence will be a
  diagnostic indicating that a function from the incorrect library is
  called.


* The following log demonstrates that with this solution we do not get
  the incorrect consequence:

hartmans@industrial-algebra:elf-libtest(1078)> ./main_foo1ns
libfoo1: foo_a
libfoo2: foo_b
libfoo3: foo_b
libfoo1: foo_c
libfoo3: foo_d

* The following log  demonstrates that  the problem exists if symbol
  versions are not used.  Note that  libfoo3 is used in both cases for
  foo_b

hartmans@industrial-algebra:noversion(1080)> ./main_foo1ns
libfoo1: foo_a
libfoo3: foo_b
libfoo3: foo_b
libfoo1: foo_c
libfoo3: foo_d


I also conducted the following other experiments.  If you run the
application linked  with symbol versions against libraries without
symbol versions, you get a warning.  If you have one of your libraries
with versions and one library without, the library without symbol
versions can replace the symbols even in libraries/applications that
were linked against symbol versioned libraries.  Applications linked
against unversioned libraries work fine against unversioned libraries,
using link order to determine what symbols are used.  If you upgrade
all the libraries to have symbol versions  then inter-library
references take advantage of the symbol versions even though  the
application was not linked against libraries with symbol versions.
You can  repeat these and other pedantic tests on your own.



Reply to: