ntdll: Move NtRaiseException() implementation to the Unix library.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-06-06 13:56:19 +02:00
parent 3cc3b44575
commit e561ce4b92
11 changed files with 314 additions and 282 deletions

View File

@ -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.@)
*

View File

@ -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)

View File

@ -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 ));
}
/*************************************************************************

View File

@ -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.@)

View File

@ -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
*

View File

@ -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.@)
*/

View File

@ -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 */

View File

@ -1018,6 +1018,7 @@ static struct unix_funcs unix_funcs =
NtQuerySemaphore,
NtQueryTimer,
NtQueryVirtualMemory,
NtRaiseException,
NtReadVirtualMemory,
NtReleaseKeyedEvent,
NtReleaseMutant,

View File

@ -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
*/

View File

@ -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;

View File

@ -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,