GNU LD将编译输出识别为链接脚本,内核编译链接报错如何解决?
问题定位
错误出在kernel.cpp的编译环节,同时还有部分编译、链接参数需要补充适配内核开发场景。
错误原因
你在编译C++代码时使用了-S参数,该参数的作用是让GCC只生成汇编代码文本,不执行汇编步骤输出二进制目标文件。你得到的kernel.o本质是纯文本的汇编源码,链接器ld无法识别该格式,才会误将其当做链接脚本解析,抛出语法错误。
此外你当前的编译、链接命令还存在多个不符合裸内核开发要求的问题,也需要同步修复:
- 内核开发属于无标准运行时的独立环境,不能直接链接用户态的
libstdc++库 - 你汇编生成的
boot.o是32位目标文件,C++编译、链接环节没有指定32位输出格式,可能出现格式不兼容问题 - C++的异常、RTTI特性依赖操作系统运行时支持,裸内核环境没有对应实现,需要手动关闭
修复步骤
- 修正C++代码编译命令
替换原有的编译命令为:
g++ -m32 -ffreestanding -fno-exceptions -fno-rtti -c kernel.cpp -o kernel.o
参数说明:
-c:执行编译、汇编步骤,直接输出二进制目标文件,替换错误的-S参数-m32:生成32位目标代码,和boot.o的格式匹配-ffreestanding:告知编译器当前为无标准库的独立运行环境-fno-exceptions、-fno-rtti:禁用内核不支持的C++特性- 移除
-lstdc++:不链接用户态标准库,所需的C++基础功能需要你自己在内核中实现
确认汇编环节正确性
你当前使用的as --32 boot.s -o boot.o命令没有问题,可以正常生成32位引导代码目标文件。修正链接命令
添加32位ELF格式指定参数,同时调整目标文件顺序保证multiboot头位于镜像头部:
ld -m elf_i386 -T linker.ld boot.o kernel.o -o OS.bin
修复完成后可以执行file OS.bin验证输出,正常会返回32-bit LSB executable, Intel 80386相关的提示,之后就可以正常制作ISO镜像在QEMU中运行。
内容的提问来源于stack exchange,提问作者user135142
相关产品推荐
相关产品推荐

