繁体   English   中英

即使修补了指令,当使用INT 3(0xCC)软件断点时,调试器如何保证正确性?

[英]How do debuggers guarantee correctness when using INT 3 (0xCC) software breakpoint even though an instruction was patched?

我读过INT 3(0xCC)用于软件断点。

它由(例如)调试器通过覆盖存储器中的实际程序代码来设置。

我还读到INT 3是一个“陷阱”而非“故障”异常,这意味着堆栈上的地址是INT3指令后面的指令地址。

如果未重新执行修补的指令,调试器如何保证正确性?

当您想在断点触发后继续执行时,您有两种可能:断点只应该触发一次,或者它应该是持久性的。 如果它只应该触发一次,你用断点指令恢复你覆盖的原始值,手动调整地址到该指令的地址(记住,不管那里有什么指令, 执行的是你的单字节断点,所以调整总是微不足道的。 然后你继续执行。

如果它应该是一个持久性断点,那么就会增加一个皱纹:在继续执行之前,在堆栈中的标志中设置单步(也就是陷阱)位。 这意味着只有设置了断点的一条指令才会执行,那么你将再次获得一个断点中断。 您可以通过将刚刚修补的int 3字节恢复到原始指令的第一个字节来响应,然后(再次)继续执行。

这已经有一段时间了,因为我已经深入研究了这种东西,但假设你是正确的,以下地址被推入堆栈,调试器可以弹出返回地址并使用它来找出断点的位置(返回地址减1,因为INT 3指令长一个字节)[编辑]。

换句话说,调试器不一定需要返回堆栈上的地址。 它可以恢复原始指令,然后在原始位置执行它。 如果断点要保持设置,它可以使用标志中的“陷阱位”仅执行一条指令 - 原始的一条指令 - 在生成另一个陷阱之前(我认为是INT 3); 然后可以在继续正确执行之前重新建立INT 3指令。

但是,大多数情况下,调试器在一个他们不直接处理陷阱的系统下运行; 例如,他们可能会发出信号告诉他们陷阱发生的位置。 很可能他们仍然需要从陷阱地址中找出“真实”地址(即INT 3指令的地址),因为操作系统无法做到这一点。

如果涉及多个线程,事情也变得复杂; 在这种情况下,恢复原来的“就地”指令可能会导致断点被另一个线程击中。 一种解决方案可能是在恢复指令之前停止所有其他线程(并在之后再次启动它们)。

通常的解决方案是让调试器修改堆栈上的地址(并恢复被陷阱覆盖的指令),因此它会执行修补的指令。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM