我能够毫无问题地设置硬件断点(写入或读取地址)并且它也可以工作。如果我尝试从 Vectored Exception 处理程序执行相同操作,则会设置寄存器(使用 set/getThreadContext 确认),但相同的 SW 永远不会中断。地址和设置函数是相同的,我看到的唯一区别是,如果我从主代码设置断点,它可以工作;如果我从向量异常处理程序(在发生不相关异常的情况下)执行相同操作,则断点将不会产生任何影响。
应该在断点处中断的代码当然在异常处理程序之外。我在 IA32 软件手册中找不到任何相关信息。
也许你们中的一些人有这个问题。任何帮助表示赞赏。
编辑:这是一个非常粗略的例子,不要介意警告。如果使用#define DIRECT 编译,程序会因为未捕获的 SINGLE_STEP 而终止,如果编译时没有任何反应。需要明确的是,这只是一个丑陋、混乱、快速的例子。
// The following macros define the minimum required platform. The minimum required platform
// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
// your application. The macros work by enabling all features available on platform versions up to and
// including the version specified.
// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef WINVER // Specifies that the minimum required platform is Windows Vista.
#define WINVER 0x0600 // Change this to the appropriate value to target other versions of Windows.
#endif
#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista.
#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows.
#endif
#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98.
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
#endif
#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0.
#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE.
#endif
#include "windows.h"
#include "stdio.h"
#define DR7_CONFIG(num, lg, rw, size) ((((rw & 3) << (16 + 4 * num)) | ((size & 3) << (18 + 4 * num))) | (lg << (2 * num)))
HANDLE mainThread;
//#define DIRECT
DWORD WINAPI LibAsilEmu_ArrayBoundsMonitor(LPVOID lpParameter)
{
MSG msg;
CONTEXT tcontext;
HANDLE th;
DWORD temp = 0;
IMAGE_SECTION_HEADER *psec;
th = OpenThread(THREAD_ALL_ACCESS, FALSE, mainThread);
temp = SuspendThread(th);
tcontext.ContextFlags = CONTEXT_DEBUG_REGISTERS;
temp = GetThreadContext(th, &tcontext);
tcontext.Dr6 = 0;
tcontext.Dr0 = lpParameter;
tcontext.Dr2 = lpParameter;
tcontext.Dr3 = lpParameter;
tcontext.Dr1 = lpParameter;
tcontext.Dr7 = 0xffffffff;//DR7_CONFIG(0, 1, 2, 3) | DR7_CONFIG(1, 1, 2, 3) | 256;
temp = SetThreadContext(th, &tcontext);
temp = GetThreadContext(th, &tcontext);
temp = ResumeThread(th);
return 0;
}
HANDLE child;
unsigned int test_array[10];
LONG WINAPI LibAsilEmu_TopLevelVectoredFilter(struct _EXCEPTION_POINTERS *ExceptionInfo)
{
child = CreateThread(NULL, 0x4000, LibAsilEmu_ArrayBoundsMonitor, &test_array[2], 0, NULL);
while (WAIT_OBJECT_0 != WaitForSingleObject(child, 0));
return EXCEPTION_CONTINUE_EXECUTION;
}
int main(void)
{
int i;
printf("%p\n", test_array); fflush(stdout);
printf("sizeof %d\n", sizeof(test_array));
mainThread = GetCurrentThreadId();
#ifdef DIRECT
child = CreateThread(NULL, 0x4000, LibAsilEmu_ArrayBoundsMonitor, &test_array[2], 0, NULL);
// Edit 2: the wait was missing
while (WAIT_OBJECT_0 != WaitForSingleObject(child, 0));
#else
AddVectoredExceptionHandler(1, &LibAsilEmu_TopLevelVectoredFilter);
RaiseException(0,0,0,0);
#endif
printf("thread ready\n");
printf("ta %p\n", &(test_array[10]));
for (i = 0; i < 15; ++i)
{
*((char*)test_array) += 0x25;
test_array[i] += 0x15151515;
printf("%2d %d %p\n", i, test_array[i], &(test_array[i])); fflush(stdout);
}
printf("ta %d\n", test_array[10]);
printf("exit\n\nexit\n\n");
return 0;
}