用VSCode + QEMU跑起来能够可视化Debug的NOVA文件系统
用VSCode + QEMU跑起来能够可视化Debug的NOVA文件系统1. 环境配置2. QEMU安装3. NOVA内核编译4. Initrd选择与QEMU启动内核5. NVM设备模拟5.1 官方方案5.2 个人方案6. 利用VSCode可视化调试上次介绍了NOVA文件系统,接下来的任务就是怎么开始代码上手NOVA文件系统了。博主具有一定强迫症,开发内核前一定要想配置好可视化Debug方法,不想
用VSCode + QEMU跑起来能够可视化Debug的NOVA文件系统
- 上次介绍了NOVA文件系统,接下来的任务就是怎么开始代码上手NOVA文件系统了。博主具有一定强迫症,开发内核前一定要想配置好可视化Debug方法,不想用printk,或是其他方法。
- 另外,现有的配置NOVA的方案都是直接改虚拟机的
grub
来模拟NVM,然后要为虚拟机更换内核,各种操作比较麻烦,可能把原有虚拟机搞崩,基于这一系列问题,本文提供一种用QEMU模拟NVM并且利用VSCODE可视化Debug的方法,希望能够成为某些和博主一样类型的人的福音。- 话不多说,芜湖,起飞✈:)
1. 环境配置
CentOS 8
服务器(虚拟机一样的)VSCode
安装Remote-SSH
拓展(用于远程连接服务器)VSCode
安装Native debug
拓展(用于Debug)
2. QEMU安装
这里我用的是QEMU 5.1.0
[deadpool@localhost linux-nova]$ qemu-system-x86_64 -version
QEMU emulator version 5.1.0
Copyright (c) 2003-2020 Fabrice Bellard and the QEMU Project developers
安装步骤(从源码安装):
# 获取压缩包
wget https://download.qemu.org/qemu-5.1.0.tar.xz
# 解压
tar xvJf qemu-5.1.0.tar.xz
# 切换目录
cd qemu-5.1.0
# 仅配置x86_64的虚拟环境(因为NOVA目前仅支持X86架构)
./configure --disable-kvm --disable-werror --prefix=/usr/local --target-list="x86_64-softmmu" --enable-libpmem
# 编译(用最大核心数编译)
echo $(nproc)
make -j$(nproc)
# 安装至路径/usr/local下
sudo make install
运行下述命令保证安装成功:
qemu-system-x86_64 -version
3. NOVA内核编译
第一步:获取内核源码:
git clone git://github.com/NVSL/linux-nova.git
# 切换至源码目录
cd linux-nova
第二步:配置编译选项
# 配置x86_64默认选项
make defconfig
# 查看内核版本
cat .config | grep Linux/x86
# 如果不是4.18,那可能要切换一下分支,至于为何是4.18,这是因为博主只在4.18上测试成功
git checkout 4.18
# 打开NOVA要求的几个选项
make menuconfig
-
第一处配置:在
Device Drivers
选项中
-
第二处配置:在
File Systems
选项中
-
第三处配置:在
Processor type and features
中
-
第四处配置:在
Memory Management options
中 -
最后:回到
Device Drivers
选项,找到DAX: direct access to differentiated memory
,进入,做如下勾选:
# 接下来配置内核Debug选项,直接用命令即可
# 下述代码-e表示enable,-d表示disable
./scripts/config -e DEBUG_INFO -e GDB_SCRIPTS -e CONFIG_DEBUG_SECTION_MISMATCH -e CONFIG_FRAME_POINTER -d CONFIG_RANDOMIZE_BASE
第三步:编译内核
编译内核并不困难,虽然我们通常被吓到。直接make
就好了。
make -j$(nproc)
编译完成后,会看到如下提示:
Kernel: arch/x86/boot/bzImage is ready
这告诉我们内核镜像已经准备好了。
内核编译速度视机器不同而不同。由于博主的服务器配置有点小好,所以用-j32
编几分钟就编好了。如果是差一点的机器,可能要编上好几个小时,这时候摸鱼就好了🤭
4. Initrd选择与QEMU启动内核
如何用QEMU启动可以Debug的内核呢?最简单的方法如下:
qemu-system-x86_64 \
-kernel arch/x86_64/boot/bzImage \
-nographic \
-smp 1 \
-append "console=ttyS0 nokaslr" \
-s -S
这里简单解释一下各参数的作用:
-kernel
:指定内核bzImage
;-nographic
:由于服务器没有配置可视化界面,因此去掉GUI;-smp
:核心数量;-append
:系统启动参数。console=ttyS0 nokaslr
指定用ttyS0
设备(该设备是串口输出)作为输出,nokaslr
说明取消内存地址随机化,避免调试的时候出现乱七八糟的情况;-s
:默认GDB调试端口为localhost: 1234-S
:停止在系统入口;
遗憾的是,光这样还不行,需要指定initrd
。initrd
全称init ram disk
,即初始化的RAM文件系统,initrd
必须和内核版本相适应。具体的制作博主并没有参透,等之后参透了会再发博客🤭,这里用了一个取巧的办法:
题外话:已经知道怎么做了,嘿嘿 👉 传送门
无意中发现/boot
目录下有很多initramfs
:
[deadpool@localhost linux-nova]$ ls /boot/
config-4.18.0-240.el8.x86_64 System.map
config-4.18.0-305.10.2.el8_4.x86_64 System.map-4.18.0-240.el8.x86_64
config-4.18.0-305.12.1.el8_4.x86_64 System.map-4.18.0-305.10.2.el8_4.x86_64
efi System.map-4.18.0-305.12.1.el8_4.x86_64
grub2 System.map-5.1.0
initramfs-0-rescue-badf97bbe70d402e99024dbf5317e538.img vmlinuz
initramfs-4.18.0-240.el8.x86_64.img vmlinuz-0-rescue-badf97bbe70d402e99024dbf5317e538
initramfs-4.18.0-240.el8.x86_64kdump.img vmlinuz-4.18.0-240.el8.x86_64
initramfs-4.18.0-305.10.2.el8_4.x86_64.img vmlinuz-4.18.0-305.10.2.el8_4.x86_64
initramfs-4.18.0-305.12.1.el8_4.x86_64.img vmlinuz-4.18.0-305.12.1.el8_4.x86_64
initramfs-5.1.0.img vmlinuz-5.1.0
loader
而且刚好NOVA文件系统支持4.18
版本的内核,因此直接拷贝一个过来用即可,我这里拷贝的是initramfs-4.18.0-305.12.1.el8_4.x86_64.img
。
qemu-system-x86_64 \
-kernel arch/x86_64/boot/bzImage \
-nographic \
-smp 1 \
-append "console=ttyS0 nokaslr" \
-initrd /boot/initramfs-4.18.0-305.12.1.el8_4.x86_64.img \
-s -S
这个镜像已上传,在这里获取
好了,现在系统可以正常启动了:在一个终端中运行上述命令,ctrl + sheit + ~
呼出新的终端,运行gdb vmlinux
,运行即可:
这里要注意,gdb
起来以后,本来需要输入额外的命令来让gdb attach
到QEMU进程上。这一步我通过修改./scripts/gdb/vmlinux-gdb.py
文件做到了自动执行,如下图所示:
即,在try
里面加入:
gdb.execute("target remote :1234", to_string=True)
这样一来,就能够让gdb attach
到QEMU上了,系统成功启动,截图如下:
但现在有个问题,NVM设备在哪里?
5. NVM设备模拟
5.1 官方方案
官方给出了一种利用NVM模拟方案:
sudo qemu-system-x86_64
-m 4G,slots=4,maxmem=32G \
-smp 4 \
-machine pc,nvdimm=on \
-object memory-backend-file,id=mem1,share,mem-path=/virtual-machines/qemu/f27nvdimm0,size=4G \
-device nvdimm,memdev=mem1,id=nv1,label-size=2M \
-object memory-backend-file,id=mem2,share,mem-path=/virtual-machines/qemu/f27nvdimm1,size=4G \
-device nvdimm,memdev=mem2,id=nv2,label-size=2M \
-kernel arch/x86_64/boot/bzImage \
-nographic \
-append "console=ttyS0 nokaslr" \
-initrd /boot/initramfs-4.18.0-305.12.1.el8_4.x86_64.img \
-s -S
但是这种模拟方式模拟的是裸板。利用NOVA挂载的时候会报错:设备不支持DAX,解决方法应该是使用impctl
等NVM工具来进行配置,这里博主没有研究过,先不谈了。
5.2 个人方案
最终解决方案是在-append
参数中加入memmap
,即仍然使用与修改GRUB类似的方式来启动QEMU,完整命令如下:
qemu-system-x86_64 \
-kernel arch/x86_64/boot/bzImage \
-nographic \
-smp 1 \
-append "console=ttyS0 nokaslr memmap=1G!1G" \
-initrd /boot/initramfs-4.18.0-305.12.1.el8_4.x86_64.img \
-s -S \
-m 8G
关于memmap
设置方式及其含义,可以参考这里。与第4节方法一样启动QEMU,截图如下:
至此,我们成功模拟出了一块NVM设备:pmem0
6. 利用VSCode可视化调试
在源码树的.vscode中,添加launch.json
文件,内容如下(确保有Native Debug
拓展):
{
"version": "0.2.0",
"configurations": [
{
"name": "Native Debugger for Linux",
"type": "gdb",
"request": "attach",
"executable": "${workspaceRoot}/vmlinux",
"gdbpath": "gdb",
"target": "127.0.0.1:1234",
"cwd": "${workspaceRoot}"
}
]
}
在终端运行第5.2节介绍命令:
qemu-system-x86_64 \
-kernel arch/x86_64/boot/bzImage \
-nographic \
-smp 1 \
-append "console=ttyS0 nokaslr memmap=1G!1G" \
-initrd /boot/initramfs-4.18.0-305.12.1.el8_4.x86_64.img \
-s -S
之后按下F5
,系统就启动了。接下来,在nova_fill_super
的位置打个断点,可以看到,效果杠杠滴。
ok,从现在开始,可以起飞🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫🛫
更多推荐
所有评论(0)