LD PRELOAD notes
From Noah.org
Contents |
See also ptrace notes for debugging down to the CPU instruction level.
Jordan Sissel offers liboverride, which is a small toolset which lets you quickly inject code into another program.
Example
An example of hooking into a library call using LD_PRELOAD:
/* This example shows how to hook into library calls using LD_PRELOAD.
* This example hooks into the malloc() call. This is not a "serious"
* example. See the end of this comment to see why.
*
* To build this example run the following:
* gcc -ldl -Wall -shared -fPIC -o malloc_hook.so -D_GNU_SOURCE malloc_hook.c
* To test this example run the following:
* LD_PRELOAD=./malloc_hook.so ls -l /proc
* Note that we need -D_GNU_SOURCE to make this work. This enables
* some non-standard GNU extensions. Without this we would get
* this compilation error:
* malloc_hook.c:51: error: 'RTLD_NEXT' undeclared (first use in this function)
*
* Note that when you hook into a library call you usually want to
* eventually hand off the work to the original call.
* Beware because you can't simply call the original library call
* because your hook is running under the LD_PRELOAD modification.
* This is what <dlfcn.h> is for. It provides the dlsym() call which
* is used to find the address of the function. Then we call the
* function directly by its address. The RTLD_NEXT handle used in
* dlsym() is specifically to allow you to create wrappers around
* functions in another shared library.
*
* The next thing to notice is that hooking into malloc this way
* is a very BAD IDEA! Notice the calls to printf() and dlsym().
* What would have happened if these calls had tried to call
* malloc() themselves? You would have ended up with an
* infinite loop. We just got lucky here. It turns out that
* Linux provides hooks for you to get around problems like this.
* In this case we should have looked at using __malloc_hook().
*
* Copyright (c) 2010, Noah Spurrier <noah@noah.org>
*/
#include <dlfcn.h>
#include <stdio.h>
void *malloc(size_t size)
{
static void * (*malloc_original)(size_t) = NULL;
void * memory_pointer;
/* This result of dlsym is preserved to speed up access next time.
* This isn't a thread-safe practice, but it shouldn't matter here
* since a library can have only one pointer to a function.
* If it became a problem I would have removed the 'if' statement
* and the 'static' declaration. It isn't much slower by calling
* dlsym() every time.
*/
if (malloc_original == NULL)
malloc_original = (void *(*)()) dlsym(RTLD_NEXT, "malloc");
memory_pointer = malloc_original(size);
printf("malloc(%d) returns pointer %p\n", size, memory_pointer);
return memory_pointer;
}