Alexandre Julliard : msvcrt: Added some assembly glue for the asm bits of __CxxFrameHandler

Alexandre Julliard julliard at wine.codeweavers.com
Thu Jan 5 10:53:58 CST 2006


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Jan  5 13:56:11 2006 +0100

msvcrt: Added some assembly glue for the asm bits of __CxxFrameHandler
to avoid having to save/restore the whole context on every call.

---

 dlls/msvcrt/cppexcept.c |   74 +++++++++++++++++++++++++----------------------
 dlls/msvcrt/msvcrt.spec |    2 +
 2 files changed, 41 insertions(+), 35 deletions(-)

diff --git a/dlls/msvcrt/cppexcept.c b/dlls/msvcrt/cppexcept.c
index 339bb7b..425a384 100644
--- a/dlls/msvcrt/cppexcept.c
+++ b/dlls/msvcrt/cppexcept.c
@@ -43,10 +43,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(seh);
 
 #ifdef __i386__  /* CxxFrameHandler is not supported on non-i386 */
 
-static DWORD cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame,
-                                PCONTEXT exc_context, EXCEPTION_REGISTRATION_RECORD** dispatch,
-                                cxx_function_descr *descr, EXCEPTION_REGISTRATION_RECORD* nested_frame,
-                                int nested_trylevel, CONTEXT86 *context );
+DWORD cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame,
+                         PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch,
+                         cxx_function_descr *descr, EXCEPTION_REGISTRATION_RECORD* nested_frame,
+                         int nested_trylevel );
 
 /* call a function with a given ebp */
 inline static void *call_ebp_func( void *func, void *ebp )
@@ -76,6 +76,14 @@ inline static void call_dtor( void *func
     __asm__ __volatile__("call *%0" : : "r" (func), "c" (object) : "eax", "edx", "memory" );
 }
 
+/* continue execution to the specified address after exception is caught */
+inline static void DECLSPEC_NORETURN continue_after_catch( cxx_exception_frame* frame, void *addr )
+{
+    __asm__ __volatile__("movl -4(%0),%%esp; leal 12(%0),%%ebp; jmp *%1"
+                         : : "r" (frame), "a" (addr) );
+    for (;;) ; /* unreached */
+}
+
 static inline void dump_type( const cxx_type_info *type )
 {
     TRACE( "flags %x type %p %s offsets %d,%d,%d size %d copy ctor %p\n",
@@ -232,19 +240,19 @@ static DWORD catch_function_nested_handl
         TRACE( "got nested exception in catch function\n" );
         return cxx_frame_handler( rec, nested_frame->cxx_frame, context,
                                   NULL, nested_frame->descr, &nested_frame->frame,
-                                  nested_frame->trylevel, context );
+                                  nested_frame->trylevel );
     }
 }
 
 /* find and call the appropriate catch block for an exception */
 /* returns the address to continue execution to after the catch block was called */
-inline static void *call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_frame *frame,
-                                      cxx_function_descr *descr, int nested_trylevel,
-                                      cxx_exception_type *info )
+inline static void call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_frame *frame,
+                                     cxx_function_descr *descr, int nested_trylevel,
+                                     cxx_exception_type *info )
 {
     UINT i;
     int j;
-    void *addr, *object = (void *)rec->ExceptionInformation[1];
+    void *addr, *prev_frame, *object = (void *)rec->ExceptionInformation[1];
     struct catch_func_nested_frame nested_frame;
     int trylevel = frame->trylevel;
     thread_data_t *thread_data = msvcrt_get_thread_data();
@@ -303,10 +311,11 @@ inline static void *call_catch_block( PE
 
             if (info && info->destructor) call_dtor( info->destructor, object );
             TRACE( "done, continuing at %p\n", addr );
-            return addr;
+            prev_frame = NtCurrentTeb()->Tib.ExceptionList;
+            __wine_pop_frame( prev_frame );
+            continue_after_catch( frame, addr );
         }
     }
-    return NULL;
 }
 
 
@@ -315,13 +324,12 @@ inline static void *call_catch_block( PE
  *
  * Implementation of __CxxFrameHandler.
  */
-static DWORD cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame,
-                                PCONTEXT exc_context, EXCEPTION_REGISTRATION_RECORD** dispatch,
-                                cxx_function_descr *descr, EXCEPTION_REGISTRATION_RECORD* nested_frame,
-                                int nested_trylevel, CONTEXT86 *context )
+DWORD cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame,
+                         PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch,
+                         cxx_function_descr *descr, EXCEPTION_REGISTRATION_RECORD* nested_frame,
+                         int nested_trylevel )
 {
     cxx_exception_type *exc_type;
-    void *next_ip;
 
     if (descr->magic != CXX_FRAME_MAGIC)
     {
@@ -342,7 +350,7 @@ static DWORD cxx_frame_handler( PEXCEPTI
         if (rec->ExceptionInformation[0] > CXX_FRAME_MAGIC &&
                 exc_type->custom_handler)
         {
-            return exc_type->custom_handler( rec, frame, exc_context, dispatch,
+            return exc_type->custom_handler( rec, frame, context, dispatch,
                                          descr, nested_trylevel, nested_frame, 0 );
         }
         if (!exc_type)  /* nested exception, fetch info from original exception */
@@ -365,29 +373,27 @@ static DWORD cxx_frame_handler( PEXCEPTI
               rec->ExceptionCode,  rec, frame, frame->trylevel, descr, nested_frame );
     }
 
-    next_ip = call_catch_block( rec, frame, descr, frame->trylevel, exc_type );
-
-    if (!next_ip) return ExceptionContinueSearch;
-    rec->ExceptionFlags &= ~EH_NONCONTINUABLE;
-    context->Eip = (DWORD)next_ip;
-    context->Ebp = (DWORD)&frame->ebp;
-    context->Esp = ((DWORD*)frame)[-1];
-    return ExceptionContinueExecution;
+    call_catch_block( rec, frame, descr, frame->trylevel, exc_type );
+    return ExceptionContinueSearch;
 }
 
 
 /*********************************************************************
  *		__CxxFrameHandler (MSVCRT.@)
  */
-void WINAPI __regs___CxxFrameHandler( PEXCEPTION_RECORD rec, EXCEPTION_REGISTRATION_RECORD* frame,
-                                      PCONTEXT exc_context, EXCEPTION_REGISTRATION_RECORD** dispatch,
-                                      CONTEXT86 *context )
-{
-    cxx_function_descr *descr = (cxx_function_descr *)context->Eax;
-    context->Eax = cxx_frame_handler( rec, (cxx_exception_frame *)frame,
-                                      exc_context, dispatch, descr, NULL, 0, context );
-}
-DEFINE_REGS_ENTRYPOINT( __CxxFrameHandler, 16, 0 );
+extern DWORD __CxxFrameHandler( PEXCEPTION_RECORD rec, EXCEPTION_REGISTRATION_RECORD* frame,
+                                PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch );
+__ASM_GLOBAL_FUNC( __CxxFrameHandler,
+                   "pushl $0\n\t"        /* nested_trylevel */
+                   "pushl $0\n\t"        /* nested_frame */
+                   "pushl %eax\n\t"      /* descr */
+                   "pushl 28(%esp)\n\t"  /* dispatch */
+                   "pushl 28(%esp)\n\t"  /* context */
+                   "pushl 28(%esp)\n\t"  /* frame */
+                   "pushl 28(%esp)\n\t"  /* rec */
+                   "call " __ASM_NAME("cxx_frame_handler") "\n\t"
+                   "add $28,%esp\n\t"
+                   "ret" );
 
 #endif  /* __i386__ */
 
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index a4d3ade..8e4a994 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -75,7 +75,7 @@
 @ extern _HUGE MSVCRT__HUGE
 @ cdecl _Strftime(str long str ptr ptr)
 @ cdecl _XcptFilter(long ptr)
-@ cdecl -i386 -register __CxxFrameHandler(ptr ptr ptr ptr)
+@ cdecl -i386 -norelay __CxxFrameHandler(ptr ptr ptr ptr)
 @ stub __CxxLongjmpUnwind #(ptr) stdcall
 @ cdecl __RTCastToVoid(ptr) MSVCRT___RTCastToVoid
 @ cdecl __RTDynamicCast(ptr long ptr ptr long) MSVCRT___RTDynamicCast




More information about the wine-cvs mailing list