假设一个调试器(常见的x86 ring3调试器,如olly,IDA,gdb ......)设置一个 软件断点到虚拟地址0x1234。
这是通过将0x1234处的任何操作码替换为“0xCC”来实现的 现在让我们假设debugee进程运行这个0xCC指令并加注 软件异常和调试器捕获了这个。
调试器检查内存内容,寄存器并做一些事情..和 现在它想恢复debugee过程。
据我所知。从现在开始,这是我的假设。
调试器恢复原始操作码(被替换为0xCC) debugee为了恢复执行。
调试器操纵debugee的CONTEXT的EIP指向 恢复的指示。
调试器处理异常,现在,debugee从断点恢复。
但调试器希望保留断点。 调试器如何管理这个?
答案 0 :(得分:2)
直接回答原始问题,来自GDB internals manual:
当用户说要继续时,GDB将恢复原始版本 指令,单步,重新插入陷阱,然后继续。
答案 1 :(得分:0)
总之和普通人的话:
由于进入调试状态是X86
和ARM
中的原子操作,处理器进入它并退出调试状态,与架构中的任何其他指令一样。
请参阅gdb documentation说明其工作原理并可以使用。
以下是ARM和X86规范的一些亮点:
ARM中的:
SW(软件)断点通过临时替换来实现 指令操作码在断点位置有一个特殊的 在踩踏或执行之前的“断点”指令 你的代码。当核心执行断点指令时,它会 被迫进入调试状态。 SW断点只能放在RAM中 因为他们依赖于修改目标记忆。
通过编程观察点单元来监视核心来设置HW(硬件)断点 用于从特定存储器位置获取指令的总线。 HW 可以在RAM或ROM中的任何位置设置断点。调试时 代码复制指令(Scatterloading),修改或 处理器MMU重新映射内存区域,应使用硬件断点。 在这些情况下,SW断点是不可靠的,因为它们可能也是如此 丢失或覆盖。
在X86中:
软件断点的工作方式非常简单。说到x86 具体来说,为了设置软件断点,调试器只需写入 目标的第一个字节上的int 3指令(操作码0xCC) 指令。这导致在执行时触发中断3 被转移到您设置断点的地址。当这个 发生时,调试器“中断”并交换0xCC操作码字节 设置时指令的原始第一个字节 断点,这样你就可以继续执行而无需点击 同样的断点立刻。实际上有更多的魔力 涉及允许您从断点继续执行 不要立即打它,但保持断点活跃以备将来使用; 我将在以后的帖子中讨论这个问题。
硬件断点正如您可能想象的那样设置 有特殊的硬件支持。特别是对于x86,这涉及到 一组特别鲜为人知的寄存器,被称为“博士” 寄存器(用于调试寄存器)。这些寄存器允许您设置为 四(对于x86,这是高度平台特定的)地址,当 读取,读取/写入或执行将导致处理器 抛出一个特殊的异常,导致执行停止和控制 转移到调试器