-
与软件断点与内存断点不同,硬件断点不依赖被调试程序,而是依赖于CPU中的调试寄存器。
-
调试寄存器有7个,分别为Dr0~Dr7。
-
用户最多能够设置4个硬件断点,这是由于只有Dr0~Dr3用于存储线性地址。
-
其中,Dr4和Dr5是保留的。
假如在Dr0寄存器中写入线性地址,是否所有线程都会受影响?其实不会,每个线程都拥有一份独立的寄存器,切换线程时,寄存器的值也会被切换。
设置硬件断点
Dr0~Dr3用于设置硬件断点,由于只有4个断点寄存器,所以最多只能设置4个硬件调试断点。在7个寄存器里面,Dr7是最重要的寄存器
L0/G0 ~ L3/G3:控制Dr0~Dr3是否有效,局部还是全局;每次异常后,Lx都被清零,Gx不清零。
若Dr0有效,L0=1则为局部,G0=1则为全局,以此类推
断点长度(LENx):00(1字节)、01(2字节)、11(4字节)
通过DR7的LEN控制
断点类型(R/Wx):00(执行断点)、01(写入断点)、11(访问断点)
流程
被调试进程:
1)CPU执行时检测当前线性地址与调试寄存器(Dr0~Dr3)中的线性地址相等。
2)查IDT表找到对应的中断处理函数(
nt!_KiTrap01
)3)CommonDispatchException
4)KiDispatchException
5)DbgkForwardException收集并发送调试事件
最终调用DbgkpSendApiMessage(x, x)
,第一个参数:消息类型,第二个参数:是否挂起其它线程
调试器进程:
1)循环判断
2)取出调试事件
3)列出信息:寄存器、内存
4)用户处理
处理硬件断点
1)硬件调试断点产生的异常是 STATUS_SINGLE_STEP
(单步异常) 2)检测Dr6寄存器的B0~B3:哪个寄存器触发的异常
这里硬件断点有两种情况,一种情况是dr0-dr3寄存器引发的异常,另外一种情况就是TF=1
引发的异常