ntdll: Move NtRaiseException() implementation to the Unix library.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
3cc3b44575
commit
e561ce4b92
|
@ -239,6 +239,15 @@ void raise_status( NTSTATUS status, EXCEPTION_RECORD *rec )
|
|||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* NtRaiseException (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
|
||||
{
|
||||
return unix_funcs->NtRaiseException( rec, context, first_chance );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* RtlRaiseStatus (NTDLL.@)
|
||||
*
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
@ stub KiRaiseUserExceptionDispatcher
|
||||
@ stub KiUserApcDispatcher
|
||||
@ stub KiUserCallbackDispatcher
|
||||
@ stub KiUserExceptionDispatcher
|
||||
@ stdcall -norelay KiUserExceptionDispatcher(ptr ptr)
|
||||
# @ stub LdrAccessOutOfProcessResource
|
||||
@ stdcall LdrAccessResource(long ptr ptr ptr)
|
||||
@ stdcall LdrAddDllDirectory(ptr ptr)
|
||||
|
|
|
@ -492,6 +492,52 @@ static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL f
|
|||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* KiUserExceptionDispatcher (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *context )
|
||||
{
|
||||
NTSTATUS status;
|
||||
DWORD c;
|
||||
|
||||
TRACE( "code=%x flags=%x addr=%p pc=%08x tid=%04x\n",
|
||||
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
|
||||
context->Pc, GetCurrentThreadId() );
|
||||
for (c = 0; c < rec->NumberParameters; c++)
|
||||
TRACE( " info[%d]=%08lx\n", c, rec->ExceptionInformation[c] );
|
||||
|
||||
if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
|
||||
{
|
||||
if (rec->ExceptionInformation[1] >> 16)
|
||||
MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
|
||||
rec->ExceptionAddress,
|
||||
(char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
|
||||
else
|
||||
MESSAGE( "wine: Call from %p to unimplemented function %s.%ld, aborting\n",
|
||||
rec->ExceptionAddress,
|
||||
(char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE( " r0=%08x r1=%08x r2=%08x r3=%08x r4=%08x r5=%08x\n",
|
||||
context->R0, context->R1, context->R2, context->R3, context->R4, context->R5 );
|
||||
TRACE( " r6=%08x r7=%08x r8=%08x r9=%08x r10=%08x r11=%08x\n",
|
||||
context->R6, context->R7, context->R8, context->R9, context->R10, context->R11 );
|
||||
TRACE( " r12=%08x sp=%08x lr=%08x pc=%08x cpsr=%08x\n",
|
||||
context->R12, context->Sp, context->Lr, context->Pc, context->Cpsr );
|
||||
}
|
||||
|
||||
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
|
||||
NtSetContextThread( GetCurrentThread(), context );
|
||||
|
||||
if ((status = call_stack_handlers( rec, context )) == STATUS_SUCCESS)
|
||||
NtSetContextThread( GetCurrentThread(), context );
|
||||
|
||||
if (status != STATUS_UNHANDLED_EXCEPTION) RtlRaiseStatus( status );
|
||||
return NtRaiseException( rec, context, FALSE );
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* segv_handler
|
||||
*
|
||||
|
@ -833,15 +879,6 @@ void WINAPI RtlUnwind( void *endframe, void *target_ip, EXCEPTION_RECORD *rec, v
|
|||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* NtRaiseException (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
|
||||
{
|
||||
NTSTATUS status = raise_exception( rec, context, first_chance );
|
||||
if (status == STATUS_SUCCESS) NtSetContextThread( GetCurrentThread(), context );
|
||||
return status;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RtlRaiseException (NTDLL.@)
|
||||
|
@ -849,12 +886,10 @@ NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL
|
|||
void WINAPI RtlRaiseException( EXCEPTION_RECORD *rec )
|
||||
{
|
||||
CONTEXT context;
|
||||
NTSTATUS status;
|
||||
|
||||
RtlCaptureContext( &context );
|
||||
rec->ExceptionAddress = (LPVOID)context.Pc;
|
||||
status = raise_exception( rec, &context, TRUE );
|
||||
if (status) raise_status( status, rec );
|
||||
RtlRaiseStatus( NtRaiseException( rec, &context, TRUE ));
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
|
|
@ -736,77 +736,60 @@ static NTSTATUS call_function_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_con
|
|||
return STATUS_UNHANDLED_EXCEPTION;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* raise_exception
|
||||
*
|
||||
* Implementation of NtRaiseException.
|
||||
* KiUserExceptionDispatcher (NTDLL.@)
|
||||
*/
|
||||
static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
|
||||
NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *context )
|
||||
{
|
||||
NTSTATUS status;
|
||||
DWORD c;
|
||||
|
||||
if (first_chance)
|
||||
TRACE( "code=%x flags=%x addr=%p pc=%lx tid=%04x\n",
|
||||
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
|
||||
context->Pc, GetCurrentThreadId() );
|
||||
for (c = 0; c < rec->NumberParameters; c++)
|
||||
TRACE( " info[%d]=%016lx\n", c, rec->ExceptionInformation[c] );
|
||||
|
||||
if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
|
||||
{
|
||||
DWORD c;
|
||||
|
||||
TRACE( "code=%x flags=%x addr=%p pc=%lx tid=%04x\n",
|
||||
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
|
||||
context->Pc, GetCurrentThreadId() );
|
||||
for (c = 0; c < rec->NumberParameters; c++)
|
||||
TRACE( " info[%d]=%016lx\n", c, rec->ExceptionInformation[c] );
|
||||
if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
|
||||
{
|
||||
if (rec->ExceptionInformation[1] >> 16)
|
||||
MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
|
||||
rec->ExceptionAddress,
|
||||
(char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
|
||||
else
|
||||
MESSAGE( "wine: Call from %p to unimplemented function %s.%ld, aborting\n",
|
||||
rec->ExceptionAddress,
|
||||
(char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
|
||||
}
|
||||
if (rec->ExceptionInformation[1] >> 16)
|
||||
MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
|
||||
rec->ExceptionAddress,
|
||||
(char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
|
||||
else
|
||||
{
|
||||
TRACE(" x0=%016lx x1=%016lx x2=%016lx x3=%016lx\n",
|
||||
context->u.s.X0, context->u.s.X1, context->u.s.X2, context->u.s.X3 );
|
||||
TRACE(" x4=%016lx x5=%016lx x6=%016lx x7=%016lx\n",
|
||||
context->u.s.X4, context->u.s.X5, context->u.s.X6, context->u.s.X7 );
|
||||
TRACE(" x8=%016lx x9=%016lx x10=%016lx x11=%016lx\n",
|
||||
context->u.s.X8, context->u.s.X9, context->u.s.X10, context->u.s.X11 );
|
||||
TRACE(" x12=%016lx x13=%016lx x14=%016lx x15=%016lx\n",
|
||||
context->u.s.X12, context->u.s.X13, context->u.s.X14, context->u.s.X15 );
|
||||
TRACE(" x16=%016lx x17=%016lx x18=%016lx x19=%016lx\n",
|
||||
context->u.s.X16, context->u.s.X17, context->u.s.X18, context->u.s.X19 );
|
||||
TRACE(" x20=%016lx x21=%016lx x22=%016lx x23=%016lx\n",
|
||||
context->u.s.X20, context->u.s.X21, context->u.s.X22, context->u.s.X23 );
|
||||
TRACE(" x24=%016lx x25=%016lx x26=%016lx x27=%016lx\n",
|
||||
context->u.s.X24, context->u.s.X25, context->u.s.X26, context->u.s.X27 );
|
||||
TRACE(" x28=%016lx fp=%016lx lr=%016lx sp=%016lx\n",
|
||||
context->u.s.X28, context->u.s.Fp, context->u.s.Lr, context->Sp );
|
||||
}
|
||||
|
||||
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION) goto done;
|
||||
|
||||
if ((status = call_function_handlers( rec, context )) == STATUS_SUCCESS) goto done;
|
||||
if (status != STATUS_UNHANDLED_EXCEPTION) return status;
|
||||
MESSAGE( "wine: Call from %p to unimplemented function %s.%ld, aborting\n",
|
||||
rec->ExceptionAddress,
|
||||
(char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE(" x0=%016lx x1=%016lx x2=%016lx x3=%016lx\n",
|
||||
context->u.s.X0, context->u.s.X1, context->u.s.X2, context->u.s.X3 );
|
||||
TRACE(" x4=%016lx x5=%016lx x6=%016lx x7=%016lx\n",
|
||||
context->u.s.X4, context->u.s.X5, context->u.s.X6, context->u.s.X7 );
|
||||
TRACE(" x8=%016lx x9=%016lx x10=%016lx x11=%016lx\n",
|
||||
context->u.s.X8, context->u.s.X9, context->u.s.X10, context->u.s.X11 );
|
||||
TRACE(" x12=%016lx x13=%016lx x14=%016lx x15=%016lx\n",
|
||||
context->u.s.X12, context->u.s.X13, context->u.s.X14, context->u.s.X15 );
|
||||
TRACE(" x16=%016lx x17=%016lx x18=%016lx x19=%016lx\n",
|
||||
context->u.s.X16, context->u.s.X17, context->u.s.X18, context->u.s.X19 );
|
||||
TRACE(" x20=%016lx x21=%016lx x22=%016lx x23=%016lx\n",
|
||||
context->u.s.X20, context->u.s.X21, context->u.s.X22, context->u.s.X23 );
|
||||
TRACE(" x24=%016lx x25=%016lx x26=%016lx x27=%016lx\n",
|
||||
context->u.s.X24, context->u.s.X25, context->u.s.X26, context->u.s.X27 );
|
||||
TRACE(" x28=%016lx fp=%016lx lr=%016lx sp=%016lx\n",
|
||||
context->u.s.X28, context->u.s.Fp, context->u.s.Lr, context->Sp );
|
||||
}
|
||||
|
||||
/* last chance exception */
|
||||
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
|
||||
NtSetContextThread( GetCurrentThread(), context );
|
||||
|
||||
status = send_debug_event( rec, FALSE, context );
|
||||
if (status != DBG_CONTINUE)
|
||||
{
|
||||
if (rec->ExceptionFlags & EH_STACK_INVALID)
|
||||
ERR("Exception frame is not in stack limits => unable to dispatch exception.\n");
|
||||
else if (rec->ExceptionCode == STATUS_NONCONTINUABLE_EXCEPTION)
|
||||
ERR("Process attempted to continue execution after noncontinuable exception.\n");
|
||||
else
|
||||
ERR("Unhandled exception code %x flags %x addr %p\n",
|
||||
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
|
||||
NtTerminateProcess( NtCurrentProcess(), rec->ExceptionCode );
|
||||
}
|
||||
done:
|
||||
return NtSetContextThread( GetCurrentThread(), context );
|
||||
if ((status = call_function_handlers( rec, context )) == STATUS_SUCCESS)
|
||||
NtSetContextThread( GetCurrentThread(), context );
|
||||
|
||||
if (status != STATUS_UNHANDLED_EXCEPTION) RtlRaiseStatus( status );
|
||||
return NtRaiseException( rec, context, FALSE );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -833,14 +816,6 @@ static struct stack_layout *setup_exception( ucontext_t *sigcontext )
|
|||
return stack;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* raise_generic_exception
|
||||
*/
|
||||
static void WINAPI raise_generic_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
|
||||
{
|
||||
NTSTATUS status = raise_exception( rec, context, TRUE );
|
||||
raise_status( status, rec );
|
||||
}
|
||||
|
||||
extern void raise_func_trampoline( EXCEPTION_RECORD *rec, CONTEXT *context, raise_func func, void *sp );
|
||||
__ASM_GLOBAL_FUNC( raise_func_trampoline,
|
||||
|
@ -880,7 +855,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout *
|
|||
PC_sig(sigcontext) = (ULONG_PTR)raise_func_trampoline; /* raise_generic_exception; */
|
||||
REGn_sig(0, sigcontext) = (ULONG_PTR)&stack->rec; /* first arg for raise_generic_exception */
|
||||
REGn_sig(1, sigcontext) = (ULONG_PTR)&stack->context; /* second arg for raise_generic_exception */
|
||||
REGn_sig(2, sigcontext) = (ULONG_PTR)raise_generic_exception; /* third arg for raise_func_trampoline */
|
||||
REGn_sig(2, sigcontext) = (ULONG_PTR)KiUserExceptionDispatcher; /* third arg for raise_func_trampoline */
|
||||
REGn_sig(18, sigcontext) = (ULONG_PTR)NtCurrentTeb();
|
||||
}
|
||||
|
||||
|
@ -1829,19 +1804,6 @@ void WINAPI RtlUnwind( void *frame, void *target_ip, EXCEPTION_RECORD *rec, void
|
|||
RtlUnwindEx( frame, target_ip, rec, retval, &context, NULL );
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* NtRaiseException (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
|
||||
{
|
||||
if (first_chance)
|
||||
{
|
||||
NTSTATUS status = send_debug_event( rec, TRUE, context );
|
||||
if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
|
||||
NtSetContextThread( GetCurrentThread(), context );
|
||||
}
|
||||
return raise_exception( rec, context, first_chance );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RtlRaiseException (NTDLL.@)
|
||||
|
|
|
@ -719,69 +719,51 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
|
|||
|
||||
|
||||
/*******************************************************************
|
||||
* raise_exception
|
||||
*
|
||||
* Implementation of NtRaiseException.
|
||||
* KiUserExceptionDispatcher (NTDLL.@)
|
||||
*/
|
||||
static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
|
||||
NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *context )
|
||||
{
|
||||
NTSTATUS status;
|
||||
DWORD c;
|
||||
|
||||
if (first_chance)
|
||||
TRACE( "code=%x flags=%x addr=%p ip=%08x tid=%04x\n",
|
||||
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
|
||||
context->Eip, GetCurrentThreadId() );
|
||||
for (c = 0; c < rec->NumberParameters; c++)
|
||||
TRACE( " info[%d]=%08lx\n", c, rec->ExceptionInformation[c] );
|
||||
|
||||
if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
|
||||
{
|
||||
DWORD c;
|
||||
|
||||
TRACE( "code=%x flags=%x addr=%p ip=%08x tid=%04x\n",
|
||||
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
|
||||
context->Eip, GetCurrentThreadId() );
|
||||
for (c = 0; c < rec->NumberParameters; c++)
|
||||
TRACE( " info[%d]=%08lx\n", c, rec->ExceptionInformation[c] );
|
||||
if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
|
||||
{
|
||||
if (rec->ExceptionInformation[1] >> 16)
|
||||
MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
|
||||
rec->ExceptionAddress,
|
||||
(char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
|
||||
else
|
||||
MESSAGE( "wine: Call from %p to unimplemented function %s.%ld, aborting\n",
|
||||
rec->ExceptionAddress,
|
||||
(char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
|
||||
}
|
||||
if (rec->ExceptionInformation[1] >> 16)
|
||||
MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
|
||||
rec->ExceptionAddress,
|
||||
(char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
|
||||
else
|
||||
{
|
||||
TRACE(" eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\n",
|
||||
context->Eax, context->Ebx, context->Ecx,
|
||||
context->Edx, context->Esi, context->Edi );
|
||||
TRACE(" ebp=%08x esp=%08x cs=%04x ds=%04x es=%04x fs=%04x gs=%04x flags=%08x\n",
|
||||
context->Ebp, context->Esp, context->SegCs, context->SegDs,
|
||||
context->SegEs, context->SegFs, context->SegGs, context->EFlags );
|
||||
}
|
||||
|
||||
/* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
|
||||
if (rec->ExceptionCode == EXCEPTION_BREAKPOINT) context->Eip--;
|
||||
|
||||
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION) goto done;
|
||||
|
||||
if ((status = call_stack_handlers( rec, context )) == STATUS_SUCCESS) goto done;
|
||||
if (status != STATUS_UNHANDLED_EXCEPTION) return status;
|
||||
MESSAGE( "wine: Call from %p to unimplemented function %s.%ld, aborting\n",
|
||||
rec->ExceptionAddress,
|
||||
(char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE(" eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\n",
|
||||
context->Eax, context->Ebx, context->Ecx,
|
||||
context->Edx, context->Esi, context->Edi );
|
||||
TRACE(" ebp=%08x esp=%08x cs=%04x ds=%04x es=%04x fs=%04x gs=%04x flags=%08x\n",
|
||||
context->Ebp, context->Esp, context->SegCs, context->SegDs,
|
||||
context->SegEs, context->SegFs, context->SegGs, context->EFlags );
|
||||
}
|
||||
|
||||
/* last chance exception */
|
||||
/* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
|
||||
if (rec->ExceptionCode == EXCEPTION_BREAKPOINT) context->Eip--;
|
||||
|
||||
status = send_debug_event( rec, FALSE, context );
|
||||
if (status != DBG_CONTINUE)
|
||||
{
|
||||
if (rec->ExceptionFlags & EH_STACK_INVALID)
|
||||
WINE_ERR("Exception frame is not in stack limits => unable to dispatch exception.\n");
|
||||
else if (rec->ExceptionCode == STATUS_NONCONTINUABLE_EXCEPTION)
|
||||
WINE_ERR("Process attempted to continue execution after noncontinuable exception.\n");
|
||||
else
|
||||
WINE_ERR("Unhandled exception code %x flags %x addr %p\n",
|
||||
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
|
||||
NtTerminateProcess( NtCurrentProcess(), rec->ExceptionCode );
|
||||
}
|
||||
done:
|
||||
return NtSetContextThread( GetCurrentThread(), context );
|
||||
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
|
||||
NtSetContextThread( GetCurrentThread(), context );
|
||||
|
||||
if ((status = call_stack_handlers( rec, context )) == STATUS_SUCCESS)
|
||||
NtSetContextThread( GetCurrentThread(), context );
|
||||
|
||||
if (status != STATUS_UNHANDLED_EXCEPTION) RtlRaiseStatus( status );
|
||||
return NtRaiseException( rec, context, FALSE );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1513,20 +1495,6 @@ static struct stack_layout *setup_exception( ucontext_t *sigcontext )
|
|||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* raise_generic_exception
|
||||
*
|
||||
* Generic raise function for exceptions that don't need special treatment.
|
||||
*/
|
||||
static void WINAPI raise_generic_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
status = raise_exception( rec, context, TRUE );
|
||||
raise_status( status, rec );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* setup_raise_exception
|
||||
*
|
||||
|
@ -1542,7 +1510,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout *
|
|||
return;
|
||||
}
|
||||
ESP_sig(sigcontext) = (DWORD)stack;
|
||||
EIP_sig(sigcontext) = (DWORD)raise_generic_exception;
|
||||
EIP_sig(sigcontext) = (DWORD)KiUserExceptionDispatcher;
|
||||
/* clear single-step, direction, and align check flag */
|
||||
EFL_sig(sigcontext) &= ~(0x100|0x400|0x40000);
|
||||
CS_sig(sigcontext) = get_cs();
|
||||
|
@ -1551,8 +1519,8 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout *
|
|||
FS_sig(sigcontext) = get_fs();
|
||||
GS_sig(sigcontext) = get_gs();
|
||||
SS_sig(sigcontext) = get_ds();
|
||||
stack->ret_addr = (void *)0xdeadbabe; /* raise_generic_exception must not return */
|
||||
stack->rec_ptr = &stack->rec; /* arguments for raise_generic_exception */
|
||||
stack->ret_addr = (void *)0xdeadbabe; /* KiUserExceptionDispatcher must not return */
|
||||
stack->rec_ptr = &stack->rec; /* arguments for KiUserExceptionDispatcher */
|
||||
stack->context_ptr = &stack->context;
|
||||
}
|
||||
|
||||
|
@ -2038,21 +2006,6 @@ __ASM_STDCALL_FUNC( RtlUnwind, 16,
|
|||
"ret $16" ) /* actually never returns */
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* NtRaiseException (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
|
||||
{
|
||||
if (first_chance)
|
||||
{
|
||||
NTSTATUS status = send_debug_event( rec, TRUE, context );
|
||||
if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
|
||||
NtSetContextThread( GetCurrentThread(), context );
|
||||
}
|
||||
return raise_exception( rec, context, first_chance );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* raise_exception_full_context
|
||||
*
|
||||
|
|
|
@ -341,6 +341,47 @@ static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL f
|
|||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* KiUserExceptionDispatcher (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *context )
|
||||
{
|
||||
NTSTATUS status;
|
||||
DWORD c;
|
||||
|
||||
TRACE( "code=%x flags=%x addr=%p ip=%x tid=%04x\n",
|
||||
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
|
||||
context->Iar, GetCurrentThreadId() );
|
||||
for (c = 0; c < rec->NumberParameters; c++)
|
||||
TRACE( " info[%d]=%08lx\n", c, rec->ExceptionInformation[c] );
|
||||
|
||||
if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
|
||||
{
|
||||
if (rec->ExceptionInformation[1] >> 16)
|
||||
MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
|
||||
rec->ExceptionAddress,
|
||||
(char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
|
||||
else
|
||||
MESSAGE( "wine: Call from %p to unimplemented function %s.%ld, aborting\n",
|
||||
rec->ExceptionAddress,
|
||||
(char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: dump context */
|
||||
}
|
||||
|
||||
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
|
||||
NtSetContextThread( GetCurrentThread(), context );
|
||||
|
||||
if ((status = call_stack_handlers( rec, context )) == STATUS_SUCCESS)
|
||||
NtSetContextThread( GetCurrentThread(), context );
|
||||
|
||||
if (status != STATUS_UNHANDLED_EXCEPTION) RtlRaiseStatus( status );
|
||||
return NtRaiseException( rec, context, FALSE );
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* segv_handler
|
||||
*
|
||||
|
@ -686,16 +727,6 @@ void WINAPI RtlUnwind( PVOID pEndFrame, PVOID targetIp, PEXCEPTION_RECORD pRecor
|
|||
FIXME( "Not implemented on PowerPC\n" );
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* NtRaiseException (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
|
||||
{
|
||||
NTSTATUS status = raise_exception( rec, context, first_chance );
|
||||
if (status == STATUS_SUCCESS) NtSetContextThread( GetCurrentThread(), context );
|
||||
return status;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RtlRaiseException (NTDLL.@)
|
||||
*/
|
||||
|
|
|
@ -2223,102 +2223,58 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_contex
|
|||
}
|
||||
|
||||
|
||||
static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
if (first_chance)
|
||||
{
|
||||
DWORD c;
|
||||
|
||||
TRACE( "code=%x flags=%x addr=%p ip=%lx tid=%04x\n",
|
||||
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
|
||||
context->Rip, GetCurrentThreadId() );
|
||||
for (c = 0; c < min( EXCEPTION_MAXIMUM_PARAMETERS, rec->NumberParameters ); c++)
|
||||
TRACE( " info[%d]=%016lx\n", c, rec->ExceptionInformation[c] );
|
||||
if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
|
||||
{
|
||||
if (rec->ExceptionInformation[1] >> 16)
|
||||
MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
|
||||
rec->ExceptionAddress,
|
||||
(char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
|
||||
else
|
||||
MESSAGE( "wine: Call from %p to unimplemented function %s.%ld, aborting\n",
|
||||
rec->ExceptionAddress,
|
||||
(char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE(" rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n",
|
||||
context->Rax, context->Rbx, context->Rcx, context->Rdx );
|
||||
TRACE(" rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx\n",
|
||||
context->Rsi, context->Rdi, context->Rbp, context->Rsp );
|
||||
TRACE(" r8=%016lx r9=%016lx r10=%016lx r11=%016lx\n",
|
||||
context->R8, context->R9, context->R10, context->R11 );
|
||||
TRACE(" r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n",
|
||||
context->R12, context->R13, context->R14, context->R15 );
|
||||
}
|
||||
|
||||
/* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
|
||||
if (rec->ExceptionCode == EXCEPTION_BREAKPOINT) context->Rip--;
|
||||
|
||||
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION) goto done;
|
||||
|
||||
if ((status = call_stack_handlers( rec, context )) == STATUS_SUCCESS) goto done;
|
||||
if (status != STATUS_UNHANDLED_EXCEPTION) return status;
|
||||
}
|
||||
|
||||
/* last chance exception */
|
||||
|
||||
status = send_debug_event( rec, FALSE, context );
|
||||
if (status != DBG_CONTINUE)
|
||||
{
|
||||
if (rec->ExceptionFlags & EH_STACK_INVALID)
|
||||
ERR("Exception frame is not in stack limits => unable to dispatch exception.\n");
|
||||
else if (rec->ExceptionCode == STATUS_NONCONTINUABLE_EXCEPTION)
|
||||
ERR("Process attempted to continue execution after noncontinuable exception.\n");
|
||||
else
|
||||
ERR("Unhandled exception code %x flags %x addr %p\n",
|
||||
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
|
||||
NtTerminateProcess( NtCurrentProcess(), rec->ExceptionCode );
|
||||
}
|
||||
|
||||
done:
|
||||
return NtSetContextThread( GetCurrentThread(), context );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* NtRaiseException (NTDLL.@)
|
||||
* KiUserExceptionDispatcher (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
|
||||
NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *context )
|
||||
{
|
||||
NTSTATUS status;
|
||||
DWORD c;
|
||||
|
||||
if (first_chance)
|
||||
TRACE( "code=%x flags=%x addr=%p ip=%lx tid=%04x\n",
|
||||
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
|
||||
context->Rip, GetCurrentThreadId() );
|
||||
for (c = 0; c < min( EXCEPTION_MAXIMUM_PARAMETERS, rec->NumberParameters ); c++)
|
||||
TRACE( " info[%d]=%016lx\n", c, rec->ExceptionInformation[c] );
|
||||
|
||||
if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
|
||||
{
|
||||
status = send_debug_event( rec, TRUE, context );
|
||||
if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
|
||||
return NtSetContextThread( GetCurrentThread(), context );
|
||||
if (rec->ExceptionInformation[1] >> 16)
|
||||
MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
|
||||
rec->ExceptionAddress,
|
||||
(char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
|
||||
else
|
||||
MESSAGE( "wine: Call from %p to unimplemented function %s.%ld, aborting\n",
|
||||
rec->ExceptionAddress,
|
||||
(char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE(" rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n",
|
||||
context->Rax, context->Rbx, context->Rcx, context->Rdx );
|
||||
TRACE(" rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx\n",
|
||||
context->Rsi, context->Rdi, context->Rbp, context->Rsp );
|
||||
TRACE(" r8=%016lx r9=%016lx r10=%016lx r11=%016lx\n",
|
||||
context->R8, context->R9, context->R10, context->R11 );
|
||||
TRACE(" r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n",
|
||||
context->R12, context->R13, context->R14, context->R15 );
|
||||
}
|
||||
|
||||
return raise_exception( rec, context, first_chance);
|
||||
/* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
|
||||
if (rec->ExceptionCode == EXCEPTION_BREAKPOINT) context->Rip--;
|
||||
|
||||
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
|
||||
NtSetContextThread( GetCurrentThread(), context );
|
||||
|
||||
if ((status = call_stack_handlers( rec, context )) == STATUS_SUCCESS)
|
||||
NtSetContextThread( GetCurrentThread(), context );
|
||||
|
||||
if (status != STATUS_UNHANDLED_EXCEPTION) RtlRaiseStatus( status );
|
||||
return NtRaiseException( rec, context, FALSE );
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* raise_generic_exception
|
||||
*
|
||||
* Generic raise function for exceptions that don't need special treatment.
|
||||
*/
|
||||
static void raise_generic_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
|
||||
{
|
||||
NTSTATUS status = raise_exception( rec, context, TRUE );
|
||||
raise_status( status, rec );
|
||||
}
|
||||
|
||||
|
||||
extern void raise_func_trampoline( EXCEPTION_RECORD *rec, CONTEXT *context, raise_func func );
|
||||
extern void CDECL raise_func_trampoline( EXCEPTION_RECORD *rec, CONTEXT *context, raise_func func );
|
||||
__ASM_GLOBAL_FUNC( raise_func_trampoline,
|
||||
__ASM_CFI(".cfi_signal_frame\n\t")
|
||||
__ASM_CFI(".cfi_def_cfa %rbp,160\n\t") /* red zone + rip + rbp + rdi + rsi */
|
||||
|
@ -2326,7 +2282,7 @@ __ASM_GLOBAL_FUNC( raise_func_trampoline,
|
|||
__ASM_CFI(".cfi_rel_offset %rbp,16\n\t")
|
||||
__ASM_CFI(".cfi_rel_offset %rdi,8\n\t")
|
||||
__ASM_CFI(".cfi_rel_offset %rsi,0\n\t")
|
||||
"call *%rdx\n\t"
|
||||
"call *%r8\n\t"
|
||||
"int $3")
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -2446,9 +2402,9 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout *
|
|||
|
||||
/* now modify the sigcontext to return to the raise function */
|
||||
RIP_sig(sigcontext) = (ULONG_PTR)raise_func_trampoline;
|
||||
RDI_sig(sigcontext) = (ULONG_PTR)&stack->rec;
|
||||
RSI_sig(sigcontext) = (ULONG_PTR)&stack->context;
|
||||
RDX_sig(sigcontext) = (ULONG_PTR)raise_generic_exception;
|
||||
RCX_sig(sigcontext) = (ULONG_PTR)&stack->rec;
|
||||
RDX_sig(sigcontext) = (ULONG_PTR)&stack->context;
|
||||
R8_sig(sigcontext) = (ULONG_PTR)KiUserExceptionDispatcher;
|
||||
RBP_sig(sigcontext) = (ULONG_PTR)rsp_ptr;
|
||||
RSP_sig(sigcontext) = (ULONG_PTR)stack;
|
||||
/* clear single-step, direction, and align check flag */
|
||||
|
|
|
@ -1018,6 +1018,7 @@ static struct unix_funcs unix_funcs =
|
|||
NtQuerySemaphore,
|
||||
NtQueryTimer,
|
||||
NtQueryVirtualMemory,
|
||||
NtRaiseException,
|
||||
NtReadVirtualMemory,
|
||||
NtReleaseKeyedEvent,
|
||||
NtReleaseMutant,
|
||||
|
|
|
@ -52,6 +52,8 @@
|
|||
#include "wine/exception.h"
|
||||
#include "unix_private.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(seh);
|
||||
|
||||
#ifndef PTHREAD_STACK_MIN
|
||||
#define PTHREAD_STACK_MIN 16384
|
||||
#endif
|
||||
|
@ -387,6 +389,87 @@ void wait_suspend( CONTEXT *context )
|
|||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* send_debug_event
|
||||
*
|
||||
* Send an EXCEPTION_DEBUG_EVENT event to the debugger.
|
||||
*/
|
||||
static NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
|
||||
{
|
||||
NTSTATUS ret;
|
||||
DWORD i;
|
||||
obj_handle_t handle = 0;
|
||||
client_ptr_t params[EXCEPTION_MAXIMUM_PARAMETERS];
|
||||
CONTEXT exception_context = *context;
|
||||
select_op_t select_op;
|
||||
sigset_t old_set;
|
||||
|
||||
if (!NtCurrentTeb()->Peb->BeingDebugged) return 0; /* no debugger present */
|
||||
|
||||
pthread_sigmask( SIG_BLOCK, &server_block_set, &old_set );
|
||||
|
||||
for (i = 0; i < min( rec->NumberParameters, EXCEPTION_MAXIMUM_PARAMETERS ); i++)
|
||||
params[i] = rec->ExceptionInformation[i];
|
||||
|
||||
SERVER_START_REQ( queue_exception_event )
|
||||
{
|
||||
req->first = first_chance;
|
||||
req->code = rec->ExceptionCode;
|
||||
req->flags = rec->ExceptionFlags;
|
||||
req->record = wine_server_client_ptr( rec->ExceptionRecord );
|
||||
req->address = wine_server_client_ptr( rec->ExceptionAddress );
|
||||
req->len = i * sizeof(params[0]);
|
||||
wine_server_add_data( req, params, req->len );
|
||||
if (!(ret = wine_server_call( req ))) handle = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (handle)
|
||||
{
|
||||
select_op.wait.op = SELECT_WAIT;
|
||||
select_op.wait.handles[0] = handle;
|
||||
server_select( &select_op, offsetof( select_op_t, wait.handles[1] ), SELECT_INTERRUPTIBLE,
|
||||
TIMEOUT_INFINITE, &exception_context, NULL, NULL );
|
||||
|
||||
SERVER_START_REQ( get_exception_status )
|
||||
{
|
||||
req->handle = handle;
|
||||
ret = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (ret >= 0) *context = exception_context;
|
||||
}
|
||||
|
||||
pthread_sigmask( SIG_SETMASK, &old_set, NULL );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* NtRaiseException (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
|
||||
{
|
||||
NTSTATUS status = send_debug_event( rec, context, first_chance );
|
||||
|
||||
if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
|
||||
NtSetContextThread( GetCurrentThread(), context );
|
||||
|
||||
if (first_chance) KiUserExceptionDispatcher( rec, context );
|
||||
|
||||
if (rec->ExceptionFlags & EH_STACK_INVALID)
|
||||
ERR("Exception frame is not in stack limits => unable to dispatch exception.\n");
|
||||
else if (rec->ExceptionCode == STATUS_NONCONTINUABLE_EXCEPTION)
|
||||
ERR("Process attempted to continue execution after noncontinuable exception.\n");
|
||||
else
|
||||
ERR("Unhandled exception code %x flags %x addr %p\n",
|
||||
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
|
||||
|
||||
NtTerminateProcess( NtCurrentProcess(), rec->ExceptionCode );
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* set_thread_context
|
||||
*/
|
||||
|
|
|
@ -50,6 +50,7 @@ static inline struct ntdll_thread_data *ntdll_get_thread_data(void)
|
|||
return (struct ntdll_thread_data *)&NtCurrentTeb()->GdiTebBatch;
|
||||
}
|
||||
|
||||
NTSTATUS WINAPI KiUserExceptionDispatcher(EXCEPTION_RECORD*,CONTEXT*);
|
||||
void WINAPI LdrInitializeThunk(CONTEXT*,void**,ULONG_PTR,ULONG_PTR);
|
||||
|
||||
void CDECL mmap_add_reserved_area( void *addr, SIZE_T size ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -28,7 +28,7 @@ struct ldt_copy;
|
|||
struct msghdr;
|
||||
|
||||
/* increment this when you change the function table */
|
||||
#define NTDLL_UNIXLIB_VERSION 30
|
||||
#define NTDLL_UNIXLIB_VERSION 31
|
||||
|
||||
struct unix_funcs
|
||||
{
|
||||
|
@ -101,6 +101,7 @@ struct unix_funcs
|
|||
NTSTATUS (WINAPI *NtQueryVirtualMemory)( HANDLE process, LPCVOID addr,
|
||||
MEMORY_INFORMATION_CLASS info_class,
|
||||
PVOID buffer, SIZE_T len, SIZE_T *res_len );
|
||||
NTSTATUS (WINAPI *NtRaiseException)( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance );
|
||||
NTSTATUS (WINAPI *NtReadVirtualMemory)( HANDLE process, const void *addr, void *buffer,
|
||||
SIZE_T size, SIZE_T *bytes_read );
|
||||
NTSTATUS (WINAPI *NtReleaseKeyedEvent)( HANDLE handle, const void *key,
|
||||
|
|
Loading…
Reference in New Issue