使用QEMU调试vmlinux时无法显示完整调用栈的问题求助
内核调试调用栈不完整问题解决方法
环境信息
- 内核版本:5.10.145-rt74+
- 调试工具:QEMU
- QEMU版本:
qemu-system-aarch64 --version QEMU emulator version 4.2.1 (Debian 1:4.2-3ubuntu6.30) Copyright (c) 2003-2019 Fabrice Bellard and the QEMU Project developers
- QEMU启动参数:
qemu-system-aarch64 -m 1024 -cpu max,sve=on,sve256=on -M virt,gic-version=3,its=on,iommu=smmuv3 -nographic -kernel arch/arm64/boot/Image -append "noinitrd nokaslr loglevel=8 sched_debug root=/dev/vda rootfstype=ext4 rw crashkernel=256M vfio.dyndbg=+pflmt irq_gic_v3_its.dyndbg=+pflmt iommu.dyndbg=+pflmt irqdomain.dyndbg=+pflmt" -drive if=none,file=/home/wzc/work/ext/temp/debug/git/rootfs_debian_arm64.ext4,id=hd0 -device virtio-blk-device,drive=hd0 --fsdev local,id=kmod_dev,path=./kmodules,security_model=none -device virtio-9p-pci,fsdev=kmod_dev,mount_tag=kmod_mount -s -S
- VSCode GDB配置:
{ "version": "0.2.0", "configurations": [ { "name": "kernel debug", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/vmlinux", "cwd": "${workspaceFolder}", "MIMode": "gdb", "miDebuggerPath":"/usr/bin/gdb-multiarch", "miDebuggerServerAddress": "localhost:1234", "stopAtEntry": true, } ] }
问题现象
调试时VSCode无法显示完整调用栈,停在未知即时编译代码处,调用栈信息:
__raw_spin_unlock_irqrestore(unsigned long flags, raw_spinlock_t * lock) (/home/wzc/work/ext/temp/debug/git/include/linux/spinlock_api_smp.h:161) _raw_spin_unlock_irqrestore(raw_spinlock_t * lock, unsigned long flags) (/home/wzc/work/ext/temp/debug/git/kernel/locking/spinlock.c:194) [Unknown/Just-In-Time compiled code] (Unknown Source:0)

解决办法
1. 检查内核编译的调试配置
内核编译必须开启完整调试符号,打开.config文件确认以下选项:
CONFIG_DEBUG_INFO=y CONFIG_DEBUG_INFO_DWARF4=y # 或DWARF5,更高版本调试信息更完整 CONFIG_FRAME_POINTER=y # 开启帧指针是GDB正确回溯调用栈的关键
修改后重新编译内核和模块,生成带完整符号的vmlinux及模块文件,替换旧文件。
2. 调整QEMU的CPU参数
当前使用的-cpu max,sve=on,sve256=on,旧版QEMU(如4.2.1)对SVE指令集的调试支持存在兼容性问题,换成更稳定的CPU型号:
-cpu cortex-a76
同时确保nokaslr参数保留,KASLR会打乱内存地址,导致符号无法匹配。
3. 优化VSCode的GDB配置
在配置中添加setupCommands段,强制GDB识别ARM64架构、加载内核符号并处理模块:
{ "version": "0.2.0", "configurations": [ { "name": "kernel debug", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/vmlinux", "cwd": "${workspaceFolder}", "MIMode": "gdb", "miDebuggerPath":"/usr/bin/gdb-multiarch", "miDebuggerServerAddress": "localhost:1234", "stopAtEntry": true, "setupCommands": [ { "text": "set arch aarch64" }, { "text": "symbol-file ${workspaceFolder}/vmlinux" }, { "text": "add-symbol-file ${workspaceFolder}/kmodules/你的模块名.ko 模块加载地址" }, { "text": "set unwindonsignal on" }, { "text": "set print frame-arguments all" } ] } ] }
模块加载地址可在QEMU启动后,登录目标系统执行cat /proc/modules获取。
4. 更新GDB版本
当前gdb-multiarch版本可能过旧,对ARM64 RT内核的调试支持不足,直接更新:
sudo apt update && sudo apt install gdb-multiarch
若更新后仍有问题,可从源码编译最新版GDB,确保支持ARM64的DWARF符号和帧指针回溯。
5. 适配RT内核特性
RT内核的自旋锁等机制为特殊实现,可能导致GDB回溯异常。若允许,调试时可暂时关闭RT特性,或编译内核时开启CONFIG_DEBUG_RT_MUTEXES等RT相关调试选项,帮助GDB识别RT代码的调用栈。
内容的提问来源于stack exchange,提问作者OoO
相关产品推荐
相关产品推荐

