Skip Navigation Links | |
Exit Print View | |
Oracle Solaris 11.1 Linkers and Libraries Guide Oracle Solaris 11.1 Information Library |
Part I Using the Link-Editor and Runtime Linker
1. Introduction to the Oracle Solaris Link Editors
Locating Shared Object Dependencies
Directories Searched by the Runtime Linker
When Relocations Are Performed
Lazy Loading of Dynamic Dependencies
Providing an Alternative to dlopen()
Initialization and Termination Routines
Initialization and Termination Order
Runtime Linking Programming Interface
5. Link-Editor Quick Reference
7. Building Objects to Optimize System Performance
10. Establishing Dependencies with Dynamic String Tokens
Part IV ELF Application Binary Interface
13. Program Loading and Dynamic Linking
A. Linker and Libraries Updates and New Features
When the runtime linker creates the memory segments for a program, the dependencies tell what shared objects are needed to supply the program's services. By repeatedly connecting referenced shared objects and their dependencies, the runtime linker generates a complete process image.
Note - Even when a shared object is referenced multiple times in the dependency list, the runtime linker connects the object only once to the process.
When linking a dynamic executable, one or more shared objects are explicitly referenced. These objects are recorded as dependencies within the dynamic executable.
The runtime linker uses this dependency information to locate, and load, the associated objects. These dependencies are processed in the same order as the dependencies were referenced during the link-edit of the executable.
Once all the dynamic executable's dependencies are loaded, each dependency is inspected, in the order the dependency is loaded, to locate any additional dependencies. This process continues until all dependencies are located and loaded. This technique results in a breadth-first ordering of all dependencies.
The runtime linker looks in two default locations for dependencies. When processing 32–bit objects, the default locations are /lib and /usr/lib. When processing 64–bit objects, the default locations are /lib/64 and /usr/lib/64. Any dependency specified as a simple file name is prefixed with these default directory names. The resulting path name is used to locate the actual file.
The dependencies of a dynamic executable or shared object can be displayed using ldd(1). For example, the file /usr/bin/cat has the following dependencies.
$ ldd /usr/bin/cat libc.so.1 => /lib/libc.so.1 libm.so.2 => /lib/libm.so.2
The file /usr/bin/cat has a dependency, or needs, the files libc.so.1 and libm.so.2.
The dependencies recorded in an object can be inspected using elfdump(1). Use this command to display the file's .dynamic section, and look for entries that have a NEEDED tag. In the following example, the dependency libm.so.2, displayed in the previous ldd(1) example, is not recorded in the file /usr/bin/cat. ldd(1) shows the total dependencies of the specified file, and libm.so.2 is actually a dependency of /lib/libc.so.1.
$ elfdump -d /usr/bin/cat Dynamic Section: .dynamic: index tag value [0] NEEDED 0x211 libc.so.1 ...
In the previous elfdump(1) example, the dependencies are expressed as simple file names. In other words, there is no `/' in the name. The use of a simple file name requires the runtime linker to generate the path name from a set of default search rules. File names that contain an embedded `/', are used as provided.
The simple file name recording is the standard, most flexible mechanism of recording dependencies. The -h option of the link-editor records a simple name within the dependency. See Naming Conventions and Recording a Shared Object Name.
Frequently, dependencies are distributed in directories other than /lib and /usr/lib, or /lib/64 and /usr/lib/64. If a dynamic executable or shared object needs to locate dependencies in another directory, the runtime linker must explicitly be told to search this directory.
You can specify additional search path, on a per-object basis, by recording a runpath during the link-edit of an object. See Directories Searched by the Runtime Linker for details on recording this information.
A runpath recording can be displayed using elfdump(1). Reference the .dynamic entry that has the RUNPATH tag. In the following example, prog has a dependency on libfoo.so.1. The runtime linker must search directories /home/me/lib and /home/you/lib before it looks in the default location.
$ elfdump -d prog | egrep "NEEDED|RUNPATH" [1] NEEDED 0x4ce libfoo.so.1 [3] NEEDED 0x4f6 libc.so.1 [21] RUNPATH 0x210e /home/me/lib:/home/you/lib
Another way to add to the runtime linker's search path is to set one of the LD_LIBRARY_PATH family of environment variables. This environment variable, which is analyzed once at process startup, can be set to a colon-separated list of directories. These directories are searched by the runtime linker before any runpath specification or default directory.
These environment variables are well suited to debugging purposes, such as forcing an application to bind to a local dependency. In the following example, the file prog from the previous example is bound to libfoo.so.1, found in the present working directory.
$ LD_LIBRARY_PATH=. prog
Although useful as a temporary mechanism of influencing the runtime linker's search path, the use of LD_LIBRARY_PATH is strongly discouraged in production software. Any dynamic executables that can reference this environment variable will have their search paths augmented. This augmentation can result in an overall degradation in performance. Also, as pointed out in Using an Environment Variable and Directories Searched by the Runtime Linker, LD_LIBRARY_PATH affects the link-editor.
Environmental search paths can result in a 64–bit executable searching a path that contains a 32–bit library that matches the name being looked for. Or, the other way around. The runtime linker rejects the mismatched 32–bit library and continues its search looking for a valid 64–bit match. If no match is found, an error message is generated. This rejection can be observed in detail by setting the LD_DEBUG environment variable to include the files token. See Debugging Facility.
$ LD_LIBRARY_PATH=/lib/64 LD_DEBUG=files /usr/bin/ls ... 00283: file=libc.so.1; needed by /usr/bin/ls 00283: 00283: file=/lib/64/libc.so.1 rejected: ELF class mismatch: 32–bit/64–bit 00283: 00283: file=/lib/libc.so.1 [ ELF ]; generating link map 00283: dynamic: 0xef631180 base: 0xef580000 size: 0xb8000 00283: entry: 0xef5a1240 phdr: 0xef580034 phnum: 3 00283: lmid: 0x0 00283: 00283: file=/lib/libc.so.1; analyzing [ RTLD_GLOBAL RTLD_LAZY ] ...
If a dependency cannot be located, ldd(1) indicates that the object cannot be found. Any attempt to execute the application results in an appropriate error message from the runtime linker.
$ ldd prog libfoo.so.1 => (file not found) libc.so.1 => /lib/libc.so.1 libm.so.2 => /lib/libm.so.2 $ prog ld.so.1: prog: fatal: libfoo.so.1: open failed: No such file or directory
The default search paths used by the runtime linker are /lib and /usr/lib for 32–bit application. For 64–bit applications, the default search paths are /lib/64 and /usr/lib/64. These search paths can be administered using a runtime configuration file created by the crle(1) utility. This file is often a useful aid for establishing search paths for applications that have not been built with the correct runpaths.
A configuration file can be constructed in the default location /var/ld/ld.config, for 32–bit applications, or /var/ld/64/ld.config, for 64–bit applications. This file affects all applications of the respective type on a system. Configuration files can also be created in other locations, and the runtime linker's LD_CONFIG environment variable used to select these files. This latter method is useful for testing a configuration file before installing the file in the default location.
The runtime linker allows for the expansion of various dynamic string tokens. These tokens are applicable for filter, runpath and dependency definitions.
$CAPABILITY – Indicates a directory in which objects offering differing capabilities can be located. See Capability Specific Shared Objects.
$ISALIST – Expands to the native instruction sets executable on this platform. See Instruction Set Specific Shared Objects.
$ORIGIN – Provides the directory location of the current object. See Locating Associated Dependencies.
$OSNAME – Expands to the name of the operating system. See System Specific Shared Objects.
$OSREL – Expands to the operating system release level. See System Specific Shared Objects.
$PLATFORM – Expands to the processor type of the current machine. See System Specific Shared Objects.