我正在制作 x86 内核,在尝试使用字符串文字时遇到了问题。 gcc 编译器将它们放入 .rodata,我当时没有将其加载到 RAM 中。我认为设置 -Trodata 0x00009400 然后使用 objdump 提取该部分并将其放入内核映像中就足够简单了。出于某种原因,readelf 向我表明,事实上 ld 根本没有重新定位该段。另外,当我将 -Tdata 设置为重叠 -Ttext 时,我收到错误,但是当我尝试对 -Trodata 执行相同操作时,它不会出错。看起来好像它完全忽略了命令行参数。
我的内核正在正确加载驱动器的数据,但在引用字符串文字而不是我在命令行上指定的rodata偏移量时,主函数指向错误的地址(ld设置的rodata偏移量)。
生成文件
kernel: kernel/init.c kernel/preinit.asm
gcc -ffreestanding -fno-pie -g -c kernel/init.c -m32 -o object/kernelinit.o
nasm -g -f elf32 ./kernel/preinit.asm -o object/kernelpreinit.o
ld -e kernelInit -Ttext 0x00007E00 -Tdata 0x00009200 -Trodata 0x00009400 object/kernelpreinit.o object/kernelinit.o -o build/kernel.elf
objcopy -O binary -j.text build/kernel.elf build/kernel_text
objcopy -O binary -j.data build/kernel.elf build/kernel_data
objcopy -O binary -j.rodata build/kernel.elf build/kernel_rodata
我尝试从 Binutils 存储库中查找 ld 的源代码,但我似乎找不到问题,除了它可能期望该部分被称为 rodata-section 而不是 rodata,但我可能误读了代码。谷歌并没有帮助找到这个问题的答案。
齐瓦列夫给出了答案。谢谢你。
新ld线:
ld -e kernelInit -Ttext 0x00007E00 -Tdata 0x00009200 --section-start=.rodata=0x00009400 object/kernelpreinit.o object/kernelinit.o object/interrupts.o -o build/kernel.elf