On 11/29/06, Bruno Haible <bruno@...> wrote:
> Sam Steingold asked:
> > > In glibc, there is a dlvsym() function for retrieving versioned symbols.
> > how about other libc implementations? woe32?
> Only glibc has dlvsym(). Woe32 uses #defines in the include files to address
> this problem.
This problem is so nontrivial that Microsoft developed COM (out of
DCE) to address it. In the base non-COM libraries, versioning is done
with size fields and other hacks, like I mentioned in my other e-mail.
But primary way by which versioning problems are addressed in the MS
environment is by writing and using COM DLL's. Interfaces are
versioned, and tied to a 128 bit GUID. The library location problem is
also solved by GUIDS.
To locate a library, a client passes a ``class ID'' (CLSID) GUID to an
API function. That API pulls out the path name from the registry and
loads the library. Next, the application asks for an interface, using
an ``interface ID'' (IID). If the object supports that interface, it
returns a pointer (which happens to point to data that is binary
compatible with the way the Microsoft compiler compiles C++ abstract
> A library does not have a "default symbol version".
> For example glibc-2.4 has symbols
> but no symbol
> If you want the address of the open() function and you don't know its
> specific version, you cannot use dlvsym(); you must use dlsym(handle,"open").
Correct. But if you are writing FFI stuff, you know exactly what is
versioned and what isn't. You know that as of a particular version of
the library, openat was introduced as a versioned symbol. So you
target that symbol, using the version that you want, and declare that
your program needs that version of the library or later.
In the case of open, since it's not a versioned symbol, you just target open.
So what happens if glibc 2.6 comes out and needs to introduce a
versioned open? How will your program run?
What will happen is that they will make open into an alias:
open -> old_open
So old clients will be redirected to old_open and continue to run.
There will be a new_open function, and some versioned symbol which
will alias to that function.
open@... -> new_open
So why use versioned symbols and not just keep repeating the aliasing
trick? Because the old unversioned symbol can only alias to one
version. You have to pick a single function, like old_open, and map
open to that. And that's what you're stuck with. Versioning allows
open to refer to different things depending on who is asking.
Newly compiled programs would be linked to the new open, requesting
version GLIBC_2.6. The dynamic linker, ld.so, uses the equivalent of
dlvsym to grab "open" at version "GLIBC_2.6". For old clients, there
is no version request, so it grabs "open" via the equivalent of dlsym,
which resolves to the same address as old_open. When glibc 2.7 comes
out, there can be an open@..., as well as an open@....
The double @@ indicates that that's the default version that is
selected by newly linked programs.
> > the only problem I see here is that we were thinking about switching to
> > libltdl - does it support this versioning?
> No. Probably because it's not as useful as Kaz thinks (see the other mail).
Versioned symbols are the reason why, at all, you can upgrade a
GNU/Linux system without everything going haywire, like it did in the
At work here, I've been able to take a vendor's embedded distro
(targetting MIPS) running glibc 2.3.4, and run their binaries under a
glibc-2.5 that I compiled.
I literally copied the new glibc over top of the root filesystem, and
by golly, it booted.
That is thanks, in part, to careful ABI versioning.
We can only speculate about the reason why libtool's library doesn't
have dlvsym (yet!). Maybe that project is more focused on different
problems. If a library with versioned symbols is linked using libtool,
all that versioning stuff still works. Libtool helps with issues
related to finding the library at link time and run time.
Maybe nobody is using dlopen() on versioned interfaces with libraries
that are used in conjunction with libtool.
Typically libaries that are designed for run-time use solve their
versioning problems in other ways, one big reason being portability.
If you're designing a platform-independent ``plugin'', then you can't
just say ``we will use ELF symbol versioning to deal with versioning
issues, and too bad those of you who are on non-ELF platforms''.
But in the case of glibc, we are run-time linking to a library which
is not normally used this way. That project has decided to deal with
versioning problems by using the versioning facilities in ELF. Which
is fine, since it gets to define the platform, basically. That means
that if you want to target that library, you have to play by its
glibc is not even linked using libtool, so it would be stupid to use
libtool's API to access it. If dlopen("libc.so.6") doesn't work, you
have a big problem that libtool won't help you with.