编译的Elf二进制文件太大
Compiled Elf binary is too big
long *video_memory = (long *)0xB8000;
int main() {
// long *video_memory = (long *)0xB8000;
*video_memory = 0x5050505050505050;
return 0;
}
为什么上面的C代码在链接时会创建一个2Mb二进制文件?
如果我对全局var进行注释,并取消对本地var的注释,它就会起作用(然后文件只有几个字节(。
这就是我链接/[交叉]编译它的方式:
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
问题是,由于x86_64 ABI中的错误,链接器具有2MB的荒谬max-page-size
,这最终导致在各个地方产生2MB的对齐要求。通常,它会将文本和数据段放在文件的同一部分,目的是将其映射两次,但这只有在ELF等合理的二进制格式下才能实现;对于原始二进制,它实现对齐的唯一方法是使用接近2MB的间隙。
正确的解决方案是在链接命令行上用-z max-page-size=4096
(内存保护的实际硬件页面大小/粒度(覆盖荒谬的默认max-page-size
。如果使用编译器驱动程序而不是直接调用ld
,则为-Wl,-z,max-page-size=4096
。无论何时使用会出现相同问题的硬化选项,现代托管工具链都会为您做到这一点,但显然裸金属仍然没有。
您还可以考虑使用一个引导加载程序,它可以为您的内核加载ELF,而不是原始二进制文件。ELF加载程序很容易编写,可以让你做一些有用的事情,比如通过映射(在裸机级别,只是加载/复制(同一页两次来避免浪费空间,在由图像头控制的位置上有一个入口点,而不是在引导加载程序中硬编码,等等。如果你愿意,你甚至可以通过这种方式使内核位置独立。
相关文章:
- 正在读取二进制文件(is_open)
- 在C++中将类(带有Vector成员)保存为二进制文件
- 如何从二进制文件中读取字符串
- 保存/加载大量短数组到二进制文件
- 从二进制文件中读取整数数组
- Android 在编译二进制文件时重建静态库
- 在 C++ 中将双精度变量写入二进制文件
- clang 的 libFuzzer 可以在同一二进制文件中测试超过 1 个 API 吗?
- C++:实际上不是从二进制文件中读取
- 如何从二进制文件中的给定符号中获取调用程序图
- 将内部带有矢量的结构保存/读取到二进制文件中
- 编译多个C++文件.调用二进制文件以运行代码
- 如何使用位字段将数据从二进制文件复制到结构中?
- uint8_t同一二进制文件的不同十进制值
- 挂接静态链接的 ELF 二进制文件
- 如何获取与 objdump 输出的标签相对应的 ELF 二进制文件中的文件偏移量
- 如何使GCC将.text部分编译为可写入ELF二进制文件
- 将动态链接的elf二进制文件转换为静态链接的
- 从GCC 2.95生成的ELF二进制文件中恢复c++类声明
- 在 ReactOS 上运行 ELF 二进制文件