【问题标题】:Cannot step into system call source code无法进入系统调用源码
【发布时间】:2011-05-14 01:14:54
【问题描述】:

我已经使用 -g 选项编译了我的 freebsd libc 源代码,所以现在我可以进入 libc 函数。

但我无法进入系统调用代码。我已经用-g编译了freebsd内核源代码。在设置断点时,gdb 会通知 .S 文件上的断点。在遇到断点时,gdb 无法进入系统调用源代码。

另外,我试过:gdb$catch syscall open

但这也行不通。

你能推荐点什么吗?

谢谢。

【问题讨论】:

  • Linux 上的调试是通过ptrace(2) 系统调用实现的; ptrace 只能检查和停止在用户空间中运行的进程。我希望 FreeBSD 的进程调试机制是相似的,并且只设计用于用户空间进程:因为操作系统内核将获取和释放锁以及快速响应中断,所以将内核设计为允许从用户空间进行全功能调试似乎非常不太可能。
  • 嗨,萨诺德,感谢您的评论。如果无法进行用户空间调试,那么 kdb/kgdb 可以达到目的吗?
  • 我已经有好几年没有研究 kdb/kgdb 了,可能情况已经发生了翻天覆地的变化。 :) 但也许this message about stack dumps 会是一个很好的起点?

标签: unix gdb systems-programming


【解决方案1】:

您似乎根本不了解 UNIX 系统的工作原理。

考虑一下。假设您能够进入实现系统调用的内核函数,例如sys_open。所以现在您正在调试器中查看sys_open 的内核源代码。问题是:内核是在那个时候运行,还是停止了。由于您会想在调试器中执行类似next 的操作,我们假设内核停止。

那么现在你按下n 键,会发生什么?

通常,内核会对键盘引发的中断做出反应,确定按下了哪个键,并将该键发送到正确的进程(在read(2) 中被阻止的进程来自控制键盘的终端)。

但是你的内核已经停止,所以你不需要按键。

结论:通过在同一台机器上运行的调试器调试内核是不可能的。

事实上,当人们调试内核时,他们通常通过在另一台机器上运行调试器来完成(这称为远程调试)。

如果你真的想进入内核,最简单的方法是使用UML

在您玩过 UML 并了解用户空间/内核接口如何工作和交互之后,您可以尝试kgdb,尽管设置通常有点复杂。您实际上不必为此使用单独的机器,您可以使用 VMWare、VirtualPC 或 VirtualBox。

【讨论】:

  • 您的“通过在同一台机器上运行的调试器调试内核是不可能的”结论是 AFAIK 仅适用于 Linux 上的 kgdb。 UML 也是 Linux 特定的解决方案。有一个 kgdb 到 FreeBSD 的端口,但是可以使用 ddb 在本地调试 FreeBSD 内核,就像 Solaris 可以使用 kmdb 一样。
  • 您对内核调试器无法工作的原因的解释是有缺陷的。内核不是单线程程序,甚至也不是多线程程序。内核是在特权上下文中执行的代码。许多内核线程可以同时运行此代码,因此影响其中一个执行指令的断点没有令人信服的理由突然“停止内核”,即停止所有其他内核线程。
【解决方案2】:

正如 Employed Russian 所说,处于用户态的 gdb 无法检查内核中运行的任何内容。

然而,没有什么能阻止在内核本身中实现调试器。在这种情况下,可以从本地调试会话(控制台)逐步设置断点并运行内核代码。对于 FreeBSD,这样的调试器可以通过 ddb 获得。

一些限制是 gdb 和 ddb 会话之间缺乏连接,我不确定 FreeBSD/ddb 下的内核代码是否可以使用源级调试 (-g)。

从用户态“调试”内核的另一种且侵入性更小的方法是使用dtrace

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-16
    • 1970-01-01
    相关资源
    最近更新 更多