1 kgdb原理
kgdb提供了一种使用gdb调试Linux内核的机制,是一种源码级调试。我们可以在本机上调试生成的linux内核镜像,还可以调试内核模块.ko。
我们需要使用两台Linux,一台目标机,或称target、服务器,运行kgdb,另一台开发机,或称host、客户端,运行gdb,两台机器使用串口相连,也可以使用网络相连。
被调试的内核运行在目标机上。需要调试时,目标机将启动kgdb,就控制权移交给kgdb,kgdb接收并运行开发机发过来的各种调试命令,并返回给开发机相应的信息。开发机使用gdb连接目标机的kgdb(所以目标机又称为服务器),然后向kgdb发送各种调试命令。
2 kgdb环境搭建
第一步:使用kgdb要先编译内核,在此过程中,要尽量去优化编译,默认情况下内核编译使用-O2,调试时显示代码混乱。
去优化方法:
- 将Makefile中的-O2变成-O1,不能改成-O0。有些地方的代码实现依赖于优化。
- 不设置CONFIG_CC_OPTIMIZE_FOR_SIZE,否则默认是-Os。
- 设置CONFIG_DEBUG_SECTION_MISMATCH,相当于-fno-inline-functions-called-once,避免看不到函数了。
第二步:利用VMWare clone虚拟机,变成两个linux系统。在快照管理器中克隆。
第三步:为两个系统配置串口。
开发机串口设置为
目标机串口设置为
第四步:在目标机进行更改,配置grub.cfg,修改/etc/default/grub
文件,增加:
GRUB_CMDLINE_LINUX="nokaslr rootdelay=90quiet splash text kgdboc=ttyS1,115200“
禁止内核地址随机化,设置串口的波特率并执行update-grub
,该命令会自动修改grub.cfg文件。
- 禁止内核地址随机化
每次加载可执行文件时,将可执行文件加载到进程地址空间的不同地址处,而不是固定地址,调试内核时要禁止。
设置完毕后下面我们进行串口测试。
目标机执行cat /dev/ttyS1
开发机执行echo “test” > /dev/ttyS1
我们看到串口连接成功。
3 kgdb调试内核源码
在目标机输入echo ttyS1 > /sys/module/kgdboc/parameters/kgdboc
和echo g > /proc/sysrq-trigger
目标机将控制权限交给kgdb,目标机进入假死状态,等待开发机的命令过来。
在开发机执行下面的命令,进入编译内核的目录
gdb ./vmlinux
用gdb调试目标机的内核映像,进入gdb环境中
set serial baud 115200
设置串口波特率
target remote /dev/ttyS1
通过串口连接kgdb
调试内核源码在哪里打断点呢?我们这里打在创建进程的sys_clone函数。
break sys_clone
打断点在sys_clone函数处
c/continue
继续运行,至触发断点
step
- gdb调试常用命令
info break
显示目前设置的断点
delete n
删除显示出来的n号断点
l x,x
显示代码范围
4 kgdb调试内核模块
调试内核模块我们一般把断点打在内核模块初始化的do_init_module函数。
- 代码2.3
break do_init_module