msvcr80: Use Cxx(Un)RegisterExceptionObject helpers in i386 nested exception handler.

Signed-off-by: Piotr Caban <piotr@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Piotr Caban 2016-03-16 21:03:19 +01:00 committed by Alexandre Julliard
parent 8348d4b40e
commit 2296261600
14 changed files with 39 additions and 83 deletions

View File

@ -4,7 +4,7 @@
@ cdecl _FindAndUnlinkFrame(ptr) ucrtbase._FindAndUnlinkFrame @ cdecl _FindAndUnlinkFrame(ptr) ucrtbase._FindAndUnlinkFrame
@ stub _GetImageBase @ stub _GetImageBase
@ stub _GetThrowImageBase @ stub _GetThrowImageBase
@ cdecl -arch=i386,x86_64,arm _IsExceptionObjectToBeDestroyed(ptr) ucrtbase._IsExceptionObjectToBeDestroyed @ cdecl _IsExceptionObjectToBeDestroyed(ptr) ucrtbase._IsExceptionObjectToBeDestroyed
@ stub _NLG_Dispatch2 @ stub _NLG_Dispatch2
@ stub _NLG_Return @ stub _NLG_Return
@ stub _NLG_Return2 @ stub _NLG_Return2

View File

@ -530,7 +530,7 @@
@ cdecl _Getmonths() @ cdecl _Getmonths()
@ cdecl _Gettnames() @ cdecl _Gettnames()
@ extern _HUGE MSVCRT__HUGE @ extern _HUGE MSVCRT__HUGE
@ cdecl -arch=i386,x86_64,arm _IsExceptionObjectToBeDestroyed(ptr) @ cdecl _IsExceptionObjectToBeDestroyed(ptr)
@ stub _NLG_Dispatch2 @ stub _NLG_Dispatch2
@ stub _NLG_Return @ stub _NLG_Return
@ stub _NLG_Return2 @ stub _NLG_Return2

View File

@ -853,7 +853,7 @@
@ cdecl _Getmonths() @ cdecl _Getmonths()
@ cdecl _Gettnames() @ cdecl _Gettnames()
@ extern _HUGE MSVCRT__HUGE @ extern _HUGE MSVCRT__HUGE
@ cdecl -arch=i386,x86_64,arm _IsExceptionObjectToBeDestroyed(ptr) @ cdecl _IsExceptionObjectToBeDestroyed(ptr)
@ stub _Lock_shared_ptr_spin_lock @ stub _Lock_shared_ptr_spin_lock
@ stub -arch=i386 _NLG_Dispatch2 @ stub -arch=i386 _NLG_Dispatch2
@ stub -arch=arm,win64 __NLG_Dispatch2 @ stub -arch=arm,win64 __NLG_Dispatch2

View File

@ -837,7 +837,7 @@
@ cdecl _Getmonths() @ cdecl _Getmonths()
@ cdecl _Gettnames() @ cdecl _Gettnames()
@ extern _HUGE MSVCRT__HUGE @ extern _HUGE MSVCRT__HUGE
@ cdecl -arch=i386,x86_64,arm _IsExceptionObjectToBeDestroyed(ptr) @ cdecl _IsExceptionObjectToBeDestroyed(ptr)
@ stub _LCbuild @ stub _LCbuild
@ stub -arch=i386 _NLG_Dispatch2 @ stub -arch=i386 _NLG_Dispatch2
@ stub -arch=arm,win64 __NLG_Dispatch2 @ stub -arch=arm,win64 __NLG_Dispatch2

View File

@ -831,7 +831,7 @@
@ cdecl _Getmonths() msvcr120._Getmonths @ cdecl _Getmonths() msvcr120._Getmonths
@ cdecl _Gettnames() msvcr120._Gettnames @ cdecl _Gettnames() msvcr120._Gettnames
@ extern _HUGE msvcr120._HUGE @ extern _HUGE msvcr120._HUGE
@ cdecl -arch=i386,x86_64,arm _IsExceptionObjectToBeDestroyed(ptr) msvcr120._IsExceptionObjectToBeDestroyed @ cdecl _IsExceptionObjectToBeDestroyed(ptr) msvcr120._IsExceptionObjectToBeDestroyed
@ stub _LCbuild @ stub _LCbuild
@ stub -arch=i386 _NLG_Dispatch2 @ stub -arch=i386 _NLG_Dispatch2
@ stub -arch=arm,win64 __NLG_Dispatch2 @ stub -arch=arm,win64 __NLG_Dispatch2

View File

@ -162,7 +162,7 @@
@ cdecl _Getmonths() @ cdecl _Getmonths()
@ cdecl _Gettnames() @ cdecl _Gettnames()
@ extern _HUGE MSVCRT__HUGE @ extern _HUGE MSVCRT__HUGE
@ cdecl -arch=i386,x86_64,arm _IsExceptionObjectToBeDestroyed(ptr) @ cdecl _IsExceptionObjectToBeDestroyed(ptr)
@ stub -arch=i386 _NLG_Dispatch2 @ stub -arch=i386 _NLG_Dispatch2
@ stub -arch=arm,win64 __NLG_Dispatch2 @ stub -arch=arm,win64 __NLG_Dispatch2
@ stub -arch=i386 _NLG_Return @ stub -arch=i386 _NLG_Return

View File

@ -157,7 +157,7 @@
@ cdecl _Getmonths() @ cdecl _Getmonths()
@ cdecl _Gettnames() @ cdecl _Gettnames()
@ extern _HUGE MSVCRT__HUGE @ extern _HUGE MSVCRT__HUGE
@ cdecl -arch=i386,x86_64,arm _IsExceptionObjectToBeDestroyed(ptr) @ cdecl _IsExceptionObjectToBeDestroyed(ptr)
@ stub _NLG_Dispatch2 @ stub _NLG_Dispatch2
@ stub _NLG_Return @ stub _NLG_Return
@ stub _NLG_Return2 @ stub _NLG_Return2

View File

@ -372,6 +372,24 @@ void CDECL _FindAndUnlinkFrame(frame_info *fi)
ERR("frame not found, native crashes in this case\n"); ERR("frame not found, native crashes in this case\n");
} }
/*********************************************************************
* _IsExceptionObjectToBeDestroyed (MSVCR80.@)
*/
BOOL __cdecl _IsExceptionObjectToBeDestroyed(const void *obj)
{
frame_info *cur;
TRACE( "%p\n", obj );
for (cur = msvcrt_get_thread_data()->frame_info_head; cur; cur = cur->next)
{
if (cur->object == obj)
return FALSE;
}
return TRUE;
}
/********************************************************************* /*********************************************************************
* __DestructExceptionObject (MSVCRT.@) * __DestructExceptionObject (MSVCRT.@)
*/ */
@ -424,13 +442,14 @@ void CDECL __CxxUnregisterExceptionObject(cxx_frame_info *frame_info, BOOL in_us
{ {
thread_data_t *data = msvcrt_get_thread_data(); thread_data_t *data = msvcrt_get_thread_data();
FIXME("(%p) semi-stub\n", frame_info); TRACE("(%p)\n", frame_info);
if(frame_info->rec == (void*)-1) if(frame_info->rec == (void*)-1)
return; return;
_FindAndUnlinkFrame(&frame_info->frame_info); _FindAndUnlinkFrame(&frame_info->frame_info);
if(data->exc_record->ExceptionCode == CXX_EXCEPTION && !in_use) /* FIXME: use _IsExceptionObjectToBeDestroyed here */ if(data->exc_record->ExceptionCode == CXX_EXCEPTION && !in_use
&& _IsExceptionObjectToBeDestroyed((void*)data->exc_record->ExceptionInformation[1]))
__DestructExceptionObject(data->exc_record); __DestructExceptionObject(data->exc_record);
data->exc_record = frame_info->rec; data->exc_record = frame_info->rec;
} }

View File

@ -74,15 +74,6 @@ int CDECL __CxxExceptionFilter( PEXCEPTION_POINTERS ptrs,
return EXCEPTION_CONTINUE_SEARCH; return EXCEPTION_CONTINUE_SEARCH;
} }
/*********************************************************************
* _IsExceptionObjectToBeDestroyed (MSVCR80.@)
*/
BOOL __cdecl _IsExceptionObjectToBeDestroyed(const void *obj)
{
FIXME("%p not implemented\n", obj);
return FALSE;
}
/********************************************************************* /*********************************************************************
* __CxxFrameHandler (MSVCRT.@) * __CxxFrameHandler (MSVCRT.@)
*/ */

View File

@ -131,7 +131,6 @@ DWORD CDECL cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame
PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch, PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch,
const cxx_function_descr *descr, const cxx_function_descr *descr,
EXCEPTION_REGISTRATION_RECORD* nested_frame, int nested_trylevel ); EXCEPTION_REGISTRATION_RECORD* nested_frame, int nested_trylevel );
BOOL __cdecl _IsExceptionObjectToBeDestroyed(const void*);
/* call a function with a given ebp */ /* call a function with a given ebp */
static inline void *call_ebp_func( void *func, void *ebp ) static inline void *call_ebp_func( void *func, void *ebp )
@ -350,11 +349,10 @@ static void cxx_local_unwind( cxx_exception_frame* frame, const cxx_function_des
struct catch_func_nested_frame struct catch_func_nested_frame
{ {
EXCEPTION_REGISTRATION_RECORD frame; /* standard exception frame */ EXCEPTION_REGISTRATION_RECORD frame; /* standard exception frame */
EXCEPTION_RECORD *prev_rec; /* previous record to restore in thread data */
cxx_exception_frame *cxx_frame; /* frame of parent exception */ cxx_exception_frame *cxx_frame; /* frame of parent exception */
const cxx_function_descr *descr; /* descriptor of parent exception */ const cxx_function_descr *descr; /* descriptor of parent exception */
int trylevel; /* current try level */ int trylevel; /* current try level */
EXCEPTION_RECORD *rec; /* rec associated with frame */ cxx_frame_info frame_info;
}; };
/* handler for exceptions happening while calling a catch function */ /* handler for exceptions happening while calling a catch function */
@ -362,19 +360,10 @@ static DWORD catch_function_nested_handler( EXCEPTION_RECORD *rec, EXCEPTION_REG
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher ) CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
{ {
struct catch_func_nested_frame *nested_frame = (struct catch_func_nested_frame *)frame; struct catch_func_nested_frame *nested_frame = (struct catch_func_nested_frame *)frame;
PEXCEPTION_RECORD prev_rec = nested_frame->rec;
if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)) if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
{ {
if (prev_rec->ExceptionCode == CXX_EXCEPTION) __CxxUnregisterExceptionObject(&nested_frame->frame_info, FALSE);
{
void *object = (void*)prev_rec->ExceptionInformation[1];
cxx_exception_type *info = (cxx_exception_type*) prev_rec->ExceptionInformation[2];
if (info && info->destructor && _IsExceptionObjectToBeDestroyed(object))
call_dtor( info->destructor, object);
}
msvcrt_get_thread_data()->exc_record = nested_frame->prev_rec;
return ExceptionContinueSearch; return ExceptionContinueSearch;
} }
@ -382,6 +371,8 @@ static DWORD catch_function_nested_handler( EXCEPTION_RECORD *rec, EXCEPTION_REG
if(rec->ExceptionCode == CXX_EXCEPTION) if(rec->ExceptionCode == CXX_EXCEPTION)
{ {
PEXCEPTION_RECORD prev_rec = msvcrt_get_thread_data()->exc_record;
if((rec->ExceptionInformation[1] == 0 && rec->ExceptionInformation[2] == 0) || if((rec->ExceptionInformation[1] == 0 && rec->ExceptionInformation[2] == 0) ||
(prev_rec->ExceptionCode == CXX_EXCEPTION && (prev_rec->ExceptionCode == CXX_EXCEPTION &&
rec->ExceptionInformation[1] == prev_rec->ExceptionInformation[1] && rec->ExceptionInformation[1] == prev_rec->ExceptionInformation[1] &&
@ -408,40 +399,6 @@ static DWORD catch_function_nested_handler( EXCEPTION_RECORD *rec, EXCEPTION_REG
nested_frame->trylevel ); nested_frame->trylevel );
} }
/*********************************************************************
* _IsExceptionObjectToBeDestroyed (MSVCR80.@)
*/
BOOL __cdecl _IsExceptionObjectToBeDestroyed(const void *obj)
{
EXCEPTION_REGISTRATION_RECORD *reg = NtCurrentTeb()->Tib.ExceptionList;
frame_info *cur;
TRACE( "%p\n", obj );
while (reg != (EXCEPTION_REGISTRATION_RECORD*)-1)
{
if (reg->Handler == catch_function_nested_handler)
{
EXCEPTION_RECORD *rec = ((struct catch_func_nested_frame*)reg)->rec;
if(!(rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
&& rec->ExceptionCode == CXX_EXCEPTION && rec->NumberParameters == 3
&& rec->ExceptionInformation[1] == (LONG_PTR)obj)
return FALSE;
}
reg = reg->Prev;
}
for (cur = msvcrt_get_thread_data()->frame_info_head; cur; cur = cur->next)
{
if (cur->object == obj)
return FALSE;
}
return TRUE;
}
/* 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 */
static inline void call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_frame *frame, static inline void call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_frame *frame,
@ -454,7 +411,6 @@ static inline void call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_frame
void *addr, *object = (void *)rec->ExceptionInformation[1]; void *addr, *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();
DWORD save_esp = ((DWORD*)frame)[-1]; DWORD save_esp = ((DWORD*)frame)[-1];
for (i = 0; i < descr->tryblock_count; i++) for (i = 0; i < descr->tryblock_count; i++)
@ -502,21 +458,17 @@ static inline void call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_frame
/* setup an exception block for nested exceptions */ /* setup an exception block for nested exceptions */
nested_frame.frame.Handler = catch_function_nested_handler; nested_frame.frame.Handler = catch_function_nested_handler;
nested_frame.prev_rec = thread_data->exc_record;
nested_frame.cxx_frame = frame; nested_frame.cxx_frame = frame;
nested_frame.descr = descr; nested_frame.descr = descr;
nested_frame.trylevel = nested_trylevel + 1; nested_frame.trylevel = nested_trylevel + 1;
nested_frame.rec = rec; __CxxRegisterExceptionObject(&rec, &nested_frame.frame_info);
__wine_push_frame( &nested_frame.frame ); __wine_push_frame( &nested_frame.frame );
thread_data->exc_record = rec;
addr = call_ebp_func( catchblock->handler, &frame->ebp ); addr = call_ebp_func( catchblock->handler, &frame->ebp );
thread_data->exc_record = nested_frame.prev_rec;
__wine_pop_frame( &nested_frame.frame ); __wine_pop_frame( &nested_frame.frame );
((DWORD*)frame)[-1] = save_esp; ((DWORD*)frame)[-1] = save_esp;
if (info && info->destructor && _IsExceptionObjectToBeDestroyed(object)) __CxxUnregisterExceptionObject(&nested_frame.frame_info, FALSE);
call_dtor( info->destructor, object );
TRACE( "done, continuing at %p\n", addr ); TRACE( "done, continuing at %p\n", addr );
continue_after_catch( frame, addr ); continue_after_catch( frame, addr );

View File

@ -71,15 +71,6 @@ int CDECL __CxxExceptionFilter( PEXCEPTION_POINTERS ptrs,
return EXCEPTION_CONTINUE_SEARCH; return EXCEPTION_CONTINUE_SEARCH;
} }
/*********************************************************************
* _IsExceptionObjectToBeDestroyed (MSVCR80.@)
*/
BOOL __cdecl _IsExceptionObjectToBeDestroyed(const void *obj)
{
FIXME ( "%p not implemented\n", obj );
return FALSE;
}
/********************************************************************* /*********************************************************************
* __CxxFrameHandler (MSVCRT.@) * __CxxFrameHandler (MSVCRT.@)
*/ */

View File

@ -217,6 +217,9 @@ typedef struct
void *unk; void *unk;
} cxx_frame_info; } cxx_frame_info;
BOOL __cdecl __CxxRegisterExceptionObject(EXCEPTION_RECORD**, cxx_frame_info*);
void __cdecl __CxxUnregisterExceptionObject(cxx_frame_info*, BOOL);
/* TLS data */ /* TLS data */
extern DWORD msvcrt_tls_index DECLSPEC_HIDDEN; extern DWORD msvcrt_tls_index DECLSPEC_HIDDEN;

View File

@ -30,7 +30,7 @@
@ cdecl _Getdays() @ cdecl _Getdays()
@ cdecl _Getmonths() @ cdecl _Getmonths()
@ cdecl _Gettnames() @ cdecl _Gettnames()
@ cdecl -arch=i386,x86_64,arm _IsExceptionObjectToBeDestroyed(ptr) @ cdecl _IsExceptionObjectToBeDestroyed(ptr)
@ stub _LCbuild @ stub _LCbuild
@ stub _LCmulcc @ stub _LCmulcc
@ stub _LCmulcr @ stub _LCmulcr

View File

@ -2,7 +2,7 @@
@ stdcall _CxxThrowException(long long) ucrtbase._CxxThrowException @ stdcall _CxxThrowException(long long) ucrtbase._CxxThrowException
@ cdecl -arch=i386 -norelay _EH_prolog() ucrtbase._EH_prolog @ cdecl -arch=i386 -norelay _EH_prolog() ucrtbase._EH_prolog
@ cdecl _FindAndUnlinkFrame(ptr) ucrtbase._FindAndUnlinkFrame @ cdecl _FindAndUnlinkFrame(ptr) ucrtbase._FindAndUnlinkFrame
@ cdecl -arch=i386,x86_64,arm _IsExceptionObjectToBeDestroyed(ptr) ucrtbase._IsExceptionObjectToBeDestroyed @ cdecl _IsExceptionObjectToBeDestroyed(ptr) ucrtbase._IsExceptionObjectToBeDestroyed
@ stub _NLG_Dispatch2 @ stub _NLG_Dispatch2
@ stub _NLG_Return @ stub _NLG_Return
@ stub _NLG_Return2 @ stub _NLG_Return2