msvcrt: Implement support for version 4 exception tables.
This commit is contained in:
parent
3415523044
commit
a1e99f544b
|
@ -379,7 +379,7 @@
|
|||
@ cdecl _errno() msvcrt._errno
|
||||
@ cdecl -i386 _except_handler2(ptr ptr ptr ptr) msvcrt._except_handler2
|
||||
@ cdecl -i386 _except_handler3(ptr ptr ptr ptr) msvcrt._except_handler3
|
||||
@ stub _except_handler4_common
|
||||
@ cdecl -i386 _except_handler4_common(ptr ptr ptr ptr ptr ptr) msvcrt._except_handler4_common
|
||||
@ varargs _execl(str str) msvcrt._execl
|
||||
@ varargs _execle(str str) msvcrt._execle
|
||||
@ varargs _execlp(str str) msvcrt._execlp
|
||||
|
@ -637,7 +637,7 @@
|
|||
@ stub _lfind_s
|
||||
@ cdecl _loaddll(str) msvcrt._loaddll
|
||||
@ cdecl -i386 _local_unwind2(ptr long) msvcrt._local_unwind2
|
||||
@ stub _local_unwind4
|
||||
@ cdecl -i386 _local_unwind4(ptr ptr long) msvcrt._local_unwind4
|
||||
@ cdecl _localtime32(ptr) msvcrt._localtime32
|
||||
@ stub _localtime32_s
|
||||
@ cdecl _localtime64(ptr) msvcrt._localtime64
|
||||
|
|
|
@ -371,7 +371,7 @@
|
|||
@ cdecl _errno() msvcrt._errno
|
||||
@ cdecl -i386 _except_handler2(ptr ptr ptr ptr) msvcrt._except_handler2
|
||||
@ cdecl -i386 _except_handler3(ptr ptr ptr ptr) msvcrt._except_handler3
|
||||
@ stub _except_handler4_common
|
||||
@ cdecl -i386 _except_handler4_common(ptr ptr ptr ptr ptr ptr) msvcrt._except_handler4_common
|
||||
@ varargs _execl(str str) msvcrt._execl
|
||||
@ varargs _execle(str str) msvcrt._execle
|
||||
@ varargs _execlp(str str) msvcrt._execlp
|
||||
|
@ -625,7 +625,7 @@
|
|||
@ stub _lfind_s
|
||||
@ cdecl _loaddll(str) msvcrt._loaddll
|
||||
@ cdecl -i386 _local_unwind2(ptr long) msvcrt._local_unwind2
|
||||
@ stub _local_unwind4
|
||||
@ cdecl -i386 _local_unwind4(ptr ptr long) msvcrt._local_unwind4
|
||||
@ cdecl _localtime32(ptr) msvcrt._localtime32
|
||||
@ stub _localtime32_s
|
||||
@ cdecl _localtime64(ptr) msvcrt._localtime64
|
||||
|
|
|
@ -56,6 +56,15 @@ typedef struct _MSVCRT_EXCEPTION_FRAME
|
|||
PEXCEPTION_POINTERS xpointers;
|
||||
} MSVCRT_EXCEPTION_FRAME;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int gs_cookie_offset;
|
||||
ULONG gs_cookie_xor;
|
||||
int eh_cookie_offset;
|
||||
ULONG eh_cookie_xor;
|
||||
SCOPETABLE entries[1];
|
||||
} SCOPETABLE_V4;
|
||||
|
||||
#define TRYLEVEL_END (-1) /* End of trylevel list */
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
|
@ -99,6 +108,11 @@ static inline int call_unwind_func( int (*func)(void), void *ebp )
|
|||
|
||||
#ifdef __i386__
|
||||
|
||||
static const SCOPETABLE_V4 *get_scopetable_v4( MSVCRT_EXCEPTION_FRAME *frame, ULONG_PTR cookie )
|
||||
{
|
||||
return (const SCOPETABLE_V4 *)((ULONG_PTR)frame->scopetable ^ cookie);
|
||||
}
|
||||
|
||||
static DWORD MSVCRT_nested_handler(PEXCEPTION_RECORD rec,
|
||||
EXCEPTION_REGISTRATION_RECORD* frame,
|
||||
PCONTEXT context,
|
||||
|
@ -158,6 +172,33 @@ static void msvcrt_local_unwind2(MSVCRT_EXCEPTION_FRAME* frame, int trylevel, vo
|
|||
TRACE("unwound OK\n");
|
||||
}
|
||||
|
||||
static void msvcrt_local_unwind4( ULONG *cookie, MSVCRT_EXCEPTION_FRAME* frame, int trylevel, void *ebp )
|
||||
{
|
||||
EXCEPTION_REGISTRATION_RECORD reg;
|
||||
const SCOPETABLE_V4 *scopetable = get_scopetable_v4( frame, *cookie );
|
||||
|
||||
TRACE("(%p,%d,%d)\n",frame, frame->trylevel, trylevel);
|
||||
|
||||
/* Register a handler in case of a nested exception */
|
||||
reg.Handler = MSVCRT_nested_handler;
|
||||
reg.Prev = NtCurrentTeb()->Tib.ExceptionList;
|
||||
__wine_push_frame(®);
|
||||
|
||||
while (frame->trylevel != -2 && frame->trylevel != trylevel)
|
||||
{
|
||||
int level = frame->trylevel;
|
||||
frame->trylevel = scopetable->entries[level].previousTryLevel;
|
||||
if (!scopetable->entries[level].lpfnFilter)
|
||||
{
|
||||
TRACE( "__try block cleanup level %d handler %p ebp %p\n",
|
||||
level, scopetable->entries[level].lpfnHandler, ebp );
|
||||
call_unwind_func( scopetable->entries[level].lpfnHandler, ebp );
|
||||
}
|
||||
}
|
||||
__wine_pop_frame(®);
|
||||
TRACE("unwound OK\n");
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* _local_unwind2 (MSVCRT.@)
|
||||
*/
|
||||
|
@ -166,6 +207,14 @@ void CDECL _local_unwind2(MSVCRT_EXCEPTION_FRAME* frame, int trylevel)
|
|||
msvcrt_local_unwind2( frame, trylevel, &frame->_ebp );
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* _local_unwind4 (MSVCRT.@)
|
||||
*/
|
||||
void CDECL _local_unwind4( ULONG *cookie, MSVCRT_EXCEPTION_FRAME* frame, int trylevel )
|
||||
{
|
||||
msvcrt_local_unwind4( cookie, frame, trylevel, &frame->_ebp );
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* _global_unwind2 (MSVCRT.@)
|
||||
*/
|
||||
|
@ -259,6 +308,78 @@ int CDECL _except_handler3(PEXCEPTION_RECORD rec,
|
|||
return ExceptionContinueSearch;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* _except_handler4_common (MSVCRT.@)
|
||||
*/
|
||||
int CDECL _except_handler4_common( ULONG *cookie, void (*check_cookie)(void),
|
||||
EXCEPTION_RECORD *rec, MSVCRT_EXCEPTION_FRAME *frame,
|
||||
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||
{
|
||||
int retval, trylevel;
|
||||
EXCEPTION_POINTERS exceptPtrs;
|
||||
const SCOPETABLE_V4 *scope_table = get_scopetable_v4( frame, *cookie );
|
||||
|
||||
TRACE( "exception %x flags=%x at %p handler=%p %p %p cookie=%x scope table=%p cookies=%d/%x,%d/%x\n",
|
||||
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
|
||||
frame->handler, context, dispatcher, *cookie, scope_table,
|
||||
scope_table->gs_cookie_offset, scope_table->gs_cookie_xor,
|
||||
scope_table->eh_cookie_offset, scope_table->eh_cookie_xor );
|
||||
|
||||
/* FIXME: no cookie validation yet */
|
||||
|
||||
if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
|
||||
{
|
||||
/* Unwinding the current frame */
|
||||
msvcrt_local_unwind4( cookie, frame, -2, &frame->_ebp );
|
||||
TRACE("unwound current frame, returning ExceptionContinueSearch\n");
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Hunting for handler */
|
||||
exceptPtrs.ExceptionRecord = rec;
|
||||
exceptPtrs.ContextRecord = context;
|
||||
*((DWORD *)frame-1) = (DWORD)&exceptPtrs;
|
||||
trylevel = frame->trylevel;
|
||||
|
||||
while (trylevel != -2)
|
||||
{
|
||||
TRACE( "level %d prev %d filter %p\n", trylevel,
|
||||
scope_table->entries[trylevel].previousTryLevel,
|
||||
scope_table->entries[trylevel].lpfnFilter );
|
||||
if (scope_table->entries[trylevel].lpfnFilter)
|
||||
{
|
||||
retval = call_filter( scope_table->entries[trylevel].lpfnFilter, &exceptPtrs, &frame->_ebp );
|
||||
|
||||
TRACE("filter returned %s\n", retval == EXCEPTION_CONTINUE_EXECUTION ?
|
||||
"CONTINUE_EXECUTION" : retval == EXCEPTION_EXECUTE_HANDLER ?
|
||||
"EXECUTE_HANDLER" : "CONTINUE_SEARCH");
|
||||
|
||||
if (retval == EXCEPTION_CONTINUE_EXECUTION)
|
||||
return ExceptionContinueExecution;
|
||||
|
||||
if (retval == EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
/* Unwind all higher frames, this one will handle the exception */
|
||||
_global_unwind2((EXCEPTION_REGISTRATION_RECORD*)frame);
|
||||
msvcrt_local_unwind4( cookie, frame, trylevel, &frame->_ebp );
|
||||
|
||||
/* Set our trylevel to the enclosing block, and call the __finally
|
||||
* code, which won't return
|
||||
*/
|
||||
frame->trylevel = scope_table->entries[trylevel].previousTryLevel;
|
||||
TRACE("__finally block %p\n",scope_table->entries[trylevel].lpfnHandler);
|
||||
call_finally_block(scope_table->entries[trylevel].lpfnHandler, &frame->_ebp);
|
||||
ERR("Returned from __finally block - expect crash!\n");
|
||||
}
|
||||
}
|
||||
trylevel = scope_table->entries[trylevel].previousTryLevel;
|
||||
}
|
||||
}
|
||||
TRACE("reached -2, returning ExceptionContinueSearch\n");
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* setjmp/longjmp implementation
|
||||
|
|
|
@ -348,7 +348,7 @@
|
|||
@ cdecl _errno() MSVCRT__errno
|
||||
@ cdecl -i386 _except_handler2(ptr ptr ptr ptr)
|
||||
@ cdecl -i386 _except_handler3(ptr ptr ptr ptr)
|
||||
# stub _except_handler4_common
|
||||
@ cdecl -i386 _except_handler4_common(ptr ptr ptr ptr ptr ptr)
|
||||
@ varargs _execl(str str)
|
||||
@ varargs _execle(str str)
|
||||
@ varargs _execlp(str str)
|
||||
|
@ -578,7 +578,7 @@
|
|||
# stub _lfind_s
|
||||
@ cdecl _loaddll(str)
|
||||
@ cdecl -i386 _local_unwind2(ptr long)
|
||||
# stub _local_unwind4
|
||||
@ cdecl -i386 _local_unwind4(ptr ptr long)
|
||||
@ cdecl _localtime32(ptr) MSVCRT__localtime32
|
||||
# stub _localtime32_s
|
||||
@ cdecl _localtime64(ptr) MSVCRT__localtime64
|
||||
|
|
Loading…
Reference in New Issue