LD PRELOAD notes
From Noah.org
Revision as of 00:32, 7 May 2010 by Root (talk | contribs) (Created page with 'Category:Engineering An example of hooking into a library call using LD_PRELOAD: <pre> /* This example shows how to hook into library calls using LD_PRELOAD. * This exampl…')
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:55: 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 dlsyn() 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(). * * Noah Spurrier */ #include <dlfcn.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/syscall.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; }