C语言 在处理异常期间设置 x86 调试寄存器



我能够毫无问题地设置硬件断点(写入或读取地址),它也可以工作。如果我尝试从向量异常处理程序执行相同的操作,则会设置寄存器(使用 set/getThreadContext 确认),但相同的软件永远不会中断。地址和设置函数是相同的,我看到的唯一区别是,如果我从主代码设置断点,它可以工作;如果我从向量异常处理程序(在发生不相关异常期间)执行相同的操作,断点将没有任何影响。

应该在断点上中断的代码当然不在异常处理程序之外。我在 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("%pn", test_array); fflush(stdout);
    printf("sizeof %dn", 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 readyn");
    printf("ta %pn", &(test_array[10]));
    for (i = 0; i < 15; ++i)
    {
        *((char*)test_array) += 0x25;
        test_array[i] += 0x15151515;
        printf("%2d %d %pn", i, test_array[i], &(test_array[i])); fflush(stdout);
    }
    printf("ta %dn", test_array[10]);
    printf("exitnnexitnn");
    return 0;
}
我不知道

您问题的细节,因为您的描述中没有提供代码。 也就是说,它可能只是一个编码错误。 因此,在没有其他信息的情况下,我所能想到的就是将您指向一个链接,其中包含一些有关使用向量异常处理的示例代码 这里 希望这有帮助,否则,发布一些代码

[编辑1]

首先,我猜你不是第一个看到这个问题的人,矢量异常处理自XP以来就已经存在。 其他人肯定已经看到了。

可能不需要说(但我还是会)调试器,当运行多个线程时,它们的行为与它们在在单线程中。 您正在从单独的线程调用向量异常处理程序。 这似乎可能与您从线程运行时看不到断点的事实有关。 您是否有能力将调试器指向特定线程?看这里

我还有一个建议 - 由于这个问题的真正重点是确定为什么在尝试使用矢量异常处理程序时没有设置硬件断点,请考虑将这篇文章的标题更改为以下内容:
无法使用矢量异常处理程序设置 HW 断点。
它可能会得到更多的关注。 (我自己会这样做,但不想假设你会接受这个:)

[编辑2]

我在您的示例中看到,在 main() 中,您正在从新线程中调用AddVectoredExceptionHandler()。 但功能

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;
}  

创建另一个新线程,LibAsilEmu_ArrayBoundsMonitor又在其中再次打开主线程。 这对我来说似乎是一系列奇怪的事件。 这段代码是您在其他地方看到的,并与向量异常处理结合使用的吗?

最新更新