Author: tkreuzer
Date: Tue Jan 25 16:26:54 2011
New Revision: 50486

URL: http://svn.reactos.org/svn/reactos?rev=50486&view=rev
Log:
[CMAKE]
On MSVC builds, compile native SEH support into PSEH library.
This should be part of the crt, but our crt is too disorganized to handle that. 
The empty C file is for cmake to get the library right.

Added:
    branches/cmake-bringup/lib/pseh/dummy.c   (with props)
    branches/cmake-bringup/lib/pseh/i386/seh.s   (with props)
    branches/cmake-bringup/lib/pseh/i386/seh_prolog.s   (with props)
Modified:
    branches/cmake-bringup/lib/pseh/CMakeLists.txt

Modified: branches/cmake-bringup/lib/pseh/CMakeLists.txt
URL: 
http://svn.reactos.org/svn/reactos/branches/cmake-bringup/lib/pseh/CMakeLists.txt?rev=50486&r1=50485&r2=50486&view=diff
==============================================================================
--- branches/cmake-bringup/lib/pseh/CMakeLists.txt [iso-8859-1] (original)
+++ branches/cmake-bringup/lib/pseh/CMakeLists.txt [iso-8859-1] Tue Jan 25 
16:26:54 2011
@@ -16,4 +16,14 @@
     add_library(pseh ${SOURCE})
     add_dependencies(pseh psdk)
 
+else()
+
+    list(APPEND SOURCE
+        dummy.c
+        i386/seh.s
+        i386/seh_prolog.s)
+
+    add_library(pseh ${SOURCE})
+    add_dependencies(pseh asm)
+
 endif()

Added: branches/cmake-bringup/lib/pseh/dummy.c
URL: 
http://svn.reactos.org/svn/reactos/branches/cmake-bringup/lib/pseh/dummy.c?rev=50486&view=auto
==============================================================================
--- branches/cmake-bringup/lib/pseh/dummy.c (added)
+++ branches/cmake-bringup/lib/pseh/dummy.c [iso-8859-1] Tue Jan 25 16:26:54 
2011
@@ -1,0 +1,2 @@
+ /* intentionally empty file */
+

Propchange: branches/cmake-bringup/lib/pseh/dummy.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: branches/cmake-bringup/lib/pseh/i386/seh.s
URL: 
http://svn.reactos.org/svn/reactos/branches/cmake-bringup/lib/pseh/i386/seh.s?rev=50486&view=auto
==============================================================================
--- branches/cmake-bringup/lib/pseh/i386/seh.s (added)
+++ branches/cmake-bringup/lib/pseh/i386/seh.s [iso-8859-1] Tue Jan 25 16:26:54 
2011
@@ -1,0 +1,441 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS CRT
+ * FILE:            lib/crt/misc/i386/seh.S
+ * PURPOSE:         SEH Support for the CRT
+ * PROGRAMMERS:     Alex Ionescu ([email protected])
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <asm.inc>
+
+#define DISPOSITION_DISMISS         0
+#define DISPOSITION_CONTINUE_SEARCH 1
+#define DISPOSITION_COLLIDED_UNWIND 3
+
+#define EXCEPTION_EXIT_UNWIND 4
+#define EXCEPTION_UNWINDING 2
+
+
+EXTERN _RtlUnwind@16:PROC
+
+/* GLOBALS *******************************************************************/
+
+PUBLIC __global_unwind2
+PUBLIC __local_unwind2
+PUBLIC __abnormal_termination
+PUBLIC __except_handler2
+PUBLIC __except_handler3
+
+/* FUNCTIONS *****************************************************************/
+
+.code
+_unwind_handler:
+
+    /* Check if we were unwinding and continue search if not */
+    mov ecx, [esp+4]
+    test dword ptr [ecx+4], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
+    mov eax, DISPOSITION_CONTINUE_SEARCH
+    jz unwind_handler_return
+
+    /* We have a collision, do a local unwind */
+    mov eax, [esp+20]
+    push ebp
+    mov ebp, [eax+16]
+    mov edx, [eax+40]
+    push edx
+    mov edx, [eax+36]
+    push edx
+    call __local_unwind2
+    add esp, 8
+    pop ebp
+
+    /* Set new try level */
+    mov eax, [esp+8]
+    mov edx, [esp+16]
+    mov [edx], eax
+
+    /* Return collided unwind */
+    mov eax, DISPOSITION_COLLIDED_UNWIND
+
+unwind_handler_return:
+    ret
+
+
+__global_unwind2:
+
+    /* Create stack and save all registers */
+    push ebp
+    mov ebp, esp
+    push ebx
+    push esi
+    push edi
+    push ebp
+
+    /* Call unwind */
+    push 0
+    push 0
+    push glu_return
+    push [ebp+8]
+    call _RtlUnwind@16
+
+glu_return:
+    /* Restore registers and return */
+    pop ebp
+    pop edi
+    pop esi
+    pop ebx
+    mov esp, ebp
+    pop ebp
+    ret
+
+
+__abnormal_termination:
+
+    /* Assume false */
+    xor eax, eax
+
+    /* Check if the handler is the unwind handler */
+    mov ecx, fs:0
+    cmp dword ptr [ecx+4], offset _unwind_handler
+    jne short ab_return
+
+    /* Get the try level */
+    mov edx, [ecx+12]
+    mov edx, [edx+12]
+
+    /* Compare it */
+    cmp [ecx+8], edx
+    jne ab_return
+
+    /* Return true */
+    mov eax, 1
+
+    /* Return */
+ab_return:
+    ret
+
+
+__local_unwind2:
+
+    /* Save volatiles */
+    push ebx
+    push esi
+    push edi
+
+    /* Get the exception registration */
+    mov eax, [esp+16]
+
+    /* Setup SEH to protect the unwind */
+    push ebp
+    push eax
+    push -2
+    push offset _unwind_handler
+    push fs:0
+    mov fs:0, esp
+
+unwind_loop:
+    /* Get the exception registration and try level */
+    mov eax, [esp+36]
+    mov ebx, [eax+8]
+    mov esi, [eax+12]
+
+    /* Validate the unwind */
+    cmp esi, -1
+    je unwind_return
+    cmp dword ptr [esp+40], -1
+    je unwind_ok
+    cmp esi, [esp+40]
+    jbe unwind_return
+
+unwind_ok:
+    /* Get the new enclosing level and save it */
+    lea esi, [esi+esi*2]
+    mov ecx, [ebx+esi*4]
+    mov [esp+8], ecx
+    mov [eax+12], ecx
+
+    /* Check the filter type */
+    cmp dword ptr [ebx+esi*4+4], 0
+    jnz __NLG_Return2
+
+    /* FIXME: NLG Notification */
+
+    /* Call the handler */
+    call dword ptr [ebx+esi*4+8]
+
+__NLG_Return2:
+    /* Unwind again */
+    jmp unwind_loop
+
+unwind_return:
+    /* Cleanup SEH */
+    pop fs:0
+    add esp, 16
+    pop edi
+    pop esi
+    pop ebx
+    ret
+
+
+__except_handler2:
+
+    /* Setup stack and save volatiles */
+    push ebp
+    mov ebp, esp
+    sub esp, 8
+    push ebx
+    push esi
+    push edi
+    push ebp
+
+    /* Clear direction flag */
+    cld
+
+    /* Get exception registration and record */
+    mov ebx, [ebp+12]
+    mov eax, [ebp+8]
+
+    /* Check if this is an unwind */
+    test dword ptr [eax+4], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
+    jnz except_unwind2
+
+    /* Save exception pointers structure */
+    mov [ebp-8], eax
+    mov eax, [ebp+16]
+    mov [ebp-4], eax
+    lea eax, [ebp-8]
+    mov [ebx+20], eax
+
+    /* Get the try level and scope table */
+    mov esi, [ebx+12]
+    mov edi, [ebx+8]
+
+except_loop2:
+    /* Validate try level */
+    cmp esi, -1
+    je except_search2
+
+    /* Check if this is the termination handler */
+    lea ecx, [esi+esi*2]
+    cmp dword ptr [edi+ecx*4+4], 0
+    jz except_continue2
+
+    /* Save registers and call filter, then restore them */
+    push esi
+    push ebp
+    mov ebp, [ebx+16]
+    call dword ptr [edi+ecx*4+4]
+    pop ebp
+    pop esi
+
+    /* Restore ebx and check the result */
+    mov ebx, [ebp+12]
+    or eax, eax
+    jz except_continue2
+    js except_dismiss2
+
+    /* So this is an accept, call the termination handlers */
+    mov edi, [ebx+8]
+    push ebx
+    call __global_unwind2
+    add esp, 4
+
+    /* Restore ebp */
+    mov ebp, [ebx+16]
+
+    /* Do local unwind */
+    push esi
+    push ebx
+    call __local_unwind2
+    add esp, 8
+
+    /* Set new try level */
+    lea ecx, [esi+esi*2]
+    mov eax, [edi+ecx*4]
+    mov [ebx+12], eax
+
+    /* Call except handler */
+    call dword ptr [edi+ecx*4+8]
+
+except_continue2:
+    /* Reload try level and except again */
+    mov edi, [ebx+8]
+    lea ecx, [esi+esi*2]
+    mov esi, [edi+ecx*4]
+    jmp except_loop2
+
+except_dismiss2:
+    /* Dismiss it */
+    mov eax, DISPOSITION_DISMISS
+    jmp except_return2
+
+except_search2:
+    /* Continue searching */
+    mov eax, DISPOSITION_CONTINUE_SEARCH
+    jmp except_return2
+
+    /* Do local unwind */
+except_unwind2:
+    push ebp
+    mov ebp, [ebx+16]
+    push -1
+    push ebx
+    call __local_unwind2
+    add esp, 8
+
+    /* Retore EBP and set return disposition */
+    pop ebp
+    mov eax, DISPOSITION_CONTINUE_SEARCH
+
+except_return2:
+    /* Restore registers and stack */
+    pop ebp
+    pop edi
+    pop esi
+    pop ebx
+    mov esp, ebp
+    pop ebp
+    ret
+
+
+__except_handler3:
+
+    /* Setup stack and save volatiles */
+    push ebp
+    mov ebp, esp
+    sub esp, 8
+    push ebx
+    push esi
+    push edi
+    push ebp
+
+    /* Clear direction flag */
+    cld
+
+    /* Get exception registration and record */
+    mov ebx, [ebp+12]
+    mov eax, [ebp+8]
+
+    /* Check if this is an unwind */
+    test dword ptr [eax+4], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
+    jnz except_unwind3
+
+    /* Save exception pointers structure */
+    mov [ebp-8], eax
+    mov eax, [ebp+16]
+    mov [ebp-4], eax
+    lea eax, [ebp-8]
+    mov [ebx-4], eax
+
+    /* Get the try level and scope table */
+    mov esi, [ebx+12]
+    mov edi, [ebx+8]
+
+    /* FIXME: Validate the SEH exception */
+
+except_loop3:
+    /* Validate try level */
+    cmp esi, -1
+    je except_search3
+
+    /* Check if this is the termination handler */
+    lea ecx, [esi+esi*2]
+    mov eax, [edi+ecx*4+4]
+    or eax, eax
+    jz except_continue3
+
+    /* Save registers clear them all */
+    push esi
+    push ebp
+    lea ebp, [ebx+16]
+    xor ebx, ebx
+    xor ecx, ecx
+    xor edx, edx
+    xor esi, esi
+    xor edi, edi
+
+    /* Call the filter and restore our registers */
+    call eax
+    pop ebp
+    pop esi
+
+    /* Restore ebx and check the result */
+    mov ebx, [ebp+12]
+    or eax, eax
+    jz except_continue3
+    js except_dismiss3
+
+    /* So this is an accept, call the termination handlers */
+    mov edi, [ebx+8]
+    push ebx
+    call __global_unwind2
+    add esp, 4
+
+    /* Restore ebp */
+    lea ebp, [ebx+16]
+
+    /* Do local unwind */
+    push esi
+    push ebx
+    call __local_unwind2
+    add esp, 8
+
+    /* FIXME: Do NLG Notification */
+
+    /* Set new try level */
+    lea ecx, [esi+esi*2]
+    mov eax, [edi+ecx*4]
+    mov [ebx+12], eax
+
+    /* Clear registers and call except handler */
+    mov eax, [edi+ecx*4+8]
+    xor ebx, ebx
+    xor ecx, ecx
+    xor edx, edx
+    xor esi, esi
+    xor edi, edi
+    call eax
+
+except_continue3:
+    /* Reload try level and except again */
+    mov edi, [ebx+8]
+    lea ecx, [esi+esi*2]
+    mov esi, [edi+ecx*4]
+    jmp except_loop3
+
+except_dismiss3:
+    /* Dismiss it */
+    mov eax, DISPOSITION_DISMISS
+    jmp except_return3
+
+except_search3:
+    /* Continue searching */
+    mov eax, DISPOSITION_CONTINUE_SEARCH
+    jmp except_return3
+
+    /* Do local unwind */
+except_unwind3:
+    push ebp
+    mov ebp, [ebx+16]
+    push -1
+    push ebx
+    call __local_unwind2
+    add esp, 8
+
+    /* Retore EBP and set return disposition */
+    pop ebp
+    mov eax, DISPOSITION_CONTINUE_SEARCH
+
+except_return3:
+    /* Restore registers and stack */
+    pop ebp
+    pop edi
+    pop esi
+    pop ebx
+    mov esp, ebp
+    pop ebp
+    ret
+
+END

Propchange: branches/cmake-bringup/lib/pseh/i386/seh.s
------------------------------------------------------------------------------
    svn:eol-style = native

Added: branches/cmake-bringup/lib/pseh/i386/seh_prolog.s
URL: 
http://svn.reactos.org/svn/reactos/branches/cmake-bringup/lib/pseh/i386/seh_prolog.s?rev=50486&view=auto
==============================================================================
--- branches/cmake-bringup/lib/pseh/i386/seh_prolog.s (added)
+++ branches/cmake-bringup/lib/pseh/i386/seh_prolog.s [iso-8859-1] Tue Jan 25 
16:26:54 2011
@@ -1,0 +1,152 @@
+/*
+ * COPYRIGHT:       GNU GPL, see COPYING in the top level directory
+ * PROJECT:         ReactOS CRT
+ * FILE:            lib/crt/misc/i386/seh_prolog.S
+ * PURPOSE:         SEH Support for MSVC
+ * PROGRAMMERS:     Timo Kreuzer
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <asm.inc>
+
+EXTERN __except_handler3:PROC
+
+/* The very first thing a function compiled with MSVC containing SEH
+ * will do is call __SEH_prolog like this:
+ *
+ *  push <Number of stackbytes>
+ *  push <Address of exception handler>
+ *  call __SEH_prolog
+ *
+ * When entering the function the stack layout is like this:
+ *
+ *  esp + 08: OLDFRAME.StackBytes
+ *  esp + 04: OLDFRAME.SEHTable
+ *  esp + 00: OLDFRAME.ReturnAddress
+ *
+ * __SEH_prolog will now setup the stack to the following layout:
+ *
+ *  esp + N + 24: SEH_FRAME.OriginalEbp       OLDFRAME.StackBytes
+ *  esp + N + 20: SEH_FRAME.Disable           OLDFRAME.SEHTable
+ *  esp + N + 1C: SEH_FRAME.SEHTable          OLDFRAME.ReturnAddress
+ *  esp + N + 18: SEH_FRAME.Handler
+ *  esp + N + 14: SEH_FRAME.PreviousRecord
+ *  esp + N + 10: SEH_FRAME.unused
+ *  esp + N + 0c: SEH_FRAME.NewEsp
+ *
+ *           N bytes local variables
+ *  ...
+ *  esp +     08: SAFE_AREA.Ebx
+ *  esp +     04: SAFE_AREA.Esi
+ *  esp +     00: SAFE_AREA.Edi
+ *
+ * all this is documented here (with some minor errors):
+ * 
http://reactos-blog.blogspot.com/2009/08/inside-mind-of-reactos-developer.html
+ */
+
+OLDFRAME_ReturnAddress   =  0 /* 0x00 */
+OLDFRAME_SEHTable        =  4 /* 0x04 */
+OLDFRAME_StackBytes      =  8 /* 0x08 */
+OLDFRAME_Size            = 12 /* 0x0c */
+
+SEH_FRAME_NewEsp         =  0 /* 0x00 */
+SEH_FRAME_unused         =  4 /* 0x04 */
+SEH_FRAME_PreviousRecord =  8 /* 0x08 */
+SEH_FRAME_Handler        = 12 /* 0x0c */
+SEH_FRAME_SEHTable       = 16 /* 0x10 */
+SEH_FRAME_Disable        = 20 /* 0x14 */
+SEH_FRAME_OriginalEbp    = 24 /* 0x18 */
+SEH_FRAME_Size           = 28 /* 0x1c */
+
+SAFE_AREA_Edi            =  0 /* 0x00 */
+SAFE_AREA_Esi            =  4 /* 0x04 */
+SAFE_AREA_Ebx            =  8 /* 0x08 */
+SAFE_AREA_Size           = 12 /* 0x0c */
+
+
+.code
+
+PUBLIC __SEH_prolog
+__SEH_prolog:
+
+    /* Get the number of stack bytes to reserve */
+    mov eax, [esp + OLDFRAME_StackBytes]
+
+    /* Push address of __except_handler3 on the stack */
+    push offset __except_handler3
+
+    /* Push the old exception record on the stack */
+    push dword ptr fs:0
+
+    /* Adjust stack allocation, add size of the stack frame minus 2 pushes */
+    add eax, SEH_FRAME_Size + SAFE_AREA_Size - OLDFRAME_Size - 8
+
+    /* Save old ebp, overwriting OLDFRAME.StackBytes */
+    mov [esp + 8 + OLDFRAME_StackBytes], ebp
+
+    /* Load new ebp, pointing to OLDFRAME.StackBytes */
+    lea ebp, [esp + 8 + OLDFRAME_StackBytes]
+
+    /* Allocate stack space */
+    sub esp, eax
+
+    /* Push the return address on the stack */
+    push dword ptr [ebp - OLDFRAME_StackBytes + OLDFRAME_ReturnAddress]
+
+    /* Get address of the SEH table */
+    mov eax, [ebp + OLDFRAME_SEHTable]
+
+    /* Save new esp */
+    mov [ebp - SEH_FRAME_OriginalEbp + SEH_FRAME_NewEsp], esp
+
+    /* Safe SEH table, overwriting OLDFRAME.ReturnAddress */
+    mov [ebp - SEH_FRAME_OriginalEbp + SEH_FRAME_SEHTable], eax
+
+    /* Safe the disable value, overwriting OLDFRAME.SEHTable */
+    mov dword ptr [ebp - SEH_FRAME_OriginalEbp + SEH_FRAME_Disable], -1
+
+    /* Load the address of the new registration record */
+    lea eax, [ebp - SEH_FRAME_OriginalEbp + SEH_FRAME_PreviousRecord]
+
+    /* Save registers */
+    mov [esp + SAFE_AREA_Edi], edi
+    mov [esp + SAFE_AREA_Esi], esi
+    mov [esp + SAFE_AREA_Ebx], ebx
+
+    /* Enqueue the new record */
+    mov fs:[0], eax
+
+    /* Return to the caller */
+    ret
+
+
+PUBLIC __SEH_epilog
+__SEH_epilog:
+
+    /* Restore the previous exception registration record */
+    mov ecx, [ebp - SEH_FRAME_OriginalEbp + SEH_FRAME_PreviousRecord]
+    mov fs:[0], ecx
+
+    /* Restore saved registers */
+    mov edi, [esp + 4 + SAFE_AREA_Edi]
+    mov esi, [esp + 4 + SAFE_AREA_Esi]
+    mov ebx, [esp + 4 + SAFE_AREA_Ebx]
+
+    /* Get the return address */
+    mov ecx, [esp]
+
+    /* Clean up stack */
+    mov esp, ebp
+
+    /* Get previous ebp */
+    mov ebp, [esp]
+
+    /* Save return address */
+    mov [esp], ecx
+
+    /* Return to the caller */
+    ret
+
+
+END

Propchange: branches/cmake-bringup/lib/pseh/i386/seh_prolog.s
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to