【问题标题】:how does debugger resume from breakpoint?调试器如何从断点恢复?
【发布时间】:2013-03-26 17:58:19
【问题描述】:

假设一个调试器(常见的 x86 ring3 调试器如 olly、IDA、gdb...)设置了一个 软件断点到虚拟地址 0x1234。

这是通过将 0x1234 处的任何操作码替换为“0xCC”来完成的 现在让我们假设被调试进程运行这条 0xCC 指令并引发 软件异常和调试器捕捉到这一点。

调试器检查内存内容、寄存器并做一些事情......和 现在它想恢复被调试进程。

据我所知。从现在开始,这是我的假设。

调试器恢复原始操作码(已替换为 0xCC) 被调试者以恢复执行。

调试器操纵被调试者的 CONTEXT 的 EIP 指向 恢复指令。

调试器处理异常,现在,被调试者从断点恢复。

但调试器希望保留断点。 调试器如何管理这个?

【问题讨论】:

  • 好问题。我猜片上调试器支持硬件必须对此有所帮助。

标签: debugging breakpoints


【解决方案1】:

直接回答原问题,来自GDB internals manual

当用户说要继续时,GDB 会恢复原来的 指令,单步,重新插入陷阱,然后继续。

【讨论】:

  • 是“单步”芯片的特性(x86),还是调试器必须确定被0xcc替换的指令的长度,然后设置另一个 i> 0xcc 在指令之后?
  • “单步”是芯片的一个特性:只要运行一条汇编指令,芯片就会坏掉。这是必不可少的,因为某些指令也可能会以一种有时难以预测的方式跳转。想想call [rax],它跳转到一个本身从内存中获取的指针。
【解决方案2】:

简而言之:

由于进入调试状态是X86ARM 中的原子操作,处理器进入调试状态并退出调试状态,与架构中的任何其他指令相同。 请参阅gdb documentation 解释它的工作原理和使用方法。

以下是 ARM 和 X86 规范的一些亮点:

ARM:

SW(软件)断点是通过临时替换 断点位置的指令操作码具有特殊的 在单步执行或执行之前的“断点”指令 你的代码。当内核执行断点指令时,它会 强制进入调试状态。软件断点只能放在 RAM 中 因为它们依赖于修改目标内存。

HW(硬件)断点是通过对观察点单元进行编程来监控内核来设置的 用于从特定内存位置获取指令的总线。硬件 断点可以设置在 RAM 或 ROM 中的任何位置。调试时 指令被复制(分散加载)、修改或 处理器 MMU 重新映射内存区域,应使用硬件断点。 在这些情况下,软件断点是不可靠的,因为它们可能是 丢失或覆盖。

X86:

软件断点的工作方式相当简单。说起 x86 具体来说,要设置软件断点,调试器只需编写 目标第一个字节上的 int 3 指令(操作码 0xCC) 操作说明。这会导致在执行时触发中断 3 被转移到你设置断点的地址。当这 发生时,调试器“闯入”并将 0xCC 操作码字节与 设置时指令的原始第一个字节 断点,这样您就可以继续执行而不会碰到 立即相同的断点。其实还有一点魔力 涉及允许您从断点继续执行,并且 不要立即点击它,而是保持断点处于活动状态以备将来使用; 我将在以后的帖子中讨论这个问题。

硬件断点,正如您可能想象的那样,设置 具有特殊的硬件支持。特别是对于 x86,这涉及到一个 一组可能鲜为人知的特殊寄存器,称为“博士” 寄存器(用于调试寄存器)。这些寄存器允许您设置 四个(对于 x86,这是高度特定于平台的)地址,当 无论是读、读/写还是执行,都会导致处理器 抛出一个特殊异常,导致执行停止并控制 转移到调试器

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多