c++ - 内联 asm 分配给 'FS:0' : handler not registered as safe handler

标签 c++ visual-studio-2015 inline-assembly seh

我正在尝试关注 this关于 Win32 结构化异常处理的文章。这篇文章很老了,但仍然被认为是对该主题的一个很好的介绍。

我正在尝试从下面转载的文章中编译代码示例 -

//==================================================
// MYSEH - Matt Pietrek 1997
// Microsoft Systems Journal, January 1997
// FILE: MYSEH.CPP
// To compile: CL MYSEH.CPP
//==================================================
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>

DWORD  scratch;

EXCEPTION_DISPOSITION
__cdecl
_except_handler(
    struct _EXCEPTION_RECORD *ExceptionRecord,
    void * EstablisherFrame,
    struct _CONTEXT *ContextRecord,
    void * DispatcherContext )
    {
    unsigned i;

    // Indicate that we made it to our exception handler
    printf( "Hello from an exception handler\n" );

    // Change EAX in the context record so that it points to someplace
    // where we can successfully write
    ContextRecord->Eax = (DWORD)&scratch;

    // Tell the OS to restart the faulting instruction
    return ExceptionContinueExecution;
    }

int main()
{
    DWORD handler = (DWORD)_except_handler;

    __asm
    {                           // Build EXCEPTION_REGISTRATION record:
        push    handler         // Address of handler function
        push    FS:[0]          // Address of previous handler
        mov     FS:[0],ESP      // Install new EXECEPTION_REGISTRATION
    }

    __asm
    {
        mov     eax,0           // Zero out EAX
        mov     [eax], 1        // Write to EAX to deliberately cause a fault
    }

    printf( "After writing!\n" );

    __asm
    {                           // Remove our EXECEPTION_REGISTRATION record
        mov     eax,[ESP]       // Get pointer to previous record.
        mov     FS:[0], EAX     // Install previous record
        add     esp, 8          // Clean our EXECEPTION_REGISTRATION off stack
    }

    return 0;
}

在用“cl”编译它时,它似乎生成了一个可执行文件,但也会抛出以下错误:

myseh.cpp(42) : warning C4733: Inline asm assigning to 'FS:0': handler not registered as safe handler
myseh.cpp(56) : warning C4733: Inline asm assigning to 'FS:0': handler not registered as safe handler

可执行文件崩溃了,自定义异常处理程序似乎没有正常工作。 在互联网上搜索似乎表明我需要将我的自定义异常处理程序函数注册为安全异常处理程序。我不是专业的开发人员。但是我还是想关注这篇文章。我需要一些关于如何获得工作可执行文件的指导。

我在 Windows 10 上使用 Visual Studio 2015。

最佳答案

来自 C4733 的描述警告:

Inline asm assigning to 'FS:0' : handler not registered as safe handler

A function modifying the value at FS:0 to add a new exception handler may not work with Safe Exceptions, because the handler may not be registered as a valid exception handler (see /SAFESEH).

To resolve this warning, either remove the FS:0 definition or turn off this warning and use .SAFESEH to specify the safe exception handlers.

这基本上意味着您正在尝试使用不会在生成的可执行镜像中注册为安全 SEH 处理程序的处理程序。
根据您的链接器设置,它可能会执行也可能不会执行。

默认情况下,链接器会生成安全处理程序表,但它不知道您的_except_handler 是异常处理程序,因此它不会将其放入安全 SEH 处理程序。要解决它,您基本上有两种选择:

  • 使用 .safeseh MASM 指令将您的函数标记为安全处理程序。
    您必须将其放入单独的 ASM 文件中,因为内联汇编不支持这些指令。

  • 使用/SAFESEH:NO 开关指示链接器不创建安全处理程序表。
    这样,您的可执行文件中的任何 SEH 处理程序都将被操作系统视为安全处理程序。

我建议查看 /SAFESEH链接器开关和 .safeseh MASM 指令文档以获取更多信息。

有关安全 SEH 处理程序的更多信息可以在此 article 中找到:

The general idea is to collect handlers' entry points in a designated read-only table and have each entry point verified against this table for exceptions prior to control being passed to the handler.

关于c++ - 内联 asm 分配给 'FS:0' : handler not registered as safe handler,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37298061/

相关文章:

c++ - 我是否需要将类型设为 POD 才能将其与内存映射文件一起保存?

c++ - 函数main(int argc, char *argv[])中的参数argv

c++ - 用于 Visual Studio 6 代码兼容性的 Visual Studio 2015

unit-testing - 如何使用VS2015 Preview运行xUnit单元测试?

c++ - 基于参数的模板内部类

c++ - 指针(*)和引用(&)的区别

c++ - 在 VC 2015 上使用带有字符串的宏失败

c - 'asm' 、 '__asm' 和 '__asm__' 之间有什么区别?

c - Linux 内核模块中 x87 内联汇编中的操作数类型不匹配

c++ - 我怎样才能使用我的CPU的MM0到MM7寄存器?