我正在使用 codesourcery g++ lite(基于 gcc4.7.2 版本)为 stm32(Cortex-m3)编程。我希望动态加载可执行文件。我知道我有两种选择:
1. 可重定位精灵,它需要精灵解析器。
2. 具有全局偏移寄存器的位置无关代码(PIC)
我更喜欢带有全局偏移寄存器的 PIC,因为它似乎更容易实现,而且我不熟悉 elf 或任何 elf 库。此外,使用一些工具可以很容易地从 elf 文件生成 .bin 文件。
我尝试使用“-msingle-pic-base -fpic”编译选项和“-pie”链接选项构建我的程序,但随后出现链接错误:
...path...ld.exe: ...path...thumb2\libstdc++.a(pure.o): 重定位 R_ARM_THM_MOVW_ABS_NC 在制作共享对象时不能使用“本地符号”;使用 -fPIC 重新编译
我不太明白错误信息。似乎默认的标准 c/c++ 库不能与我的选项一起使用,我需要获取库的源代码并为自己的目的进行重建。
那么,
1. 任何人都可以向我提供有关如何使用与位置无关的可执行文件的任何有用信息/链接吗?
2. 有了 -msingle-pic-base 选项,我就不需要太在意 GOT 和 ld 脚本了,对吧?
注意:如果没有“-pie”链接选项,我可以构建程序。但是在调用 c++ 虚函数时程序会失败(当我使用 IDE(keil) 的模拟器来调试我的程序时)。我不明白发生了什么以及我错过了什么。
-------------------------------------------------- ------------------
-- 添加 20130314
- 使用-msingle-pic-base选项,我不再需要过多关心 GOT 和 ld 脚本,对吧?
根据我的实验,寄存器(我的程序中使用了 r9)应该指向 got.plt 部分的开头。删除“-pie”选项,链接将成功,(正确设置r9)然后成功调用c ++虚函数。不过,我仍然认为“-pie”选项很重要,它可以确保当前的标准库是位置无关的。谁能为我解释一下?
-------------------------------------------------- --------------------
-- 添加了 20130315
我查看了 ARM 网站上关于 ABI 的文档。但这没有什么帮助,因为他们没有针对特定平台。似乎有一个 EABI 的概念(我使用的是 sourcery 的 arm-none-eabi 版本),但我在 arm 的网站上找不到任何关于“EABI”的文档。我也无法从 sourcery 和 gcc 中找到有关此主题的文档。PIC 的实现不止一种,那么在非 eabi 情况下,sourcery g++ 使用的是哪一种?我认为“-msingle-pic-base”、“-fpie”、“-pie”选项的行为记录太差了!
从反汇编代码中,我刚刚发现,在“-msingle-pic-base”中,r9 应该指向“.got”部分的基地址,.got 部分中的指针是绝对指针并且变量的寻址类似于文章中的描述:共享库中的位置独立代码(PIC)。所以我仍然需要在加载时修改“.got”部分。我不知道我的程序中使用的“.got.plt”部分是什么。似乎函数调用正在使用 PC 相对寻址。
如何使用“-pie”构建或如何链接使用“-fpic”编译的标准库对我来说仍然是一个问题。