On occasion, it may happen that trying to run a binary may provide an error message like the following:
# screen -DR
/usr/lib/hpux32/dld.so: Unable to find library 'libtermcap.so'.
When a binary is loaded in UNIX (and Linux), shared libraries may need to be loaded (like the above example, libtermcap.so). Each version of UNIX has its own specific method of searching for libraries; specifically, this process is done by a program called ld.so or (on HP-UX) dld.so or similar. The Linux dynamic loader is part of the GNU libc libraries; the loader thus generally works the same across Linux distributions that use GNU libc.
Each program has an embedded library search path, in addition to the system search process. In HP-UX, there are several places that may influence the search for dynamic libraries:
- LD_LIBRARY_PATH (environment variable – standard PATH format)
- SHLIB_PATH (environment variable – standard PATH format – from /etc/SHLIB_PATH)
- LD_PRELOAD (environment variable – specifies library names)
- rpath (the executable’s embedded path, embedded at link time by ld)
- /etc/dld.sl.conf (one library directory per line)
The search can also be influenced by a number of factors:
- How the executable was linked and with which options
- Whether the executable is setguid or setuid
- Whether dld.sl.conf has the right permissions or not (must be writable only by root)
- Whether the system is PA-RISC or Itanium
- Whether the system is 32-bit or 64-bit
- What the settings of _HP_DLDOPTS are
On HP-UX for PA-RISC, the loader was dld.sl(5) and all the libraries had .sl extensions. On Itanium, the loader is dld.so(5). Both loaders are loaded and run by a “starter” program called crt0.o (although there are different versions for each architecture).
To get a view of the search process, use the ldd(1) command. Here is an example of successful ldd output:
# ldd `which screen`
libtermcap.so => /opt/termcap-1.3.1/lib/hpux32/libtermcap.so
libelf.so.1 => /usr/lib/hpux32/libelf.so.1
libc.so.1 => /usr/lib/hpux32/libc.so.1
libdl.so.1 => /usr/lib/hpux32/libdl.so.1
Note that if a library cannot be found by the HP-UX loader, an error will be returned about the missing library and nothing else will be reported. In HP-UX, the -s option to ldd provides a detailed list of what directories are being searched.
When you add libraries to the system, make sure to check the following:
- Does the library directory need to be in /etc/dld.sl.conf? The dld.sl.conf file is used as a very basic search path; it is used when security or other factors mandate that virtually no shared libraries be used. Note that both Itanium and PA-RISC systems use this file (that is, both dld.so and dld.sl check /etc/dld.sl.conf). If you put a directory into dld.sl.conf, it must also be in either SHLIB_PATH (through the use of /etc/SHLIB_PATH) or in LD_LIBRARY_PATH.
- Check file and path permissions. Libraries must not be world-writable, and the directories in the path must also not be world-writable – and almost certainly, none of these should be group-writable. Make sure that directories in the path are owned by root.
- Check the executable for setuid and setgid flags. If testing a shared library, check if the executable is setgid or setuid. If these are set, then the loader will strip down the shared library search to almost nil. Check if the library search directory needs to be put in /etc/dld.sl.conf.
- Check the permissions of /etc/dld.sl.conf. If this file is not writable only by root, then it will be ignored.
- Check SHLIB_PATH for directories contained in /etc/dld.sl.conf. If a search directory contained in /etc/dld.sl.conf is not located in either SHLIB_PATH (from /etc/SHLIB_PATH) or in LD_LIBRARY_PATH, then it is ignored.
- Is the directory fully specified from root? If a directory is not fully specified starting with ‘/’ then it wil be ignored.
When debugging the library search path, there are several utilities that can help. The aforementioned ldd -s command is one. Another is the _HP_DLDOPTS environment variable:
- _HP_DLDOPTS=”-symtab_stat” – get statistical information
- _HP_DLDOPTS=”-no_setuidpath” – disable all dynamic path lookup for setuid programs
- _HP_DLDOPTS=”-warnings” – display additional dynamic loader warning messages
- _HP_DLDOPTS=”-fbverbose” – related to fastbind(1)
- _HP_DLDOPTS=”-nofastbind” – related to fastbind(1)
In addition, Itanium systems and PA-RISC 64-bit systems will recognize the variable DLD_VERBOSE_ERR: when set to true, all error messages will be displayed.
When programming, it is also possible to manipulate the loader, including loading and unloading of shared libraries. The functions are:
Next week I’ll talk about shared libraries on Linux.