我有一个我不写的二进制文件(ELF),但我想使用此二进制文件中的1个函数(我知道该函数的地址/偏移量),该函数未从二进制文件中导出。
我的目标是从我编写的C代码中调用此函数,并在我的二进制文件中静态编译该函数(我使用gcc进行编译)。
我该怎么办?
答案 0 :(得分:2)
我要回答
从我编写的C代码中调用此函数
部分。
以下内容在某些假设下有效,例如动态链接和位置无关代码。我很久没想过如果它们坏了会发生什么(如果有兴趣,让我们进行实验/讨论)。
$ cat lib.c
int data = 42;
static int foo () { return data; }
gcc -fpic -shared lib.c -o lib.so
$ nm lib.so | grep foo
00000000000010e9 t foo
以上内容复制了您所知道的地址。我们现在知道的地址是0x10e9
。重定位之前它是foo
的虚拟地址。我们将通过简单地添加动态加载器进行的重定位建模,只需添加lib.so
加载时的基址即可。
$ cat 1.c
#define _GNU_SOURCE
#include <stdio.h>
#include <link.h>
#include <string.h>
#include <elf.h>
#define FOO_VADDR 0x10e9
typedef int(*func_t)();
int callback(struct dl_phdr_info *info, size_t size, void *data)
{
if (!(strstr(info->dlpi_name, "lib.so")))
return 0;
Elf64_Addr addr = info->dlpi_addr + FOO_VADDR;
func_t f = (func_t)addr;
int res = f();
printf("res = %d\n", res);
return 0;
}
int main()
{
void *handle = dlopen("./lib.so", RTLD_LAZY);
if (!handle) {
puts("failed to load");
return 1;
}
dl_iterate_phdr(&callback, NULL);
dlclose(handle);
return 0;
}
现在...
$ gcc 1.c -ldl && ./a.out
res = 42
Voila-奏效了!很好玩。
信用:this很有帮助。
如果您有任何疑问,请随时阅读此人并在评论中提问。
至
在我的二进制文件中静态编译此函数
我不知道该怎么做。这将比较棘手。你为什么要那样?另外,您是否知道该函数是否依赖原始ELF文件中的某些数据(或者可能调用了其他函数),就像上面的示例一样?