硬件断点和软件断点

时间:2022-09-01 08:15:36

在嵌入式开发,经常用到JTAG仿真器。JTAG仿真器可以满足嵌入式程序调试的基本要求:断点设置、单步调试、内存编辑、变量、寄存器观测等。而断点设置是JTAG仿真器最基本的调试功能。用户需要系统在设置断点处停下来后再进行调试。断点根据原理和用途不同又分为几个不同的种类。
 
断点可分为硬件断点和软件断点两大类:
 
1.硬件断点需要目标CPU的硬件支持,当前流行的ARM7/9内部硬件设计提供两组寄存器用来存贮断点信息,所以ARM7/9内核最多支持两个硬件断点,而ARM11则可以支持到8个硬件断点。这与调试器无关。
 
硬件断点可以设置在任何位置的代码上,包括ROM和RAM;而软件断点由于需要修改相应地址的值,所以一般只能设在RAM上,但是数量可以不受限制。由于硬件断点设置的灵活性,所以是最优先选用的断点资源,但是两个断点往往很难满足工程师进行深入调试的需要,于是软件断点可以作为硬件断点的补充资源来使用。
 
2.软件断点则是通过在代码中设置特征值的方式来实现的。当需要在某地址代码处设置软件断点的时候,仿真器会先将此处代码进行备份保护,然后将预先设定好的断点特征值(一般为0x0000等不易与代码混淆的值)写入此地址,覆盖原来的代码数据。当程序运行到此特征值所在的地址时,仿真器识别出此处是一个软断点,便会产生中断。当取消断点时,之前受保护的代码信息会被自动恢复。
 
3. 由于通常的软件断点只能设在RAM运行的代码上,而随着系统的代码量越来越大,特别是在移动通信领域,扩充大容量的RAM势必会增加产品的成本,所以现在很多系统直接在FlashROM上运行代码。对于这种在FlashROM上运行代码的系统,一般的软件断点是无法设置的,这也是软件断点的局限性。对于这样的系统,只能通过交替使用两个硬件断点满足需要,但是会带来一定的不便。
 
要很好的解决这一矛盾,只有使仿真器增加在FlashROM上设置软件断点的功能,拓展仿真器中可供利用的断点资源。例如,日本横河计算机株式会社(YDC)最新推出的高端ARM仿真器—advicePRO,就是第一个支持Flash断点的ICE仿真器产品。
 
在FlashROM上设置软件断点的原理与在RAM上设置软断点类似,也是在设定的断点处用特征码替换原有代码,通过识别特征码使断点事件发生。不同的是,在FlashROM上设置软件断点需要对Flash进行擦写操作,这就需要仿真器能够有Flash编程功能,并且能够在尽可能短的时间内完成特征码的写入。完成这一系列的读写操作,就可使在FlashROM上调试代码的工程师获得更充裕的断点资源,从而大大提高了开发效率。
 
除了JTAG 仿真器, GDB 是调试的另一有力武器。
 
信号是实现GDB断点功能的基础。以x86为例,向某个地址打入断点,实际上就是往该地址写入断点指令INT 3,即0xCC。目标程序运行到这条指令之后就会触发SIGTRAP信号,gdb捕获到这个信号,根据目标程序当前停止位置查询gdb维护的断点链表,若发现在该地址确实存在断点,则可判定为断点命中。 
 
GDB的指令级单步
所谓指令级单步就是指gdb控制目标程序只运行一条指令之后即停止。指令级单步是next/step (C语言源码级)、nexti/stepi(指令级)等运行类调试命令的基础。指令级单步有硬件单步和软件单步之分。所谓硬件单步是指cpu架构本身就支持指令级单步,目标程序可以在运行一条指令之后自动停止。所谓软件单步是指cpu架构不支持指令级单步,需要gdb用软件方法来实现指令级单步。(arm架构的kprobe也采用类似的方法)
 
支持硬件单步的架构如x86和ppc。对于x86,可通过设置EFLAGS寄存器中的TF标志来将cpu置于单步模式。对于ppc,则可通过设置MSR寄存器中的SE标志来将cpu置于单步模式。在单步模式中,cpu每执行一条指令,就会产生一个单步异常,通知gdb进行处理。
 
不支持硬件单步的架构如arm和mips。对于此类架构,gdb采用的是用临时的软件断点来模拟单步的方法。即在需执行指令的下一条指令处临时插入一个断点,然后让目标程序继续运行,它会在执行完当前指令之后遇到下一条指令处的临时断点,于是目标程序停止,通知gdb命中断点,gdb再将此断点删除,由此来完成指令级单步的过程。(插入临时断点需要gdb实现代码分支预测的功能)
 
step 和 next 的区别:
对于简单语句,step完全等同于next。唯一不同的是,若单步过程中遇到函数调用,step命令将停止在子函数的起始处,而不是将其跨越(无调试信息的子函数除外)。
参考
http://www.eet-china.com/ART_8800448644_480401_TA_b5f39204.HTM