作者Michael Chourdakis, 翻译Binhua Liu
下载源代码 –56.1KB
简介
我是基于以下理由决定写一篇关于硬件断点的文章的:
1,Visual C++只支持硬件写断点,而你可能需要在数据读取时触发断点。
2,或许你用的不是Visual C++,而你的调试器使用的是一些速度很慢的基于软件的断点机制。
3,你可能希望能程序中设置和移除断点。
4,或许你对CPU的底层机制感兴趣。
特性
支持x86和x64平台
支持为每个线程设置4个硬件断点
调试寄存器
x86/x64包括一组调试寄存器:DR0,DR1,DR2,DR3,DR6和DR7. 这些寄存器在32位模式下为32-bit, 64位模式下为64-bit. 其中DR0,DR1,DR2和DR3包含断点的线性地址, DR7包含的位解释如下:
位 | 功能 |
0-7 | 4个调试寄存器的标志位(每2个位对应一个寄存器).第一个标志位指定是否是一个本地断点(local breakpoint)(CPU在切换任务时重设该标志位),第二个标志位指定是否是一个全局断点(global breakpoint).在Windows平台,你只能使用第一个标志位(虽然我没有试过第二个). |
16-23 | 每2个位对应一个寄存器,用来定义断点合适被触发: 01b - 数据写入时触发 10b - 保留 11b - 数据读写时触发 |
24-31 | 每2个位对应一个寄存器,定义断点的大小 00b - 1字节 01b - 2字节 10b - 8字节 11b - 4字节 |
我们使用SetThreadContext来为线程设置断点. 之后,一旦断点被触发, 将产生一个单步异常EXCEPTION_SINGLE_STEP.
设置断点
见附件中的源代码:
HANDLE SetHardwareBreakpoint(HANDLE hThread,HWBRK_TYPE Type,HWBRK_SIZE Size,void* s);
hThread
- 被设置断点的线程的句柄
Type - 断点类型:
- HWBRK_TYPE_CODE
- HWBRK_TYPE_READWRITE
- HWBRK_TYPE_WRITE
Size - 断点的大小(Size)
- HWBRK_SIZE_1
- HWBRK_SIZE_2
- HWBRK_SIZE_4
- HWBRK_SIZE_8
addr - 设置断点的地址
该函数返回断点的句柄, 在 RemoveHardwareBreakpoint中被使用. 如果返回的是0,则表示
1,你不能访问这个线程
2,你已经在这个线程上设置了最大数量的断点(4个)
移除断点
bool RemoveHardwareBreakpoint(HANDLE hBrk);
移除断点,如果成功,返回true
例子
int __stdcall WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
char c1[100] = {0};
lstrcpyA(c1,"Hello 1");
HANDLE hX1 = 0;
hX1 = SetHardwareBreakpoint(GetCurrentThread(),
HWBRK_TYPE_READWRITE,HWBRK_SIZE_4,c1);
__try
{
volatile char a1 = c1[2];
// To ensure that it won't be optimized out.
}
__except(GetExceptionCode() == STATUS_SINGLE_STEP)
{
MessageBoxA(0,"Breakpoint hit!",0,MB_OK);
}
RemoveHardwareBreakpoint(hX1);
return 0;
}
期待你们的评论和问题!
历史
本文写于2008/7/24
作者 Michael Chourdakis . http://www.turboirc.com
Binhua Liu 翻译于2011/7/21. 原文链接http://www.codeproject.com/KB/debug/hardwarebreakpoint.aspx
所有评论(0)