As mentioned in other SO answers I am using the wrapping mechanism of GNU ld to intercept calls to malloc
on Linux (see here for an example).
The used linker flag is -Wl,--wrap=malloc
and the respective void __wrap_malloc(size_t)
is also defined.
This works fine in a test application where all compilation unit are linked into the same binary.
Now, I need to modify a dynamically linked library which is loaded into a main program via dlopen()
.
Linking the library succeeds, but loading it into the main program fails with undefined symbol: __real_malloc
.
Running nm
on the library shows that __wrap_malloc
is defined but __real_malloc
is not.
But, according to man ld
and this SO answer, malloc
should get replaced with __wrap_malloc
and __real_malloc
should point to malloc
when using this technique.
In the test application, I see that __real_malloc
is undefined in the compiled object files but is resolved after getting linked into the executable.
So, why is the symbol resolved in the test application but not in the dynamic library?
In both cases a final link step is performed which should resolve this symbol.
Or is it required to add another library during the link step of the dynamic library in order to get __real_malloc
resolved?
Just in case, it is not possible to modify the target application which loads the dynamic library via dlopen
.
It should work and only requires slight changes to the code in the question you linked.
testapp.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
typedef void f_t(void);
int main()
{
void* h = dlopen("./malloc_wrapper.so", RTLD_NOW);
if (h == NULL)
{
puts(dlerror());
exit(1);
}
f_t* f = (f_t*)dlsym(h, "test");
if (f == NULL)
{
puts(dlerror());
exit(1);
}
(*f)();
return 0;
}
malloc_wrapper.c
#include <stdlib.h> /* added */
#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;
}
void test(void) /* added */
{
free(malloc(1024));
}
Compile and run.
gcc -Wl,-wrap,malloc -shared -fpic malloc_wrapper.c -o malloc_wrapper.so
gcc testapp.c -o testapp -ldl
./testapp
Malloc: 1024 bytes @0x1d44680
Compiling malloc_wrapper.so like this reproduces the error you describe:
gcc -shared -fpic malloc_wrapper.c -o malloc_wrapper.so
./testapp
./malloc_wrapper.so: undefined symbol: __real_malloc
Perhaps you were using wrap when compiling and linking the executable instead of the shared object?