gcc 为什么我可以在没有基址的帮助下获得elf条目?

pxiryf3j  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(134)

我试图在UEFI引导加载程序中获得内核入口函数,我很困惑。
这段代码为什么有效?

int (*kmain)(void*) = (int(*)(void*)) (elf->entry);

这就是我把它和

gcc -no-pie -nostdlib -ffreestanding -e kmain -o kernel.elf kernel.o

我知道这与-no-pie有关,因为没有它就不会工作
elf-〉条目是一个虚拟地址,但由于我在引导程序中,它引用了一个物理地址,对吗?
如果elf-〉entry是0x 4000,那么它进入物理地址0x 4000,但是如果物理地址0x 4000已经被其他东西使用了呢?
如果没有-no-pie,我必须使用base + elf->entry来完成,其中base是elf文件的开始,我完全可以理解,但我不明白为什么elf->entry就可以了

7kqas0il

7kqas0il1#

通常,链接器并不关心它在内存中的 * 什么地方 * 放置任何东西。它的主要工作是确保所有的内存引用都是一致的,而不管 * 内存是如何,布局的。链接器脚本的目的是告诉链接器如何布局内存。如果你没有提供链接器脚本,它将使用自己的默认值。换句话说,链接器不知道也不关心您是否已经在0x4000处加载了一些内容。您的工作是了解内存是如何布局的,如果您希望以特定的方式布局,则提供链接器脚本。
至于问题的-no-pie位,这归结为位置无关和非位置无关的可执行文件是如何加载的。UEFI引导加载程序是一个加载程序。在可执行文件中有一个标志,告诉加载程序它是否是一个PIE。如果不是,那么加载程序只需要使用文件中编码的确切地址。在这种情况下,elf->entry指针将是完全正确的。如果它 * 是 * 一个PIE,那么加载程序可以将它放置在它喜欢的任何内存地址,在这种情况下,elf->entry指针将相对于可执行文件被加载的地址。这就是为什么当你不提供-no-pie标志时,你需要使用base + elf->entry

相关问题