内核态
1、gdb
大部分工程师常用的单步调试方式都会选择gdb,它是最常用的工具,信号是gdb实现断点功能的基础,使用gdb打断点的时候实际上就是朝某个地址写入断点指令,当程序运行到这条指令后就会触发SIGTRAP信号,然后gdb收到信号后会停在这个位置查询断点表,如果在表里查到就判定找到断点。
内核态要是用gdb需要内核先支持kgdb
#: make menuconfig
---->Kernel hacking
---->Compile-time checks and compiler options
---->Compile the kernel with frame pointers
---->Compile-time checks and compiler options
---->Compile the kernel with debug info
---->KGDB: kernel debugger
配置成功后编译内核,然后需要增加启动参数支持kgdb调试
#kgdbwait:kgdb启动的时候停下来等待连接
kgdboc=ttyS0,115200 kgdbwait
后面uboot启动的时候等到kgdb的位置会停下来等待gdb连接,后面就可以调试vmlinux了
$arm-none-linux-gnueabi-gdb vmlinux
接下来就和用户空间一样了
2、crash
除了单步调试还有一种情况是linux运行过程中内核发生崩溃,常见的log字眼比如oops,panic之类的或者干脆一堆堆栈,这个时候linux会使用kdump搜集好崩溃前 的内存,生成vmcore,我们可以使用crash工具分析vmcore
$:crash vmlinuz-4.3.0-27-generic
后面可以使用crash命令来调试,类似gdb
用户态
1、gdb
2、addr2line
另外还能通过出错的地址使用addr2line定位symbol文件中崩溃的代码位置,然后前向查找
另外还可以通过反汇编的方式