Deferred Dependencies

A deferred dependency identifies a dependency for which all references to that dependency are deferred. Deferred dependencies are established at link-edit time using the link-editors -z deferred option.

$ cc -G -o libdef.so.1 def.c -lfoo -z deferred -lbar -lc

The deferred nature of these references can be observed from the symbol information and dynamic information defined within the referring object.

$ elfdump -d libdef.so.1 | egrep "NEEDED|POSFLAG"
    [0]  NEEDED          0x85        libfoo.so
    [1]  POSFLAG_1       0x4         [ DEFERRED ]
    [2]  NEEDED          0x8f        libbar.so
    [3]  NEEDED          0x99        libc.so

$ elfdump -y libdep.so.1 | egrep "foo|bar"
    [4]  [ DEPEND DEFERRED ]   [2]   libbar.so  bar1
    [7]  [ DEPEND ]            [0]   libfoo.so  foo1
    ...

Having established libbar.so.1 as a deferred dependency, 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);
                ....
        }
}

Deferred dependencies offer an additional level of flexibility. Provided the dependency has not already been loaded, the dependency can be changed at runtime. This mechanism offers a level of flexibility similar to dlopen(3C), where different objects can be loaded and bound to by the caller.

If the original dependency name is known, then the original dependency can be exchanged for a new dependency using dlinfo(3C) with the RTLD_DI_DEFERRED argument. Alternatively, a deferred symbol that is associated with the dependency can be used to identify the deferred dependency using dlinfo(3C) with the RTLD_DI_DEFERRED_SYM argument.