美文网首页学ubuntu
内核必须懂(六): 使用kgdb调试内核

内核必须懂(六): 使用kgdb调试内核

作者: sean_depp | 来源:发表于2019-04-17 19:56 被阅读5次

    内核必须懂(一): 用系统调用打印Hello, world!
    内核必须懂(二): 文件系统初探
    内核必须懂(三): 重编Ubuntu18.04LTS内核4.15.0
    内核必须懂(四): 撰写内核驱动
    内核必须懂(五): per-CPU变量
    内核必须懂(六): 使用kgdb调试内核


    目录

    • 前言
    • 虚拟机串口设置
    • 测试串口
    • 配置目标机
    • 开始调试
    • 调试驱动模块
    • 最后

    前言

    调试内核肯定不是什么轻松的事情, 这里是使用kgdb进行调试, 你理解的没错, 就是kernel版的gdb.


    虚拟机串口设置

    首先克隆下已经重新编译内核的虚拟机
    然后设置两者的串口, 这里是用的win, mac端的串口我暂时还弄不太好, 所以很不情愿地用了下win:

    • 开发机
    开发机串口设置
    • 目标机
    目标机串口设置

    测试串口

    目标机执行:

    sudo cat /dev/ttyS1
    

    开发机切换成root用户, 执行:

    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调试一样了.


    最后

    如果要写驱动模块, 必须要调试内核, 上述方法并不是唯一方法. 下一篇将会介绍一些更实用的小工具来进行类似的调试. 喜欢记得点赞, 有意见或者建议评论区见哦~


    相关文章

      网友评论

        本文标题:内核必须懂(六): 使用kgdb调试内核

        本文链接:https://www.haomeiwen.com/subject/aflowqtx.html