昨天遇到一个奇怪的问题, 上网搜索没找到有用的回答. 今天偶然解决了, 希望通过记录解决方法, 为以后提供帮助吧.
问题
- 同样的原版 xv6 (b818915),
make qemu
在笔记本上可以运行, PC 上一直刷新 Booting from hard disk.
求解
- qemu 版本 / gcc 版本?
- 在 PC 上编译不同版本的 qemu, 开启或关闭 KVM, 尝试 canonical 源的 qemu. 都是同样结果
- 笔记本和 PC 上 qemu 都是 2.5, 笔记本可以, PC 不行
- 笔记本使用 gcc-5.4, 在 PC 上切换成 gcc-5.4 也不行
- 笔记本编译出的镜像可以在 PC 上运行; PC 编译出的镜像在笔记本上不能运行, 同样错误.
- 结论: 应该是编译环境的问题. 检查用到的所有工具
$ make clean $ make qemu -n | cut -d\ -f1 | sort | uniq # dd gcc ld ./mkfs objcopy objdump qemu-system-i386 ./sign.pl ./vectors.pl
- 排查过 qemu 和 gcc 应该不是问题, 重点放到了 binutils.
- objcopy / objdump 的版本完全一样
- ld: 版本一样, 但是发现 PC 上用了 ld.gold, 笔记本用的 ld.bfd.
- 在 PC 上, 将 ld 切换成 ld.bfd 之后
make qemu
也能正常运行了.
关于 gold
gold 是另外的 linker, 比默认的 bfd 更快更省内存, 尤其是编译大型 C++ 项目的时候.
根据男人, gold 是 the GNU ELF linker, 而 bfd 是 the GNU linker.
- bfd 能适配的文件格式更多, 如古老的 a.out 格式 (参见 Linkers and Loaders 一书).
而 gold 只支持 ELF 格式. 在 xv6 的构建过程中, 有
ld -m elf_i386 -T kernel.ld -o kernel <a bunch of .o files> -b binary initcode entryother
虽然 ld.gold 接受
-b binary
, 但是看起来它的支持并不好.
另外一些信息如
- bfd 使用的 BFD library 是 binary file descriptor 的缩写.
- bfd 自称能提供更好的 error diagnostics
gold 的作者写了一堆关于 linker 的 blog.
其他
前几天遇到类似的问题, 在一个学生的电脑上, qemu (riscv) 运行某 奇怪操作系统 也是卡在 booting from hard disk.
这次原因又是 qemu 的问题了 – 我把我的 qemu 给他就好了.
后来又遇到类似的问题. 这次是, 同样的 kernel image. 我在 ubuntu 上运行, 然后另外的人可以在他的 ubuntu 上运行. 但另外的人无法在他的 mac OS 上运行. 我怀疑是 qemu 版本, 但都是 3.10. 加上 mac OS 似乎无法直接运行我给他的 ELF, 所以只好让他在 ubuntu 上开发.
之后遇到其他的问题, 这次是因为在内核中访问了非法地址 i.e. 内核中 pagefault.
可以在 xv6 的 main 中加入一行 while (*(int*) 0xDEADBEE0) ;
来复现这个错误.
如果想要防止 qemu 不断重启, 可以加入选项 -no-reboot
.