内核必须懂(一): 用系统调用打印Hello, world!linux
内核必须懂(二): 文件系统初探shell
内核必须懂(三): 重编Ubuntu18.04LTS内核4.15.0vim
内核必须懂(四): 撰写内核驱动bash
- 前言
- 虚拟机串口设置
- 测试串口
- 配置目标机
- 开始调试
- 调试驱动模块
- 最后
调试内核确定不是什么轻松的事情, 这里是使用kgdb进行调试, 你理解的没错, 就是kernel版的gdb.测试
首先克隆下已经从新编译内核的虚拟机 而后设置二者的串口, 这里是用的win, mac端的串口我暂时还弄不太好, 因此很不情愿地用了下win:ui
- 开发机
- 目标机
目标机执行:google
sudo cat /dev/ttyS1
复制代码
开发机切换成root用户, 执行:spa
echo “Hello, world!”>/dev/ttyS1
复制代码
打开grub文件:
sudo vim /etc/default/grub
复制代码
增长以下内容:
GRUB_CMDLINE_LINUX="nokaslr rootdelay=90quiet splash text kgdboc=ttyS1,115200“ 复制代码
更新grub:
sudo update-grub
复制代码
nokaslr, 禁止内核地址随机化, 具体内容请自行google:
reboot
复制代码
而后重启的时候, 就可以看到一行关于nokaslr的提示了.
而后开始测试一下kgdb的调试, 目标机切换为root用户, 控制权限交给kgdb, 目标机进入假死状态:
echo g > /proc/sysrq-trigger
复制代码
开发机进入自编译内核目录
gdb ./vmlinux
target remote /dev/ttyS1
handle SIGSEGV noprint nostop pass
break sys_clone
c
s
复制代码
这里把断点给到sys_clone, 就是你们熟悉的fork会调用的, 这样基本等一会, 系统就本身调用, 而后进入调试了. 以后就和使用gdb无异了:
要调试本身的写的驱动模块, 就有些麻烦了, 首先须要常规的插入模块, 很少说了. 而后这里有个shell脚本能够获取下一些所需参数, 主要是用来插入符号参数:
#!/bin/bash
#
# usage: gdbline.sh module_name module_path
#
# This script will outputs an add-symbol-file line suitable for pasting into gdb to examine
# a loaded module.
#
cd /sys/module/$1/sections
echo -n add-symbol-file $2 `/bin/cat .text`
for section in .[a-z]* *; do
if [ $section != ".text" ]; then
echo " \\"
echo -n " -s" $section `/bin/cat $section`
fi
done
echo
复制代码
首先, 须要在目标机make生成.ko文件, 而后将这个.ko文件拷贝至开发机的同名目录下.
而后在目标机插入.ko文件 用shell脚本获取.text, .data, .bss段基址. 若是你不太清楚这些东西, 仍是请自行google, 由于若是展开, 篇幅就控制不住了.
目标机切换为root用户, 控制权限交给kgdb, 目标机进入假死状态:
echo g > /proc/sysrq-trigger
复制代码
开发机进入自编译内核目录
gdb ./vmlinux
target remote /dev/ttyS1
handle SIGSEGV noprint nostop pass
复制代码
常规操做以前也说了, 而后就是新的操做, 要用add-symbol-file插入符号信息, 而后输入y确认:
而后把断点打在模块函数DriverWrite中, 开始运行:
切回目标机, 已经不是假死了, 运行用户态程序:
而后开发机就会触发断点:
接下来就和日常使用gdb调试同样了.
若是要写驱动模块, 必需要调试内核, 上述方法并非惟一方法. 下一篇将会介绍一些更实用的小工具来进行相似的调试. 喜欢记得点赞, 有意见或者建议评论区见哦~