May 16, 2005

CLI Magic: ldconfig and friends

Author: Joe Barr

If you're like most Linux desktop users, there will come a day when you will want or need a program that isn't included or supported by your distribution of choice. If you build the needed app from source code, you might still not be able to run it because of missing dependencies. But nothing is more frustrating than fighting your way through that unsupported landscape, including finding and building the missing libraries, only to still get an error message like this one: "error while loading shared libraries: libXrender.so.1: cannot open shared object file: No such file or directory."
That's where ldconfig comes in, and why it pays to know a little about what it does and how to use it.Dynamically linked libraries are located and loaded at run time, either by ld.so or ld-linux.so, depending on how it was compiled: in a.out or ELF format. Each of these programs looks through a list of places to find libraries when they are needed. One place they both look in is a file named /etc/ld.so.cache, which contains an ordered list of libraries to be searched for the needed module.

To get an idea how this works, let's use ldd to print the dependencies for a well-known program, like the GIMP. On my system, that command looks like this:

ldd /opt/gnome/bin/gimp

ldd then politely shows each dependency, including a pointer to the actual library location where it was found, and an offset
and results in this:

        linux-gate.so.1 =>  (0xffffe000)
        libgimpwidgets-2.0.so.0 => /opt/gnome/lib/libgimpwidgets-2.0.so.0 (0x4002d000)
        libgimpmodule-2.0.so.0 => /opt/gnome/lib/libgimpmodule-2.0.so.0 (0x4010c000)
        libgimpcolor-2.0.so.0 => /opt/gnome/lib/libgimpcolor-2.0.so.0 (0x40111000)
        libgimpthumb-2.0.so.0 => /opt/gnome/lib/libgimpthumb-2.0.so.0 (0x4011a000)
        libgimpmath-2.0.so.0 => /opt/gnome/lib/libgimpmath-2.0.so.0 (0x40122000)
        libgimpbase-2.0.so.0 => /opt/gnome/lib/libgimpbase-2.0.so.0 (0x40127000)
        libgtk-x11-2.0.so.0 => /opt/gnome/lib/libgtk-x11-2.0.so.0 (0x40135000)
        libgdk-x11-2.0.so.0 => /opt/gnome/lib/libgdk-x11-2.0.so.0 (0x403fd000)
        libatk-1.0.so.0 => /opt/gnome/lib/libatk-1.0.so.0 (0x40478000)
        libgdk_pixbuf-2.0.so.0 => /opt/gnome/lib/libgdk_pixbuf-2.0.so.0 (0x40491000)
        libm.so.6 => /lib/tls/libm.so.6 (0x404a5000)
        libpangoxft-1.0.so.0 => /opt/gnome/lib/libpangoxft-1.0.so.0 (0x404c8000)
        libpangox-1.0.so.0 => /opt/gnome/lib/libpangox-1.0.so.0 (0x404d0000)
        libart_lgpl_2.so.2 => /usr/lib/libart_lgpl_2.so.2 (0x404db000)
        libpangoft2-1.0.so.0 => /opt/gnome/lib/libpangoft2-1.0.so.0 (0x404f1000)
        libpango-1.0.so.0 => /opt/gnome/lib/libpango-1.0.so.0 (0x40517000)
        libgobject-2.0.so.0 => /opt/gnome/lib/libgobject-2.0.so.0 (0x4054f000)
        libgmodule-2.0.so.0 => /opt/gnome/lib/libgmodule-2.0.so.0 (0x40583000)
        libdl.so.2 => /lib/libdl.so.2 (0x40588000)
        libglib-2.0.so.0 => /opt/gnome/lib/libglib-2.0.so.0 (0x4058c000)
        libfontconfig.so.1 => /usr/lib/libfontconfig.so.1 (0x4060c000)
        libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0x4063a000)
        libc.so.6 => /lib/tls/libc.so.6 (0x406a9000)
        libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x407c2000)
        libXrandr.so.2 => /usr/X11R6/lib/libXrandr.so.2 (0x408bf000)
        libXi.so.6 => /usr/X11R6/lib/libXi.so.6 (0x408c3000)
        libXinerama.so.1 => /usr/X11R6/lib/libXinerama.so.1 (0x408cb000)
        libXft.so.2 => /usr/X11R6/lib/libXft.so.2 (0x408ce000)
        libXfixes.so.3 => /usr/X11R6/lib/libXfixes.so.3 (0x408e1000)
        libXcursor.so.1 => /usr/X11R6/lib/libXcursor.so.1 (0x408e6000)
        libXrender.so.1 => /usr/X11R6/lib/libXrender.so.1 (0x408f0000)
        libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x408f8000)
        /lib/ld-linux.so.2 (0x40000000)
        libexpat.so.0 => /usr/lib/libexpat.so.0 (0x40906000)

Now let's see what happens if we rename one of those dependencies, so it can't be found at run time. We'll rename to /usr/X11R6/lib/libXrender.so.1 to /usr/X11R6/lib/libXrender.backup.so.1 with this mv command:


mv /usr/X11R6/lib/libXrender.so.1 /usr/X11R6/lib/libXrender.backup.so.1

Now, when we try to run the GIMP from the command line, we get:

warthawg@linux:~> gimp
gimp: error while loading shared libraries: libXrender.so.1: cannot open shared object file: No such file or directory

Important Note: Do this right now, before you forget. Use the mv command to restore the library back to its original name, like this:

mv /usr/X11R6/lib/libXrender.backup.so.1 /usr/X11R6/lib/libXrender.so.1

Failure to do so will cause your X session to crash.

Where is there?

Remember that file mentioned right up at the top, /etc/ld.so.cache? It contains a complete list of all the shared object libraries that ld.so or ld-linux.so will search in machine readable format. It is created by ldconfig, based on the contents of a human readable text file named /etc/ld.so.conf. Here's a dump of my /etc/ld.so.conf file:

/usr/X11R6/lib/Xaw95
/usr/X11R6/lib/Xaw3d
/usr/X11R6/lib
/usr/i486-linux/lib
/usr/i486-linux-libc5/lib=libc5
/usr/i486-linux-libc6/lib=libc6
/usr/i486-linuxaout/lib
/usr/i386-suse-linux/lib
/usr/local/lib
/usr/openwin/lib
/opt/kde/lib
/opt/kde2/lib
/opt/kde3/lib
/opt/gnome/lib
/opt/gnome2/lib
include /etc/ld.so.conf.d/*.conf

Now let's say that I've added a new application to my system. Following the project documentation, I've also added libXYZ.so.2, and when I did the library ended up in the /usr/local/XYZ/lib directory. Since my /etc/ld.so.conf file doesn't contain a reference to that directory, the library will never get into the cache used by ld.so and ld-linux.so at run time, and I won't be able to run the new application.

Fixing that problem is exactly as easy as it sounds. Simply add the directory to your /etc/ld.so.conf file, and then -- as root -- run the ldconfig program so it rebuilds /etc/ld.so.cache.

Note that even if that directory had been in your /etc/ld.so.conf file previously, the cache would not contain an entry for the new library. You would still need to run the ldconfig program to update the cache.

There you have it. A little deeper than we usually go in CLI Magic, but very much worth the effort when you just gotta have that app.

Click Here!