Commit abb170fa authored by Alexandre Julliard's avatar Alexandre Julliard

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

to avoid having to save/restore the whole context on every call.
parent b235d795
...@@ -43,10 +43,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(seh); ...@@ -43,10 +43,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(seh);
#ifdef __i386__ /* CxxFrameHandler is not supported on non-i386 */ #ifdef __i386__ /* CxxFrameHandler is not supported on non-i386 */
static DWORD cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame, DWORD cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame,
PCONTEXT exc_context, EXCEPTION_REGISTRATION_RECORD** dispatch, PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch,
cxx_function_descr *descr, EXCEPTION_REGISTRATION_RECORD* nested_frame, cxx_function_descr *descr, EXCEPTION_REGISTRATION_RECORD* nested_frame,
int nested_trylevel, CONTEXT86 *context ); int nested_trylevel );
/* call a function with a given ebp */ /* call a function with a given ebp */
inline static void *call_ebp_func( void *func, void *ebp ) inline static void *call_ebp_func( void *func, void *ebp )
...@@ -76,6 +76,14 @@ inline static void call_dtor( void *func, void *object ) ...@@ -76,6 +76,14 @@ inline static void call_dtor( void *func, void *object )
__asm__ __volatile__("call *%0" : : "r" (func), "c" (object) : "eax", "edx", "memory" ); __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 ) 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", 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_handler( EXCEPTION_RECORD *rec, EXCEPTION_REG ...@@ -232,19 +240,19 @@ static DWORD catch_function_nested_handler( EXCEPTION_RECORD *rec, EXCEPTION_REG
TRACE( "got nested exception in catch function\n" ); TRACE( "got nested exception in catch function\n" );
return cxx_frame_handler( rec, nested_frame->cxx_frame, context, return cxx_frame_handler( rec, nested_frame->cxx_frame, context,
NULL, nested_frame->descr, &nested_frame->frame, NULL, nested_frame->descr, &nested_frame->frame,
nested_frame->trylevel, context ); nested_frame->trylevel );
} }
} }
/* find and call the appropriate catch block for an exception */ /* find and call the appropriate catch block for an exception */
/* returns the address to continue execution to after the catch block was called */ /* 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, inline static void call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_frame *frame,
cxx_function_descr *descr, int nested_trylevel, cxx_function_descr *descr, int nested_trylevel,
cxx_exception_type *info ) cxx_exception_type *info )
{ {
UINT i; UINT i;
int j; 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; struct catch_func_nested_frame nested_frame;
int trylevel = frame->trylevel; int trylevel = frame->trylevel;
thread_data_t *thread_data = msvcrt_get_thread_data(); thread_data_t *thread_data = msvcrt_get_thread_data();
...@@ -303,10 +311,11 @@ inline static void *call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_frame ...@@ -303,10 +311,11 @@ inline static void *call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_frame
if (info && info->destructor) call_dtor( info->destructor, object ); if (info && info->destructor) call_dtor( info->destructor, object );
TRACE( "done, continuing at %p\n", addr ); 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( PEXCEPTION_RECORD rec, cxx_exception_frame ...@@ -315,13 +324,12 @@ inline static void *call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_frame
* *
* Implementation of __CxxFrameHandler. * Implementation of __CxxFrameHandler.
*/ */
static DWORD cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame, DWORD cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame,
PCONTEXT exc_context, EXCEPTION_REGISTRATION_RECORD** dispatch, PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch,
cxx_function_descr *descr, EXCEPTION_REGISTRATION_RECORD* nested_frame, cxx_function_descr *descr, EXCEPTION_REGISTRATION_RECORD* nested_frame,
int nested_trylevel, CONTEXT86 *context ) int nested_trylevel )
{ {
cxx_exception_type *exc_type; cxx_exception_type *exc_type;
void *next_ip;
if (descr->magic != CXX_FRAME_MAGIC) if (descr->magic != CXX_FRAME_MAGIC)
{ {
...@@ -342,7 +350,7 @@ static DWORD cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* fram ...@@ -342,7 +350,7 @@ static DWORD cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* fram
if (rec->ExceptionInformation[0] > CXX_FRAME_MAGIC && if (rec->ExceptionInformation[0] > CXX_FRAME_MAGIC &&
exc_type->custom_handler) 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 ); descr, nested_trylevel, nested_frame, 0 );
} }
if (!exc_type) /* nested exception, fetch info from original exception */ if (!exc_type) /* nested exception, fetch info from original exception */
...@@ -365,29 +373,27 @@ static DWORD cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* fram ...@@ -365,29 +373,27 @@ static DWORD cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* fram
rec->ExceptionCode, rec, frame, frame->trylevel, descr, nested_frame ); rec->ExceptionCode, rec, frame, frame->trylevel, descr, nested_frame );
} }
next_ip = call_catch_block( rec, frame, descr, frame->trylevel, exc_type ); call_catch_block( rec, frame, descr, frame->trylevel, exc_type );
return ExceptionContinueSearch;
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;
} }
/********************************************************************* /*********************************************************************
* __CxxFrameHandler (MSVCRT.@) * __CxxFrameHandler (MSVCRT.@)
*/ */
void WINAPI __regs___CxxFrameHandler( PEXCEPTION_RECORD rec, EXCEPTION_REGISTRATION_RECORD* frame, extern DWORD __CxxFrameHandler( PEXCEPTION_RECORD rec, EXCEPTION_REGISTRATION_RECORD* frame,
PCONTEXT exc_context, EXCEPTION_REGISTRATION_RECORD** dispatch, PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch );
CONTEXT86 *context ) __ASM_GLOBAL_FUNC( __CxxFrameHandler,
{ "pushl $0\n\t" /* nested_trylevel */
cxx_function_descr *descr = (cxx_function_descr *)context->Eax; "pushl $0\n\t" /* nested_frame */
context->Eax = cxx_frame_handler( rec, (cxx_exception_frame *)frame, "pushl %eax\n\t" /* descr */
exc_context, dispatch, descr, NULL, 0, context ); "pushl 28(%esp)\n\t" /* dispatch */
} "pushl 28(%esp)\n\t" /* context */
DEFINE_REGS_ENTRYPOINT( __CxxFrameHandler, 16, 0 ); "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__ */ #endif /* __i386__ */
......
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
@ extern _HUGE MSVCRT__HUGE @ extern _HUGE MSVCRT__HUGE
@ cdecl _Strftime(str long str ptr ptr) @ cdecl _Strftime(str long str ptr ptr)
@ cdecl _XcptFilter(long 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 @ stub __CxxLongjmpUnwind #(ptr) stdcall
@ cdecl __RTCastToVoid(ptr) MSVCRT___RTCastToVoid @ cdecl __RTCastToVoid(ptr) MSVCRT___RTCastToVoid
@ cdecl __RTDynamicCast(ptr long ptr ptr long) MSVCRT___RTDynamicCast @ cdecl __RTDynamicCast(ptr long ptr ptr long) MSVCRT___RTDynamicCast
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment