Deferred Symbol References
Deferred symbol references are established from
mapfile
definitions. The
following mapfile
identifies a family
of bar
() functions as deferred references
that should be resolved to
libbar.so.1
.
$ cat mapfile
$mapfile_version 2
SYMBOL_SCOPE {
global:
bar1 { DEFERRED = libbar.so.1 };
bar2 { DEFERRED = libbar.so.1 };
....
};
The deferred nature of these references can be observed from the symbol information and dynamic information defined within the referring object.
$ cc -G -o libdef.so.1 def.c -Kpic -M mapfile -lc $ elfdump -y libdef.so.1 | fgrep DEFERRED [9] [ DEPEND DEFERRED ] [2] libbar.so.1 bar1 [15] [ DEPEND DEFERRED ] [2] libbar.so.1 bar2 .... $ elfdump -d libdef.so.1 | fgrep DEFERRED [2] SUNW_DEFERRED 0x176 libbar.so.1
At runtime, a dlsym(RTLD_PROBE)
against one
of the bar
() symbols can be used to
determine whether the family of symbols are available. On
success, the members of the family can be called as direct
function calls. These calls are much more legible and easier
to write, and allow the compiler to catch errors in their
calling sequences.
void dep() { if (dlsym(RTLD_PROBE, "bar1")) { bar1(arg1); bar2(arg2); .... } }
There are a couple scenarios that can be useful for this technique. The first is to test for new functionality in an existing dependency, and the other is to test whether a dependency exists.
Applications can be built so that they execute on a series of OS releases. The core functionality of the application must execute on the oldest version of the OS the application is targeted to. However, newer OS releases can provide new, or more optimal features. By establishing deferred references to these features, an application can test for the features existence before calling the associated functionality.
Deferred references can also be used to test that a dependency
exists. This capability is essentially equivalent to
establishing a deferred dependency with the -z
deferred
option. See the following section
Deferred Dependencies.
In both scenarios, the dlsym(RTLD_PROBE)
test ensures at runtime that a dependency defining the
required symbol exists. The dependency can be one that is
already in use by the caller to provide other symbol
definitions. Or, the dependency may be loaded explicitly to
satisfy the dlsym
() request. In either
case, once the existence of the dependency is confirmed, the
associated symbol, or others that are known to exist with
the associated symbol, can be called freely.