linux内核栈回溯,[原创]Linux kernel debug设计浅析

QEMU启动参数

linux版本5.2.0-rc4

qemu-system-x86_64  -smp 4 -kernel bzImage  -m 4096 -hda ~/stretch.img  -serial stdio -append "earlyprintk=serial console=ttyS0 kgdboc=ttyS0 kgdbwait root=/dev/sda nokaslr" -enable-kvm -cpu host  -s -S -display none

启动后效果如下:

749903c459086d761c7967f267ddfc35.png

图1

得到一个可以交互的kernel debug。这里是kdb的命令行,并不是kgdb的部分。后面会说明它们之间的关系。

此在在调试端按ctrl+ c 中断,看到此时kdb的栈回溯。

9d9b6e1acd7a77a9a07d9f7a3ae388f7.png

图2

内核命令行参数分析

图2看到kdb是从一个int3中断进入的。分析参数后发现是kgdbwait参数最后调用kgdb_breakpoint()也就是int 3的原因。

d58e14224cf5464b30f514acbf7c59b9.png

图3

从int3中断向上找关键函数。发现kgdb_cpu_enter()是kdb的入口。重启虚拟机对kgdb_cpu_enter()下断点。发现kgdb_cpu_enter()并不是中断一次

7ed950ac1c398e0c3c608507cf5e390a.png

图4

这次是从nmi中断进入的。也就是还有代码给cpu发送了一个nmi导致。最后找到是kgdb_cpu_enter()发送的nmi中断。

72d5e2ec0b0ea3f369a179b6e2483af6.png

图5

代码给了解释。原来是int3中断只能让一个核进入kdb。对于多核系统仅让一个核进入kdb其他核正常运行显然不合理,所以要让所有核都进入kdb。kgdb_cpu_enter()--->kdb_stub()--->kdb_main_loop()--->kdb_parse ()执行1054行对应每个命令的处理函数

de788542c66b87083273c973f5277682.png

图6

各个命令注册的处理函数如下

737255beb1e68150420dfceaa033850b.png

图7

kgdb部分

上面是kdb的处理部分,常用的是用kgdb和gdb双机调试的方案。进入kgdb的代码

b8896c83347389e8e65d39f3bbecc6e3.png

图8

kdb切换到kgdb需要一条命令

129643b20ed3edb4a14236e15a4cd47d.png

图9

为了能用从qemu动态抓到这个过程,需要修改qemu的启动参数。

647f8a2ed09a644102c0da1638315370.png

图10

又增加了一个串口,第一个串口ttyS0用于打印内核启动流程,ttyS1用于在建立gdb和内核建立连接。所以除了用target remote localhost:1234 连接的调试还可以用 target remote /dev/pts/3连接。这样就可以从第一个gdb中看到第二个的连接过程和处理逻辑。

在第一个gdb对kdb_parse()下断点,然后第二个gdb开始连接

c8b92563aac8c1ceb28e7fcc8c6b8ba9.png

图11

第一个gdb此时断下来。.

2ddffde44d1de768d254a6c7c079f822.png

图12

gdb发送正是kgdb命令,此时从kdb转换到kgdb。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值