使用Qemu+Ubuntu调试4.16.0-rc6内核时kgdb无法设断点求助
解决kgdb调试4.16-rc6内核时设置断点失败的问题
你碰到的这个问题,大概率是新版本内核默认开启的KASLR(内核地址空间随机化)加上调试配置差异导致的,我给你梳理几个实用的排查和解决方向:
1. 先关闭内核地址随机化(KASLR)
4.8版本之后的Linux内核默认开启了KASLR,这会让内核的虚拟地址每次启动都随机变化。而你gdb加载的vmlinux里的符号地址是编译时的固定值,自然会出现"Cannot access memory"的错误。
解决方法很直接:在客户机的启动参数里加上nokaslr,和你现有的kgdb参数放在一起:
kgdbwait kgdboc=ttyS0,115200 nokaslr
你可以修改Qemu的启动命令行,或者在客户机的GRUB配置里添加这个参数,重启后再尝试设置断点。
2. 确认gdb加载的vmlinux与运行内核完全匹配
一定要保证你在gdb里用file vmlinux加载的是带完整调试符号、和客户机运行的4.16.0-rc6完全一致的内核镜像:
- 如果是自己编译的内核,编译时必须开启
CONFIG_DEBUG_INFO=y,用编译目录下原生的vmlinux,别用被去掉符号的stripped版本。 - 如果是通过包安装的内核,要安装对应的调试包(比如
linux-image-4.16.0-rc6-dbg这类),然后加载调试包提供的vmlinux文件。
你可以在gdb里执行info symbol 0xffffffff8124b170,如果返回"No symbol matches 0xffffffff8124b170",基本就能确认是符号不匹配或者KASLR的问题。
3. 检查内核调试配置是否正确
对比4.8版本,4.16的内核调试配置有一些变化,确保你的内核开启了以下关键选项:
CONFIG_DEBUG_KERNEL=y:启用内核调试基础功能CONFIG_DEBUG_INFO=y:生成调试符号(必须开,否则gdb根本看不到内核符号)CONFIG_KGDB=y:启用kgdb调试框架CONFIG_KGDB_SERIAL_CONSOLE=y:支持串口方式的kgdb通信CONFIG_KASLR=n:如果想永久关闭KASLR,编译内核时直接关掉这个选项,就不用每次加启动参数了
4. 换用函数名设置断点更可靠
与其直接用内存地址设断点,不如试试直接用函数名,比如break sys_open。这种方式gdb会自动匹配符号对应的正确地址(前提是符号匹配且KASLR已关闭),能避开手动输入地址的误差。
内容的提问来源于stack exchange,提问作者Joontaek Oh
相关产品推荐
相关产品推荐

