异常链验证 (SEHOP) 处于活动状态的光纤的 SEH 设置

问题描述 投票:0回答:2

我正在研究本地纤程/协程实现 - 相当标准,对于每个纤程,分配一个单独的堆栈,并且为了切换上下文,寄存器被推入源上下文堆栈并从目标堆栈弹出。它运行良好,但现在我遇到了一个小问题:

我需要 SEH 在纤程内工作(如果程序终止或奇怪的事情开始发生,直到纤程的最后一个堆栈帧之前未处理异常,它都不会)。只需在上下文切换期间保存/恢复

FS:[0]
(显然,还有
FS:[4]
FS:[8]
),并初始将新分配的纤程的 FS:[0] 设置为
0xFFFFFFFF
(以便在上下文之后设置异常处理程序) switch 将成为链的根)几乎有效。

准确地说,它适用于我测试的所有非服务器 Windows 操作系统 - 问题是 Windows Server 2008 和 2008 R2 默认启用了异常链验证(SEHOP、SEH 覆盖保护)功能,这使得

RaiseException
检查如果原始处理程序(ntdll.dll 中的某处)仍然是链的根,则立即终止程序,就像没有安装任何处理程序一样。

因此,我面临着在堆栈上构造适当的根框架以使验证代码满意的问题。是否有任何(隐藏的?)API 函数我可以调用来做到这一点,或者我是否必须弄清楚需要什么才能让

RtlDispatchException
和朋友们满意并自己构建适当的
_EXCEPTION_REGISTRATION
条目?我不能只重用创建线程中 Windows 提供的地址,因为它会位于错误的地址(SEH 实现还会检查处理程序地址是否在
FS:[4]
FS:[8]
给出的边界内,并且可能还如果地址顺序一致)。

哦,我强烈建议诉诸

CreateFiber
WinAPI 系列函数。

winapi stack coroutine seh fiber
2个回答
1
投票

我在评论中提到的方法,生成一个指向

EXCEPTION_REGISTRATION
的假
ntdll!FinalExceptionHandler
条目,似乎在实践中确实有效 - 至少,这就是我们现在在 D 运行时中所拥有的,并且到目前为止还没有任何报告问题:

https://github.com/D-Programming-Language/druntime/blob/c39de42dd11311844c0ef90953aa65f333ea55ab/src/core/thread.d#L4027


0
投票

查看您的 github.com 链接中的代码,@dnadlinger,我不太清楚您的 64 位 Windows 代码是否缺少您为 32 位 Windows 描述的解决方案,或者实际上是否缺少针对 64 位 Windows 的相应解决方案Windows 更简单。

假设是后者,我尝试调整Boost.Context 64位Windows fcontext masm实现以在每次上下文切换时保存和恢复

GS:[0]
处的三指针块,这就是我推断D语言的64位Windows Fiber上下文切换代码正在做。

不幸的是,即使有了链接的更改,我用来在异常处理期间执行上下文切换的测试程序(在 PR 中链接)的行为与未修改的 Boost.Context 相同。

我错过了什么?

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.