我的理解是,插入软件断点涉及将要执行的代码中的下一条指令替换为软件中断指令,当CPU到达该指令时会导致CPU停止运行。
硬件断点则涉及将断点后面要执行的下一条指令地址放入寄存器中,当地址匹配时,通过使用硬件比较器,这会导致CPU停止运行(如有错误请纠正)。
我所困惑的是,我们只在使用硬件调试器通过JTAG等调试板时才使用硬件断点吗?还是JTAG也可以使用软件断点?
GDB只能与软件断点一起使用吗,还是它也可以与JTAG一起使用?如果问题太广泛,请原谅。
我的理解是,插入软件断点涉及将要执行的代码中的下一条指令替换为软件中断指令,当CPU到达该指令时会导致CPU停止运行。
硬件断点则涉及将断点后面要执行的下一条指令地址放入寄存器中,当地址匹配时,通过使用硬件比较器,这会导致CPU停止运行(如有错误请纠正)。
我所困惑的是,我们只在使用硬件调试器通过JTAG等调试板时才使用硬件断点吗?还是JTAG也可以使用软件断点?
GDB只能与软件断点一起使用吗,还是它也可以与JTAG一起使用?如果问题太广泛,请原谅。
在本文的语境中,我们一起确认一下断点的统一定义。这里讨论的断点是程序位置,在这些位置我们希望处理器停止运行,以便我们进行某种形式的调试。虽然可能存在其他类型的断点,例如由数据访问触发的断点,但是在本文中,我们仅讨论程序断点,即我们希望在应用程序代码中遇到每个代码时都停止。
硬件断点和软件断点的区别是什么?显而易见的答案是“硬件断点是通过硬件实现的”,“软件断点是通过软件实现的”。但这具体意味着什么,有什么影响?我为什么要选择一个而不是另一个?
http://processors.wiki.ti.com/index.php/How_Do_Breakpoints_Work
"如果我错了,请纠正我"
断点是设置在指令上而不是指令之后 - 断点发生在指令执行之前而非之后 - 否则在跳转、调用或分支指令上设置断点将会失败。
"当使用硬件调试器通过JTAG来调试板子时,我们只能使用硬件断点吗?"
JTAG是芯片内部调试的简单通信接口(也用于其他用途,例如电路中的存储器和FPGA编程以及边界扫描等)。
虽然在不同架构上可能有所不同,例如在ARM Cortex-M上,您可以从目标代码访问芯片内部调试寄存器并设置硬件断点。同时,您还可以使用BKPT指令(而不是SWI)在代码中放置软件断点。
或者JTAG也可以使用软件断点吗?
正如我所说,JTAG只是芯片内部调试的通信接口,但是通过芯片内部调试,您可以直接设置任何RAM内容,因此开发主机上运行的JTAG连接的调试器软件可以临时修改RAM中的代码以设置软件断点(通过用BKPT替换目标指令,然后当断点被触发时,恢复回原来的指令以便执行)。对于从ROM运行的代码,软件断点并不是那么简单,尽管一些调试器支持无限制的ROM断点(需要付费)- 这类硬件的制造商不一定会公布他们所使用的方法。
在JTAG和芯片内部调试变得广泛可用之前,采用了In-Circuit Emulation和ROM仿真等技术。这些通常是昂贵且复杂的解决方案。
"GDB只能与软件断点一起使用,还是可以与JTAG一起使用?"
GDB可以用多种方式。它需要一个“调试 stub” - 一个将调试器软件映射到可用硬件的软件层 - 其性质取决于所使用的调试接口和目标设备。例如,当使用UART或Ethernet端口时,stub实际上是在目标本身上运行的代码(例如Linux的gdbserver
)。在这种情况下,由于软件错误可能会阻止调试端口驱动程序实际运行,因此它不太可靠,特别是在缺乏MMU保护的目标中。更简单的JTAG设备通过在开发主机上运行的stub与GDB进行接口,例如常用的OpenOCD软件。更昂贵的JTAG调试硬件可能会在JTAG硬件本身上运行stub - 例如Abatron的BDI2000。无论哪种方式,调试 stub都将能够使用硬件和软件断点,具体取决于目标的功能。