When an executable is run that relies on shared libraries not defined in the global search path, an error similar to the following is displayed:
$ curl
ld.so.1: curl: fatal: libgcc_s.so.1: open failed: No such file or directory
Killed
Typically this problem is fixed by running ldd(1) on the executable, locating the missing shared libraries, and adding one or more directories to the LD_LIBRARY_PATH environment variable:
$ ldd curl
libcurl.so.3 => /tmp/curl1/lib/libcurl.so.3
libdl.so.1 => /usr/lib/libdl.so.1
libsocket.so.1 => /usr/lib/libsocket.so.1
libnsl.so.1 => /usr/lib/libnsl.so.1
libz.so.1 => /usr/lib/libz.so.1
libc.so.1 => /usr/lib/libc.so.1
<b>libgcc_s.so.1 => (file not found)</b>
libmp.so.2 => /usr/lib/libmp.so.2
/usr/platform/SUNW,Ultra-5_10/lib/libc_psr.so.1
$ export LD_LIBRARY_PATH=/usr/local/lib
$ curl
curl: try 'curl --help' or 'curl --manual' for more information
Using LD_LIBRARY_PATH for this purpose is a complete hack, and according to the linker gurus, this variable should be avoided. This is easy to do, since the vast majority of executable formats allow a runtime search path to be added to the executable. For Solaris ELF executables, the native linker’s “-R” (record path) option can be used to record a runtime search path:
$ export LDFLAGS="-R/usr/local/lib"
$ ./configure --prefix=/tmp/curl2
$ make
$ make install
To view the runtime search path in a Solaris ELF executable, the dump utility can be run with the “-L” (dump dynamic linking information) and “-v” (print verbose information) options, and an executable to query:
$ dump -Lv curl | egrep '(RPATH|RUNPATH)'
[9] RUNPATH /usr/local/lib
[10] RPATH /usr/local/lib
$ curl
curl: try 'curl --help' or 'curl --manual' for more information
If a binary is already built, the setrpath utility can often be used to update the search path in an ELF executable:
$ curl
ld.so.1: curl: fatal: libgcc_s.so.1: open failed: No such file or directory
Killed
$ gcc -o setrpath setrpath.c -lelf
$ setrpath curl "/usr/local/lib"
Old RPATH: /tmp/curl1/lib:/tmp/curl:/tmp:/curl:/tmp/curl:/tmp/curl
New RPATH set to: /usr/local/lib
$ setrpath libcurl.so.3.0.0 "/usr/local/lib"
Old RPATH: /tmp/curl:/tmp:/curl:/tmp/curl:/tmp/curl
New RPATH set to: /usr/local/lib
$ curl
curl: try 'curl --help' or 'curl --manual' for more information
To use setrpath, you need to ensure that enough space exists to accomodate the new seach path. For binaries that need to move within a file system, the Solaris $ORIGIN variable should be used instead of absolute paths. If you haven’t already, I highly recommend sitting down with the Solaris linkers and libraries guide. This document contains an awesome introduction to the Solaris linker, and provides a detailed overview of the dynamic linking process.
The following references were used while writing this article: