如何调试 Linux 内核模块 `init()` 中的问题?

Posted

技术标签:

【中文标题】如何调试 Linux 内核模块 `init()` 中的问题?【英文标题】:How to debug problems in Linux kernel module `init()`? 【发布时间】:2011-02-06 02:17:14 【问题描述】:

我正在使用远程 (k)gdb 调试模块中的问题,该问题在加载时会导致崩溃,例如当init() 被调用时。

堆栈跟踪只是显示do_one_initcall(mod->init) 导致了崩溃。为了在 gdb 中加载符号文件,我需要获取模块文本部分的地址,并且要获取该地址,我需要加载模块。

因为busybox (1.16.1) 中的insmod 不支持-m,所以我坚持使用grep modulename /proc/modules + 添加从nm 的偏移量来计算地址。

所以我在这里面临着鸡和蛋的问题——为了能够调试模块加载,我需要加载模块——但是为了加载模块,我需要调试问题...

所以我目前正在考虑两个选项 - 是否有办法获取地址信息:

    通过模块初始化代码中的 printk() 通过内核代码中某处的 printk()

所有这些都在调用mod->init() 之前 - 所以我可以在那里放置一个断点,加载符号文件,点击 c 并看到它崩溃并烧毁......

【问题讨论】:

【参考方案1】:

您可以将代码构建到内核中而不是作为模块吗?这可能会简化init() 调用的调试。

您还可以在do_one_initcall() 处设置断点并查看mod->init 的地址以获取加载地址。

【讨论】:

将代码编译到内核中太麻烦了(每次都需要刷写开发板而不是 wget 到 ramdisk)。闯入do_one_initcall() 足以确定问题所在,以便我可以推迟崩溃,直到启动与模块通信的用户模式进程。谢谢。

以上是关于如何调试 Linux 内核模块 `init()` 中的问题?的主要内容,如果未能解决你的问题,请参考以下文章

如何编译出带有调试信息的内核模块

Linux内核驱动调试总结

Linux内核驱动调试总结

Linux内核分析-使用gdb跟踪调试内核从start_kernel到init进程启动

gdb跟踪调试内核从start_kernel到init进程启动

深度解析KGDB调试Linux模块和内核