在什么条件下我需要为x86-64汇编函数设置SEH展开信息?

时间:2017-07-26 17:06:00

标签: windows x86 nasm x86-64 seh

64位Windows ABI定义了一个通用的exception handling mechanism,我认为它可以在C ++异常和结构化异常之间共享,即使在其他语言中也是如此。

如果我正在编写一个x86-64程序集例程,要在nasm中编译并链接到C或C ++库,那么在生成展开信息等方面我需要在Windows上做些什么?

我不打算直接在汇编代码中生成任何异常,但我认为如果用户提供的缓冲区无效等,代码可能会出现访问冲突。

我希望编写尽可能少的代码才能使其工作,特别是因为似乎nasm对生成展开信息的支持不足,并且使用MASM不是此选项的选项平台项目。我确实需要使用(因此保存和恢复)非易失性寄存器。

2 个答案:

答案 0 :(得分:8)

作为一般规则,Windows x64需要所有功能来提供展开信息。唯一的例外是叶函数不修改v-for并且不修改任何非易失性寄存器。

答案 1 :(得分:3)

根据您的问题的上下文来判断,您真正想知道的是不在x64 Windows上为非叶装配功能提供展开信息的实际后果。由于C ++异常是基于SEH异常实现的,当我谈到下面的异常时,我的意思是所有“本机”(访问冲突,使用RaiseException抛出的东西等)和C ++异常。这是我头顶的清单:

  • 例外将无法通过您的功能

重要的是要注意,这一点不是要在您的函数中抛出异常,或直接发生访问冲突。假设您的汇编代码调用C ++函数,该函数抛出异常。即使汇编函数的调用者具有匹配的catch块,它也永远无法捕获异常,因为展开将在没有展开数据的情况下停止在您的函数中。

  • 当走遍堆栈时,堆栈步行将停止在没有展开数据的函数处(或误入歧途;重点是,你将得到一个无效的调用堆栈)

基本上,如果你的函数出现在调用堆栈上(调试器显示调用堆栈,分析器等)时,任何走过堆栈的东西都会被搞砸。

这会干扰依赖UEF的任何事情。例如,自定义崩溃处理程序。或者可能更相关的东西:在这种情况下,如果你的程序抛出一个未处理的C ++异常(因为它是由C ++标准规定的),则不会回调std::terminate。 MSVC运行时使用UEF来实现它,因此这也不会起作用。

您正在开发第三方图书馆吗?如果是这种情况,上述要点的重要性将取决于客户的使用情况。