Overview
在调试代码时,一个常见的问题就是断点到底是怎么工作的。另一个问题就是软件断点和硬件断点有什么不同,我应该选择哪种。本文将会深入的介绍软件和硬件断点的不同。也会更加详细的提供Code Composer Studio 和 Target的内部工作机制。并且,也会讨论特殊的断点的case和高级用法。
Abbreviation Used t
CCS - Code Composer Studio (用于 TI DSP、微处理器和应用处理器的集成开发环境)t
HWBP Hardware Breakpoint PABt
Program-Address Bus t
SWBP - Software Breakpoint
Breakpoint Definition
在本文中,首先统一断点的定义。这里讨论的断点是我们想要将程序在CPU执行过程中暂停的位置,然后我们可以进行某种程度上的调试。可能还有其他形式的断点,比如由访问数据触发的断点,但是在本文中,我们只讨论程序断点,每次代码执行到该位置时,都会暂停的断点。
Hardware vs. Software Breakpoints
硬件断点和软件断点的区别是什么?很显然,硬件断点是由硬件实现的,软件断点是由软件实现的。但是这究竟意味着什么?我究竟什么时候该进行选择?
Hardware Breakpoints
硬件断点是由特殊的逻辑实现的,并且集成到了设备中。你可以想象硬件断点是一套可编程的比较器,连接到了程序地址总线上。这些比较器是由特定的地址赋值的。当代码执行的时候,如果该地址的所有bit都与程序总线一致,硬件断点逻辑就会产生一个暂停信号给CPU。
使用硬件断点的优势是可以使用任何形式的存储器。在讨论了软件断点之后,这点会更加清楚。在讨论软件断点时,我们会发现它只能被应用在可变存储器中。不管程序代码是在RAM还是ROM中,硬件断点可以使用。因为对于硬件断点来说,没有什么不同。它只是比对PAB的地址,然后匹配的时候暂停CPU。
HWBP的缺点就是,它们是硬件实现的,只有有限个。HWBP的个数不同的架构不同,但是大多数只有2~8个。最简单的发现你有多少个硬件断点的方式就是,持续的设置硬件断点,直到它报错说没有可用的了。
Software Definition
正如提到的,软件断点是在软件上实现的,通常有两种不同的实现方式。
一些器件在它们的opcode定义中,保留了一个专用的bit,用于表明是软件断点。比如,在C6000 中的一种结构,指令是32bit长度的,但是第28bit被保留用于表明是软件断点。在这个case中,当CCS中设置了软件断点之后,它实际上将会修改代码所在位置的uop,然后将第28bit设置为1。仿真逻辑然后会持续监控程序代码,直到代码的28bit为1,然后暂停CPU。**要注意这是一个很少见的情况。**大多数的架构并不这样实现。原因是这个限制了指令集的灵活性,并且变长指令时也不易实现。并且还限制了代码密度。
更常用的实现软件断点的方法也更加的复杂。在这类场景中,有一个专门的断点opcode。通常opcode 是8bit。无论何时断点被设置,开头的8bit的指令会被移除然后替换为8bit的断点opcode。原始的8bit 指令被存储在断点表中。当遇到断点的时候,CPU暂停然后CCS将断点处的breakpoint opcode替换为原始的8bit指令代码。当程序重启时,CCS一定要取巧,因为现在CPU中的实际的流水线并不正确,CPU实际上还有被修改过为breakpoint opcode的程序。所以CCS会flush CPU的流水线,然后重新取指,恢复到原来的状态,PC所指的下一条指令就是断点所在的源指令。
与此同时,CCS会重新加载指令,将指令设置为断点指令,这样下一次代码执行时,就又会暂停了。
SWBP的优势就是不会限制断点的数目,所以你可以想要设置多少个,就设置多少个。这个缺点是你不能非可修改的存储器上运行,比如ROM和FLASH,因为CCS不能修改断点位置的opcode。
TI:How Do Breakpoints Work
X86
虽然上述内容是TI的断点介绍,但是软件断点在X86体系结构实现的机制也是类似的。X86的软件断点就是通过将断点所在位置的1byte指令设置为INT3指令,对应的十六进制0xCC,当程序执行发现代码是0xCC时,就会意识到这是一个断点,然后触发中断处理程序,也就是调试器所注册的调试程序,然后我们就可以调试了。比较有意思的是visual studio也会为未分配或静态分配而未赋初值的内存空间,初值用0xCC填充。这时候我们如果访问了就会打印常见的“烫烫烫”。
欢迎关注我的公众号《处理器与AI芯片》