一个基本问题,我对 C/C++ 和 GDB 很陌生。
我们使用 GDB 来调试一个进程。我们将 GDB 附加到一个进程,然后指定 filename.c 以及行号以放置断点。
我的问题是“在我们将 GDB 连接到正在运行的进程后,GDB 或操作系统或其他任何东西如何知道它必须在指定的行号(在 filename.c 中)中断?”
例如,当前进程在调试模式下运行并且应用了断点并且进程执行必须在该点中断(等待用户输入)?
同样,如果您的程序在特定点停止或崩溃,调试器可以告诉您该点在程序中的哪个位置。
要使这两种方法正常工作,程序二进制文件必须包含额外的调试信息,这些信息将程序映像中的地址与源代码中的位置(源文件和行号)相关联。
要在特定行添加断点,调试器会找到最接近该行的程序地址,修改内存中可执行文件的副本以在该位置插入特殊的“break”指令,这将导致程序的执行被中断,然后“跟踪”程序的执行并等待它到达断点并停止。
有关更多详细信息,请参阅http://eli.thegreenplace.net/2011/01/23/how-debuggers-work-part-1/和http://www.howzatt.demon.co.uk/articles/SimplePTrace.html
我无法评论最新版本的 gdb - 但许多调试器实际上将所需断点位置(内存中)的汇编指令与中断指令交换。这“唤醒”了此时控制的调试器。
使用替代的中断指令意味着 CPU 可以全速执行您的程序并在所需位置“跳闸”。
然而,现代处理器非常复杂,并且可能具有更出色的调试功能。
GDB 知道您的代码:它知道一切。当您在某行设置断点时,GDB 会获得等效的机器指令地址:您的所有代码(作为机器指令)都加载到内存中,因此您的代码指令有一个地址。
所以现在 GDB 知道了你想要中断的指令的地址。当您运行程序时,GDB 将使用 ptrace,它允许 GDB 在执行之前“查看”每条指令。然后 GDB 只需查看当前指令(将被执行)是否与您的指令(您想要中断的指令)相同。