I have a shared library - plugin.so
, which is dlopen
-ed by the host program with flag RTLD_LOCAL
, I have my own memory operation functions defined in that library:
void *plugin_malloc(size_t size) { /* ... */ }
void plugin_free(void *ptr) { /* ... */ }
What I need is to replace ALL malloc/free
calls in plugin.so
with my own plugin_malloc/plugin_free
, I tried using GCC's alias attribute extension:
void *malloc(size_t) __attribute__((alias("plugin_malloc"), used))
void free(void*) __attribute__((alias("plugin_free"), used))
However, this only works when the library is linked into the host program, but not work with the dlopen
way.
I'm on Linux with compiler GCC-4.8.5, and I have the source code of plugin.so
and can modify it as I like, but I cannot modify the host program, and replace malloc/free
not only in plugin.so
but also in entire program is also acceptable.
So, is there any solution? Thanks.
EDIT: I also have no permission to modify the host program's startup arguments, environment variables, what I can do is just providing the plugin.so
to guys who own the host program, and they run the host program and dlopen
my plugin.so
.
What I need is to replace ALL malloc/free calls in plugin.so with my own plugin_malloc/plugin_free,
This is trivial to do.
Suppose you have foo.o
and plugin_malloc.o
that are linked into plugin.so
. The foo.o
uses malloc
and free
, while plugin.o
defines plugin_malloc
and plugin_free
.
Then:
objcopy --redefine-sym malloc=plugin_malloc --redefine-sym free=plugin_free foo.o foo2.o
gcc -shared -fPIC plugin.o foo2.o -o plugin.so
Voila: all references to malloc
and free
in foo.o
have been replaced. Enjoy.
Update:
if I call a glibc function which allocates memory and needs to be freed in my code, the program crashes. e.g. char *s = strdup("hello"); free(s); because strdup calls glibc's malloc, but the later free is my plugin_free
There are a few ways, only some of which satisfy your other constraints:
malloc
s and free
s with your own for the entire program (e.g. via LD_PRELOAD
, or by statically linking malloc
implementation into the main executable), ormalloc
that you expect to free
later, orstdup
or asprintf
etc., when you want to deallocate this memory, you must call __libc_free
rather than plugin_free
, orplugin_malloc
, pad all memory you allocate with 16 extra byte header (for alignment) write magic number to the start of the block, and return a pointer past the header to the caller. In plugin_free
, check for proper alignment, then check the header for magic number. If it's there, subtract 16 from the pointer and use the rest of plugin_free
to free the memory. If the magic number is not there, assume the pointer didn't come from plugin_malloc
, and call __libc_free
on it instead.plugin_malloc
keep track of all the blocks you've ever allocated. In plugin_free
check that list, and use __libc_free
if the pointer is not on the list.Since you have all sources for your plugin, either solution 2 or 3 should be doable, but obviously requires that you audit every call to free
to see where the memory came from.
Variants 4 and 5 don't require such audit, but don't cleanly separate memory allocated by plugin from that allocated by the main program.
Don't forget about other ways to allocate memory: realloc
, memalign
, posix_memalign
, etc.