LD_LIBRARY_PATH Is Not The Answer

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
        libgcc_s.so.1 =>         (file not found)
        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.  If you have questions or comments on the article, please  feel free to E-mailthe author.

References

The following references were used while writing this article:

  • Linkers & Loaders
  • setrpath executable
  • How to write shared libraries
  • Solaris linkers and libraries guide

你可能感兴趣的:(LD_LIBRARY_PATH Is Not The Answer)