Linker and Libraries Guide

Using Interposition

The special handle RTLD_NEXT allows 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, in this case, /usr/lib/libdl.so.1 and then /usr/lib/libc.so.1. If this code fragment was contained in the file B.so.1 from the example shown in Figure 3-2, then foo will be searched for in the associated shared object C.so.1 only.

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


#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/libc.so.1 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 malloc.so.1 -G -K pic malloc.c
$ cc -o prog file1.o file2.o ..... -R. malloc.so.1
$ prog
malloc: 0x32 bytes
malloc: 0x14 bytes
..........

Alternatively, this same interposition can be achieved by:


$ cc -o malloc.so.1 -G -K pic malloc.c
$ cc -o prog main.c
$ LD_PRELOAD=./malloc.so.1 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. However, care should be taken when using this technique in a generic object dependency, as the actual load order of objects is not always predictable (see "Dependency Ordering").