Dynamic applications consist of one or more dynamic objects. They are typically a dynamic executable and its shared object dependencies. As part of the initialization and execution of a dynamic application, an interpreter is called. This interpreter completes the binding of the application to its shared object dependencies. In Solaris, this interpreter is referred to as the runtime linker.
During the link-editing of a dynamic executable, a special .interp section, together with an associated program header, is created. This section contains a pathname specifying the program's interpreter. An interpreter pathname can be specified when the executable is constructed using the -I option to ld(1), the link-editor. The default name supplied by the link-editor is that of the runtime linker ld.so.1.
During the process of executing a dynamic executable, the kernel maps the file, and locates the required interpreter. See exec(2) and mmap(2). The kernel maps this interpreter and transfers control to it. Sufficient information is passed to the interpretor to allow it to continue binding the application and then run it.
In addition to initializing an application, the runtime linker provides services that allow the application to extend its address space. Additional shared objects can be mapped, and symbols within these shared objects can be bound to.
The runtime linker performs the following functions:
It opens and processes any applicable configuration file. Configuration files may be employed to alter default search paths, provide a directory cache, and provide alternative object dependencies. See crle(1). By default, the configuration file /var/ld/ld.config is used for 32–bit objects, and the configuration file /var/ld/64/ld.config for 64–bit objects. Alternative configuration files can be specified with the LD_CONFIG environment variable, or encoded within a dynamic executable using the -c option of ld(1).
It analyzes the application's dynamic information section (.dynamic) and determines which shared object dependencies are required.
It locates and maps in these dependencies. It then analyzes the dynamic information section of each dependency to determine if any additional shared object dependencies are required.
Once all shared object dependencies are located an mapped, the runtime linker performs any necessary relocations. These relocations bind the shared objects in preparation for process execution.
It calls any initialization functions provided by the shared object dependencies and, possibly, by the dynamic executable. By default, these are called in the reverse order of the topologically sorted dependencies. If cyclic dependencies exist, the initialization functions are called using the sorted order with the cycle removed. ldd(1) can be used to display the initialization order of shared object dependencies.
It passes control to the application.
During the application's execution, the runtime linker can be called upon to perform any delayed function binding.
It calls any finalization functions on deletion of shared objects from the process. By default, these are called in the order of the topologically sorted dependencies.
Further details on each of the above topics may be found in the Linker and Libraries Guide.
The runtime linker uses a prescribed search path for locating the dynamic dependencies of an object. The default search paths are the runpath recorded in the object, followed by /usr/lib for 32–bit objects or /usr/lib/64 for 64–bit objects. This latter component can be modified using a configuration file created with crle(1). The runpath is specified when the dynamic object is constructed using the -R option to ld(1). The environment variable LD_LIBRARY_PATH can be used to indicate directories to be searched before the default directories.
A colon-separated list of objects that are loaded by the runtime linker. As each object is loaded, it is examined for Link-Auditing interface routines. The routines that are present are called as specified in the Link-Auditing interface described in the Linker and Libraries Guide. Also, see the -p and -P options of ld(1).
The runtime linker's default mode of performing lazy binding can be overridden by setting the environment variable LD_BIND_NOW to any non-null value. This setting causes the runtime linker to perform both immediate reference and lazy reference relocations during process initialization, before transferring control to the application. Also, see the -z now option of ld(1).
Provides an alternative configuration file. Configuration files may be employed to alter default search paths, provide a directory cache, and provide alternate object dependencies. See crle(1).
Provides a comma, or colon-separated list of tokens to cause the runtime linker to print debugging information to standard error. The special token help indicates the full list of tokens available. The environment variable LD_DEBUG_OUTPUT may also be supplied to specify a file to which the debugging information is sent. The filename is suffixed with the process ID of the application generating the debugging information.
Any symbol name used as part of a diagnostic message is shown as it is defined within an ELF file. When LD_DEMANGLE is set to any non-null value, the runtime linker attempts to decode (demangle) any C++ symbol name.
Provides an alternative means of supplying environment variable information. Any of the LD_XXX environment variables can be specified as a xxx token. Multiple tokens can be supplied separated by commas. See EXAMPLES.
The LD_LIBRARY_PATH environment variable, if set, is used to enhance the search path that the runtime linker uses to find dynamic dependencies. LD_LIBRARY_PATH specifies a colon-separated list of directories that are searched before the default directories. Also notice that LD_LIBRARY_PATH adds additional semantics to ld(1).
Filters are a form of shared object. They allow an alternative shared object to be selected at runtime that provide the implementation for any symbols defined within the filter. See the -f and -F options of ld(1). By default, the alternative shared object processing is deferred until symbol resolution occurs against the filter. When LD_LOADFLTR is set to any non-null value, any filters are processed immediately when they are loaded. Also, see the -z loadfltr option of ld(1).
Local auditing libraries can be defined within applications and shared objects. See the -p and -P options of ld(1). When LD_NOAUDIT is set to any non-null value, the runtime linker ignores any local auditing libraries.
Auxiliary filters are a form of shared object. They allow an alternative shared object to be selected at runtime which provides the implementation for any symbols defined within the filter. See the -f option of ld(1). When LD_NOAUXFLTR is set to any non-null value, the runtime linker disables this alternative shared object lookup.
By default the runtime linker attempts to open and process a configuration file. When LD_NOCONFIG is set to any non-null value, the runtime linker disables this configuration file processing.
Provides a subset of LD_NOCONFIG in that any directory cache information provided in a configuration file is ignored.
Direct binding information instructs the runtime linker to search directly for a symbol in an associated object. See the -B direct option of ld(1). Without direct binding, the symbol search performed by the runtime linker follows the default model. When LD_NODIRECT is set to any non-null value, the runtime linker ignores any direct binding information.
Provides a subset of LD_NOCONFIG in that any environment variables provided in a configuration file are ignored.
Dependencies labeled for lazy loading are not loaded into memory until explicit reference has been made to them. See the -z lazyload option of ld(1). When LD_NOLAZYLOAD is set to any non-null value, the runtime linker ignores a dependencies lazy loading label and loads it immediately.
Provides a subset of LD_NOCONFIG in that any alternative object dependencies provided in a configuration file are ignored.
By default, the runtime linker verifies version dependencies for the primary executable and all of its dependencies. When LD_NOVERSION is set to any non-null value, the runtime linker disables this version checking.
The immediate processing of $ORIGIN can be triggered by setting the environment variable LD_ORIGIN to any non-null value. Before Solaris 9, this option was useful for applications that invoked chdir(2) prior to locating dependencies that employed the $ORIGIN string token. The establishment of the current working directory by the runtime linker is now default thus making this option redundant.
Provides a list of shared objects, separated by spaces. These objects are loaded after the program being executed but before any other shared objects that the program references. Symbol definitions provided by the preloaded objects interpose on references made by the shared objects that the program references. Symbol definitions provided by the preloaded objects do not interpose on the program itself.
Defines a shared object to be profiled by the runtime linker. When profiling is enabled, a profiling buffer file is created and mapped. The name of the buffer file is the name of the shared object being profiled with a .profile extension. By default, this buffer is placed under /var/tmp. The environment variable LD_PROFILE_OUTPUT may also be supplied to indicate an alternative directory in which to place the profiling buffer.
This buffer contains profil(2) and call count information similar to the gmon.out information generated by programs that have been linked with the -xpg option of cc. Any applications that use the named shared object and run while this environment variable is set, accumulate data in the profile buffer. See also NOTES. The profile buffer information may be examined using gprof(1).
Notice that this profiling technique is an alternative to those that may be provided by the compilation system. The shared object being profiled does not have to be instrumented in any way, and LD_PROFILE should not be combined with a profile-instrumented application. See the Linker and Libraries Guide for more information on profiling shared objects.
Provides a numeric signal number that the runtime linker uses to kill the process in the event of a fatal runtime error. See thr_kill(3THR). By default,
SIGKILL is used. For example, providing the alternative signal number 6 (
SIGABRT), can provide for the creation of a core file to aid debugging. See also the RTLD_DI_SETSIGNAL request to dlinfo(3DL).
Each environment variable can be specified with a _32 or _64 suffix. This makes the environment variable specific, respectively, to 32–bit or 64–bit processes. This environment variable overrides any non-suffixed version of the environment variable that may be in effect.
Notice that environment variable names beginning with the characters 'LD_' are reserved for possible future enhancements to ld(1) and ld.so.1.
Secure processes have some restrictions applied to the evaluation of their dependencies and runpaths to prevent malicious dependency substitution or symbol interposition.
The runtime linker categorizes a process as secure if the user is not a super-user, and the real user and effective user identifiers are not equal. Similarly, if the user is not a super-user and the real group and effective group identifiers are not equal, the process is deemed secure. See getuid(2), geteuid(2), getgid(2), and getegid(2).
The default trusted directory known to the runtime linker is /usr/lib/secure for 32-bit objects or /usr/lib/secure/64 for 64-bit objects. The utility crle(1) may be used to specify additional trusted directories applicable for secure applications. Administrators who use this technique should ensure that the target directories are suitably protected from malicious intrusion.
If an LD_LIBRARY_PATH family environment variable is in effect for a secure process, only the trusted directories specified by this variable are used to augment the runtime linker's search rules.
In a secure process, any runpath specifications provided by the application or any of its dependencies is used, provided it is a full pathname, that is, the pathname starts with a '/'.
In a secure process, the expansion of the $ORIGIN string is allowed only if it expands to a trusted directory.
In a secure process, LD_CONFIG is ignored. A secure process uses the default configuration file, if it exists. See crle(1).
In a secure process, LD_SIGNAL is ignored.
Additional objects may be loaded with a secure process using the LD_PRELOAD, or LD_AUDIT environment variables. These objects must be specified as full pathnames or simple file names. Full pathnames are restricted to known trusted directories. Simple file names, in which no '/' appears in the name, are located subject to the search path restrictions previously described. Simple file names resolve only to known trusted directories.
In a secure process, any dependencies that consist of simple filenames are processed using the pathname restrictions previously described. Dependencies expressed as full or relative pathnames are used as is. Therefore, the developer of a secure process should ensure that the target directory referenced as a full or relative pathname dependency is suitably protected from malicious intrusion.
When creating a secure process, it is recommended that relative pathnames not be used to express dependencies or to construct dlopen(3DL) pathnames. This restriction should be applied to the application and to all dependencies.
The following use of LD_FLAGS is equivalent to setting the individual environment variables LD_BIND_NOW and LD_LIBRARY_PATH for 32–bit applications:
The following use of LD_FLAGS is equivalent to setting the individual environment variables LD_LIBRARY_PATH and LD_PRELOAD for 64–bit applications:
Default runtime linker.
Alternate runtime linker.
Alternate interpreter for SVID ABI compatibility.
AOUT (BCP) runtime linker.
Null character pointer compatibility library. See NOTES.
LD_PRELOAD location for secure applications.
LD_PRELOAD location for secure 64–bit applications.
Default runtime linker for 64–bit applications.
Null character pointer compatibility library for the 64–bit applications.
Default configuration file for 32–bit applications.
Default configuration file for 64–bit applications.
See attributes(5) for descriptions of the following attributes:
|ATTRIBUTE TYPE||ATTRIBUTE VALUE|
crle(1), gprof(1), ld(1), ldd(1), exec(2), getegid(2), geteuid(2), getuid(2),, mmap(2), profil(2), dladdr(3DL), dlclose(3DL), dldump(3DL), dlerror(3DL), dlinfo(3DL), dlopen(3DL), dlsym(3DL), thr_kill(3THR)proc(4), attributes(5)
Care should be exercised when using LD_PROFILE in combination with other process monitoring techniques, such as users of proc(4). Multiple process monitoring techniques can result in deadlock conditions that leave the profile buffer locked. A locked buffer blocks any processes that try to record profiling information. To reduce this likelihood, the runtime linker's profile implementation determines if the process is being monitored at startup. If so, profiling of the process is silently disabled. However, this mechanism can not catch monitoring processes that attach to the process during its execution.
The user compatibility library /firstname.lastname@example.org provides a mechanism that establishes a value of 0 at location 0. Some applications exist that erroneously assume a null character pointer should be treated the same as a pointer to a null string. A segmentation violation occurs in these applications when a null character pointer is accessed. If this library is added to such an application at runtime using LD_PRELOAD, it provides an environment that is sympathetic to this errant behavior. However, the user compatibility library is intended neither to enable the generation of such applications, nor to endorse this particular programming practice.