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, the application prog can contain the following code fragment.

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

In this case, foo is searched for in the shared objects associated with prog, which in this case is /lib/ If this code fragment was contained in the file from the example that is shown in Figure 3–1, then foo is searched for in only.

Use of 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, the following code fragment can be 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 (NULL);
        (void) sprintf(buffer, "malloc: %#x bytes\n", size);
        (void) write(1, buffer, strlen(buffer));
        return ((*fptr)(size));
} can be interposed before the system library /lib/ where malloc(3C) usually resides. Any calls to malloc() are now interposed upon 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, the same interposition can be achieved using the following commands.

$ 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) possibly using malloc(3C).

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