SEH在Windows上,调用堆栈回溯消失了

Tan*_*sen 5 windows debugging seh

我正在阅读有关Windows上SEH的这篇文章.这是myseh.cpp的源代码

我调试了myseh.cpp.我printf("Hello from an exception handler\n");在第24 DWORD handler = (DWORD)_except_handler;行和第36行分别设置了2个断点.

然后我跑了它,它突破了线:36.我看到堆栈跟踪如下.

在此输入图像描述 随着时间的推移, 发生了AccessViolationException,因为mov [eax], 1 它在第24行中断了.我看到堆栈跟踪如下. 在此输入图像描述

同一线程,但main不见了!而不是_except_handle.ESP从跳跃0018f6c80018ef34;它0018f6c80018ef34 After Exception 之间的差距很大.

我知道_except_handle必须在用户模式而不是内核模式下运行.后_except_handle返回,线程转向RING0然后windows内核修改的上下文EAX&scratch&然后回到环3.因此线程不断运行.

我很好奇窗口处理异常的机制:为什么调用main消失了?

为什么ESP从跳下0018f6c80018ef34?(我指的是大间距),做那些ESP地址属于同一线程的堆栈??? 内核是否在ring3中对ESP进行了一些技巧?如果是这样,为什么选择0018ef34处理程序回调框架的地址?非常感谢!

Han*_*ant 7

您使用的是默认调试器设置,但不足以查看所有详细信息.选择它们是为了帮助您专注于自己的代码并尽快启动调试会话.

[外部代码]块告诉您堆栈帧的某些部分不属于您编写的代码.他们没有,他们属于操作系统.使用工具>选项>调试>常规,取消选中"启用我的代码"选项.

[下面的框架可能不正确...]警告告诉您调试器没有准确的PDB来正确地移动堆栈.使用工具>选项>调试>符号并勾选"Microsoft Symbol Servers"选项并选择缓存位置.调试器现在将下载您需要通过操作系统DLL调试的PDB.可能需要一段时间,它只需要完成一次.

你可以推断出大的ESP变化,CONTEXT结构相当大,占用了堆栈空间.

在这些变化之后,您现在应该看到类似的东西:

ConsoleApplication1942.exe!_except_handler(_EXCEPTION_RECORD * ExceptionRecord, void * EstablisherFrame, _CONTEXT * ContextRecord, void * DispatcherContext) Line 22    C++
ntdll.dll!ExecuteHandler2@20()  Unknown
ntdll.dll!ExecuteHandler@20()   Unknown
ntdll.dll!_KiUserExceptionDispatcher@8()    Unknown
ConsoleApplication1942.exe!main() Line 46   C++
ConsoleApplication1942.exe!invoke_main() Line 64    C++
ConsoleApplication1942.exe!__scrt_common_main_seh() Line 255    C++
ConsoleApplication1942.exe!__scrt_common_main() Line 300    C++
ConsoleApplication1942.exe!mainCRTStartup() Line 17 C++
kernel32.dll!@BaseThreadInitThunk@12()  Unknown
ntdll.dll!__RtlUserThreadStart()    Unknown
ntdll.dll!__RtlUserThreadStart@8()  Unknown
Run Code Online (Sandbox Code Playgroud)

记录在Win10版本1607和VS2015 Update 2上.这不是编写SEH处理程序的正确方法,在本文中找到了更好的示例.