ntdll: Use a .seh handler for the unwind exception handler.
This commit is contained in:
parent
658a0665d4
commit
f704b80a26
3 changed files with 87 additions and 58 deletions
|
@ -205,37 +205,67 @@ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEX
|
|||
}
|
||||
|
||||
|
||||
struct unwind_exception_frame
|
||||
{
|
||||
EXCEPTION_REGISTRATION_RECORD frame;
|
||||
DISPATCHER_CONTEXT *dispatch;
|
||||
};
|
||||
|
||||
/**********************************************************************
|
||||
* unwind_exception_handler
|
||||
*
|
||||
* Handler for exceptions happening while calling an unwind handler.
|
||||
*/
|
||||
static DWORD __cdecl unwind_exception_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
|
||||
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||
EXCEPTION_DISPOSITION WINAPI unwind_exception_handler( EXCEPTION_RECORD *record, void *frame,
|
||||
CONTEXT *context, DISPATCHER_CONTEXT *dispatch )
|
||||
{
|
||||
struct unwind_exception_frame *unwind_frame = (struct unwind_exception_frame *)frame;
|
||||
DISPATCHER_CONTEXT *dispatch = (DISPATCHER_CONTEXT *)dispatcher;
|
||||
DISPATCHER_CONTEXT *orig_dispatch = ((DISPATCHER_CONTEXT **)frame)[-2];
|
||||
|
||||
/* copy the original dispatcher into the current one, except for the TargetIp */
|
||||
dispatch->ControlPc = unwind_frame->dispatch->ControlPc;
|
||||
dispatch->ImageBase = unwind_frame->dispatch->ImageBase;
|
||||
dispatch->FunctionEntry = unwind_frame->dispatch->FunctionEntry;
|
||||
dispatch->EstablisherFrame = unwind_frame->dispatch->EstablisherFrame;
|
||||
dispatch->ContextRecord = unwind_frame->dispatch->ContextRecord;
|
||||
dispatch->LanguageHandler = unwind_frame->dispatch->LanguageHandler;
|
||||
dispatch->HandlerData = unwind_frame->dispatch->HandlerData;
|
||||
dispatch->HistoryTable = unwind_frame->dispatch->HistoryTable;
|
||||
dispatch->ScopeIndex = unwind_frame->dispatch->ScopeIndex;
|
||||
dispatch->ControlPc = orig_dispatch->ControlPc;
|
||||
dispatch->ImageBase = orig_dispatch->ImageBase;
|
||||
dispatch->FunctionEntry = orig_dispatch->FunctionEntry;
|
||||
dispatch->EstablisherFrame = orig_dispatch->EstablisherFrame;
|
||||
dispatch->ContextRecord = orig_dispatch->ContextRecord;
|
||||
dispatch->LanguageHandler = orig_dispatch->LanguageHandler;
|
||||
dispatch->HandlerData = orig_dispatch->HandlerData;
|
||||
dispatch->HistoryTable = orig_dispatch->HistoryTable;
|
||||
dispatch->ScopeIndex = orig_dispatch->ScopeIndex;
|
||||
TRACE( "detected collided unwind\n" );
|
||||
return ExceptionCollidedUnwind;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* unwind_handler_wrapper
|
||||
*/
|
||||
#ifdef __WINE_PE_BUILD
|
||||
extern DWORD WINAPI unwind_handler_wrapper( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch );
|
||||
__ASM_GLOBAL_FUNC( unwind_handler_wrapper,
|
||||
"push {r1,lr}\n\t"
|
||||
".seh_save_regs {r1,lr}\n\t"
|
||||
".seh_endprologue\n\t"
|
||||
".seh_handler " __ASM_NAME("unwind_exception_handler") ", %except, %unwind\n\t"
|
||||
"mov r3, r1\n\t" /* dispatch */
|
||||
"ldr r1, [r3, #0x0c]\n\t" /* dispatch->EstablisherFrame */
|
||||
"ldr r2, [r3, #0x14]\n\t" /* dispatch->ContextRecord */
|
||||
"ldr ip, [r3, #0x18]\n\t" /* dispatch->LanguageHandler */
|
||||
"blx ip\n\t"
|
||||
"pop {r1,pc}\n\t" )
|
||||
#else
|
||||
static DWORD unwind_handler_wrapper( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch )
|
||||
{
|
||||
struct
|
||||
{
|
||||
DISPATCHER_CONTEXT *dispatch;
|
||||
ULONG lr;
|
||||
EXCEPTION_REGISTRATION_RECORD frame;
|
||||
} frame;
|
||||
DWORD res;
|
||||
|
||||
frame.frame.Handler = (PEXCEPTION_HANDLER)unwind_exception_handler;
|
||||
frame.dispatch = dispatch;
|
||||
__wine_push_frame( &frame.frame );
|
||||
res = dispatch->LanguageHandler( rec, (void *)dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch );
|
||||
__wine_pop_frame( &frame.frame );
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* call_unwind_handler
|
||||
*
|
||||
|
@ -243,20 +273,13 @@ static DWORD __cdecl unwind_exception_handler( EXCEPTION_RECORD *rec, EXCEPTION_
|
|||
*/
|
||||
static DWORD call_unwind_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch )
|
||||
{
|
||||
struct unwind_exception_frame frame;
|
||||
DWORD res;
|
||||
|
||||
frame.frame.Handler = unwind_exception_handler;
|
||||
frame.dispatch = dispatch;
|
||||
__wine_push_frame( &frame.frame );
|
||||
|
||||
TRACE( "calling handler %p (rec=%p, frame=0x%lx context=%p, dispatch=%p)\n",
|
||||
dispatch->LanguageHandler, rec, dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch );
|
||||
res = dispatch->LanguageHandler( rec, (void *)dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch );
|
||||
res = unwind_handler_wrapper( rec, dispatch );
|
||||
TRACE( "handler %p returned %lx\n", dispatch->LanguageHandler, res );
|
||||
|
||||
__wine_pop_frame( &frame.frame );
|
||||
|
||||
switch (res)
|
||||
{
|
||||
case ExceptionContinueSearch:
|
||||
|
|
|
@ -206,37 +206,50 @@ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEX
|
|||
}
|
||||
|
||||
|
||||
struct unwind_exception_frame
|
||||
{
|
||||
EXCEPTION_REGISTRATION_RECORD frame;
|
||||
DISPATCHER_CONTEXT *dispatch;
|
||||
};
|
||||
|
||||
/**********************************************************************
|
||||
* unwind_exception_handler
|
||||
*
|
||||
* Handler for exceptions happening while calling an unwind handler.
|
||||
*/
|
||||
static DWORD __cdecl unwind_exception_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
|
||||
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||
EXCEPTION_DISPOSITION WINAPI unwind_exception_handler( EXCEPTION_RECORD *record, void *frame,
|
||||
CONTEXT *context, DISPATCHER_CONTEXT *dispatch )
|
||||
{
|
||||
struct unwind_exception_frame *unwind_frame = (struct unwind_exception_frame *)frame;
|
||||
DISPATCHER_CONTEXT *dispatch = (DISPATCHER_CONTEXT *)dispatcher;
|
||||
DISPATCHER_CONTEXT *orig_dispatch = ((DISPATCHER_CONTEXT **)frame)[-2];
|
||||
|
||||
/* copy the original dispatcher into the current one, except for the TargetIp */
|
||||
dispatch->ControlPc = unwind_frame->dispatch->ControlPc;
|
||||
dispatch->ImageBase = unwind_frame->dispatch->ImageBase;
|
||||
dispatch->FunctionEntry = unwind_frame->dispatch->FunctionEntry;
|
||||
dispatch->EstablisherFrame = unwind_frame->dispatch->EstablisherFrame;
|
||||
dispatch->ContextRecord = unwind_frame->dispatch->ContextRecord;
|
||||
dispatch->LanguageHandler = unwind_frame->dispatch->LanguageHandler;
|
||||
dispatch->HandlerData = unwind_frame->dispatch->HandlerData;
|
||||
dispatch->HistoryTable = unwind_frame->dispatch->HistoryTable;
|
||||
dispatch->ScopeIndex = unwind_frame->dispatch->ScopeIndex;
|
||||
/* copy the original dispatcher into the current one, except for the TargetPc */
|
||||
dispatch->ControlPc = orig_dispatch->ControlPc;
|
||||
dispatch->ImageBase = orig_dispatch->ImageBase;
|
||||
dispatch->FunctionEntry = orig_dispatch->FunctionEntry;
|
||||
dispatch->EstablisherFrame = orig_dispatch->EstablisherFrame;
|
||||
dispatch->ContextRecord = orig_dispatch->ContextRecord;
|
||||
dispatch->LanguageHandler = orig_dispatch->LanguageHandler;
|
||||
dispatch->HandlerData = orig_dispatch->HandlerData;
|
||||
dispatch->HistoryTable = orig_dispatch->HistoryTable;
|
||||
dispatch->ScopeIndex = orig_dispatch->ScopeIndex;
|
||||
TRACE( "detected collided unwind\n" );
|
||||
return ExceptionCollidedUnwind;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* unwind_handler_wrapper
|
||||
*/
|
||||
extern DWORD WINAPI unwind_handler_wrapper( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch );
|
||||
__ASM_GLOBAL_FUNC( unwind_handler_wrapper,
|
||||
"stp x29, x30, [sp, #-32]!\n\t"
|
||||
".seh_save_fplr_x 32\n\t"
|
||||
"mov x29, sp\n\t"
|
||||
".seh_set_fp\n\t"
|
||||
".seh_endprologue\n\t"
|
||||
".seh_handler " __ASM_NAME("unwind_exception_handler") ", @except, @unwind\n\t"
|
||||
"str x1, [sp, #16]\n\t" /* frame[-2] = dispatch */
|
||||
"mov x3, x1\n\t"
|
||||
"ldr x1, [x3, #0x18]\n\t" /* dispatch->EstablisherFrame */
|
||||
"ldr x2, [x3, #0x28]\n\t" /* dispatch->ContextRecord */
|
||||
"ldr x15, [x3, #0x30]\n\t" /* dispatch->LanguageHandler */
|
||||
"blr x15\n\t"
|
||||
"ldp x29, x30, [sp], #32\n\t"
|
||||
"ret" )
|
||||
|
||||
/**********************************************************************
|
||||
* call_unwind_handler
|
||||
*
|
||||
|
@ -244,20 +257,13 @@ static DWORD __cdecl unwind_exception_handler( EXCEPTION_RECORD *rec, EXCEPTION_
|
|||
*/
|
||||
static DWORD call_unwind_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch )
|
||||
{
|
||||
struct unwind_exception_frame frame;
|
||||
DWORD res;
|
||||
|
||||
frame.frame.Handler = unwind_exception_handler;
|
||||
frame.dispatch = dispatch;
|
||||
__wine_push_frame( &frame.frame );
|
||||
|
||||
TRACE( "calling handler %p (rec=%p, frame=%I64x context=%p, dispatch=%p)\n",
|
||||
dispatch->LanguageHandler, rec, dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch );
|
||||
res = dispatch->LanguageHandler( rec, (void *)dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch );
|
||||
dispatch->LanguageHandler, rec, dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch );
|
||||
res = unwind_handler_wrapper( rec, dispatch );
|
||||
TRACE( "handler %p returned %lx\n", dispatch->LanguageHandler, res );
|
||||
|
||||
__wine_pop_frame( &frame.frame );
|
||||
|
||||
switch (res)
|
||||
{
|
||||
case ExceptionContinueSearch:
|
||||
|
|
|
@ -367,9 +367,9 @@ DWORD WINAPI exception_handler_call_wrapper( EXCEPTION_RECORD *rec, void *frame,
|
|||
C_ASSERT( offsetof(DISPATCHER_CONTEXT, LanguageHandler) == 0x30 );
|
||||
|
||||
__ASM_GLOBAL_FUNC( exception_handler_call_wrapper,
|
||||
".seh_endprologue\n\t"
|
||||
"subq $0x28, %rsp\n\t"
|
||||
".seh_stackalloc 0x28\n\t"
|
||||
".seh_endprologue\n\t"
|
||||
"callq *0x30(%r9)\n\t" /* dispatch->LanguageHandler */
|
||||
"nop\n\t" /* avoid epilogue so handler is called */
|
||||
"addq $0x28, %rsp\n\t"
|
||||
|
@ -1076,9 +1076,9 @@ C_ASSERT( offsetof(struct unwind_exception_frame, dispatch) == 0x20 );
|
|||
C_ASSERT( offsetof(DISPATCHER_CONTEXT, LanguageHandler) == 0x30 );
|
||||
|
||||
__ASM_GLOBAL_FUNC( unwind_handler_call_wrapper,
|
||||
".seh_endprologue\n\t"
|
||||
"subq $0x28,%rsp\n\t"
|
||||
".seh_stackalloc 0x28\n\t"
|
||||
".seh_endprologue\n\t"
|
||||
"movq %r9,0x20(%rsp)\n\t" /* unwind_exception_frame->dispatch */
|
||||
"callq *0x30(%r9)\n\t" /* dispatch->LanguageHandler */
|
||||
"nop\n\t" /* avoid epilogue so handler is called */
|
||||
|
|
Loading…
Add table
Reference in a new issue