Testing for Functionality
The special handles RTLD_DEFAULT and
RTLD_PROBE enable an application to test
for the existence of a symbol.
The RTLD_DEFAULT handle employs the same default
search rules used by the runtime linker to resolve any symbol
reference from the calling object. See Default Symbol Lookup Model.
Two aspects of this model should be noted.
-
In the absence of direct binding, a symbol reference from a shared object that matches a symbol reference from a dynamic executable is bound to the procedure linkage table entry associated with the reference from the executable. See Procedure Linkage Table (Processor-Specific). This artifact of dynamic linking enables both components within the process see a single address for a function.
-
If a symbol definition can not be found to satisfy a non-weak symbol reference within the objects that are currently loaded in the process, a lazy loading fallback is initiated. This fallback iterates through each loaded dynamic object, and loads any pending lazy loadable, non-deferred, objects in an attempt to resolve the symbol. This model compensates for objects that have not fully defined their dependencies. However, this compensation can undermine the advantages of lazy loading. Unnecessary objects can be loaded, or an exhaustive loading of all lazy loadable objects can occur should the relocation symbol not be found.
RTLD_PROBE follows a similar model to
RTLD_DEFAULT, but differs in the two
aspects noted with RTLD_DEFAULT.
-
RTLD_PROBEonly binds to explicit symbol definitions, and is not bound to any procedure linkage table entry within the executable. -
RTLD_PROBEdoes not initiate an exhaustive lazy loading fallback.
RTLD_PROBE is the most appropriate flag to use to
detect the presence of a symbol within an existing process.
RTLD_DEFAULT and RTLD_PROBE can
both initiate an explicit lazy load. An object can make reference to
a function, and that reference can be established through a lazy
loadable dependency. Prior to calling this function,
RTLD_DEFAULT or
RTLD_PROBE can be used to test for the
existence of the function. Because the object makes reference to the
function, an attempt is first made to load the associated lazy
dependency. The rules for RTLD_DEFAULT and
RTLD_PROBE are then followed to bind to
the function. In the following example, an
RTLD_PROBE call is used both to trigger a
lazy load, and to bind to the loaded dependency if the dependency
exists.
void foo()
{
if (dlsym(RTLD_PROBE, "foo1")) {
foo1(arg1);
foo2(arg2);
....
}To provide a robust and flexible model for testing for functionally, the associated lazy dependencies should be explicitly tagged as deferred. See Providing an Alternative to dlopen. This tagging also provides a means of changing the deferred dependency at runtime.
The use of RTLD_DEFAULT or
RTLD_PROBE provide a more robust
alternative to the use of undefined weak references, as discussed in
Weak Symbols.