Establishing Dependencies with Dynamic String Tokens
A dynamic object can establish dependencies explicitly or through filters. Each of these mechanisms can be augmented with a runpath, which directs the runtime linker to search for and load the required dependency. String names used to record dependency and runpath information can be augmented with the reserved dynamic string tokens:
$OSNAME, $OSREL and $PLATFORM
The following sections provide specific examples of how each of these tokens may be employed.
Instruction Set Specific Shared Objects
Any string name that incorporates the $ISALIST token is effectively duplicated into multiple strings. Each string is assigned one of the available instruction sets. This token is only available for filter or runpath specifications.
The following example shows how the auxiliary filter libfoo.so.1 can be designed to access an instruction set specific filtee libbar.so.1.
$ LD_OPTIONS='-f /opt/ISV/lib/$ISALIST/libbar.so.1' \ cc -o libfoo.so.1 -G -K pic -h libfoo.so.1 -R. foo.c $ dump -Lv libfoo.so.1 | egrep "SONAME|AUXILIARY"  SONAME libfoo.so.1  AUXILIARY /opt/ISV/lib/$ISALIST/libbar.so.1
Or alternatively the runpath can be used.
$ LD_OPTIONS='-f libbar.so.1' \ cc -o libfoo.so.1 -G -K pic -h libfoo.so.1 -R'/ot/ISV/lib/$ISALIST' foo.c $ dump -Lv libfoo.so.1 | egrep "RUNPATH|AUXILIARY"  RUNPATH /opt/ISV/lib/$ISALIST  AUXILIARY libbar.so.1
In either case the runtime linker will use the platform available instruction list to construct multiple search paths. For example, the following application has a dependency on libfoo.so.1 and is executed on a SUNW,Ultra-2:
$ ldd -ls prog ..... find object=libbar.so.1; required by ./libfoo.so.1 search path=/opt/ISV/lib/$ISALIST (RPATH from file ./libfoo.so.1) trying path=/opt/ISV/lib/sparcv9+vis/libbar.so.1 trying path=/opt/ISV/lib/sparcv9/libbar.so.1 trying path=/opt/ISV/lib/sparcv8plus+vis/libbar.so.1 trying path=/opt/ISV/lib/sparcv8plus/libbar.so.1 trying path=/opt/ISV/lib/sparcv8/libbar.so.1 trying path=/opt/ISV/lib/sparcv8-fsmuld/libbar.so.1 trying path=/opt/ISV/lib/sparcv7/libbar.so.1 trying path=/opt/ISV/lib/sparc/libbar.so.1
Or an application with similar dependencies is executed on an MMX configured Pentium Pro:
$ ldd -ls prog ..... find object=libbar.so.1; required by ./libfoo.so.1 search path=/opt/ISV/lib/$ISALIST (RPATH from file ./libfoo.so.1) trying path=/opt/ISV/lib/pentium_pro+mmx/libbar.so.1 trying path=/opt/ISV/lib/pentium_pro/libbar.so.1 trying path=/opt/ISV/lib/pentium+mmx/libbar.so.1 trying path=/opt/ISV/lib/pentium/libbar.so.1 trying path=/opt/ISV/lib/i486/libbar.so.1 trying path=/opt/ISV/lib/i386/libbar.so.1 trying path=/opt/ISV/lib/i86/libbar.so.1
Reducing Auxiliary Searches
The use of $ISALIST within an auxiliary filter enables one or more filtees to provide alternative implementations of interfaces defined within the filter.
Any interface defined in a filter that does not have an alternative implementation defined in a filtee will result in an exhaustive search of all potential filtees in an attempt to locate the required interface. If filtees are being employed to provide performance critical functions, this exhaustive filtee searching can be counterproductive.
A filtee can be built with the link-editor's -z endfiltee option to indicate that it is the last of the available filtees. This option terminates any further filtee searching for that filter. For example, from the previous SPARC example, if the sparcv9 filtee existed, and was tagged with -z endfiltee, the filtee searches would be:
$ ldd -ls prog ..... find object=libbar.so.1; required by ./libfoo.so.1 search path=/opt/ISV/lib/$ISALIST (RPATH from file ./libfoo.so.1) trying path=/opt/ISV/lib/sparcv9+vis/libbar.so.1 trying path=/opt/ISV/lib/sparcv9/libbar.so.1
System Specific Shared Objects
The dynamic tokens $OSNAME, $OSREL and $PLATFORM are expanded at runtime to provide system specific information. $OSNAME expands to reflect the name of the operating system, as displayed by the utility uname(1) with the -s option. $OSREL expands to reflect the operating system release level, as displayed by uname -r. $PLATFORM expands to reflect the underlying hardware implementation, as displayed by uname -i.
The following example shows how the auxiliary filter libfoo.so.1 can be designed to access a platform specific filtee libbar.so.1.
$ LD_OPTIONS='-f /usr/platform/$PLATFORM/lib/libbar.so.1' \ cc -o libfoo.so.1 -G -K pic -h libfoo.so.1 -R. foo.c $ dump -Lv libfoo.so.1 | egrep "SONAME|AUXILIARY"  SONAME libfoo.so.1  AUXILIARY /usr/platform/$PLATFORM/lib/libbar.so.1
This mechanism is used in the Solaris operating environment to provide platform specific extensions to the shared object /usr/lib/libc.so.1.
Note - The environment variable LD_NOAUXFLTR can be set to disable the runtime linkers auxiliary filter processing. Because auxiliary filters are frequently employed to provide platform specific optimizations, this option can be useful in evaluating a filtee's use and performance impact.
Locating Associated Dependencies
Typically, an unbundled product is designed to be installed in a standalone, unique location. This product is composed of binaries, shared object dependencies, and associated configuration files. For example, the unbundled product ABC might have the layout shown in the following figure.
Figure C-1 Unbundled Dependencies
Assume that the product is designed for installation under /opt. Normally you would augment the PATH with /opt/ABC/bin to locate the product's binaries. Each binary will locate their dependencies using a hard-coded runpath within the binary. For the application abc, this runpath would be:
% dump -Lv abc  NEEDED libA.so.1  RUNPATH /opt/ABC/lib
and similarly for the dependency libA.so.1 this would be:
% dump -Lv libA.so.1  NEEDED libB.so.1  RUNPATH /opt/ABC/lib
This dependency representation works until the product is installed in some directory other than the recommended default.
The dynamic token $ORIGIN expands to the directory in which an object originated. This feature depends on an auxiliary vector provided by the kernel to the runtime linker on process startup. See to the getexecname(3C) man page. Using this technology, you can now redefine the unbundled application to locate its dependencies in terms of $ORIGIN:
% dump -Lv abc  NEEDED libA.so.1  RUNPATH $ORIGIN/../lib
and the dependency libA.so.1 can also be defined in terms of $ORIGIN:
% dump -Lv libA.so.1  NEEDED libB.so.1  RUNPATH $ORIGIN
If this product is now installed under /usr/local/ABC and the user's PATH is augmented with /usr/local/ABC/bin, invocation of the application abc will result in a path-name lookup for its dependencies as follows:
% ldd -s abc ..... find object=libA.so.1; required by abc search path=$ORIGIN/../lib (RPATH from file abc) trying path=/usr/local/ABC/lib/libA.so.1 libA.so.1 => /usr/local/ABC/lib/libA.so.1 find object=libB.so.1; required by /usr/local/ABC/lib/libA.so.1 search path=$ORIGIN (RPATH from file /usr/local/ABC/lib/libA.so.1) trying path=/usr/local/ABC/lib/libB.so.1 libB.so.1 => /usr/local/ABC/lib/libB.so.1