在程序中设置读、写、执行的硬件断点

作者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个位对应一个寄存器,用来定义断点合适被触发:
00b - 代码执行时触发

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

posted @ 2011-07-21 15:46  Binhua Liu  阅读(6705)  评论(4编辑  收藏  举报