You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在GDB中提前加载外部Linux内核模块的调试符号以调试其初始化过程

如何在GDB中提前加载外部Linux内核模块的调试符号以调试其初始化过程

没问题,我刚好折腾过这个场景,给你一步步说怎么搞定这个需求:

首先得确保你的内核模块编译时带了调试符号——在模块的Makefile里加上CFLAGS_MODULE += -g,不然.ko文件里没调试信息,再怎么折腾GDB也认不出来。

接下来按这个流程走:

  1. 启动带调试暂停的QEMU
    启动QEMU的时候加上-S-s参数:

    qemu-system-x86_64 -kernel vmlinux -initrd rootfs.cpio -S -s
    

    -S会让内核启动后立刻暂停在入口点,不会直接跑起来;-s是默认开启1234端口的GDB调试服务,方便后续连接。

  2. 用GDB连接QEMU并加载基础符号
    打开另一个终端,启动GDB并加载内核镜像的符号:

    gdb vmlinux
    

    进入GDB后,连接到QEMU的调试端口:

    target remote :1234
    
  3. 提前加载模块的调试符号
    这时候内核还没开始运行,直接加载你的模块符号就行,用add-symbol-file命令,虽然现在不知道模块实际的加载地址,暂时填0就行:

    add-symbol-file mymodule.ko 0
    

    执行后GDB会弹出一堆section地址的提示,问你要不要确认,直接输入y回车就行——它会把模块里的所有符号都记下来,等模块实际加载时自动匹配地址。

  4. 设置初始化函数的断点
    现在就可以直接给模块的初始化函数设断点了,比如你的模块初始化函数叫mymodule_init

    b mymodule_init
    

    这时候GDB可能会提示“函数未定义,是否设置待决断点”,输入y确认就行。

  5. 启动内核并触发断点
    最后让内核继续运行:

    c
    

    等你在QEMU的系统里执行insmod mymodule.ko加载模块时,GDB会自动把之前设的待决断点关联到模块实际的内存地址,初始化函数一运行就会立刻触发断点,刚好能抓到初始化的全过程。

另外补充个小技巧:如果担心模块加载时的断点没触发,也可以先给sys_init_module设个断点——这是内核处理模块加载的系统调用入口,触发后再手动确认符号加载情况,不过前面的方法已经足够覆盖你的需求了。

备注:内容来源于stack exchange,提问作者Kirill

火山引擎 最新活动