是否可以将数组编号作为函数执行?

时间:2013-01-12 07:42:37

标签: c++ c linux elf

长话短说,我有一个整数数组,它代表一个函数的ELF二进制文件的.text部分。我想执行这个功能。我在尝试执行命令之前运行了此命令:

mprotect(function, sHeader.sh_size, PROT_EXEC | PROT_READ | PROT_WRITE);

认为它可以解决权限问题,但是当我尝试运行它时仍然会出现段错误:

int (*fp)(int, int) = (int (*)(int, int))getFunc("t.o");
int a = 2;
int b = 3;
cout << fp(a, b) << "\n";

但是当我尝试运行它时仍然会出现段错误:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000603010 in ?? ()

有什么我错过的吗?

我试图执行的函数的objdump:

0000000000000000 <mult>:
mult():
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   89 7d fc                mov    %edi,-0x4(%rbp)
   7:   89 75 f8                mov    %esi,-0x8(%rbp)
   a:   8b 45 fc                mov    -0x4(%rbp),%eax
   d:   0f af 45 f8             imul   -0x8(%rbp),%eax
  11:   5d                      pop    %rbp
  12:   c3                      retq   

2 个答案:

答案 0 :(得分:3)

ELF目标文件包含relocation信息,很可能其.text部分包含要重定位的代码,因此代码不会按原样运行。使用objdumpreadelf命令进行探索。如果你真的想以你的方式加载它,你应该处理重定位信息,这是复杂的,处理器特定的,乏味的。如果你真的想花几周的时间来研究这个问题,请研究x86-64 ABI。但是使用dlopen的{​​{1}}然后.so要简单得多(因为dlsymdlopen来自mmap的段后进行重定位),见下文。

x86-64 ABI曾经在http://x86-64.org/documentation/abi.pdf上,但该网站今天不起作用

什么是t.so?你如何在getFunc内进行搬迁?为什么你不能拥有t.o共享对象(例如使用t.so编译),然后使用dlopen(3)gcc -Wall -fPIC -O -shared t.c -o t.so加载它,例如

dlsym(3)

一旦typedef int functionsig_t (int, int); void* dlh = dlopen("./t.so", RTLD_NOW); if (!dlh) { fprintf(stderr, "dlopen t.so failed with %s\n", dlerror()); exit(EXIT_FAILURE); }; functionsig_t* fp = (functionsig_t*) dlsym(dlh, "myfunc"); if (!fp) { fprintf(stderr, "dlsym myfunc failed with %s\n", dlerror()); exit(EXIT_FAILURE), } // now you can call fp int res = (*fp) (1,2); 返回并且使用fp中的任何函数都不存在调用堆栈帧,您可t.so dlclose(dlh);来自munmap的段。您可以避免调用t.so(这通常会导致进程地址空间无关紧要;请参阅文件dlclose以获取pid 1234的进程),尤其是如果您没有/proc/1234/maps很多共享对象。

如果dlopen插件调用主程序中的函数,您希望该主程序与t.so选项-rdynamicld

相关联

如果已从某些C ++源代码编译gcc,则应声明

t.so

extern "C" int myfunc(int,int);

完成name mangling

我的manydl.c程序显示您可以在Linux进程中执行数十万个g++ - s。它的工作原理是生成“随机”C代码,将其编译为dlopen.so - dlopen文件,然后重复多次。

如果您不希望将.so.c代码编译成.cc插件,您可以考虑使用{生成内存即时代码生成{3}},LLVMasmjitlibjit等...

答案 1 :(得分:2)

您缺少搬迁。二进制文件不包含绝对地址,而是包含偏移量。

当加载二进制文件时,OS通过将分配的段地址添加到二进制文件中的偏移量来重定位函数指针(以及所有其他符号)。