37

断点是 GDB 等最流行的调试器支持的最酷的特性之一。但是断点是如何工作的?编译器做了哪些代码修改来实现断点?是否有任何特殊的硬件功能用于支持断点?

4

2 回答 2

26

编译器不需要以任何方式“修改”二进制文件来支持断点。然而,重要的是:

  • 编译器在可执行文件中包含足够的信息(不在代码本身中,而是在同一文件的特殊部分中),以便调试器可以将用户想要调试的源代码与机器代码相关联。调试器需要知道的一个典型的事情是能够设置断点(除非您直接指定地址),即程序函数和源代码行(在机器代码内)从哪里(在哪个地址)开始。
  • 编译器不会以任何方式优化代码,这使得无法关联源代码和机器代码。通常,您将需要未优化的调试代码或仅执行精心选择的优化的代码。

然后由调试器本身执行其余的工作。

  1. 软件断点不一定需要特殊的硬件功能。这里的调试器依赖于修改原始二进制文件(它是加载到内存中的副本)。当您设置断点时,调试器将在断点位置放置特殊指令。这条特殊指令需要以某种方式让调试器检测到它(这条特殊指令)何时执行。这可能是一些导致某种中断/异常的指令,调试器可以挂钩,或者是一些处理对调试单元的控制的指令。如果它在某些操作系统下运行,则该操作系统需要支持修改正在运行的程序(使用 ptrace poke/peek 之类的东西)。软件断点的缺点是调试器需要能够修改正在运行的程序,如果程序从某种只读存储器运行(在嵌入式世界中很常见),这是不可能的。
  2. 硬件断点(需要 CPU 支持)在不修改程序二进制文件的情况下实现类似的行为。这是特定于 CPU 的,但通常它允许您至少定义一个程序地址,在该地址处执行应该遇到断点。CPU不断将当前PC与这些断点地址进行比较,一旦条件匹配,它就会中断执行。这些断点的数量总是有限的。
于 2013-01-30T08:43:16.350 回答
2

首先要设置断点,我们必须在二进制文件中添加一些特殊信息。我们在编译 c 源文件时使用标志 -g 来包含此信息。软件调试器实际上使用此信息来放置断点。最好的例子正如我所经历的那样,对于硬件断点的支持在 VxWorks 中。基本上在断点处处理器停止。因此在内部,任何会给处理器带来异常的步骤都可以用来放置软件断点。而硬件断点通过匹配存储在硬件寄存器中的地址来工作,从而导致异常。所以硬件断点非常强大,但它严重依赖于架构。

这里有一个很好的解释 ,硬件断点和软件断点有什么区别? 此处提供了与处理器相关信息的良好介绍 http://processors.wiki.ti.com/index.php/How_Do_Breakpoints_Work

于 2015-09-08T07:15:24.443 回答