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_PROBE
only binds to explicit symbol definitions, and is not bound to any procedure linkage table entry within the executable. -
RTLD_PROBE
does 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.