调试器中的断点如何工作?

时间:2013-01-30 07:13:18

标签: debugging compiler-construction gdb breakpoints

断点是大多数流行调试器(如GDB)支持的最酷功能之一。但断点如何运作?编译器为实现断点做了哪些代码修改?是否有用于支持断点的特殊硬件功能?

2 个答案:

答案 0 :(得分:24)

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

  • 编译器在可执行文件中包含足够的信息(不在代码本身中,但在同一文件的特殊部分中),因此调试器可以将用户想要调试的源与机器代码相关联。调试器需要知道的一个典型的东西是能够设置断点(除非你直接指定地址),程序函数和源代码行的位置(在哪个地址)(在机器代码中)。
  • 编译器没有以任何方式优化代码,这使得无法关联源代码和机器代码。通常,您需要未经优化的调试代码或仅执行精心选择的优化的代码。
然后,其余的工作由调试器本身执行。

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

答案 1 :(得分:1)

首先要设置一个断点,我们必须在二进制文件中添加一些特殊信息。我们在编译c源文件时使用标志-g来包含这个信息。软件调试器实际上使用这个信息来放置断点。硬件断点支持的最佳示例是我所经历的VxWorks。 基本上在断点处处理器停止。所以内部任何给处理器例外的步骤都可以用来设置软件断点。虽然硬件断点通过匹配存储在硬件寄存器中的地址来引起异常。所以硬件断点非常强大,但它依赖于架构。

这里有一个很好的解释 What is the difference between hardware and software breakpoints? 这里给出了与处理器相关的信息的简介 http://processors.wiki.ti.com/index.php/How_Do_Breakpoints_Work