我正在为嵌入式平台开发,而我正在努力研究如何动态链接共享库。我正在使用bFLT文件格式,我无法控制可执行文件和共享库的加载位置。
我的加载程序正确地将共享库和可执行文件加载到内存中,并在运行时修改可执行文件的GOT以链接到共享库。
我可以成功获取该函数的地址,我知道在该位置反汇编代码是正确的。但是,如果我尝试调用该函数,整个事情就会崩溃。
当调用共享库函数时,GCC会添加一个'code veneer',并且在调用该函数时会绕道并且实际上不会转移到函数的地址。代码表单分支到的地址未正确重定位,因为它没有显示在可执行二进制文件的重定位列表中。
单板的反汇编如下:
000008d0 <__library_call_veneer>:
8d0: e51ff004 ldr pc, [pc, #-4] ; 8d4 <__library_call_veneer+0x4>
8d4: 03000320 .word 0x03000320 ; This address isn't correctly relocated!
如果我获取函数的地址并将其放入函数指针(因此绕过'代码表单')并调用它,则共享库可以正常工作。
例如:
#define DIRECT_LIB_CALL(x, args...) do { \
typeof(x) * volatile tmp = x; \
tmp(#args); \
} while (0)
DIRECT_LIB_CALL(library_call); /* works */
library_call(); /* crashes */
有没有办法要么告诉GCC不生成代码胶合代码并直接分支到位于GOT中的地址,要么以某种方式使代码胶合板分支的地址显示在重定位列表中以执行?
答案 0 :(得分:2)
我找到了解决此问题的方法。这不是最好或最干净的方法,但它可以完成我的工作。
我利用链接器中的--wrap
选项将符号重定向到__wrap_symbol
。有了这个,我设置了一个awk脚本,自动生成ASM文件,将正确重新定位的地址加载到pc中。任何库调用都将重定向到此代码。基本上我做的是制作我自己的代码贴面。由于生成的代码贴面未被引用,因此它只是被优化掉了。
此外,我必须将我的胶合代码放在.data部分,因为.text部分中的任何内容都未正确重定位。因为,我正在研究的平台没有那么多地区分代码和数据,这种hacky解决方法可行。
Here's a link我正在研究的项目,你可以在那里查找具体细节。