Linux-Kongreß´97


Symbol versioning in ELF shared libraries

Eric Youngdale

Over the past several years ELF file format has become the standard for all Linux systems. Despite it's flexibility and despite it's extensibility, one piece that has always been missing is the ability to have a single shared library contain more than one incompatible version of a given function. An example of an incompatible change to a function would be when the number of arguments to a function changes, a structure passed as an argument changes in some way, or the meaning of the return value of the function changes.

In addition, there was effectively no checking of libraries at anything below the major number level, and this could lead to applications unexpectedly crashing when run using older shared libraries.

The result of these deficiencies is that library maintainers could only increase the major number of a library when an incompatible change was made, but this action should only be rarely taken - the logical result of this was that needed changes to interfaces were never made, or that a new interface which was *almost* compatible was slipped in as a compatible upgrade. Both of these outcomes are clearly undesireable.

These deficiencies have been well understood for quite some time - the hard question has always been how best to solve them. After many long discussions, a workable approach was agreed upon and is now being implemented. The solution primarily involves first implementing an approach for symbol versioning as implemented by Sun in Solaris 2.5. Sun's implementation by itself provides a way for the dynamic linker to verify that the libraries that are loaded contain all of the functions that the application needs.

While Sun's solution does not allow for multiple incompatible versions of a function to be present in a given shared library, it does allow interfaces to be tied to specific versions of a library. As a result it was possible to extend Sun's approach and allow multiple versions of a given function to be present in a given shared library. With this new functionality, an old application would continue to use the version of the function that it was linked against, and not against a new and incompatible version of a function. It is only when the application is recompiled and relinked that it will use the new version of the function.