[PSEH3]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Sun, 2 Mar 2014 19:36:50 +0000 (19:36 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Sun, 2 Mar 2014 19:36:50 +0000 (19:36 +0000)
- Switch the registration asm functions from a complete custom calling convention to regparm(2), so that it can be used in "returns_twice" based algorithm (required by CLANG, which doesn't support "asm goto" construct)
- Add support for saving all non-volatiles in the registration frame (also required by CLANG, since without asm goto, we cannot give the compiler the required hints to save these registers itself)

svn path=/trunk/; revision=62383

reactos/include/reactos/libs/pseh/pseh3.h
reactos/lib/pseh/i386/pseh3.c
reactos/lib/pseh/i386/pseh3_asmdef.h
reactos/lib/pseh/i386/pseh3_i386.S

index d116889..0b75e7d 100644 (file)
 
 #include "excpt.h"
 
+/* CLANG must safe non-volatiles, because it uses a return-twice algorithm */
+#if defined(__clang__) && !defined(_SEH3$_FRAME_ALL_NONVOLATILES)
+#define _SEH3$_FRAME_ALL_NONVOLATILES 1
+#endif
+
 typedef struct _SEH3$_SCOPE_TABLE
 {
     void *Target;
@@ -42,7 +47,11 @@ typedef struct _SEH3$_REGISTRATION_FRAME
     /* Registers that we need to save */
     unsigned long Esp;
     unsigned long Ebp;
-
+#ifdef _SEH3$_FRAME_ALL_NONVOLATILES
+    unsigned long Ebx;
+    unsigned long Esi;
+    unsigned long Edi;
+#endif
 } SEH3$_REGISTRATION_FRAME ,*PSEH3$_REGISTRATION_FRAME;
 
 /* Prevent gcc from inlining functions that use SEH. */
@@ -95,7 +104,7 @@ void * __cdecl __attribute__((error("Can only be used inside an exception filter
 
 /* This is an asm wrapper around _SEH3$_RegisterFrame */
 #define _SEH3$_RegisterFrame(_TrylevelFrame, _DataTable, _Target) \
-    asm goto ("leal %0, %%ecx\n" \
+    asm goto ("leal %0, %%edx\n" \
               "call __SEH3$_RegisterFrame\n" \
               : \
               : "m" (*(_TrylevelFrame)), "a" (_DataTable) \
@@ -104,7 +113,7 @@ void * __cdecl __attribute__((error("Can only be used inside an exception filter
 
 /* This is an asm wrapper around _SEH3$_EnterTryLevel */
 #define _SEH3$_RegisterTryLevel(_TrylevelFrame, _DataTable, _Target) \
-    asm goto ("leal %0, %%ecx\n" \
+    asm goto ("leal %0, %%edx\n" \
               "call __SEH3$_RegisterTryLevel\n" \
               : \
               : "m" (*(_TrylevelFrame)), "a" (_DataTable) \
index 13e5df1..1d37ca0 100644 (file)
@@ -34,6 +34,8 @@
 #include <windef.h>
 #include <winnt.h>
 
+/* We need the full structure with all non-volatile */
+#define _SEH3$_FRAME_ALL_NONVOLATILES 1
 #include "pseh3.h"
 #include "pseh3_asmdef.h"
 
index 6fd821c..f8d847e 100644 (file)
@@ -7,6 +7,9 @@
 #define SEH3_REGISTRATION_FRAME_ExceptionPointers 16
 #define SEH3_REGISTRATION_FRAME_Esp 20
 #define SEH3_REGISTRATION_FRAME_Ebp 24
+#define SEH3_REGISTRATION_FRAME_Ebx 28
+#define SEH3_REGISTRATION_FRAME_Esi 32
+#define SEH3_REGISTRATION_FRAME_Edi 36
 
 #define SEH3_SCOPE_TABLE_Target 0
 #define SEH3_SCOPE_TABLE_Filter 4
index eca7182..e647312 100644 (file)
 
 .text
 
-
 .extern __SEH3$_except_handler
 
 /*
  *  void
- *  _SEH3$_RegisterFrame(
- *       PSEH_REGISTRATION_FRAME RegistrationRecord<ecx>,
- *       PSEH_DATA_TABLE DataTable<eax>);
+ *  __attribute__((regparm(2)))
+ *  __attribute__((returns_twice))
+ *  _SEH3$_RegisterFrame[WithNonVolatiles](
+ *       PSEH_DATA_TABLE DataTable<eax>,
+ *       PSEH_REGISTRATION_FRAME RegistrationRecord<edx>);
  */
+.global __SEH3$_RegisterFrameWithNonVolatiles
+__SEH3$_RegisterFrameWithNonVolatiles:
+
+    /* Save non-volatiles in the registration frame */
+    mov [edx + SEH3_REGISTRATION_FRAME_Ebx], ebx
+    mov [edx + SEH3_REGISTRATION_FRAME_Esi], esi
+    mov [edx + SEH3_REGISTRATION_FRAME_Edi], edi
+
 .global __SEH3$_RegisterFrame
 __SEH3$_RegisterFrame:
 
     /* Save the address of the static data table */
-    mov [ecx + SEH3_REGISTRATION_FRAME_ScopeTable], eax
+    mov [edx + SEH3_REGISTRATION_FRAME_ScopeTable], eax
 
     /* Set the handler address */
-    mov dword ptr [ecx + SEH3_REGISTRATION_FRAME_Handler], offset __SEH3$_except_handler
+    mov dword ptr [edx + SEH3_REGISTRATION_FRAME_Handler], offset __SEH3$_except_handler
 
     /* Set this as the end of the internal chain */
-    mov dword ptr [ecx + SEH3_REGISTRATION_FRAME_EndOfChain], ecx
+    mov dword ptr [edx + SEH3_REGISTRATION_FRAME_EndOfChain], edx
 
     /* Register the frame in the TEB */
     mov eax, dword ptr fs:[0]
-    mov [ecx + SEH3_REGISTRATION_FRAME_Next], eax
-    mov dword ptr fs:[0], ecx
+    mov [edx + SEH3_REGISTRATION_FRAME_Next], eax
+    mov dword ptr fs:[0], edx
 
-    /* Save the registers */
-    mov [ecx + SEH3_REGISTRATION_FRAME_Esp], esp
-    mov [ecx + SEH3_REGISTRATION_FRAME_Ebp], ebp
+    /* Save the stack registers */
+    mov [edx + SEH3_REGISTRATION_FRAME_Esp], esp
+    mov [edx + SEH3_REGISTRATION_FRAME_Ebp], ebp
 
+    /* Set eax to 0 to indicate 1st return */
+    xor eax, eax
     ret
 
 
+/*
+ *  void
+ *  __attribute__((regparm(2)))
+ *  __attribute__((returns_twice))
+ *  _SEH3$_RegisterTryLevel[WithNonVolatiles](
+ *       PSEH_DATA_TABLE DataTable<eax>,
+ *       PSEH_REGISTRATION_FRAME RegistrationRecord<edx>);
+ */
+.global __SEH3$_RegisterTryLevelWithNonVolatiles
+__SEH3$_RegisterTryLevelWithNonVolatiles:
+
+    /* Save non-volatiles in the registration frame */
+    mov [edx + SEH3_REGISTRATION_FRAME_Ebx], ebx
+    mov [edx + SEH3_REGISTRATION_FRAME_Esi], esi
+    mov [edx + SEH3_REGISTRATION_FRAME_Edi], edi
+
 .global __SEH3$_RegisterTryLevel
 __SEH3$_RegisterTryLevel:
 
     /* Save the address of the static data table */
-    mov [ecx + SEH3_REGISTRATION_FRAME_ScopeTable], eax
+    mov [edx + SEH3_REGISTRATION_FRAME_ScopeTable], eax
 
     /* Set the handler address to NULL as identification */
-    and dword ptr [ecx + SEH3_REGISTRATION_FRAME_Handler], 0
+    and dword ptr [edx + SEH3_REGISTRATION_FRAME_Handler], 0
 
     /* Get the current registered frame */
     mov eax, dword ptr fs:[0]
 
     /* Get the current end of the chain and set this as Next */
-    mov edx, [eax + SEH3_REGISTRATION_FRAME_EndOfChain]
-    mov [ecx + SEH3_REGISTRATION_FRAME_Next], edx
+    mov ecx, [eax + SEH3_REGISTRATION_FRAME_EndOfChain]
+    mov [edx + SEH3_REGISTRATION_FRAME_Next], ecx
 
     /* Set this as the end of the internal chain */
-    mov dword ptr [eax + SEH3_REGISTRATION_FRAME_EndOfChain], ecx
+    mov dword ptr [eax + SEH3_REGISTRATION_FRAME_EndOfChain], edx
 
-    /* Save the registers */
-    mov [ecx + SEH3_REGISTRATION_FRAME_Esp], esp
-    mov [ecx + SEH3_REGISTRATION_FRAME_Ebp], ebp
+    /* Save the stack registers */
+    mov [edx + SEH3_REGISTRATION_FRAME_Esp], esp
+    mov [edx + SEH3_REGISTRATION_FRAME_Ebp], ebp
 
+    /* Set eax to 0 to indicate 1st return */
+    xor eax, eax
     ret
 
-