15.2. win32: Safe Structured Exception Handling

Among other improvements in Windows XP SP2 and Windows Server 2003 Microsoft introduced the concept of "safe structured exception handling." 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. In order for an executable to be created with a safe exception handler table, each object file on the linker command line must contain a special symbol named @feat.00. If any object file passed to the linker does not have this symbol, then the exception handler table is omitted from the executable and thus the run-time checks will not be performed for the application. By default, the table is omitted from the executable silently if this happens and therefore can be easily overlooked. A user can instruct the linker to refuse to produce an executable without this table by passing the /safeseh command line option.

As of version 1.1.0, Yasm adds this special symbol to win32 object files so its output does not fail to link with /safeseh.

Yasm also has directives to support registering custom exception handlers. The safeseh directive instructs the assembler to produce appropriately formatted input data for the safe exception handler table. A typical use case is given in Example 15.1.

Example 15.1. Win32 safeseh Example

section .text
extern  _MessageBoxA@16
safeseh handler         ; register handler as "safe handler"
handler:
        push    DWORD 1 ; MB_OKCANCEL
        push    DWORD caption
        push    DWORD text
        push    DWORD 0
        call    _MessageBoxA@16
        sub     eax,1   ; incidentally suits as return value
                        ; for exception handler
        ret
global  _main
_main:
        push    DWORD handler
        push    DWORD [fs:0]
        mov     DWORD [fs:0],esp ; engage exception handler
        xor     eax,eax
        mov     eax,DWORD[eax]   ; cause exception
        pop     DWORD [fs:0]     ; disengage exception handler
        add     esp,4
        ret
text:   db      'OK to rethrow, CANCEL to generate core dump',0
caption:db      'SEGV',0

section .drectve info
        db      '/defaultlib:user32.lib /defaultlib:msvcrt.lib '

If an application has a safe exception handler table, attempting to execute any unregistered exception handler will result in immediate program termination. Thus it is important to register each exception handler’s entry point with the safeseh directive.

All mentions of linker in this section refer to the Microsoft linker version 7.x and later. The presence of the @feat.00 symbol and the data for the safe exception handler table cause no backward incompatibilities and thus "safeseh" object files generated can still be linked by earlier linker versions or by non-Microsoft linkers.