This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc 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] |
If I've followed the threads on this list correctly (http://sources.redhat.com/ml/libc-alpha/2003-06/msg00124.html), then it appears that H.J. Lu's libc-base patch has not been accepted. H.J. created this patch in response to what I reported as broken behavior. Ulrich Drepper commented: > I've never seen an adequate description of the problem and the way it is > thought it should be. The test case is wrong since this basemodnew.c > file defines symbols with empty version names but the version map > doesn't export them. Empty version names are obviously not possible. > If there are only problems with such invalid input this is a user > problem and needs no changes in glibc. I hope that this message suffices to describe the problem and how (I believe) things should be. The remainder of this message is broken into the following parts: 1. For the benefit of readers not familiar with the topic, I'll briefly explain some background: i.e., what is the problem that this patch (or something equivalent) allows us to solve. 2. I'll outline possible solutions to the problem. The last of these is what I believe is, and the ld manual documents as, the correct solution to the problem. Unfortunately this feature has broken. Ulrich has said of the feature: > I don't know who came up with this. It is not the right way. > Supporting this might very well cause problems for the correct > way do handle newly versioned DSOs. but as far as I can see, Ulrich hasn't mentioned what the preferred solution is -- it may be one of the other methods I outline -- if that is so, could you please tell us which one is the right way Ulrich. Alternatively, could we please have H.J.'s patch applied. 3. I'll show a test case that demonstrate the problem. Cheers, Michael 1. BACKGROUND glibc 2.1 introduced the concept of symbol versioning, which allows a shared library to export multiple versions of the same symbol. Each program uses the version of the function that was current when the program was (statically) linked against the shared library. As a result, we can make an incompatible change to a shared library without having to increase the library's major version number. In effect symbol versioning replaces much of the functionality of shared library major and minor version numbers. For example, this allows a single file, /lib/libc.so.6, to export different symbol definitions for applications linked against glibc 2.0, 2.1, 2.2, and 2.3 (and beyond). To distinguish the various versions of a symbol, we make use of linker version scripts and .symver assembler directives. Some examples appear below. There is however one question to be faced by library maintainers who want to use symbol versioning: if we make the transition from an unversioned shared library (for example, glibc 2.0 did not employ symbol versioning) to a symbol-versioned library, how can we do this transparently to applications that were linked against the old (unversioned) library? (In other words we should not need to perform any re-linking, etc, of old applications. They should continue to use the "original" symbol definition.) 2. SOLUTIONS TO THE PROBLEM OF TRANSPARENTLY MAKING THE TRANSITION FROM AN UNVERSIONED SHARED LIBRARY TO A LIBRARY WITH SYMBOL VERSIONING I see three possible solutions to the problem. The last of these is the one that is documented in the glibc manual. It is also the method which appears to be broken, and which H.J. Lu's patch fixes. a) We create a new (incompatible) major version of the shared library, built using a version script, and deploy that in parallel with the previous version of the shared library. We then carry on creating new versions of symbols (as required) in the new major library version. The advantage of this approach is simplicity. The disadvantage is the need to deploy two shared libraries. Clearly this is not optimal. b) We continue to use the same major library major version, but rebuild the library using a version script. In this case, applications that were linked against the earlier non-versioned library will make use of the symbols corresponding to the first (i.e., oldest) version tag in the version script. According to my tests, this method seems to work, and this appears to be the approach taken in glibc 2.1 (though I'm not sure of this). However, the behaviour described here is not documented in the glibc manual (I diescovered it by experimentation). c) The ld manual says that we should make use of the "unspecified base version" to solve this problem: [[ To do this, you must use multiple `.symver' directives in the source file. Here is an example: __asm__(".symver original_foo,foo@"); __asm__(".symver old_foo,foo@VERS_1.1"); __asm__(".symver old_foo1,foo@VERS_1.2"); __asm__(".symver new_foo,foo@@VERS_2.0"); In this example, `foo@' represents the symbol `foo' bound to the unspecified base version of the symbol. The source file that contains this example would define 4 C functions: `original_foo', `old_foo', `old_foo1', and `new_foo'. ]] In other words, if we create a new edition of a shared library employing symbol versioning, then applications that were linked against the old unversioned library will make use of the symbol ("original_foo" in this case) corresponding to the first of the .symver directive above. Unfortunately, this feature does not work. 3. DEMONSTRATION OF BROKEN 'UNSPECIFIED BASE VERSION' FEATURE [This demonstration comes from a modified version of some code that H.J. and I exchanged when I initially reported the problem. The attached tarball contains all of this code, and a makefile to automate things.] We begin by creating an unversioned library: $ cat old.c void xyz () { printf ("%s\n", __FUNCTION__); } $ cc -fPIC -c -o old.o old.c $ cc -Wl,-soname,libfoo.so -shared -o libold.so old.o Now we create a program, 'olp', linked against that version of the library: $ cat main.c int main () { xyz (); return 0; } $ cc -o oldp libold.so main.c When we run 'olpd', we see the expected output: $ ln -sf libold.so libfoo.so $ LD_LIBRARY_PATH=. ./oldp xyz Now we create a new edition of the shared library. This version exports two versions of the function 'xyz'. The 'original_xyz' function is the unspecified base version, i.e., the one that according to the ld documentation should be used by 'oldp'. The 'new_xyz' function is the one that will be used by new programs lined against this library: $ cat new.c void original_xyz () { printf ("%s\n", __FUNCTION__); } void new_xyz () { printf ("%s\n", __FUNCTION__); } __asm__(".symver original_xyz,xyz@"); __asm__(".symver new_xyz,xyz@@VERS_2.0"); $ cc -c -o new.o new.c $ cat foo.v VERS_2.0 { global: xyz; local: *; } ; $ cc -Wl,-soname,libfoo.so,--version-script=foo.v -shared \ -o libnew.so new.o Now we create 'newp', a new program linked against the new edition of the shared library. When we run the program, we see the expected result. $ cc -o newp libnew.so main.c $ ln -sf libnew.so libfoo.so $ LD_LIBRARY_PATH=. ./newp new_xyz However, when we run 'oldp', things go wrong: $ LD_LIBRARY_PATH=. ./oldp new_xyz We should of course see the output: "original_xyz". One final note, which was the source of some grief when I initially tried to isolate this problem: the visibility of this bug is influenced by the choice of function name. For example, after my initial problem report, H.J. sent me a "working" version of the code which used the name 'foo' for the test function instead of 'xyz'. However, when I substituted all occurrences of 'foo' for 'xyz', the breakage was once more revealed. -- +++ GMX - Mail, Messaging & more http://www.gmx.net +++ Bitte lächeln! Fotogalerie online mit GMX ohne eigene Homepage!
Attachment:
test.tar.gz
Description: application/gzip-compressed
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |