Changeset 21474


Ignore:
Timestamp:
Nov 14, 2010, 12:41:50 AM (15 years ago)
Author:
dmik
Message:

kernel32/SEH: Added support for setjmp()/longjmp() within the try block. See #26.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/excpt.h

    r21448 r21474  
    1313 * crash the application):
    1414 *
    15  * 1. You cannot use return, goto and longjmp statements within __try or
    16  *    __except or __finally blocks.
     15 * 1. You cannot use the return statement within __try or __except or __finally
     16 *    blocks.
     17 *
     18 * 2. You cannot use the goto statement or the longjmp() function within __try
     19 *    or __except or __finally blocks if it passes control outside these blocks.
    1720 *
    1821 * 2. If you use __try and friends inside a do/while/for/switch block, you will
     
    3942#if defined(__GNUC__)
    4043
    41 struct ___seh_PEXCEPTION_FRAME;
     44struct ___seh_EXCEPTION_FRAME;
    4245typedef int (*__seh_PEXCEPTION_HANDLER)(PEXCEPTION_RECORD,
    43                                         struct ___seh_PEXCEPTION_FRAME *,
     46                                        struct ___seh_EXCEPTION_FRAME *,
    4447                                        PCONTEXT, PVOID);
    4548
    46 typedef struct ___seh_PEXCEPTION_FRAME
     49#pragma pack(1)
     50
     51typedef struct ___seh_EXCEPTION_FRAME
    4752{
    48     struct ___seh_PEXCEPTION_FRAME *pPrev;
    49     __seh_PEXCEPTION_HANDLER pHandler;
    50     void *pFilterCallback;
    51     void *pHandlerCallback;
    52     void *pHandlerContext;
    53     int filterResult;
    54     DWORD pTryRegs[6]; /* EBX/ESI/EDI/EBP/ESP/ExceptionHandler */
    55     EXCEPTION_POINTERS Pointers;
    56     int state;
     53    /* + 0 */ struct ___seh_EXCEPTION_FRAME *pPrev;
     54    /* + 4 */ __seh_PEXCEPTION_HANDLER pHandler;
     55    /* + 8 */ void *pFilterCallback;
     56    /* +12 */ void *pHandlerCallback;
     57    /* +16 */ void *pHandlerContext;
     58    /* +20 */ int filterResult;
     59    /* +24 */ DWORD EBX;
     60    /* +28 */ DWORD ESI;
     61    /* +32 */ DWORD EDI;
     62    /* +36 */ DWORD EBP;
     63    /* +40 */ DWORD ESP;
     64    /* +44 */ DWORD pPrevFrameOS2;
     65    /* +48 */ EXCEPTION_POINTERS Pointers;
     66    /* +56 */ int state;
     67    /* +60 */ DWORD pPrevFrameWin32;
    5768}
    58 __seh_PEXCEPTION_FRAME;
     69__seh_EXCEPTION_FRAME;
    5970
    60 int __seh_handler(PEXCEPTION_RECORD pRec,
    61                   struct ___seh_PEXCEPTION_FRAME *pFrame,
    62                   PCONTEXT pContext, PVOID pVoid);
     71#pragma pack()
     72
     73extern int __seh_handler(PEXCEPTION_RECORD pRec,
     74                         struct ___seh_EXCEPTION_FRAME *pFrame,
     75                         PCONTEXT pContext, PVOID pVoid);
    6376
    6477#define _exception_code() (__seh_frame.Pointers.ExceptionRecord->ExceptionCode)
    65 #define _exception_info() (&__seh_frame.Pointers)
     78#define _exception_info() ((void *)&__seh_frame.Pointers)
     79
     80#define exception_code _exception_code
     81#define exception_info (PEXCEPTION_POINTERS)_exception_info
    6682
    6783#define GetExceptionCode _exception_code
    68 #define GetExceptionInformation _exception_info
     84#define GetExceptionInformation (PEXCEPTION_POINTERS)_exception_info
    6985
    7086#define __try \
    71     volatile __seh_PEXCEPTION_FRAME __seh_frame;                               \
     87    volatile __seh_EXCEPTION_FRAME __seh_frame;                                \
     88    __seh_frame.pHandler = __seh_handler;                                      \
    7289    __seh_frame.Pointers.ExceptionRecord = NULL;                               \
    7390    __seh_frame.Pointers.ContextRecord = NULL;                                 \
     
    7794        if (__seh_frame.state == 0)                                            \
    7895        {                                                                      \
    79             /* install exception handler */                                    \
    80             __asm__ ("\n.extern ___seh_handler\n"                              \
    81                      ""                                                        \
    82                      "leal %0, %%ecx; "                                        \
     96            /* install exception handler (both Win32 and OS/2 chains) */       \
     97            __asm__ ("leal %0, %%ecx; "                                        \
    8398                     "movl %%fs:0, %%eax; "                                    \
    8499                     "movl %%eax, 0(%%ecx); "                                  \
    85                      "movl $___seh_handler, %%eax; "                           \
    86                      "movl %%eax, 4(%%ecx); "                                  \
     100                     "movl %%eax, 60(%%ecx); "                                 \
    87101                     "movl $0b, 8(%%ecx); "                                    \
    88102                     ""                                                        \
     
    98112                     "movl %%fs:0, %%eax; "                                    \
    99113                     "movl %%eax, 44(%%ecx); "                                 \
     114                     "movl %%ecx, %%fs:0; "                                    \
    100115                     "popl %%fs; "                                             \
    101116                     ""                                                        \
     
    119134        else if (__seh_frame.state == 3)                                       \
    120135            /* remove exception handler */                                     \
    121             __asm__ ("movl %%fs:0, %%eax; "                                    \
    122                      "movl 0(%%eax), %%eax; "                                  \
     136            __asm__ ("movl %%fs:0, %%ecx; "                                    \
     137                     "movl 60(%%ecx), %%eax; "                                 \
    123138                     "movl %%eax, %%fs:0; "                                    \
     139                     ""                                                        \
     140                     "pushl %%fs; "                                            \
     141                     "pushl $Dos32TIB; "                                       \
     142                     "popl %%fs; "                                             \
     143                     "movl 44(%%ecx), %%eax; "                                 \
     144                     "movl %%eax, %%fs:0; "                                    \
     145                     "popl %%fs; "                                             \
    124146                     : :                                                       \
    125                      : "%eax");                                                \
     147                     : "%eax", "%ecx");                                        \
    126148        else /* __seh_frame.state == 2 -> execute except block */
    127149
     
    140162        else if (__seh_frame.state == 3)                                       \
    141163            /* remove exception handler */                                     \
    142             __asm__ ("movl %%fs:0, %%eax; "                                    \
    143                      "movl 0(%%eax), %%eax; "                                  \
     164            __asm__ ("movl %%fs:0, %%ecx; "                                    \
     165                     "movl 60(%%ecx), %%eax; "                                 \
    144166                     "movl %%eax, %%fs:0; "                                    \
     167                     ""                                                        \
     168                     "pushl %%fs; "                                            \
     169                     "pushl $Dos32TIB; "                                       \
     170                     "popl %%fs; "                                             \
     171                     "movl 44(%%ecx), %%eax; "                                 \
     172                     "movl %%eax, %%fs:0; "                                    \
     173                     "popl %%fs; "                                             \
    145174                     : :                                                       \
    146                      : "%eax");                                                \
     175                     : "%eax", "%ecx");                                        \
    147176        else /* __seh_frame.state == 2 -> execute finally block */
    148177
  • trunk/src/kernel32/seh/sehutil.s

    r21431 r21474  
    1111/*
    1212 * int __seh_handler(PEXCEPTION_RECORD pRec,
    13  *                   struct ___seh_PEXCEPTION_FRAME *pFrame,
     13 *                   struct ___seh_EXCEPTION_FRAME *pFrame,
    1414 *                   PCONTEXT pContext, PVOID)
    1515 *
     
    1818 *
    1919 * NOTE: This is a heavily platform specific stuff. The code depends on the
    20  * struct ___seh_PEXCEPTION_FRAME layout so be very careful and keep both
     20 * struct ___seh_EXCEPTION_FRAME layout so be very careful and keep both
    2121 * in sync!
    2222 *
     
    3333     * 12(%ebp) - pFrame
    3434     * 16(%ebp) - pContext
    35      * 20(%ebp) - pVOid
     35     * 20(%ebp) - pVoid
    3636     */
    3737
     
    4040    pushl %edi
    4141    pushl %esi
     42
     43    pushl %fs
     44    popl %eax
     45    andl $0x0000FFFF, %eax
     46    cmpl $Dos32TIB, %eax /* Running along the OS/2 chain? */
     47    jne ___seh_handler_Win32 /* No, assume the Win32 chain */
     48
     49    movl 8(%ebp), %eax
     50    movl 0(%eax), %eax
     51    cmpl $0xC0000026, %eax  /* XCPT_UNWIND? */
     52    je ___seh_handler_OS2_Unwind
     53
     54    /* restore the OS/2 chain in our frame */
     55    movl 12(%ebp), %eax
     56    movl 44(%eax), %ecx /* pPrevFrameOS2 */
     57    movl %ecx, 0(%eax)  /* pPrev */
     58
     59    xorl %eax, %eax  /* return XCPT_CONTINUE_SEARCH (0) */
     60    jmp ___seh_handler_Return
     61
     62___seh_handler_OS2_Unwind:
     63
     64    /* restore the Win32 chain in our frame */
     65    movl 12(%ebp), %eax
     66    movl 60(%eax), %ecx /* pPrevFrameWin32 */
     67    movl %ecx, 0(%eax)  /* pPrev */
     68
     69    /* unwind the Win32 chain including our frame as someone's definitely
     70     * jumping outside it if we're being unwound */
     71    pushl %fs
     72    pushl $1
     73    call _SetWin32TIB@4 /* _stdcall, rtl, callee cleans stack */
     74    pushl $0        /* DWORD (unused) */
     75    pushl $0        /* PEXCEPTION_RECORD */
     76    pushl $0        /* LPVOID (unused) */
     77    pushl %ecx      /* PEXCEPTION_FRAME */
     78    call _RtlUnwind@16 /* _stdcall, rtl, callee cleans stack */
     79    popl %fs
     80
     81    /* restore the OS/2 chain in our frame */
     82    movl 12(%ebp), %eax
     83    movl 44(%eax), %ecx /* pPrevFrameOS2 */
     84    movl %ecx, 0(%eax)  /* pPrev */
     85
     86    xor %eax, %eax  /* return code is irrelevant for XCPT_UNWIND */
     87    jmp ___seh_handler_Return
     88
     89___seh_handler_Win32:
     90
     91    /* restore the Win32 chain in our frame */
     92    movl 12(%ebp), %eax
     93    movl 60(%eax), %ecx /* pPrevFrameWin32 */
     94    movl %ecx, 0(%eax)  /* pPrev */
    4295
    4396    /* skip EH_UNWINDING calls (for compatibility with MSVC) */
     
    140193    jmp ___seh_handler_Return
    1411941:
    142     /* Assume EXCEPTION_CONTINUE_SEARCH (0) */
     195    /* assume EXCEPTION_CONTINUE_SEARCH (0) */
    143196    movl $1, %eax /* ExceptionContinueSearch */
    144197    jmp ___seh_handler_Return
     
    146199___seh_handler_Unwind:
    147200
    148     /* Unwind Win32 exception chain up to ours */
     201    /* unwind Win32 exception chain up to ours */
    149202    pushl $0        /* DWORD (unused) */
    150203    pushl 8(%ebp)   /* PEXCEPTION_RECORD */
     
    153206    call _RtlUnwind@16 /* _stdcall, rtl, callee cleans stack */
    154207
    155     /* Unwind OS/2 exception chain */
    156     movl 12(%ebp), %eax
     208    /* restore the OS/2 chain in our frame */
     209    movl 12(%ebp), %eax
     210    movl 44(%eax), %ecx /* pPrevFrameOS2 */
     211    movl %ecx, 0(%eax)  /* pPrev */
     212
     213    /* unwind OS/2 exception chain up to ours */
     214    pushl %fs
     215    pushl $Dos32TIB
     216    popl %fs
    157217    pushl $0        /* PEXCEPTIONREPORTRECORD */
    158218    pushl $1f       /* PVOID pTargetIP */
    159     pushl 44(%eax)  /* PEXCEPTIONREGISTRATIONRECORD */
     219    pushl 12(%ebp)  /* PEXCEPTIONREGISTRATIONRECORD */
    160220    call _DosUnwindException /* _syscall, rtl, caller cleans stack */
    1612211:
    162222    addl $12, %esp
     223    popl %fs
     224
     225    /* restore the Win32 chain in our frame */
     226    movl 12(%ebp), %eax
     227    movl 60(%eax), %ecx /* pPrevFrameWin32 */
     228    movl %ecx, 0(%eax)  /* pPrev */
    163229
    164230    /* restore __try/__except context */
Note: See TracChangeset for help on using the changeset viewer.