Linker and Libraries Guide

Providing an Alternative to dlopen()

Lazy loading can provide an alternative to dlopen(3C) and dlsym(3C) use. See Runtime Linking Programming Interface. For example, the following code from libfoo.so.1 verifies an object is loaded, and then calls interfaces provided by that object.


void foo()
{
    void * handle;

    if ((handle = dlopen("libbar.so.1", RTLD_LAZY)) != NULL) {
        int (* fptr)();

        if ((fptr = (int (*)())dlsym(handle, "bar1")) != NULL)
            (*fptr)(arg1);
        if ((fptr = (int (*)())dlsym(handle, "bar2")) != NULL)
            (*fptr)(arg2);
        ....
}

This code can be simplified if the object that supplies the required interfaces satisfies the following conditions.

By exploiting lazy loading, the same deferred loading of libbar.so.1 can be achieved. In this case, the reference to the function bar1() results in lazy loading the associated dependency. In addition, the use of standard function calls provides for compiler, or lint(1) validation.


void foo()
{
    bar1(arg1);
    bar2(arg2);
    ....
}
$ cc -G -o libfoo.so.1 foo.c -L. -zlazyload -zdefs -lbar -R'$ORIGIN'

However, this model fails if the object that provides the required interfaces is not always available. In this case, the ability to test for the existence of the dependency, without having to know the dependencies name, is desirable. A means of testing for the availability of a dependency that satisfies a function reference is required.

dlsym(3C) with the RTLD_PROBE handle can be used to verify the existence, and loading of a dependency. For example, a reference to bar1() can verify that the lazy dependency that was established at link-edit time is available. This test can be used to control the reference to functions provided by the dependency in the same manner as dlopen(3C) had been used.


void foo()
{
    if (dlsym(RTLD_PROBE, "bar1")) {
        bar1(arg1);
        bar2(arg2);
        ....
}

This technique provides for safe deferred loading of recorded dependencies, together with standard function call use.


Note –

The special handle RTLD_DEFAULT provides a mechanism that is similar to using RTLD_PROBE. However, the use of RTLD_DEFAULT can result in pending lazy loaded objects being processed in an attempt to locate a symbol that does not exist. This loading compensates for objects that have not fully defined their dependencies. However, this compensation can undermine the advantages of a lazy loading.

The use of the -z defs option to build any objects that employ lazy loading, is recommended.