根据Using ld doc:
链接器命令语言包括专门用于 在输出文件(其条目)中定义 first 可执行指令 点)。
如何在这里理解第一?是逻辑上要跳转的第一条指令吗?还是物理上放置在.text
节中的第一条指令?
我将here中的以下链接描述文件用作实验:
ENTRY(__entry) /* <=============== HERE, the __entry */
/*kernel will be loaded at this address after boot*/
INCLUDE linker.ld
SECTIONS
{
/*kernel will be compiled with virtual address base at 2GB*/
. = 0x80000000 + start_address; /*2GB + start_address = (0x80010000)*/
PROVIDE(_kernel_start = .); /*defined at kernel/include/kernel.h, set to 0x80010000*/
.text : AT(start_address)
{
*(.text)
}
.data :
{
*(.data)
}
.bss :
{
*(.bss COMMON)
}
. = ALIGN(8);
PROVIDE(_fb_start = .);
. += framebuffer_size;
PROVIDE(_kernel_end = .); /*defined at kernel/include/kernel.h*/
}
我试图在最终构建的二进制文件的__entry
中搜索指令字节。并发现这些说明确实位于.text
部分的开头。
那么这是否意味着ENTRY()
命令总是将入口点放置在最终二进制文件的.text
部分的开头?
答案 0 :(得分:1)
可执行文件中的第一机器指令是指先执行的指令。它不一定是 .text 段中所有指令的有序列表中的第一个(偏移量最小)。
许多程序都是以自然的 top-down 风格编写的,它们的 entry 实际上指向物理上的第一条指令(偏移量为零)。但是,在这种情况下,程序代码也可能以helper子例程开头,并且其进入点将在代码中更深地移位。
答案 1 :(得分:0)
ENTRY(__entry)
将在最终目标文件中记录__entry
符号的VMA位置。例如,在ELF标头中。加载程序将目标文件的每个 section 加载到内存中后,加载程序或运行时将仅跳转到入口点。
但是在我的情况下,ENTRY(__entry)
实际上不必要。因为EwokOS在裸机上运行,所以没有加载程序。在尝试时,如果我注释掉ENTRY(__entry)
,EwokOS仍然可以在裸机上启动。
__entry
的第一条指令恰好是最终EwokOS.bin
文件的第一条指令的原因,是两个因素的组合:
目标文件到链接器ld
boot.S
文件中的编码顺序。
有3个文件以ld
的顺序馈入boot.o system.o context.o
。因此,我们可以看到boot.o
是要链接的第一个对象文件。
组装成boot.S
的{{1}}文件包含boot.o
作为第一行代码。
这两个因素导致__entry
位于最后一个__entry
的开头,而这是从EwokOS.bin
的{{1}}部分提取的。
在我的场景中,我需要.text
出现在EwokOS.elf
文件的开头,因为bin文件加载在0x10000地址上,该地址是QEMU ARM通用pb的起始地址虚拟机。