编辑补充:我现在已经将这个问题同时发布到GNU ARM嵌入式工具链网站上,因为我相当确定这是一个链接器的错误。
此外,我注意到当第一个程序段适合ELF文件中的第一页时(即其页面内的起始偏移量>= ELF头中的字节数),它似乎会发生。在这种情况下,该段错误地向下扩展到文件的开头。这就解释了为什么如果将起始地址的页面内偏移从0x80减少到0x40,则问题会消失。
我正在为ARM Cortex M0实现一个独立的操作系统,但我遇到了链接器的奇怪问题。这是我的源文件
我将其编译和链接:
根据这个,唯一的程序段在 ELF 输出文件中的偏移量为
但奇怪的是,如果我在链接器脚本文件中将
现在程序段已经在文件中正确的位置,并且长度为
这是GCC ARM编译器中的一个错误吗?使用
此外,我注意到当第一个程序段适合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]