【问题标题】:Does a debugger interpret code or just runs it?调试器是解释代码还是只运行它?
【发布时间】:2014-07-09 22:06:26
【问题描述】:

假设我在代码中的某处放置了一个断点。调试器是让程序运行到那个点还是它实际上逐条解释它?假设程序是使用 -g 标志编译的。我在问,因为我的朋友说调试器无法将变量的地址保存在符号表中的堆栈中,因此需要解释。但是,我认为,当输入函数时,至少调试器知道这些堆栈变量与堆栈开头的偏移量。

【问题讨论】:

  • 它运行代码,并知道给定当前堆栈指针的堆栈中变量的偏移量。它曾经通过在 x86 上使用 INT 3 指令覆盖操作码来支持断点,这是调试器的陷阱。我不是 100% 确定 x86_64 上的机制。

标签: c gcc gdb stack symbol-table


【解决方案1】:

AFAIK,GDB“虚拟化”环境。以逆向执行为例:根本无法“逆向”真正的 CPU。 GDB 所做的是跟踪进程,在最远点暂停执行,并为您提供环境先前状态的“视图”,直到您返回实际状态。

此外,GDB 可以交叉调试,即 GDB 在您的系统上运行,调试后的可执行文件在连接的嵌入式系统上运行。在这种情况下,GDB 甚至没有在相同的 CPU 架构上运行……但它没有“解释”可执行文件(它仍然需要其他系统来实际执行);它正在检测它,即跟踪事物并允许您暂停并检查其执行情况。

-g 所做的是添加调试符号。在发布代码中,您的变量foo 不再是foo,而只是内存中的一个地址。 使用调试符号,GDB 仍然可以判断地址0xdeadbeef 确实是foo。在堆栈跟踪中查看函数名称也比地址列表更具启发性......

(免责声明:我远非 GDB grok。虽然我每天都在使用它,但我的用途是面包和黄油的种类。我相信其他人会出现更多更多详细的答案,甚至指出我错在哪里,但在此之前,这是能给出的最佳答案。;-))

【讨论】:

    【解决方案2】:

    假设我在代码中的某处放置了一个断点。调试器是让程序运行到那个点还是它实际上逐条解释它?

    这取决于!如果您的系统有硬件断点,只需将要中断的地址写入硬件寄存器。如果 cpu 程序计数器到达其中一个陷阱地址,则 cpu 会生成某种陷阱/irq/... 停止程序并调用调试器的某些函数。

    如果您的系统具有可写内存但没有硬件断点,通常断点处的代码将被替换为某种类型的陷阱指令,该指令在调试器中执行某些功能。

    如果您的执行内存无法写入并且没有可用的硬件断点,则有时可以在单步模式下运行代码。在每个汇编程序步骤之后,调试器都会被回调。调试器本身包含断点列表。

    假设程序是使用 -g 标志编译的。我在问,因为我朋友说调试器无法将变量的地址保存在符号表中的堆栈中,因此需要解释

    这是完全错误的。调试信息还包含每个堆栈帧的格式。哪些信息/变量/内容放置在堆栈中的哪个 realtiv 位置取决于实际运行的堆栈帧的上下文。调试信息包含所有需要的信息!如果你停止你的程序,调试器知道地址并且可以计算程序的实际上下文/块。并且调试信息知道在这个帧中实际使用了哪个堆栈帧内容。

    但是,我认为,当输入函数时,至少调试器知道这些堆栈变量与堆栈开头的偏移量。

    没错!

    调试器本身并没有“运行”或“模拟”程序。调试器本身只控制程序在给定系统上的执行方式。该系统也可以是模拟cpu和目标系统的模拟器。在这种情况下,远程调试也是一个主题。每种系统都需要系统本身的调试接口。

    【讨论】:

      猜你喜欢
      • 2016-04-04
      • 1970-01-01
      • 1970-01-01
      • 2021-07-01
      • 2012-05-04
      • 2018-01-19
      • 1970-01-01
      • 2020-10-27
      • 1970-01-01
      相关资源
      最近更新 更多