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 _errno() msvcrt._errno
|
||||||
@ cdecl -i386 _except_handler2(ptr ptr ptr ptr) msvcrt._except_handler2
|
@ cdecl -i386 _except_handler2(ptr ptr ptr ptr) msvcrt._except_handler2
|
||||||
@ cdecl -i386 _except_handler3(ptr ptr ptr ptr) msvcrt._except_handler3
|
@ 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 _execl(str str) msvcrt._execl
|
||||||
@ varargs _execle(str str) msvcrt._execle
|
@ varargs _execle(str str) msvcrt._execle
|
||||||
@ varargs _execlp(str str) msvcrt._execlp
|
@ varargs _execlp(str str) msvcrt._execlp
|
||||||
@ -637,7 +637,7 @@
|
|||||||
@ stub _lfind_s
|
@ stub _lfind_s
|
||||||
@ cdecl _loaddll(str) msvcrt._loaddll
|
@ cdecl _loaddll(str) msvcrt._loaddll
|
||||||
@ cdecl -i386 _local_unwind2(ptr long) msvcrt._local_unwind2
|
@ 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
|
@ cdecl _localtime32(ptr) msvcrt._localtime32
|
||||||
@ stub _localtime32_s
|
@ stub _localtime32_s
|
||||||
@ cdecl _localtime64(ptr) msvcrt._localtime64
|
@ cdecl _localtime64(ptr) msvcrt._localtime64
|
||||||
|
@ -371,7 +371,7 @@
|
|||||||
@ cdecl _errno() msvcrt._errno
|
@ cdecl _errno() msvcrt._errno
|
||||||
@ cdecl -i386 _except_handler2(ptr ptr ptr ptr) msvcrt._except_handler2
|
@ cdecl -i386 _except_handler2(ptr ptr ptr ptr) msvcrt._except_handler2
|
||||||
@ cdecl -i386 _except_handler3(ptr ptr ptr ptr) msvcrt._except_handler3
|
@ 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 _execl(str str) msvcrt._execl
|
||||||
@ varargs _execle(str str) msvcrt._execle
|
@ varargs _execle(str str) msvcrt._execle
|
||||||
@ varargs _execlp(str str) msvcrt._execlp
|
@ varargs _execlp(str str) msvcrt._execlp
|
||||||
@ -625,7 +625,7 @@
|
|||||||
@ stub _lfind_s
|
@ stub _lfind_s
|
||||||
@ cdecl _loaddll(str) msvcrt._loaddll
|
@ cdecl _loaddll(str) msvcrt._loaddll
|
||||||
@ cdecl -i386 _local_unwind2(ptr long) msvcrt._local_unwind2
|
@ 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
|
@ cdecl _localtime32(ptr) msvcrt._localtime32
|
||||||
@ stub _localtime32_s
|
@ stub _localtime32_s
|
||||||
@ cdecl _localtime64(ptr) msvcrt._localtime64
|
@ cdecl _localtime64(ptr) msvcrt._localtime64
|
||||||
|
@ -56,6 +56,15 @@ typedef struct _MSVCRT_EXCEPTION_FRAME
|
|||||||
PEXCEPTION_POINTERS xpointers;
|
PEXCEPTION_POINTERS xpointers;
|
||||||
} MSVCRT_EXCEPTION_FRAME;
|
} 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 */
|
#define TRYLEVEL_END (-1) /* End of trylevel list */
|
||||||
|
|
||||||
#if defined(__GNUC__) && defined(__i386__)
|
#if defined(__GNUC__) && defined(__i386__)
|
||||||
@ -99,6 +108,11 @@ static inline int call_unwind_func( int (*func)(void), void *ebp )
|
|||||||
|
|
||||||
#ifdef __i386__
|
#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,
|
static DWORD MSVCRT_nested_handler(PEXCEPTION_RECORD rec,
|
||||||
EXCEPTION_REGISTRATION_RECORD* frame,
|
EXCEPTION_REGISTRATION_RECORD* frame,
|
||||||
PCONTEXT context,
|
PCONTEXT context,
|
||||||
@ -158,6 +172,33 @@ static void msvcrt_local_unwind2(MSVCRT_EXCEPTION_FRAME* frame, int trylevel, vo
|
|||||||
TRACE("unwound OK\n");
|
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.@)
|
* _local_unwind2 (MSVCRT.@)
|
||||||
*/
|
*/
|
||||||
@ -166,6 +207,14 @@ void CDECL _local_unwind2(MSVCRT_EXCEPTION_FRAME* frame, int trylevel)
|
|||||||
msvcrt_local_unwind2( frame, trylevel, &frame->_ebp );
|
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.@)
|
* _global_unwind2 (MSVCRT.@)
|
||||||
*/
|
*/
|
||||||
@ -259,6 +308,78 @@ int CDECL _except_handler3(PEXCEPTION_RECORD rec,
|
|||||||
return ExceptionContinueSearch;
|
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
|
* setjmp/longjmp implementation
|
||||||
|
@ -348,7 +348,7 @@
|
|||||||
@ cdecl _errno() MSVCRT__errno
|
@ cdecl _errno() MSVCRT__errno
|
||||||
@ cdecl -i386 _except_handler2(ptr ptr ptr ptr)
|
@ cdecl -i386 _except_handler2(ptr ptr ptr ptr)
|
||||||
@ cdecl -i386 _except_handler3(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 _execl(str str)
|
||||||
@ varargs _execle(str str)
|
@ varargs _execle(str str)
|
||||||
@ varargs _execlp(str str)
|
@ varargs _execlp(str str)
|
||||||
@ -578,7 +578,7 @@
|
|||||||
# stub _lfind_s
|
# stub _lfind_s
|
||||||
@ cdecl _loaddll(str)
|
@ cdecl _loaddll(str)
|
||||||
@ cdecl -i386 _local_unwind2(ptr long)
|
@ cdecl -i386 _local_unwind2(ptr long)
|
||||||
# stub _local_unwind4
|
@ cdecl -i386 _local_unwind4(ptr ptr long)
|
||||||
@ cdecl _localtime32(ptr) MSVCRT__localtime32
|
@ cdecl _localtime32(ptr) MSVCRT__localtime32
|
||||||
# stub _localtime32_s
|
# stub _localtime32_s
|
||||||
@ cdecl _localtime64(ptr) MSVCRT__localtime64
|
@ cdecl _localtime64(ptr) MSVCRT__localtime64
|
||||||
|
Loading…
x
Reference in New Issue
Block a user