[CRT]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Tue, 25 Jan 2011 01:28:41 +0000 (01:28 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Tue, 25 Jan 2011 01:28:41 +0000 (01:28 +0000)
Implement ms compatible __SEH_prolog

svn path=/branches/cmake-bringup/; revision=50482

lib/sdk/crt/CMakeLists.txt
lib/sdk/crt/except/i386/seh_prolog.s [new file with mode: 0644]

index 2760bf1..f3c3c58 100644 (file)
@@ -279,15 +279,12 @@ list(APPEND CRT_SOURCE
     wine/heap.c
     wine/undname.c)
 
-if(NOT ARCH MATCHES arm)
-    list(APPEND CRT_SOURCE
-        except/${ARCH}/seh.s)
-endif()
-
 if(ARCH MATCHES i386)
     list(APPEND CRT_SOURCE
         except/i386/chkstk_asm.s
         except/i386/prolog.s
+        except/i386/seh.s
+        except/i386/seh_prolog.s
         except/i386/unwind.c
         float/i386/clearfp.c
         float/i386/cntrlfp.c
@@ -298,6 +295,7 @@ if(ARCH MATCHES i386)
 elseif(ARCH MATCHES amd64)
     list(APPEND CRT_SOURCE
         except/amd64/chkstk_asm.s
+        except/amd64/seh.s
         float/i386/clearfp.c
         float/i386/cntrlfp.c
         float/i386/fpreset.c
@@ -470,15 +468,12 @@ list(APPEND LIBCNTPR_SOURCE
     wstring/wcsspn.c
     wstring/wcsstr.c)
 
-if(NOT ARCH MATCHES arm)
-    list(APPEND LIBCNTPR_SOURCE
-        except/${ARCH}/chkstk_asm.s
-        except/${ARCH}/seh.s
-        setjmp/${ARCH}/setjmp.s)
-endif()
-
 if(ARCH MATCHES i386)
     list(APPEND LIBCNTPR_SOURCE
+        except/i386/chkstk_asm.s
+        except/i386/seh.s
+        except/i386/seh_prolog.s
+        setjmp/i386/setjmp.s
         math/i386/alldiv_asm.s
         math/i386/alldvrm_asm.s
         math/i386/allmul_asm.s
@@ -505,6 +500,9 @@ if(ARCH MATCHES i386)
         misc/i386/readcr4.S)
 elseif(ARCH MATCHES amd64)
     list(APPEND LIBCNTPR_SOURCE
+        except/amd64/chkstk_asm.s
+        except/amd64/seh.s
+        setjmp/amd64/setjmp.s
         math/cos.c
         math/sin.c
         math/amd64/alldiv.S
diff --git a/lib/sdk/crt/except/i386/seh_prolog.s b/lib/sdk/crt/except/i386/seh_prolog.s
new file mode 100644 (file)
index 0000000..b4fe264
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * 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
+
+    /* Save registers */
+    mov [esp + SAFE_AREA_Edi], edi
+    mov [esp + SAFE_AREA_Esi], esi
+    mov [esp + SAFE_AREA_Ebx], ebx
+
+    /* Load the address of the new registration record */
+    lea eax, [ebp - SEH_FRAME_OriginalEbp + SEH_FRAME_PreviousRecord]
+
+    /* Safe the disable value, overwriting OLDFRAME.SEHTable */
+    mov dword ptr [ebp - SEH_FRAME_OriginalEbp + SEH_FRAME_Disable], -1
+
+    /* Enqueue the new record */
+    mov fs:[0], eax
+
+    /* Return to the caller */
+    ret
+
+END