Overwriting Dynamically Linked Stuff

This is just another one of these “I have to write it down somewhere or I’ll forget it” things.

Changing the implementation of dynamically linked library functions via LD_PRELOAD isn’t hard at all - but what wasn’t completely obvious to me is how to write implementations that use the original version of the function.

As an example, let’s say we want a version of open(2) that prints everything it tries to open - but otherwise doesn’t change its behaviour. After printing the pathname, we would like to just do return open(path, flags);. But that wouldn’t work, of course - it would recursively call our own open().

How do we get the original open(2)? The trick is to use dlsym(3) with the special RTLD_NEXT handle. This will find the next occurrence of the specified function after the current library (that is, after our LD_PRELOADed hook).

#define _GNU_SOURCE /* RTLD_NEXT is a GNU extension */
#include <dlfcn.h>
#include <stdio.h>

int open(const char *pathname, int flags)
{

Now we need to obtain a function pointer to the original open:

    static int (*sys_open)(const char *, int) = NULL;
    if (sys_open == NULL) {
        sys_open = dlsym(RTLD_NEXT, "open");
    }

And then we can use it:

    printf("%s\n", pathname);
    return sys_open(pathname, flags);
}

Compile the whole thing with:

gcc -fPIC -shared -o print_open.so print_open.c

And use it as follows:

LD_PRELOAD=`pwd`/print_open.so PROGRAM

See Also

Previously: Javahaha

Next up: 26th Ludum Dare - Postmortem

The machine thinks that the Web-Log entries Overwriting Dynamically Linked Stuff, Purely Functional Games, and Channels in Newsqueak might be related to the topic so eloquently discussed above. The machine is sometimes right.