为ARM M4编译和链接位置独立代码(PIC)

为ARM M4编译和链接位置独立代码(PIC),c,arm,position,pic,bootloader,C,Arm,Position,Pic,Bootloader,我正在制作一个引导加载程序,让它能够自我更新。这个过程包括将二进制文件复制到一个新位置,跳转到它,并使用它在原始位置刷新新的引导加载程序。这些都是为Eclipse中的M4处理器开发的,使用ARM GCC工具链 为此,我收集了我需要编译为位置独立代码(PIC)的信息 我到处搜索并找到了这篇优秀的文章,所以当我在ARM GCC编译器调用中添加“-fPIC”时,我希望看到缺少关于GET和PLT的链接器错误 在我的链接器脚本中,我将这些位置添加到.data部分,如下所示: .data : AT(__D

我正在制作一个引导加载程序,让它能够自我更新。这个过程包括将二进制文件复制到一个新位置,跳转到它,并使用它在原始位置刷新新的引导加载程序。这些都是为Eclipse中的M4处理器开发的,使用ARM GCC工具链

为此,我收集了我需要编译为位置独立代码(PIC)的信息

我到处搜索并找到了这篇优秀的文章,所以当我在ARM GCC编译器调用中添加“-fPIC”时,我希望看到缺少关于GET和PLT的链接器错误

在我的链接器脚本中,我将这些位置添加到.data部分,如下所示:

.data : AT(__DATA_ROM)
{
. = ALIGN(4);
__DATA_RAM = .;
__data_start__ = .; /* Create a global symbol at data start. */
*(.got*) /* .got and .plt for position independent code */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
KEEP(*(.jcr*))
. = ALIGN(4);
__data_end__ = .; /* Define a global symbol at data end. */
} > m_data
但是,该代码无法从ROM复制到RAM

我的下一个想法是,也许我的链接器需要知道它正在链接一个PIC可执行文件。为了找到答案,我在LD链接器脚本调用中添加了“-pic executable”。然而,链接器现在为“interp”、“dyn”、“rel.dyn”和“hash”生成了部分。我也尝试将这些内容放入数据部分,但出现以下错误:

gcc-arm-none-eabi-4_9/bin/./lib/gcc/arm-none-eabi/4.9.3/../../../../../../../arm-none-eabi/bin/ld.exe: 找不到输出节。哈希

gcc-arm-none-eabi-4_9/bin/./lib/gcc/arm-none-eabi/4.9.3/../../../../../../../arm-none-eabi/bin/ld.exe: 最终链接失败:输出上不可呈现的部分

我假设这意味着编译器实际上没有用任何东西填充“.hash”部分,因此链接失败


我这样做对吗?还有什么我需要添加的来让编译器完成的吗?任何帮助都将不胜感激。

引导代码和重新定位涉及许多仔细的步骤以及RAM、SPI和其他必要外围设备配置的初始化


我知道U-Boot会按照你想要达到的顺序来做。因此,更好的开始是浏览u-boot和感兴趣的处理器或主板的特定于机器的文件夹中的源代码。

无论如何,我和NXP的技术支持团队都无法让他们的S32DS IDE编译真正独立于位置的代码


到目前为止,我们有两个引导加载程序-一个是为位置A编译的,另一个是位置B的中间程序。这两个都是更新所必需的

TI使用Tivaware引导加载程序来实现这一点。您可以使用链接器gnu ld欺骗:

.text 0x20000000 : AT (0x00000000)
{
_text = .;
KEEP(*(.isr_vector))
*(.text*)
*(.rodata*)
_etext = .;
}

将此代码从0x0处的闪存复制到0x2000_0000处的SRAM的启动代码留给读卡器作为练习。

在此实现中,新位置的旧引导加载程序正在执行完全复制和系统初始化。外围设备的初始化不是问题所在。如果我编译引导加载程序以在新地址运行,它将按设计工作。因此,我只需要使程序地址独立—这不是唯一的解决方案,这是一种痛苦的方式。只需复制并跳转以从ram运行引导加载程序。您以前作为其他用户问过这个问题吗?这已经包括在内,对于之前的一个问题,您似乎非常熟悉尝试做同样的事情。@我同意,但如果程序是为静态位置编译的,则复制到另一个位置并运行是不起作用的。不可避免地,编译器决定抛出一个BLX[来自原始位置的地址],如果那里什么都没有,程序就会崩溃。它必须被编译成位置独立的,或者需要一个我不知道的编译器指令。不,我以前没有问过这个问题。当然,它可以工作,就像任何其他引导加载程序一样,您可以将它链接到它将运行的位置,而不是它不会运行的位置。@old_timer此引导加载程序通常位于(例如)0x10000,因为它的主要任务是闪存固件。它需要编译为在0x10000或理想情况下在任何其他位置运行。我将非常感谢您的帮助,帮助我将其编译为在其他位置运行……。这不只是一个拷贝,以便该段可以从特定的SRAM位置运行吗?我非常感谢有时间回答,但这个问题更多的是关于如何使其完全独立于位置-即,如果移动到0x30000000(或任何地方)(这个特定的引导加载程序对于RAM段来说太大),那么让相同的二进制文件从0x30000000(或任何地方)运行。据我所知,位置独立代码没有得到很好的支持,而且你需要外部支持——有些东西必须告诉PIC东西在哪里,也许可以通过配置一个寄存器。因此,采用上述TI方法的原因是:引导加载程序总是会耗尽SRAM,因此它可以更新自身,或者更确切地说是更新自身的预拷贝版本。