Linker and Libraries Guide

Using Interposition

The special handle RTLD_NEXT enables an application to locate the next symbol in a symbol scope. For example, if the application prog contained the following code fragment:

        if ((fptr = (int (*)())dlsym(RTLD_NEXT, "foo")) == NULL) {
                (void) printf("dlsym: %s\n", dlerror());
                exit (1);
        return ((*fptr)());

then foo will be searched for in the shared objects associated with prog, which in this case are /usr/lib/ and then /usr/lib/ If this code fragment was contained in the file from the example shown in Figure 3-1, then foo will be searched for in the associated shared object only.

Using RTLD_NEXT provides a means to exploit symbol interposition. For example, a function within an object can be interposed upon by a preceding object, which can then augment the processing of the original function. For example, if the following code fragment is placed in the shared object

#include    <sys/types.h>
#include    <dlfcn.h>
#include    <stdio.h>
void *
malloc(size_t size)
        static void * (* fptr)() = 0;
        char             buffer[50];
        if (fptr == 0) {
                fptr = (void * (*)())dlsym(RTLD_NEXT, "malloc");
                if (fptr == NULL) {
                        (void) printf("dlopen: %s\n", dlerror());
                        return (0);
        (void) sprintf(buffer, "malloc: %#x bytes\n", size);
        (void) write(1, buffer, strlen(buffer));
        return ((*fptr)(size));

then by interposing this shared object between the system library /usr/lib/ where malloc(3C) usually resides, any calls to this function will be interposed on before the original function is called to complete the allocation:

$ cc -o -G -K pic malloc.c
$ cc -o prog file1.o file2.o ..... -R.
$ prog
malloc: 0x32 bytes
malloc: 0x14 bytes

Alternatively, this same interposition can be achieved by:

$ cc -o -G -K pic malloc.c
$ cc -o prog main.c
$ LD_PRELOAD=./ prog
malloc: 0x32 bytes
malloc: 0x14 bytes

Note -

Users of any interposition technique must be careful to handle any possibility of recursion. The previous example formats the diagnostic message using sprintf(3C), instead of using printf(3C) directly, to avoid any recursion caused by printf(3C)'s possible use of malloc(3C).

The use of RTLD_NEXT within a dynamic executable or preloaded object provides a predictable and useful interposition technique. Be careful when using this technique in a generic object dependency, as the actual load order of objects is not always predictable.