Alexandre Julliard : include: Add a target address for unwinding for platforms that need it.

Alexandre Julliard julliard at winehq.org
Thu Jun 18 09:11:33 CDT 2009


Module: wine
Branch: master
Commit: c152b4e7d19d954e8f37057aad3a9b8bb8f31547
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=c152b4e7d19d954e8f37057aad3a9b8bb8f31547

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Jun 18 13:32:26 2009 +0200

include: Add a target address for unwinding for platforms that need it.

---

 include/wine/exception.h |   40 ++++++++++++++++++++++++++++++----------
 tools/widl/typegen.c     |   25 ++++++++++++++-----------
 2 files changed, 44 insertions(+), 21 deletions(-)

diff --git a/include/wine/exception.h b/include/wine/exception.h
index 007688f..7f01349 100644
--- a/include/wine/exception.h
+++ b/include/wine/exception.h
@@ -213,6 +213,18 @@ static inline EXCEPTION_REGISTRATION_RECORD *__wine_pop_frame( EXCEPTION_REGISTR
 #endif
 }
 
+static inline EXCEPTION_REGISTRATION_RECORD *__wine_get_frame(void)
+{
+#if defined(__GNUC__) && defined(__i386__)
+    EXCEPTION_REGISTRATION_RECORD *ret;
+    __asm__ __volatile__(".byte 0x64\n\tmovl (0),%0" : "=r" (ret) );
+    return ret;
+#else
+    NT_TIB *teb = (NT_TIB *)NtCurrentTeb();
+    return teb->ExceptionList;
+#endif
+}
+
 /* Exception handling flags - from OS/2 2.0 exception handling */
 
 /* Win32 seems to use the same flags as ExceptionFlags in an EXCEPTION_RECORD */
@@ -238,26 +250,36 @@ extern void __wine_enter_vm86( CONTEXT *context );
 
 NTSYSAPI void WINAPI RtlUnwind(PVOID,PVOID,PEXCEPTION_RECORD,PVOID);
 
+static inline void DECLSPEC_NORETURN __wine_unwind_target(void)
+{
+    __WINE_FRAME *wine_frame = (__WINE_FRAME *)__wine_get_frame();
+    __wine_pop_frame( &wine_frame->frame );
+    siglongjmp( wine_frame->jmp, 1 );
+}
+
 /* wrapper for RtlUnwind since it clobbers registers on Windows */
-static inline void __wine_rtl_unwind( EXCEPTION_REGISTRATION_RECORD* frame, EXCEPTION_RECORD *record )
+static inline void DECLSPEC_NORETURN __wine_rtl_unwind( EXCEPTION_REGISTRATION_RECORD* frame,
+                                                        EXCEPTION_RECORD *record,
+                                                        void (*target)(void) )
 {
 #if defined(__GNUC__) && defined(__i386__)
-    int dummy1, dummy2, dummy3;
+    int dummy1, dummy2, dummy3, dummy4;
     __asm__ __volatile__("pushl %%ebp\n\t"
                          "pushl %%ebx\n\t"
                          "pushl $0\n\t"
+                         "pushl %3\n\t"
                          "pushl %2\n\t"
-                         "pushl $0\n\t"
                          "pushl %1\n\t"
                          "call *%0\n\t"
                          "popl %%ebx\n\t"
                          "popl %%ebp"
-                         : "=a" (dummy1), "=S" (dummy2), "=D" (dummy3)
-                         : "0" (RtlUnwind), "1" (frame), "2" (record)
-                         : "ecx", "edx", "memory" );
+                         : "=a" (dummy1), "=S" (dummy2), "=D" (dummy3), "=c" (dummy4)
+                         : "0" (RtlUnwind), "1" (frame), "2" (target), "3" (record)
+                         : "edx", "memory" );
 #else
-    RtlUnwind( frame, 0, record, 0 );
+    RtlUnwind( frame, target, record, 0 );
 #endif
+    for (;;) target();
 }
 
 static inline void DECLSPEC_NORETURN __wine_unwind_frame( EXCEPTION_RECORD *record,
@@ -269,9 +291,7 @@ static inline void DECLSPEC_NORETURN __wine_unwind_frame( EXCEPTION_RECORD *reco
     wine_frame->ExceptionCode   = record->ExceptionCode;
     wine_frame->ExceptionRecord = wine_frame;
 
-    __wine_rtl_unwind( frame, record );
-    __wine_pop_frame( frame );
-    siglongjmp( wine_frame->jmp, 1 );
+    __wine_rtl_unwind( frame, record, __wine_unwind_target );
 }
 
 static inline DWORD __wine_exception_handler( EXCEPTION_RECORD *record,
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index 1b7c79d..b60a53c 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -3989,6 +3989,19 @@ void write_exceptions( FILE *file )
     fprintf( file, "    __DECL_EXCEPTION_FRAME\n");
     fprintf( file, "};\n");
     fprintf( file, "\n");
+    fprintf( file, "static inline void __widl_unwind_target(void)\n" );
+    fprintf( file, "{\n");
+    fprintf( file, "    struct __exception_frame *exc_frame = (struct __exception_frame *)__wine_get_frame();\n" );
+    fprintf( file, "    if (exc_frame->finally_level > exc_frame->filter_level)\n" );
+    fprintf( file, "    {\n");
+    fprintf( file, "        exc_frame->abnormal_termination = 1;\n");
+    fprintf( file, "        exc_frame->finally( exc_frame );\n");
+    fprintf( file, "        __wine_pop_frame( &exc_frame->frame );\n");
+    fprintf( file, "    }\n");
+    fprintf( file, "    exc_frame->filter_level = 0;\n");
+    fprintf( file, "    siglongjmp( exc_frame->jmp, 1 );\n");
+    fprintf( file, "}\n");
+    fprintf( file, "\n");
     fprintf( file, "static DWORD __widl_exception_handler( EXCEPTION_RECORD *record,\n");
     fprintf( file, "                                       EXCEPTION_REGISTRATION_RECORD *frame,\n");
     fprintf( file, "                                       CONTEXT *context,\n");
@@ -4007,17 +4020,7 @@ void write_exceptions( FILE *file )
     fprintf( file, "    }\n" );
     fprintf( file, "    exc_frame->code = record->ExceptionCode;\n");
     fprintf( file, "    if (exc_frame->filter_level && exc_frame->filter( record, exc_frame ) == EXCEPTION_EXECUTE_HANDLER)\n" );
-    fprintf( file, "    {\n");
-    fprintf( file, "        __wine_rtl_unwind( frame, record );\n");
-    fprintf( file, "        if (exc_frame->finally_level > exc_frame->filter_level)\n" );
-    fprintf( file, "        {\n");
-    fprintf( file, "            exc_frame->abnormal_termination = 1;\n");
-    fprintf( file, "            exc_frame->finally( exc_frame );\n");
-    fprintf( file, "            __wine_pop_frame( frame );\n");
-    fprintf( file, "        }\n");
-    fprintf( file, "        exc_frame->filter_level = 0;\n");
-    fprintf( file, "        siglongjmp( exc_frame->jmp, 1 );\n");
-    fprintf( file, "    }\n");
+    fprintf( file, "        __wine_rtl_unwind( frame, record, __widl_unwind_target );\n");
     fprintf( file, "    return ExceptionContinueSearch;\n");
     fprintf( file, "}\n");
     fprintf( file, "\n");




More information about the wine-cvs mailing list