Ignore:
Timestamp:
Apr 15, 2011, 2:47:32 AM (14 years ago)
Author:
dmik
Message:

kernel32/SEH: Fixed a couple of bugs in SEH processing that could cause a bunch of various crashes when unwinding the Win32 exception chain (usually at process termination, as a result of both a fatal exception or a clean exit).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kernel32/seh/sehutil.s

    r21612 r21618  
    88
    99.global ___seh_handler
     10.global ___seh_get_prev_frame
    1011
    1112/*
     13 * extern "C"
    1214 * int __seh_handler(PEXCEPTION_RECORD pRec,
    1315 *                   struct ___seh_EXCEPTION_FRAME *pFrame,
     
    2426 * the stack.
    2527 */
     28
    2629___seh_handler:
    2730
     
    7073     * jumping outside it if we're being unwound */
    7174    pushl %fs
     75
    7276    pushl $1
    7377    call _SetWin32TIB@4 /* _stdcall, rtl, callee cleans stack */
     78
     79    /* check if we could successfully switch to Win32 FS. A failure means the
     80     * Win32 thread is about to exit and TIB has been already destroyed. */
     81    movl (%esp), %ecx   /* (%esp) is OS/2 FS pushed above */
     82    andl $0x0000FFFF, %ecx
     83    cmpl %ecx, %eax
     84    je ___seh_handler_Skip_Win32_Unwind
     85
    7486    pushl $0        /* DWORD (unused) */
    7587    pushl $0        /* PEXCEPTION_RECORD */
     
    7789    pushl %ebx      /* PEXCEPTION_FRAME */
    7890    call _RtlUnwind@16 /* _stdcall, rtl, callee cleans stack */
     91
     92___seh_handler_Skip_Win32_Unwind:
    7993    popl %fs
    8094
     
    212226
    213227    /* unwind OS/2 exception chain up to ours */
    214     pushl %fs
     228    movl %fs, %ebx
    215229    pushl $Dos32TIB
    216230    popl %fs
     
    218232    pushl $1f       /* PVOID pTargetIP */
    219233    pushl 12(%ebp)  /* PEXCEPTIONREGISTRATIONRECORD */
    220     call _DosUnwindException /* _syscall, rtl, caller cleans stack */
     234    call _DosUnwindException /* _syscall, rtl, but stack is not restored! */
    2212351:
    222     addl $12, %esp
    223     popl %fs
     236    movl %ebx, %fs
    224237
    225238    /* restore the Win32 chain in our frame */
     
    256269    ret
    257270
     271/*
     272 * extern "C"
     273 * EXCEPTION_FRAME *__seh_get_prev_frame(EXCEPTION_FRAME *pFrame)
     274 *
     275 * Returns the previous Win32 exception frame given an existing frame.
     276 *
     277 * If SEH is used, the pFrame->Prev expression will not always return a correct
     278 * result: the SEH handler is installed on both the Win32 and OS/2 exception
     279 * chains and it dynamically substitutes the Prev field in its frame with the
     280 * Win32 or OS/2 tail depending on the source of the exception. This function
     281 * takes this into account and always returns the correct pointer to the
     282 * previous Win32 frame.
     283 *
     284 * NOTE: This is a heavily platform specific stuff. The code depends on the
     285 * struct ___seh_EXCEPTION_FRAME layout so be very careful and keep both
     286 * in sync!
     287 *
     288 * __cdecl: EAX/ECX/EDX are not preserved, result in EAX/EDX, caller cleans up
     289 * the stack.
     290 */
     291
     292___seh_get_prev_frame:
     293
     294    /*
     295     * 4(%esp) - pFrame
     296     */
     297
     298    movl 4(%esp), %eax
     299    /*leal ___seh_handler, %ecx*/
     300    movl 4(%eax), %ecx /* pFrame->Handler */
     301    cmpl $___seh_handler, %ecx
     302    jne ___seh_get_prev_frame_Normal
     303
     304    movl 60(%eax), %eax /* pPrevFrameWin32 */
     305    ret
     306
     307___seh_get_prev_frame_Normal:
     308
     309    movl 0(%eax), %eax /* pFrame->Prev */
     310    ret
     311
Note: See TracChangeset for help on using the changeset viewer.