Linux, GNU GCC, ld, version scripts and the ELF binary format -- How does it work?

7,021

This doesn't exactly answer your question, but...

First of all, ELF is the specification use by Linux for executable files (programs), shared libraries, and also object files which are the intermediate files found when compiling software. Object files end in .o, shared libraries end with .so followed by zero or more digits separated by periods, and executable files don't have any extension normally.

There are typically three forms to name a shared library, the first form simply ends in .so. For example, a library called readline is stored in a file called libreadline.so and is located under one of /lib, /usr/lib, or /usr/local/lib normally. That file is located when compiling software with an option like -lreadline. -l tells the compiler to link with the following library. Because libraries change from time to time, it may become obsolete so libraries embed something called a SONAME. The SONAME for readline might look like libreadline.so.2 for the second version major version of libreadline. There may also be many minor versions of readline that are compatible and do not require software to be recompiled. A minor version of readline might be named libreadline.so.2.14. Normally libreadline.so is just a symbolic link to the most recent major version of readline, libreadline.so.2 in this case. libreadline.so.2 is also a symbolic link to libreadline.so.2.14 which is actually the file being used.

The SONAME of a library is embedded inside the library file itself. Somewhere inside the file libreadline.so.2.14 is the string libreadline.so.2. When a program is compiled and linked with readline, it will look for the file libreadline.so and read the SONAME embedded in it. Later, when the program is actually executed, it will load libreadline.so.2, not just libreadline.so, since that was the SONAME that was read when it was first linked. This allows a system to have multiple incompatible versions of readline installed, and each program will load the appropriate major version it was linked with. Also, when upgrading readline, say, to 2.17, I can just install libreadline.so.2.17 alongside the existing library, and once I move the symbolic link libreadline.so.2 from libreadline.so.2.13 to libreadline.so.2.17, all software using that same major version will now see the new minor update to it.

Share:
7,021

Related videos on Youtube

themoondothshine
Author by

themoondothshine

Updated on September 17, 2022

Comments

  • themoondothshine
    themoondothshine almost 2 years

    I'm trying to learn more about library versioning in Linux and how to put it all to work. Here's the context:

    -- I have two versions of a dynamic library which expose the same set of interfaces, say libsome1.so and libsome2.so.

    -- An application is linked against libsome1.so.

    -- This application uses libdl.so to dynamically load another module, say libmagic.so.

    -- Now libmagic.so is linked against libsome2.so. Obviously, without using linker scripts to hide symbols in libmagic.so, at run-time all calls to interfaces in libsome2.so are resolved to libsome1.so. This can be confirmed by checking the value returned by libVersion() against the value of the macro LIB_VERSION.

    -- So I try next to compile and link libmagic.so with a linker script which hides all symbols except 3 which are defined in libmagic.so and are exported by it. This works... Or at least libVersion() and LIB_VERSION values match (and it reports version 2 not 1).

    -- However, when some data structures are serialized to disk, I noticed some corruption. In the application's directory if I delete libsome1.so and create a soft link in its place to point to libsome2.so, everything works as expected and the same corruption does not happen.

    I can't help but think that this may be caused due to some conflict in the run-time linker's resolution of symbols. I've tried many things, like trying to link libsome2.so so that all symbols are alised to symbol@@VER_2 (which I am still confused about because the command nm -CD libsome2.so still lists symbols as symbol and not symbol@@VER_2)... Nothing seems to work!!! Help!!!!!!

    • RobotHumans
      RobotHumans over 13 years
      Your last approach is the one I would have started with. And I agree that the corruption is probably some symbol confusion. Sadly I don't have an answer for you.
    • xenoterracide
      xenoterracide over 13 years
      this might do better on SO, though tbh I don't understand it enough to say for sure. flag it if you'd like us to move it.
    • stribika
      stribika over 13 years
      Try the RTLD_LOCAL and RTLD_DEEPBIND dlopen flags in you app. I don't have time to test this now but it should work based on the manpage.