Suppose I want to completely take over the open() system call, maybe to wrap the actual syscall and perform some logging. One way to do this is to use LD_PRELOAD to load a (user-made) shared object library that takes over the open() entry point.
The user-made open() routine then obtains the pointer to the glibc function open()
by dlsym()
ing it, and calling it.
The solution proposed above is a dynamic solution, however. Suppose I want to link my own open()
wrapper statically. How would I do it? I guess the mechanism is the same, but I also guess there will be a symbol clash between the user-defined open()
and the libc open()
.
Please share any other techniques to achieve the same goal.
You can use the wrap feature provided by ld
. From man ld
:
--wrap symbol
Use a wrapper function for symbol. Any undefined reference tosymbol
will be resolved to__wrap_symbol
.Any undefined reference to
__real_symbol
will be resolved tosymbol
.
So you just have to use the prefix __wrap_
for your wrapper function and __real_
when you want to call the real function. A simple example is:
malloc_wrapper.c
:
#include <stdio.h>
void *__real_malloc (size_t);
/* This function wraps the real malloc */
void * __wrap_malloc (size_t size)
{
void *lptr = __real_malloc(size);
printf("Malloc: %lu bytes @%p\n", size, lptr);
return lptr;
}
Test application testapp.c
:
#include <stdio.h>
#include <stdlib.h>
int main()
{
free(malloc(1024)); // malloc will resolve to __wrap_malloc
return 0;
}
Then compile the application:
gcc -c malloc_wrapper.c
gcc -c testapp.c
gcc -Wl,-wrap,malloc testapp.o malloc_wrapper.o -o testapp
The output of the resulting application will be:
$ ./testapp
Malloc: 1024 bytes @0x20d8010