What are the ELF shared lib symbol versioning best practices?

Daniel P. Berrange berrange at redhat.com
Tue Oct 21 16:11:03 UTC 2014

On Tue, Oct 21, 2014 at 03:59:46PM +0100, David Howells wrote:
> Is there a good description of ELF shared library symbol versioning best
> practices somewhere?
> In particular, under what conditions do you need to create a new section in
> the versioning file given to the linker's --version-script option when new
> symbols are added?

For libvirt, we create a new version section for each new upstream release.
ie so all new APIs in a release get tagged with the version number of the
release they first appeared in.

> And what do you do if you've done it wrong?

Cry, and then live with it forever, unless you want to break ABI and force
all downstream apps to re-link :-(

> For example, in libkeyutils, I added a couple of symbols to KEYUTILS_1.4 when
> I should perhaps have created KEYUTILS_1.5 and added them there:
> 	http://git.kernel.org/cgit/linux/kernel/git/dhowells/keyutils.git/commit/?id=49249ce7d84a967fcdc06fbe6bf1d0cf89ac5215
> I have been given a patch to move these symbols to KEYUTILS_1.5, but checking
> the keyctl program with "readelf -s", I see:
>     47: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND recursive_session_key_sca at KEYUTILS_1.4 (7)
> so I would guess applying this patch would break anything that uses this.

Yes, unfortunately anything which has already linked against your library
*and* used these original symbols will have the 1.4 version encoded in their
ELF section. So if you change the version to 1.5 you will cause linker
loading failures which can only be fixed by rebuilding the downstream

> I assumed that adding them to KEYUTILS_1.4 would be okay because nothing
> would've tried to use them previously because they didn't exist in any
> version.

One thing to bear in mind with symbol versioning is that it also interacts
with RPM versioning. ie, if an application links to a symbol foo at MYLIB_X.Y
then the RPM will automatically get a "Requires: mylib.so(MYLIB_X.Y)"
added to it. 

This ensures that when you install the application, it pulls in a version
of the library that is new enough to have all the symbols the application

Note that RPM only depends on the version, not the full symbol name. So
by adding new symbols to the existing KEYUTILS_1.4 version section, no new
RPM dependancies will be introduced. So an RPM install of an application
that uses the new symbols, will still be (mistakenly) satisfied by the
an old version of the library that lacks the symbols.

This is the primary reason why for libvirt, we take the approach of always
introducing a new version block for each new release that includes new APIs.

BTW, there is one tricky thing to be aware of if you ever backport new APIs
to old "stable branches". You likely want to avoid adding a linker version
section for the stable branch, since if an app links against the stable
branch version of the library, you want a clean upgrade path to the next
major version of the library (assuming preserved ABI).

I've never found any particularly good docs on symbol versioning when I've
looked previously. In case it helps though, here's how we deal with it in


In summary, I'd probably suggest you just live with the symbols as part
of the KEYUTILS_1_4 version block. It isn't a particularly serious hardship
that those were added to an old version block, so not worth the pain of
changing them (unless you plan to break ABI and change soname version
anyway). Then for future API additions just define a new version section
for each new release that adds APIs.

|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

More information about the devel mailing list