【发布时间】:2019-01-11 17:50:57
【问题描述】:
编辑添加:我现在已将其交叉发布到 GNU ARM Embedded Toolchain 网站,因为我相当确定这是一个链接器错误。
另外,我注意到它似乎发生在第一个程序段适合 ELF 文件的第一页时(即它在其页面内的起始偏移量 >= ELF 标头中的字节数)。在这种情况下,该段错误地向下延伸到文件的开头。这可以解释为什么如果起始地址的页内偏移量从 0x80 减少到 0x40,问题就会消失。
我正在为 ARM Cortex M0 实现一个独立的操作系统,但我的链接器有一个奇怪的问题。这是我的源文件OS.c,为了说明问题而进行了精简:
int EntryPoint (void) { return 99 ; }
这是我的链接器脚本文件OS.ld,只需将所有代码分配给从0x10080开始的区域:
MEMORY
{
NVM (rx) : ORIGIN = 0x10080, LENGTH = 0x1000
}
SECTIONS
{
.text 0x10080 :
{
OS.o (.text)
} > NVM
}
我编译并链接它:
arm-none-eabi-gcc.exe -march=armv6-m -mthumb -c OS.c
arm-none-eabi-gcc.exe -oOS.elf -Xlinker --script=OS.ld OS.o -nostartfiles -nodefaultlibs
现在当我用readelf OS.elf -l 列出程序段时,我得到:
Elf file type is EXEC (Executable file)
Entry point 0x10080
There are 1 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x00010000 0x00010000 0x0008c 0x0008c R E 0x10000
据此,唯一的程序段在 ELF 输出文件中的偏移量 0x000000 处开始,这很疯狂:该区域包含与操作系统无关的 ELF 标头信息。而物理起始地址是0x00010000,在我的硬件中是不存在的。
但奇怪的是,如果我在链接器脚本文件中将0x10080 的两个实例都更改为0x10040,它就可以工作!我明白了:
Elf file type is EXEC (Executable file)
Entry point 0x10040
There are 1 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x010040 0x00010040 0x00010040 0x0000c 0x0000c R E 0x10000
现在程序段在文件中的正确位置,长度为0x0000c 而不是0x0008c。不幸的是地址0x00010040在我的硬件中也不存在,所以这不是一个解决方案。
这是 GCC ARM 编译器中的错误吗?使用--version 运行它会得到:
arm-none-eabi-gcc.exe (GNU Tools for Arm Embedded Processors 7-2018-q2-update) 7.3.1 20180622 (release) [ARM/embedded-7-branch revision 261907]
【问题讨论】:
-
我想我已经看到了很多年并且没有注意到这种细微差别,尽管使用 objcopy 或 openocd 或其他类似的东西,elf 文件工作得很好。由于您使用 gcc 调用 ld 而不是直接调用 ld ,因此您还应该包括您正在使用的 ld 版本。
-
launchpad 是否有遗留原因?并且是一个获得预建的地方,如果有什么可以去 binutils 支持这样的东西,你应该这样做。我的二进制文件是直接从源代码构建的并显示了问题(多年来,gcc 的许多主要修订版和/或 binutils 的许多版本,可能回到 1.x.x)
-
有更简单的方法来获取您想要的入口点顺便说一句...imo...有趣的是会显示您为某些地址而不是其他地址描述的这个问题。
-
@old_timer:入口点很好,我没有问题。问题是代码段从一个不存在的地址开始。所以当我自己的软件从 ELF 文件中读取段时,它会看到一个无效的地址。我已修复我的软件以忽略此特定错误,但最好不必这样做。
-
是的,如前所述,多年来一直看到这一点,并且同意你的看法,这很容易理解。您是否确认问题与 readelf 无关? (你自己检查过elf文件吗?)
标签: gcc arm embedded linker-scripts