diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c index c0309ab6dbb..4b77f1a5e97 100644 --- a/dlls/ntdll/exception.c +++ b/dlls/ntdll/exception.c @@ -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.@) * diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index c4d78128758..11fa03b4d1b 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -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) diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c index 8ff9f66d3f0..291536ecb86 100644 --- a/dlls/ntdll/signal_arm.c +++ b/dlls/ntdll/signal_arm.c @@ -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 )); } /************************************************************************* diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c index 104ffbf6df9..4abcee52962 100644 --- a/dlls/ntdll/signal_arm64.c +++ b/dlls/ntdll/signal_arm64.c @@ -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.@) diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 1b0b9352a87..ccdc8ec7f3f 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -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 * diff --git a/dlls/ntdll/signal_powerpc.c b/dlls/ntdll/signal_powerpc.c index 7e73322cbeb..18ae3dbf2c8 100644 --- a/dlls/ntdll/signal_powerpc.c +++ b/dlls/ntdll/signal_powerpc.c @@ -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.@) */ diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index 0ccc7cbceb6..961b6a9ab82 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -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 */ diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index b5ee692024c..3116c885d15 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1018,6 +1018,7 @@ static struct unix_funcs unix_funcs = NtQuerySemaphore, NtQueryTimer, NtQueryVirtualMemory, + NtRaiseException, NtReadVirtualMemory, NtReleaseKeyedEvent, NtReleaseMutant, diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index b6458da61ad..1fc7dc84543 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -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 */ diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index a422fd825ed..292c7f05c9a 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -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; diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h index 58bdad19397..779b91c89b9 100644 --- a/dlls/ntdll/unixlib.h +++ b/dlls/ntdll/unixlib.h @@ -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,