1
0
Fork 0
mirror of synced 2025-03-07 03:53:26 +01:00

ntdll: Share exception dispatch implementation across platforms.

This commit is contained in:
Alexandre Julliard 2024-02-20 20:27:46 +01:00
parent 61564202b5
commit 8bd411da0a
6 changed files with 88 additions and 254 deletions

View file

@ -36,6 +36,7 @@
#include "ntdll_misc.h"
WINE_DEFAULT_DEBUG_CHANNEL(seh);
WINE_DECLARE_DEBUG_CHANNEL(threadname);
typedef struct
{
@ -58,7 +59,7 @@ static RTL_CRITICAL_SECTION vectored_handlers_section = { &critsect_debug, -1, 0
static PRTL_EXCEPTION_FILTER unhandled_exception_filter;
const char *debugstr_exception_code( DWORD code )
static const char *debugstr_exception_code( DWORD code )
{
switch (code)
{
@ -143,7 +144,7 @@ static ULONG remove_vectored_handler( struct list *handler_list, VECTORED_HANDLE
*
* Call the vectored handlers chain.
*/
LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
static LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
{
struct list *ptr;
LONG ret = EXCEPTION_CONTINUE_SEARCH;
@ -185,6 +186,77 @@ LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
}
/*******************************************************************
* dispatch_exception
*/
NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
{
NTSTATUS status;
DWORD i;
switch (rec->ExceptionCode)
{
case 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.%u, aborting\n",
rec->ExceptionAddress,
(char *)rec->ExceptionInformation[0], (USHORT)rec->ExceptionInformation[1] );
break;
case EXCEPTION_WINE_NAME_THREAD:
if (rec->ExceptionInformation[0] == 0x1000)
{
const char *name = (char *)rec->ExceptionInformation[1];
DWORD tid = (DWORD)rec->ExceptionInformation[2];
if (tid == -1 || tid == GetCurrentThreadId())
WARN_(threadname)( "Thread renamed to %s\n", debugstr_a(name) );
else
WARN_(threadname)( "Thread ID %04lx renamed to %s\n", tid, debugstr_a(name) );
set_native_thread_name( tid, name );
}
break;
case DBG_PRINTEXCEPTION_C:
WARN( "%s\n", debugstr_an((char *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
break;
case DBG_PRINTEXCEPTION_WIDE_C:
WARN( "%s\n", debugstr_wn((WCHAR *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
break;
case STATUS_ASSERTION_FAILURE:
ERR( "assertion failure exception\n" );
break;
default:
if (!TRACE_ON(seh)) WARN( "%s exception (code=%lx) raised\n",
debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
break;
}
TRACE( "code=%lx (%s) flags=%lx addr=%p\n",
rec->ExceptionCode, debugstr_exception_code(rec->ExceptionCode),
rec->ExceptionFlags, rec->ExceptionAddress );
for (i = 0; i < min( EXCEPTION_MAXIMUM_PARAMETERS, rec->NumberParameters ); i++)
TRACE( " info[%ld]=%p\n", i, (void *)rec->ExceptionInformation[i] );
TRACE_CONTEXT( context );
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
NtContinue( context, FALSE );
if ((status = call_seh_handlers( rec, context )) == STATUS_SUCCESS)
NtContinue( context, FALSE );
if (status != STATUS_UNHANDLED_EXCEPTION) RtlRaiseStatus( status );
return NtRaiseException( rec, context, FALSE );
}
#if defined(__WINE_PE_BUILD) && !defined(__i386__)
/*******************************************************************

View file

@ -60,7 +60,8 @@ extern UINT_PTR page_size;
#endif
/* exceptions */
extern LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context );
extern NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *context );
extern NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context );
extern NTSTATUS WINAPI dispatch_user_callback( void *args, ULONG len, ULONG id );
extern EXCEPTION_DISPOSITION WINAPI user_callback_handler( EXCEPTION_RECORD *record, void *frame,
CONTEXT *context, void *dispatch );
@ -86,7 +87,6 @@ extern void (WINAPI *pWow64PrepareForException)( EXCEPTION_RECORD *rec, CONTEXT
/* debug helpers */
extern LPCSTR debugstr_us( const UNICODE_STRING *str );
extern const char *debugstr_exception_code( DWORD code );
extern void set_native_thread_name( DWORD tid, const char *name );
/* init routines */

View file

@ -35,7 +35,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(seh);
WINE_DECLARE_DEBUG_CHANNEL(relay);
WINE_DECLARE_DEBUG_CHANNEL(threadname);
/* layering violation: the setjmp buffer is defined in msvcrt, but used by RtlUnwindEx */
@ -335,11 +334,11 @@ static DWORD call_teb_handler( EXCEPTION_RECORD *rec, CONTEXT *context, DISPATCH
/**********************************************************************
* call_function_handlers
* call_seh_handlers
*
* Call the per-function handlers.
* Call the SEH handlers.
*/
static NTSTATUS call_function_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context )
NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context )
{
EXCEPTION_REGISTRATION_RECORD *teb_frame = NtCurrentTeb()->Tib.ExceptionList;
UNWIND_HISTORY_TABLE table;
@ -441,64 +440,6 @@ static NTSTATUS call_function_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_con
/*******************************************************************
* KiUserExceptionDispatcher (NTDLL.@)
*/
NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
{
NTSTATUS status;
DWORD 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.%Id, aborting\n",
rec->ExceptionAddress,
(char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
}
else if (rec->ExceptionCode == EXCEPTION_WINE_NAME_THREAD && rec->ExceptionInformation[0] == 0x1000)
{
if ((DWORD)rec->ExceptionInformation[2] == -1 || (DWORD)rec->ExceptionInformation[2] == GetCurrentThreadId())
WARN_(threadname)( "Thread renamed to %s\n", debugstr_a((char *)rec->ExceptionInformation[1]) );
else
WARN_(threadname)( "Thread ID %04lx renamed to %s\n", (DWORD)rec->ExceptionInformation[2],
debugstr_a((char *)rec->ExceptionInformation[1]) );
set_native_thread_name((DWORD)rec->ExceptionInformation[2], (char *)rec->ExceptionInformation[1]);
}
else if (rec->ExceptionCode == DBG_PRINTEXCEPTION_C)
{
WARN( "%s\n", debugstr_an((char *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
}
else if (rec->ExceptionCode == DBG_PRINTEXCEPTION_WIDE_C)
{
WARN( "%s\n", debugstr_wn((WCHAR *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
}
else
{
if (rec->ExceptionCode == STATUS_ASSERTION_FAILURE)
ERR( "%s exception (code=%lx) raised\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
else
WARN( "%s exception (code=%lx) raised\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
}
TRACE( "code=%lx flags=%lx addr=%p\n",
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
for (c = 0; c < rec->NumberParameters; c++)
TRACE( " info[%ld]=%08Ix\n", c, rec->ExceptionInformation[c] );
TRACE_CONTEXT( context );
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
NtContinue( context, FALSE );
if ((status = call_function_handlers( rec, context )) == STATUS_SUCCESS)
NtContinue( context, FALSE );
if (status != STATUS_UNHANDLED_EXCEPTION) RtlRaiseStatus( status );
return NtRaiseException( rec, context, FALSE );
}
__ASM_GLOBAL_FUNC( KiUserExceptionDispatcher,
__ASM_SEH(".seh_custom 0xee,0x02\n\t") /* MSFT_OP_CONTEXT */
__ASM_SEH(".seh_endprologue\n\t")

View file

@ -37,7 +37,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(seh);
WINE_DECLARE_DEBUG_CHANNEL(relay);
WINE_DECLARE_DEBUG_CHANNEL(threadname);
/* layering violation: the setjmp buffer is defined in msvcrt, but used by RtlUnwindEx */
@ -338,11 +337,11 @@ static DWORD call_teb_handler( EXCEPTION_RECORD *rec, CONTEXT *context, DISPATCH
/**********************************************************************
* call_function_handlers
* call_seh_handlers
*
* Call the per-function handlers.
* Call the SEH handlers.
*/
static NTSTATUS call_function_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context )
NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context )
{
EXCEPTION_REGISTRATION_RECORD *teb_frame = NtCurrentTeb()->Tib.ExceptionList;
UNWIND_HISTORY_TABLE table;
@ -441,65 +440,6 @@ static NTSTATUS call_function_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_con
}
NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
{
NTSTATUS status;
DWORD 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.%Id, aborting\n",
rec->ExceptionAddress,
(char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
}
else if (rec->ExceptionCode == EXCEPTION_WINE_NAME_THREAD && rec->ExceptionInformation[0] == 0x1000)
{
if ((DWORD)rec->ExceptionInformation[2] == -1 || (DWORD)rec->ExceptionInformation[2] == GetCurrentThreadId())
WARN_(threadname)( "Thread renamed to %s\n", debugstr_a((char *)rec->ExceptionInformation[1]) );
else
WARN_(threadname)( "Thread ID %04lx renamed to %s\n", (DWORD)rec->ExceptionInformation[2],
debugstr_a((char *)rec->ExceptionInformation[1]) );
set_native_thread_name((DWORD)rec->ExceptionInformation[2], (char *)rec->ExceptionInformation[1]);
}
else if (rec->ExceptionCode == DBG_PRINTEXCEPTION_C)
{
WARN( "%s\n", debugstr_an((char *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
}
else if (rec->ExceptionCode == DBG_PRINTEXCEPTION_WIDE_C)
{
WARN( "%s\n", debugstr_wn((WCHAR *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
}
else
{
if (rec->ExceptionCode == STATUS_ASSERTION_FAILURE)
ERR( "%s exception (code=%lx) raised\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
else
WARN( "%s exception (code=%lx) raised\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
}
TRACE( "code=%lx flags=%lx addr=%p\n",
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
for (c = 0; c < rec->NumberParameters; c++)
TRACE( " info[%ld]=%016I64x\n", c, rec->ExceptionInformation[c] );
TRACE_CONTEXT( context );
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
NtContinue( context, FALSE );
if ((status = call_function_handlers( rec, context )) == STATUS_SUCCESS)
NtContinue( context, FALSE );
if (status != STATUS_UNHANDLED_EXCEPTION) RtlRaiseStatus( status );
return NtRaiseException( rec, context, FALSE );
}
/*******************************************************************
* KiUserExceptionDispatcher (NTDLL.@)
*/

View file

@ -37,7 +37,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(seh);
WINE_DECLARE_DEBUG_CHANNEL(relay);
WINE_DECLARE_DEBUG_CHANNEL(threadname);
struct x86_thread_data
{
@ -139,11 +138,11 @@ static DWORD unwind_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECOR
/**********************************************************************
* call_stack_handlers
* call_seh_handlers
*
* Call the stack handlers chain.
* Call the SEH handlers chain.
*/
static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
{
EXCEPTION_REGISTRATION_RECORD *frame, *dispatch, *nested_frame;
DWORD res;
@ -195,64 +194,6 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
/*******************************************************************
* KiUserExceptionDispatcher (NTDLL.@)
*/
NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
{
NTSTATUS status;
DWORD 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.%Id, aborting\n",
rec->ExceptionAddress,
(char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
}
else if (rec->ExceptionCode == EXCEPTION_WINE_NAME_THREAD && rec->ExceptionInformation[0] == 0x1000)
{
if ((DWORD)rec->ExceptionInformation[2] == -1 || (DWORD)rec->ExceptionInformation[2] == GetCurrentThreadId())
WARN_(threadname)( "Thread renamed to %s\n", debugstr_a((char *)rec->ExceptionInformation[1]) );
else
WARN_(threadname)( "Thread ID %04lx renamed to %s\n", (DWORD)rec->ExceptionInformation[2],
debugstr_a((char *)rec->ExceptionInformation[1]) );
set_native_thread_name((DWORD)rec->ExceptionInformation[2], (char *)rec->ExceptionInformation[1]);
}
else if (rec->ExceptionCode == DBG_PRINTEXCEPTION_C)
{
WARN( "%s\n", debugstr_an((char *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
}
else if (rec->ExceptionCode == DBG_PRINTEXCEPTION_WIDE_C)
{
WARN( "%s\n", debugstr_wn((WCHAR *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
}
else
{
if (rec->ExceptionCode == STATUS_ASSERTION_FAILURE)
ERR( "%s exception (code=%lx) raised\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
else
WARN( "%s exception (code=%lx) raised\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
}
TRACE( "code=%lx flags=%lx addr=%p\n",
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
for (c = 0; c < rec->NumberParameters; c++)
TRACE( " info[%ld]=%08Ix\n", c, rec->ExceptionInformation[c] );
TRACE_CONTEXT( context );
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
NtContinue( context, FALSE );
if ((status = call_stack_handlers( rec, context )) == STATUS_SUCCESS)
NtContinue( context, FALSE );
if (status != STATUS_UNHANDLED_EXCEPTION) RtlRaiseStatus( status );
return NtRaiseException( rec, context, FALSE );
}
__ASM_STDCALL_FUNC( KiUserExceptionDispatcher, 8,
"pushl 4(%esp)\n\t"
"pushl 4(%esp)\n\t"

View file

@ -35,7 +35,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(seh);
WINE_DECLARE_DEBUG_CHANNEL(relay);
WINE_DECLARE_DEBUG_CHANNEL(threadname);
/* layering violation: the setjmp buffer is defined in msvcrt, but used by RtlUnwindEx */
@ -258,11 +257,11 @@ static DWORD call_teb_handler( EXCEPTION_RECORD *rec, CONTEXT *context, DISPATCH
/**********************************************************************
* call_stack_handlers
* call_seh_handlers
*
* Call the stack handlers chain.
* Call the SEH handlers chain.
*/
static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context )
NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context )
{
EXCEPTION_REGISTRATION_RECORD *teb_frame = NtCurrentTeb()->Tib.ExceptionList;
UNWIND_HISTORY_TABLE table;
@ -359,65 +358,6 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_contex
}
NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
{
NTSTATUS status;
DWORD 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.%I64d, aborting\n",
rec->ExceptionAddress,
(char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
}
else if (rec->ExceptionCode == EXCEPTION_WINE_NAME_THREAD && rec->ExceptionInformation[0] == 0x1000)
{
if ((DWORD)rec->ExceptionInformation[2] == -1 || (DWORD)rec->ExceptionInformation[2] == GetCurrentThreadId())
WARN_(threadname)( "Thread renamed to %s\n", debugstr_a((char *)rec->ExceptionInformation[1]) );
else
WARN_(threadname)( "Thread ID %04lx renamed to %s\n", (DWORD)rec->ExceptionInformation[2],
debugstr_a((char *)rec->ExceptionInformation[1]) );
set_native_thread_name((DWORD)rec->ExceptionInformation[2], (char *)rec->ExceptionInformation[1]);
}
else if (rec->ExceptionCode == DBG_PRINTEXCEPTION_C)
{
WARN( "%s\n", debugstr_an((char *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
}
else if (rec->ExceptionCode == DBG_PRINTEXCEPTION_WIDE_C)
{
WARN( "%s\n", debugstr_wn((WCHAR *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
}
else
{
if (rec->ExceptionCode == STATUS_ASSERTION_FAILURE)
ERR( "%s exception (code=%lx) raised\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
else
WARN( "%s exception (code=%lx) raised\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
}
TRACE( "code=%lx flags=%lx addr=%p\n",
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
for (c = 0; c < min( EXCEPTION_MAXIMUM_PARAMETERS, rec->NumberParameters ); c++)
TRACE( " info[%ld]=%016I64x\n", c, rec->ExceptionInformation[c] );
TRACE_CONTEXT( context );
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
NtContinue( context, FALSE );
if ((status = call_stack_handlers( rec, context )) == STATUS_SUCCESS)
NtContinue( context, FALSE );
if (status != STATUS_UNHANDLED_EXCEPTION) RtlRaiseStatus( status );
return NtRaiseException( rec, context, FALSE );
}
/*******************************************************************
* KiUserExceptionDispatcher (NTDLL.@)
*/