假设我在代码中的某处放置了一个断点。调试器只是让程序运行到那一点,还是实际解释它,逐个指令?假设使用-g标志编译程序。我问,因为我的朋友说调试器无法在符号表中保留堆栈中的变量地址,因此需要解释。但是,我认为至少调试器在输入函数时知道这些堆栈变量从堆栈开头的偏移量。
答案 0 :(得分:2)
假设我在代码中的某处放置了一个断点。调试器只是让程序运行到那一点,还是实际解释它,按指令说明?
这取决于!如果您的系统有硬件断点,则只需将要断开的地址写入硬件寄存器。如果cpu程序计数器到达其中一个陷阱地址,则cpu会生成某种陷阱/ irq / ...,它会停止程序并调用调试器的某些功能。
如果您的系统具有可写内存但通常没有硬件断点,则断点处的代码将被某种陷阱指令替换,该指令在调试器中执行某些功能。
如果无法写入执行内存并且没有可用的硬件断点,则有时可以在单步模式下运行代码。在每个汇编程序步骤之后调用调试器。调试器本身保存断点列表。
假设使用-g标志编译程序。我问,因为我的朋友说调试器无法在符号表中保留堆栈中的变量地址,因此需要解释
这是非常错误的。调试信息还包含每个堆栈帧的格式。在堆栈中的 realtiv 位置放置哪些信息/变量/内容取决于实际运行的堆栈帧的上下文。调试信息包含所有需要的信息!如果停止程序,调试器会知道地址并可以计算程序的实际上下文/块。并且调试信息知道在该帧实际使用哪个堆栈帧内容。
但是,我认为至少调试器在输入函数时知道这些堆栈变量从堆栈开头的偏移量。
右键!
调试器本身没有“运行”或“模拟”程序。调试器本身仅控制程序在给定系统上的执行方式。该系统也可以是模拟cpu和目标系统的模拟器。远程调试也是此上下文中的主题。在每种系统上都需要一个系统本身的调试接口。
答案 1 :(得分:1)
AFAIK,GDB"虚拟化"环境。采取反向执行,例如:你根本无法反转"真正的CPU。 GDB所做的是跟踪流程,在最远点停止执行,并为您提供一个"视图"之前的环境状态,直到你回到实际状态。
此外,GDB可以交叉 -debug,即在您的系统上运行GDB并在已连接的嵌入式系统上运行调试的可执行文件。在这种情况下,GDB甚至不能在相同的CPU架构上运行......但它并没有解释"可执行文件(它仍然需要其他系统实际执行);它正在检测它,即跟踪事物并允许你暂停并检查它的执行。
-g
的作用是添加调试符号。在发布代码中,变量foo
不再是foo
,而只是内存中的地址。 使用调试符号,GDB仍然可以告诉地址0xdeadbeef
确实是foo
。在堆栈跟踪中查看函数名称也比地址列表更具启发性......
(免责声明:我离GDB很远。虽然我每天都在使用它,但我的用途是面包和黄油。我相信其他人会出现很多更多详细的答案,甚至指出我错在哪里,但在那之前,这是我可以给予的最佳答案。;-))