编辑添加:我现在已将此交叉发布到 GNU ARM Embedded Toolchain网站,因为我相当确定这是一个链接器错误。
另外,我注意到当第一个程序段适合 ELF 文件的第一页时(即它在其页内的起始偏移量 >= ELF header 中的字节数)似乎会发生这种情况。在这种情况下,段错误地向下扩展到文件的开头。这可以解释为什么如果起始地址的页内偏移量从 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
据此,唯一的程序段开始于偏移量
0x000000
在 ELF 输出文件中,这很疯狂:该区域包含与操作系统无关的 ELF header 信息。而物理起始地址是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]
最佳答案
你所看到的可能不是你所期望的,但仍然是正确的,恕我直言。
ELF 是为 System V 创建的。一个支持虚拟内存和 mmap()
的操作系统。 (将文件内容映射到内存的系统调用)。
您正在查看 ELF 程序头( 而不是 节头,见下文)。程序头是一个(具有虚拟内存能力)操作系统的 ELF 加载器的信息,关于它应该在哪里mmap()
将(完整的)ELF 文件放入它作为进程镜像准备的虚拟内存中。然后,该操作系统将在某处分配一个(或多个)页面,调用该(虚拟)0x10000(对于该进程),映射文件并跳转到 0x10080(入口点)。
对于您的第二个示例,当您指定(虚拟)起始地址 时,这将不起作用。之前 ELF 文件头的结尾(ELF 头 + 程序头 + 节头),所以它不能只是将文件映射到页面边界,这使得操作系统更复杂(甚至不可能)做到这一点 mmap()
诡计。
对于您的裸机操作系统(很可能不支持虚拟内存,至少在启动时不支持),ELF 程序头信息可能完全无关。
您可能更应该查看部分标题。它们描述物理内存。
关于GCC for ARM -- ELF 输出文件段错位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54151670/