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

问题描述 投票:0回答:2

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

debugging gdb breakpoints
2个回答
35
投票

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

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

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

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

2
投票

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

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

© www.soinside.com 2019 - 2024. All rights reserved.