qemu 单步调试 arm64 linux kernel
一、背景和目的
https://xie.infoq.cn/article/3415445f1c8831423a94c4bc2 《qemu 搭建 arm64 linux kernel 调试环境》
之前介绍了 qemu 启动 kernel 的配置步骤和方法,现在开始我们的调试,这篇文章主要讲解如何单步调试内核,所有的实验还是基于 ARM64;
二、环境准备
需要准备 host=x86 target = arm64 的 gdb, 有三种方式:一种是 sudo apt install gdb-multiarch;
另外一种是用 ARM 官网下载交叉编译工具链,其中自带 gdb(目前我使用的方式Arm GNU Toolchain Downloads – Arm Developer); 还有一种是下载 gdb 源码并编译;
不同的方式有些差异,用 apt 安装的如果 ubuntu 比较老,可能存在部分特性不支持(比如 ARMv8.5 的 PAC,BTI 等,之前用 ubuntu18.04 就遇到了);
注意:使用 ARM 官网 gdb 的伙伴启动时可能会遇到缺少库和 python3.8 的报错(依赖 libncurses5 ,libncursesw5 及 python3.8),可以参考下面解决(偷懒可以直接安装 gdb-multiarch)
三、kernel debug
单步调试 kernel 只需要三步:
第一步:qemu 启动内核并暂停等待(暂停是可选的,如果不调启动,可以去掉),同时需要建立网络端口等待 gdb attach;
第二步:启动 gdb(target=arm64)加载对应 kernel Image 的 vmlinux, attach 到指定端口即可;
第三步:如果是启动是挂起,直接设置断点即可调试,如果未选择启动暂停,ctrl + c 会触发挂起,然后就可以和前面一样,正常设置断点。
qemu 启动调试脚本(注意这里有个小坑,直接调试的伙伴直接跳转到最后拷贝即可)
gdb 启动找到 vmlinux 所在目录(最好在 linux 编译的根目录,不要拷贝出来,这样调试源码可以直接显示,不然还要在 gdb 中设置 src path),geek@geek-virtual-machine:~/workspace/linux/linux-6.6.1$ aarch64-none-linux-gnu-gdb vmlinux
这里的原因也是经常会遇到和遗忘的,查看 kernel log 可以看到 KASLR 字样
KASLR 是内核启动添加随机地址保护,启动后实际运行地址和 vmlinux 有一个随机偏移值,在 gdb 中设置断点是基于 vmlinux 的(这个是不带偏移值的),实际 qemu 中运行的内核是在这个地址 + 随机偏移值,所以断点无法触发,出现上面的问题;
上面的问题有两种解决方法:
1、是重新编译内核,在 arch/arm64/configs/defconfig 中将 CONFIG_RANDOMIZE_BASE=y 修改成 CONFIG_RANDOMIZE_BASE=n
2、是在 qemu 启动的 cmdline 中增加 nokaslr 参数,通过参数方式关闭
修改正常后,断点能正确停止,bt 调用栈显示正常
四、总结
qemu 内核调试时需要注意关闭 kaslr,更新正确的脚本,也不依赖 kenerl config 是否开启 kaslr
qemu 启动脚本(最终版本):
关于 kaslr 原理相关的知识,有兴趣的伙伴参考 文章 kaslr原理分析
版权声明: 本文为 InfoQ 作者【无人知晓】的原创文章。
原文链接:【http://xie.infoq.cn/article/6befd29e6d671f1527b3a03d6】。文章转载请联系作者。
评论