DLL 中的大型向量异常处理程序导致程序在没有调试器的情况下崩溃

问题描述

我目前正在研究实现向量异常处理程序 (VEH) 的 DLL(Windows 10、x64)。它导出函数是为了附加到可执行文件,没有别的。在附加 VEH 期间,它还使用以下代码段计算基本偏移量:

uint64_t GetModuleBase(const char *modname)
{
    HANDLE hModSnap;
    MODULEENTRY32 pe32;
    void *bs = NULL;

    // Take a snapshot of all processes in the system.
    hModSnap = Createtoolhelp32Snapshot( TH32CS_SNAPMODULE,GetCurrentProcessId() );
    if( hModSnap == INVALID_HANDLE_VALUE )
    {
        return NULL;
    }

    // Set the size of the structure before using it.
    pe32.dwSize = sizeof( MODULEENTRY32 );

    if( !Module32First( hModSnap,&pe32 ) )
    {
        CloseHandle( hModSnap );     // Must clean up the snapshot object!
        return NULL;
    }

    do
    {
        if (!StrCmpI(pe32.szModule,modname)) {
            bs = pe32.modBaseAddr;
            break;
        }
    } while( Module32Next( hModSnap,&pe32 ) );

    CloseHandle( hModSnap );

    return (uint64_t)bs;
}

在异常处理程序中,我只处理代码为“0xc000001d”的异常,在其他情况下,VEH 将执行传递回程序。

在VEH中注册的内部处理函数我有以下结构(简化):

#define FUNCTION_1(arg1,arg2,arg3,arg4)
    if (exception_offset == arg1) { \
        5_lines_of_code .... \
       return EXCEPTION_CONTINUE_EXECUTION; \
    }


#define FUNCTION_2(arg1,arg4)
    if (exception_offset == arg1) { \
        5_lines_of_code .... \
        return EXCEPTION_CONTINUE_EXECUTION; \
    } 


#define FUNCTION_3(arg1,arg4) 
    if (exception_offset == arg1) { \
        5_lines_of_code .... \
        return EXCEPTION_CONTINUE_EXECUTION; \
    } \

...

# 15 functions like that.

FUNCTION_1(0x192385,cpu_REGISTER1,cpu_REGISTER2);
FUNCTION_2(0x145685,cpu_REGISTER3,cpu_REGISTER4);
FUNCTION_3(0x456685,cpu_REGISTER5);

# 1719 lines like that

我收到来自 MSVC 的警告:函数使用了 '81340' 字节的堆栈:超过 /analyze:stacksize '16384'。考虑将一些数据移到堆中。

使用调试器一切正常。使用 Windbg 一切正常。

没有调试器 - 应用程序静崩溃。

更深入的调查表明,它注册了 DLL,开始执行甚至调用处理程序几次,但具有不同的异常代码(从 0x8..... 这是调试代码),因此 VEH 代码在早期阶段返回。在正常的应用程序操作期间,我可以看到相同偏移量的相同代码,顺便说一句。

函数调用数量大约为 1400 左右时,一切都运行良好(如果我对其中的一部分进行评论,则不管是哪一个,只要我减少数量即可)

我尝试过:

  • 注释掉相同的函数调用(以确保它不是函数实现错误)-> 只有数量很重要
  • 禁用优化
  • 将堆栈大小增加到 140 Mb
  • 使用静态 MSVC 分析检查未初始化或归零的变量 - 没有。
  • 在互联网上阅读类似案例。
  • 用于调试的文件日志

没有任何效果。我猜,这是一个重载的堆栈。

因此问题:

  • 有没有办法在没有调试模式的情况下从崩溃中获取更多信息?
  • 有没有办法表示如此大量的调用,这样代码会很快,但不会使堆栈过载?注意:所有函数调用都根据发生异常的偏移量提供不同的参数,因此分组将减少非常小的调用量。
  • 如果您遇到此类问题以进行调试,您的下一步是什么?

谢谢并希望得到您的帮助。

解决方法

好的,我解决了这个问题:

  1. 选择了不同的调试器 - x64dbg。惊人的调试器,它附加到启动的进程,而不是在调试模式下启动它。
  2. 这允许在进程初始化期间识别堆栈溢出问题。
  3. 我已经对此应用了快速修复,因为我正在制作原型:使用 editbin /F stacksize 修改应用程序的 .exe 文件以增加它。
  4. 一切正常。