The odyssey of preserved-libs feature

After my previous post about preserved-libs feature, I was asked by many users if I was against this feature because it incremented the usability of Gentoo. I sincerely think I shown before that I don’t want Gentoo to remain for elitists, and thus I won’t be going to say nay to anything to make stuff easier to the users.

On the other hand, I want to make sure that users, excited about being able to upgrade stuff without breaking their system, won’t break it even further. For this reason I want to warn again users against trying the unstable Portage version (2.2) on their stable systems just yet.

Thanks to Zac and Marius, the problem I’m going to talk about is already being taken care of, so it won’t appear once 2.2 final will arrive. So why am I writing about this anyway? Well the reason is actually quite simple: future memory.

On the topic of linking, loaders, ELF files and all the things related, there isn’t a lot of documentation that is available to newcomers. Most of it is very technical and requires good knowledge of many concepts to be useful. I only know of a book that goes in deep of this, Rob Levine’s Linkers and Loaders is probably the most interesting reading on the subject ,as far as I can see. Unfortunately I haven’t tried converting the downloadable version in LRF to load it on the EBook Reader and I haven’t got the printed copy. I should probably get that too, as a reference, I’m just afraid that all the hardcopies I have here will remain at my parents’ house once I move out.

Okay, let’s return back on topic now. What is the problem I found today with preserved-libs? Well as I updated to Xorg 1.5 pre-releases to check if my RandR problems were fixed (by the way, they are), there was a libGL update. I also took the time to switch back to gcc 4.2 for a short time as I wanted to rebuild VirtualBox without ALSA support (whenever I can I’m using PulseAudio), and I could also rebuild xmlrpc-c (the reason why I couldn’t build this with GCC 4.3 is good for a different entry one day). After these builds, Portage told me this:

!!! existing preserved libs:
>>> package: media-libs/mesa-7.1_rc3
 *  - /usr/lib64/libGLU.so.1.3
 *  - /usr/lib64/libGLU.so.1.3.070003
>>> package: dev-libs/xmlrpc-c-1.06.27
 *  - /usr/lib64/libxmlrpc.so.3.6.4

I was surprised because I know libGLU rarely changes interface, and I didn’t think xmlrpc-c would have either. And indeed a quick scanelf run over the files confirmed my ideas:

flame@enterprise ~ % scanelf -S /usr/lib64/libGLU.so*
 TYPE   SONAME FILE 
ET_DYN libGLU.so.1 /usr/lib64/libGLU.so 
ET_DYN libGLU.so.1 /usr/lib64/libGLU.so.1 
ET_DYN libGLU.so.1 /usr/lib64/libGLU.so.1.3 
ET_DYN libGLU.so.1 /usr/lib64/libGLU.so.1.3.070003 
ET_DYN libGLU.so.1 /usr/lib64/libGLU.so.1.3.070100 
flame@enterprise ~ % scanelf -S /usr/lib64/libxmlrpc.so*
 TYPE   SONAME FILE 
ET_DYN libxmlrpc.so.3 /usr/lib64/libxmlrpc.so 
ET_DYN libxmlrpc.so.3 /usr/lib64/libxmlrpc.so.3 
ET_DYN libxmlrpc.so.3 /usr/lib64/libxmlrpc.so.3.6.15 
ET_DYN libxmlrpc.so.3 /usr/lib64/libxmlrpc.so.3.6.4 

As you can see the soname for both the versions of libGLU and both the versions of libxmlrpc is the same. So there is no ABI break, and no good reason for the file to disappear, right?

Indeed if we focus solely on the xmlrpc-c case, the result of preserved-libs actions is that there is now an orphaned unused and unusable shared object:

flame@enterprise ~ % ls -l /usr/lib64/libxmlrpc.so*    
lrwxrwxrwx 1 root root    19 2008-07-22 18:04 /usr/lib64/libxmlrpc.so -> libxmlrpc.so.3.6.15
lrwxrwxrwx 1 root root    19 2008-07-22 18:04 /usr/lib64/libxmlrpc.so.3 -> libxmlrpc.so.3.6.15
-rwxr-xr-x 1 root root 56864 2008-07-22 18:04 /usr/lib64/libxmlrpc.so.3.6.15
-rwxr-xr-x 1 root root 56368 2008-02-23 13:36 /usr/lib64/libxmlrpc.so.3.6.4

Let’s see, ld.so (the runtime linker) will look for a library with, as filename, the soname listed in a program’s NEEDED entry in the dynamic seciton of the ELF file. In this case, the soname of libxmlrpc is libxmlrpc.so.3 so that’s what the linker will look for. On my system, that filename is linked to the 3.6.15 version, so the runtime linker will always load the new version of libxmlrpc. The build-time linker (ld) looks instead for the filename with the simple .so prefix (or .a for static libraries). That one is also pointing to 3.6.15.

So who is using the 3.6.4 version that Portage preserved? Well, the only way to use it is to dlopen() it directly and accessing it that way. Which, if anything would be doing that, would be craziness, to the point that I’d rather not see such a software in my system at all. The other option is for an ELF file to have a tweaked NEEDED entry that points explicitly to the full version, but I can tell you I have none of those.

So for now I’ll simply remove the two files, and get rid of the problem. But as you can see, it’s too soon to expect preserve-libs to work out of the box in a perfect manner.

Anyway, Marius, Zac, please keep up with the good work, it’s really needed 🙂 Thanks guys!