通过GDB
调试代码的便利性无需赘言。我们直接以调试meta-hypervisor
为示例进行说明。
准备工作
- 代码
代码请参考meta-hypervisor
和meta-demos
。代码里边有详细的说明文档。 - QEMU
安装qemu-system-aarch64
,版本要求大于5.0
。
启动QEMU
启动QEMU的命令:
qemu_cmd:=qemu-system-aarch64 run: platform @$(qemu_cmd) -nographic\ -M virt,secure=on,virtualization=on,gic-version=3 \ -cpu cortex-a53 -smp 4 -m 4G\ -bios $(atf-fip)\ -device loader,file="$(meta_image)",addr=0x50000000,force-raw=on\ -device virtio-net-device,netdev=net0\ -netdev user,id=net0,net=192.168.42.0/24,hostfwd=tcp:127.0.0.1:5555-:22\ -device virtio-serial-device -chardev pty,id=serial3 -device virtconsole,chardev=serial3\ -S -s
-bios $(atf-fip)
atf-fip
是指编译出的ATF
和U-boot
的二进制文件。-device loader,file="$(meta_image)",addr=0x50000000,force-raw=on
meta_image
指的是meta-hypervisor
的二进制代码。addr=0x50000000
指的是加载到物理内存0x50000000
地址处。-M virt,secure=on,virtualization=on,gic-version=3
指定需要使用的machine
类型,virt
是qemu
提供的一个通用machine
,可以同时支持arm32
和arm64
(部分cortex
不支持),-M help
可以列出所有支持的machine
列表。secure=on
是支持安全空间。virtualization=on
是支持虚拟化扩展。gic-version=3
是支持GICv3
通用中断控制器类型。-cpu cortex-a53 -smp 4 -m 4G
-cpu cortex-a53
:指定模拟的CPU类型。可以使用-cpu help
,查看当前支持的CPU类型。-m 4G
:指定内存大小。-smp 4
:指定CPU核的数量,默认是1
。-s -S
:可选,调试参数。-S
,可以让qemu
加载image
到指定位置后停止运行,等待gdb
连接;-s
, 等价于--gdb tcp::1234
,启动gdb server
并默认监听1234
端口。
启动gdb客户端
再打开一个命令行窗口:
gdb-multiarch --tui ./bin/qemu-aarch64-virt/meta.elf
启动后的界面,如下所示:
连接gdb-server
:
(gdb) target remote localhost:1234
在cpu_init
函数打breakpoint
。然后,执行命令continue
。回到gdb-server
端,输入go 0x50000000
开始运行程序。
gdb
客户端,执行单步执行,最后发现是mem_init_vm_config(config_addr)
函数执行出现问题。打印变量print/x config_addr
,结果是1
。而我们配置平台的物理内存是从0x40000000
处开始的。这样,等于我们访问非法物理地址。
用VSCode可视化环境调试
vscode
中集成了gdb
功能,我们可以用它来图形化的调试meta-hypervisor
。
首先,我们按下ctrl+alt+D
,调出debug
窗口,选择创建launch.json
文件,添加vscode
的gdb
配置文件(.vscode/launch.json
):
{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "(gdb-multiarch) Launch", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/wrkdir/srcs/meta/bin/qemu-aarch64-virt/meta.elf", "cwd": "${workspaceFolder}", "MIMode": "gdb", "miDebuggerPath": "/usr/bin/gdb-multiarch", "miDebuggerServerAddress": "localhost:1234" } ] }
这里对几个重点参数做一些说明:
program
: 调试的符号文件miDebuggerPath
:gdb
的路径, 这里需要注意的是,由于我们是arm64
内核,因此需要用gdb-multiarch
来进行调试miDebuggerServerAddress
:对端地址,qemu
会默认使用1234
这个端口
配置完成之后,可以直接启动GDB
, 连接上meta-hypervisor
(gdb-server
端的启动顺序参考前面的一段),界面如下所示:
在vscode
中,可以设置断点,进行单步调试。可以查看变量、通用寄存器、系统寄存器、浮点寄存器等。还可以查看调用栈的过程。具体如下红色方框和文字注释所示: