【发布时间】:2012-01-16 10:30:41
【问题描述】:
硬件断点和软件断点有什么区别?
是否据说硬件断点比软件断点快,如果是,那么如何,以及为什么我们需要软件断点?
【问题讨论】:
标签: debugging gdb breakpoints
硬件断点和软件断点有什么区别?
是否据说硬件断点比软件断点快,如果是,那么如何,以及为什么我们需要软件断点?
【问题讨论】:
标签: debugging gdb breakpoints
这篇文章很好地讨论了利弊: http://www.nynaeve.net/?p=80
要直接回答您的问题,软件断点更加灵活,因为硬件断点在某些功能上受到限制并且高度依赖于体系结构。文章中给出的一个例子是 x86 硬件有 4 个硬件断点的限制。
硬件断点速度更快,因为它们具有专用寄存器并且比软件断点的开销更少。
【讨论】:
硬件断点实际上是比较器,将当前 PC 与比较器中的地址进行比较(启用时)。设置断点时,硬件断点是最好的解决方案。通常通过调试探针设置(使用 JTAG、SWD、...)。硬件断点的缺点:它们是有限的。 CPU 只有有限数量的硬件断点(比较器)。可用硬件断点的数量取决于 CPU。 ARM 7/9 内核有 2 个,现代 ARM 设备(Cortex-M 0,3,4)介于 2 和 6 之间, x86 通常为 4。
软件断点实际上是通过将要设置断点的指令替换为断点指令来设置的。断点指令存在于大多数 CPU 中,并且通常与最短指令一样短,因此 x86 上只有一个字节(0xcc,INT 3)。在 Cortex-M CPU 上,指令为 2 字节或 4 字节,因此断点指令为 2 字节指令。
如果程序位于 RAM 中(例如在 PC 上),则可以轻松设置软件断点。许多嵌入式系统的程序位于闪存中。这里交换指令不是那么容易,因为flash需要重新编程,所以主要使用硬件断点。如果程序位于闪存中,大多数调试探针仅支持硬件断点。但是,有些(例如 SEGGER 的 J-Link)允许使用断点指令重新编程闪存,并且即使在调试位于闪存中的程序时也允许无限数量的(软件)断点。
【讨论】:
您可以通过GDB internals,它很好地解释了硬件和软件断点。
硬件断点需要 MCU 的支持。 ARM 控制器具有特殊的寄存器,您可以在其中写入一些地址空间,只要 PC(程序计数器)== sp 寄存器 CPU 停止。 Jtag 通常需要写入那些特殊的寄存器。
在 GDB 中通过插入陷阱、非法除法或其他会导致异常的指令来实现 SW 断点,然后当遇到异常时,gdb 将处理异常并停止程序。当用户说要继续时,gdb 会恢复原来的指令,单步执行,重新插入陷阱,然后继续。
使用硬件调试器比使用软件调试器有很多优势,尤其是在处理中断和内存总线设备时。 AFAIK 中断无法使用软件调试器进行调试。
【讨论】:
除了上述答案之外,还需要注意的是,虽然软件断点会覆盖程序中的特定指令以知道在哪里停止,但数量有限的硬件断点实际上是处理器的一部分。
Justin Seitz 在他的书 Gray Hat Python 中指出,这里的重要区别在于,通过覆盖指令,软件断点实际上会更改文件的 CRC,因此任何类型的程序(例如计算它的 CRC 可以响应设置的断点而改变其行为,而对于硬件断点,调试器停止并单步执行某些代码块的情况不太明显。
【讨论】:
简而言之,硬件断点使用专用寄存器,因此数量有限。这些可以在易失性和非易失性存储器上设置。
软件断点是通过用断点指令替换RAM内存中指令的操作码来设置的。这些只能在RAM内存中设置(Flash内存不可行),不受限制。
This article provides good explanation about breakpoints.
感谢和问候, Shivakumar V W
【讨论】:
观察点会产生巨大的影响
这是硬件处理速度更快的情况:
watch var
rwatch var
awatch var
当您在 GDB 7.7 x86-64 上输入这些命令时,它会显示:
Hardware watchpoint 2: var
在http://en.wikipedia.org/wiki/X86_debug_register 中提到了 x86 的此硬件功能
这很可能是因为现有的分页电路管理每个内存访问。
“软件”替代品是single step the program,它非常很慢。
与常规断点相比,至少软件实现会在断点处注入 int3 指令并让程序运行,因此您只需在断点被命中时支付开销。
【讨论】:
英特尔系统调试器帮助文档中的一些引用:
硬件与软件断点 调试器可以同时使用这两种硬件 和软件断点,每个都有优点和缺点:
硬件断点是使用 DRx 架构实现的 Intel SDM 中描述的断点寄存器。他们有 具有可在复位时直接使用、非易失性和 可用于闪存或其他只读存储器。缺点是 他们是有限的资源。 软件断点需要 修改系统内存,因为它们是通过替换实现的 带有特殊指令的所需位置的操作码。这使得 它们是无限的资源,但内存依赖性意味着你不能 在将模块加载到内存之前安装它们,如果 目标软件会覆盖该内存,然后它们将变得无效。 通常,必须由调试器启用的任何调试功能 重置后不会持续存在,并且可能会在其他情况下受到影响 架构模式转换,例如 SMM 进入/退出或 VM 进入/退出。具体例子包括:
CPU 复位将清除所有调试功能,复位中断除外。这 意味着例如用户指定的断点将无效 直到目标在重置后停止一次。请注意,此停止可以是 由于重置中断或由于用户启动的暂停。在 无论哪种情况,调试器都会恢复必要的调试功能。 SMM 进入/退出将禁用/重新启用断点,这意味着您 在 SMRAM 之外暂停时无法在 SMRAM 中指定断点。如果 你希望在 SMRAM 内休息,你必须先停在 SMM entry-break 并手动应用断点。或者,您可以 修补 BIOS 以在进入 SMM 时重新启用断点,但这 需要能够修改无法在 BIOS 中使用的 生产代码。
【讨论】:
软件断点在 RAM 中放置一条指令,当您的程序到达该地址时,该指令会像 TRAP 一样执行。
虽然硬件断点使用 CPU 的寄存器来实现断点本身。这就是为什么硬件断点要快得多的原因。这就是我们需要软件断点的原因:硬件断点仅限于处理器专用断点的寄存器数量。
我今天在工作中学到了它:)
【讨论】: