Linux 覆盖DLED库中的malloc/free
我有一个共享库-Linux 覆盖DLED库中的malloc/free,linux,malloc,libc,dlopen,Linux,Malloc,Libc,Dlopen,我有一个共享库-插件。因此,它是由主机程序使用标志RTLD_LOCAL定义的dlopen,我在该库中定义了自己的内存操作函数: void *plugin_malloc(size_t size) { /* ... */ } void plugin_free(void *ptr) { /* ... */ } 我需要的是替换plugin中的所有malloc/free调用。因此使用我自己的plugin\u malloc/plugin\u free,我尝试使用GCC的别名属性扩展: void *mall
插件。因此
,它是由主机程序使用标志RTLD_LOCAL
定义的dlopen
,我在该库中定义了自己的内存操作函数:
void *plugin_malloc(size_t size) { /* ... */ }
void plugin_free(void *ptr) { /* ... */ }
我需要的是替换plugin中的所有malloc/free
调用。因此
使用我自己的plugin\u malloc/plugin\u 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,我有插件的源代码。因此
可以随意修改,但我不能修改主机程序,并且不仅在插件中替换malloc/free
。因此
而且在整个程序中也是可以接受的
那么,有什么解决办法吗?谢谢
编辑:我也没有权限修改主机程序的启动参数、环境变量,我能做的只是提供
插件。所以
给拥有主机程序的人,它们运行主机程序和dlopen
my插件。因此
考虑到您在使用-fPIC
编译的共享库中提供了一对名为malloc和free的函数(例如,而不是plugin\u malloc),那么在调用客户端应用程序时,您只需LD\u预加载它即可:
LD_PRELOAD=/path/mymalloc.so executable
或在呼叫您的客户之前将其导出:
export LD_PRELOAD=/path/mymalloc.so
executable
更多详情:
[更新]
考虑到您不能更改环境,只能替换动态库,而无需其他内容,因此您可以:
- 查找malloc/free在内存中的位置
- 将jmp的原始函数条目代码替换为您自己的函数
你的库需要一个初始化函数来完成这项肮脏的工作。检查构造函数属性。但是,可能不允许替换代码
另一种探索的可能性(oit?)是:如果代码使用glibc,那么可以尝试在库中提供一个
还有一个:在库init函数中获取应用程序控件,然后使用自定义设置再次执行该应用程序
考虑到你的限制,我现在不能提出任何其他的可能性
我需要的是替换plugin中的所有malloc/free调用。因此,使用我自己的plugin\u malloc/plugin\u free
这是一件小事
假设您有foo.o
和plugin\u malloc.o
链接到plugin.so
。foo.o
使用malloc
和free
,而plugin.o
定义plugin\u malloc
和plugin\u free
然后:
瞧:foo.o
中对malloc
和free
的所有引用都已被替换。享受
更新:
如果我调用一个glibc函数来分配内存,并且需要在代码中释放,那么程序就会崩溃。e、 g.char*s=strdup(“你好”);免费的;因为strdup调用glibc的malloc,但是后面的免费插件是我的免费插件
有几种方法可以满足您的其他约束:
对于整个程序,您必须将所有malloc
s和free
s替换为您自己的(例如,通过LD_PRELOAD
,或通过将malloc
实现静态链接到主可执行文件中),或
您必须确保不调用任何通过malloc
分配内存的函数,这些函数在free
之后将被调用,或者
对于对stdup
或asprintf等的任何此类调用,当您要释放此内存时,必须调用\uu libc\u free
,而不是plugin\u free
,或者
plugin\u malloc
中,用16个额外字节的头(用于对齐)填充所有分配的内存,将幻数写入块的开头,并将一个指针经过头返回给调用者。在plugin_free中,检查对齐是否正确,然后检查标题是否有幻数。如果有,从指针中减去16,然后使用剩余的plugin\u free
释放内存。如果魔法数字不在那里,则假定指针不是来自插件\u malloc
,并对其调用\uu libc\u free
plugin\u malloc
中跟踪您分配的所有块。在plugin\u free
中检查该列表,如果指针不在列表中,则使用\u libc\u free
free
的每次调用,以查看内存来自何处
变体4和5不需要这样的审计,但并没有将插件分配的内存与主程序分配的内存完全分开
不要忘记其他分配内存的方法:
realloc
,memalign
,posix\u memalign
,等等。你可以通过LD\u预加载技巧来实现这一点:@Leo对不起,我不能这样做,因为我没有运行该程序的权限,我所能做的就是提供插件。因此,
给拥有主机程序的人,我在帖子中添加了此信息。抱歉,我不能这样做,因为我没有运行该程序的权限,我所能做的就是提供插件。因此
对于拥有该主机程序的人,我将此信息添加到帖子中。不,你没有说你不能更改环境。是的,这是我的错,现在我将其添加到帖子中。所以。。。将.text
段更改为可写,找到malloc/free
的地址,然后在函数开始处编写JMP plugin\u malloc/plugin\u free
指令?看起来是可行的,但这真的是一个肮脏的解决方案…它既肮脏又粗糙。看起来像是破解了别人的密码。然而,你的c
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