1

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

4

2 回答 2

2

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

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

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

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

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

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

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

正确的!

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

于 2014-05-21T10:49:06.443 回答
1

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

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

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

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

于 2014-05-21T10:30:56.377 回答