如何解决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 将执行传递回程序。
#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 分析检查未初始化或归零的变量 - 没有。
- 在互联网上阅读类似案例。
- 用于调试的文件日志
因此问题:
- 有没有办法在没有调试模式的情况下从崩溃中获取更多信息?
- 有没有办法表示如此大量的调用,这样代码会很快,但不会使堆栈过载?注意:所有函数调用都根据发生异常的偏移量提供不同的参数,因此分组将减少非常小的调用量。
- 如果您遇到此类问题以进行调试,您的下一步是什么?
谢谢并希望得到您的帮助。
解决方法
好的,我解决了这个问题:
- 选择了不同的调试器 - x64dbg。惊人的调试器,它附加到启动的进程,而不是在调试模式下启动它。
- 这允许在进程初始化期间识别堆栈溢出问题。
- 我已经对此应用了快速修复,因为我正在制作原型:使用 editbin /F stacksize 修改应用程序的 .exe 文件以增加它。
- 一切正常。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。