4

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

我需要 SEH 在纤程内工作(如果程序终止或奇怪的事情开始发生,直到纤程的最后一个堆栈帧之前未处理异常,这没关系,它不会)。只是在上下文切换期间保存/恢复FS:[0](显然与FS:[4]and一起FS:[8])并最初为新分配的纤程设置 FS:[0] 0xFFFFFFFF(以便在上下文切换后设置的异常处理程序将成为链的根)几乎可以工作。

准确地说,它适用于我测试过的所有非服务器 Windows 操作系统——问题是 Windows Server 2008 和 2008 R2 默认启用了异常链验证(SEHOP、SEH 覆盖保护)功能,这使得RaiseException检查原始处理程序是否(在 ntdll.dll 中的某处)仍然是链的根,并立即终止程序,就好像没有安装任何处理程序一样。

因此,我面临着在堆栈上构建适当的根框架以保持验证代码满意的问题。是否有任何(隐藏的?)API 函数我可以调用来做到这一点,还是我必须弄清楚需要什么才能让RtlDispatchException朋友开心并_EXCEPTION_REGISTRATION自己构建适当的条目?我不能只重用创建线程中的 Windows 提供的地址,因为它会位于错误的地址(SEH 实现还检查处理程序地址是否在 and 给出的边界内FS:[4]FS:[8]并且还可能检查地址顺序是否一致)。

哦,我强烈希望诉诸CreateFiberWinAPI 系列函数。

4

1 回答 1

1

我在评论中提到的方法,生成一个EXCEPTION_REGISTRATION指向的虚假条目ntdll!FinalExceptionHandler似乎在实践中确实有效——至少,这就是我们现在在 D 运行时中所拥有的,到目前为止还没有关于问题的报告:

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

于 2012-11-11T02:45:00.453 回答