编译的Elf二进制文件太大

织物
long *video_memory = (long *)0xB8000;

int main() {
    // long *video_memory = (long *)0xB8000;
    *video_memory = 0x5050505050505050;
    return 0;
}

为什么上面的C代码在链接时会创建2Mb二进制文件?

如果我注释全局变量而取消注释本地变量,那么它将起作用(文件只有几个字节)。

这是我链接/ [交叉]编译它的方式:

x86_64-elf-gcc -m64 -ffreestanding -nostdlib -mno-red-zone -c kernel.c -o bin/kernel.o
objcopy --remove-section .eh_frame bin/kernel.o
x86_64-elf-ld --oformat binary -Ttext 0x8000 bin/kernel_entry.o bin/kernel.o -o bin/kernel.bin
#  kernel.bin is now 2Mb
R .. GitHub停止帮助ICE

问题在于,链接器max-page-size由于x86_64 ABI中的错误而导致了2MB的荒谬,最终导致在各个地方产生2MB的对齐要求。通常,它将文本和数据段放在文件的同一部分中,目的是将它映射两次,但是只有像ELF这样的合理二进制格式才能表示它;对于原始二进制文件,唯一能够实现对齐的方法是将近2MB的间隙。

正确的解决方法是在链接命令行上max-page-size使用-z max-page-size=4096(实际的硬件页面大小/内存保护的粒度)覆盖荒谬的默认值如果您使用编译器驱动程序而不是ld直接调用,那就是-Wl,-z,max-page-size=4096每当您使用会导致出现相同问题的强化选项时,现代托管工具链都会为您做到这一点,但显然裸机仍然没有。

您可能还考虑使用可以为内核加载ELF而不是原始二进制文件的引导加载程序。ELF加载程序易于编写,并让您做一些有用的事情,例如通过两次映射(在裸机级别,只需加载/复制)同一页两次来避免浪费的空间,在图像标题控制的位置设置入口点,而不是在引导程序等中进行硬编码。如果愿意,您甚至可以通过这种方式使内核独立于位置。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章