我有一个共享库-plugin.so
,由带有标志dlopen
的主机程序RTLD_LOCAL
编辑,我在该库中定义了自己的内存操作函数:>
void *plugin_malloc(size_t size) { /* ... */ }
void plugin_free(void *ptr) { /* ... */ }
我需要用自己的malloc/free
替换plugin.so
中的所有plugin_malloc/plugin_free
调用,我尝试使用GCC的别名属性扩展名:
void *malloc(size_t) __attribute__((alias("plugin_malloc"), used))
void free(void*) __attribute__((alias("plugin_free"), used))
但是,这仅在将库链接到主机程序中时有效,而不能以dlopen
方式工作。
我在Linux上使用的是GCC-4.8.5编译器,并且源代码为plugin.so
,可以根据需要进行修改,但是我无法修改主机程序 ,并且不仅可以在malloc/free
中替换plugin.so
,而且在整个程序中也可以替换。
那么,有什么解决办法吗?谢谢。
编辑:我也无权修改宿主程序的启动参数,环境变量,我所能做的只是向拥有宿主程序的人提供plugin.so
,并且他们运行主机程序,dlopen
我的plugin.so
。
答案 0 :(得分:1)
考虑到您在使用-fPIC
编译的共享库中提供了一对名为malloc和free的函数(例如,而不是plugin_malloc),那么在调用客户端应用程序时只需要LD_PRELOAD
就可以了:
LD_PRELOAD=/path/mymalloc.so executable
或在致电客户之前将其导出:
export LD_PRELOAD=/path/mymalloc.so
executable
更多详细信息:
[更新]
考虑到您不能更改环境,而只能替换动态库,那么您便可以:
您的库将需要一个初始化函数来完成此肮脏的工作。检查构造函数属性here。但是,可能不允许替换代码。
另一种可能的探索方法(oit?):如果代码使用glibc,则可以尝试在库中提供__malloc_hook。
另一个:在您的库init函数中抓住应用程序控件,再也不要从其返回,然后使用自定义设置再次执行该应用程序。
考虑到您的限制,我暂时无法提出其他任何可能性。
答案 1 :(得分:1)
我需要用我自己的plugin_malloc / plugin_free替换plugin.so中的所有malloc / free调用,
这很简单。
假设您有foo.o
和plugin_malloc.o
链接到plugin.so
中。 foo.o
使用malloc
和free
,而plugin.o
定义plugin_malloc
和plugin_free
。
然后:
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:malloc
中对free
和foo.o
的所有引用已被替换。享受。
更新:
如果我调用分配内存的glibc函数,并且需要在我的代码中将其释放,则程序崩溃。例如char * s = strdup(“ hello”);免费;因为strdup调用了glibc的malloc,但后来的免费版本是我的plugin_free
有几种方法,只有其中一些可以满足您的其他限制:
malloc
和free
替换(例如,通过LD_PRELOAD
,或通过将malloc
实现静态链接到主可执行文件),或malloc
之后通过free
分配内存的任何函数,或者stdup
或asprintf
等的任何此类调用,当您要取消分配此内存时,必须调用__libc_free
而不是plugin_free
或plugin_malloc
中,用16个额外的字节标头(用于对齐)填充分配的所有内存,以将幻数写入块的开头,然后将指针越过标头返回给调用者。在plugin_free
中,检查是否正确对齐,然后检查标题的幻数。如果存在,请从指针中减去16,然后使用plugin_free
的其余部分释放内存。如果幻数不存在,则假定指针不是来自plugin_malloc
,然后调用__libc_free
。plugin_malloc
中,跟踪您分配的所有块。在plugin_free
中检查该列表,如果指针不在列表中,则使用__libc_free
。由于您拥有插件的所有来源,因此解决方案2或3应该都可行,但是显然要求您审核对free
的每次调用,以查看内存的来源。
变体4和5不需要进行此类审核,但不会将插件分配的内存与主程序分配的内存完全分开。
别忘了分配内存的其他方法:realloc
,memalign
,posix_memalign
等