Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
I personally find +seh a bit too verbose to track exceptions, this series is trying to make warn+seh a bit more informative without spamming the debug log too much.
About PATCH 2, it is a bit redundant with +debugstr, but as the exceptions may be raised manually, +debugstr won't catch everything. It also adds support for the new DBG_PRINTEXCEPTION_WIDE_C exception code.
dlls/ntdll/signal_arm.c | 4 ++++ dlls/ntdll/signal_arm64.c | 4 ++++ dlls/ntdll/signal_i386.c | 4 ++++ dlls/ntdll/signal_x86_64.c | 4 ++++ include/wine/exception.h | 6 ++++++ programs/winedbg/debugger.h | 6 ------ programs/winedbg/gdbproxy.c | 5 +++-- programs/winedbg/tgt_active.c | 2 +- 8 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c index b1544ba15fe..f4da2e5c71d 100644 --- a/dlls/ntdll/signal_arm.c +++ b/dlls/ntdll/signal_arm.c @@ -160,6 +160,10 @@ NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *conte rec->ExceptionAddress, (char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] ); } + else if (rec->ExceptionCode == EXCEPTION_WINE_NAME_THREAD && rec->ExceptionInformation[0] == 0x1000) + { + WARN( "Thread %04x renamed to %s\n", (DWORD)rec->ExceptionInformation[2], debugstr_a((char *)rec->ExceptionInformation[1]) ); + } else { TRACE( " r0=%08x r1=%08x r2=%08x r3=%08x r4=%08x r5=%08x\n", diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c index 9db8a8b17b4..88e31d88f7b 100644 --- a/dlls/ntdll/signal_arm64.c +++ b/dlls/ntdll/signal_arm64.c @@ -501,6 +501,10 @@ NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *conte rec->ExceptionAddress, (char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] ); } + else if (rec->ExceptionCode == EXCEPTION_WINE_NAME_THREAD && rec->ExceptionInformation[0] == 0x1000) + { + WARN( "Thread %04x renamed to %s\n", (DWORD)rec->ExceptionInformation[2], debugstr_a((char *)rec->ExceptionInformation[1]) ); + } else { TRACE(" x0=%016lx x1=%016lx x2=%016lx x3=%016lx\n", diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 93e03ae5b8b..a570be10024 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -192,6 +192,10 @@ NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context ) rec->ExceptionAddress, (char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] ); } + else if (rec->ExceptionCode == EXCEPTION_WINE_NAME_THREAD && rec->ExceptionInformation[0] == 0x1000) + { + WARN( "Thread %04x renamed to %s\n", (DWORD)rec->ExceptionInformation[2], debugstr_a((char *)rec->ExceptionInformation[1]) ); + } else { TRACE(" eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\n", diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index 7e39991ad1a..7a3fd4be204 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -538,6 +538,10 @@ NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context ) rec->ExceptionAddress, (char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] ); } + else if (rec->ExceptionCode == EXCEPTION_WINE_NAME_THREAD && rec->ExceptionInformation[0] == 0x1000) + { + WARN( "Thread %04x renamed to %s\n", (DWORD)rec->ExceptionInformation[2], debugstr_a((char *)rec->ExceptionInformation[1]) ); + } else { TRACE(" rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n", diff --git a/include/wine/exception.h b/include/wine/exception.h index a2b0bb08dc3..3d28ff6b110 100644 --- a/include/wine/exception.h +++ b/include/wine/exception.h @@ -302,6 +302,12 @@ static inline EXCEPTION_REGISTRATION_RECORD *__wine_get_frame(void) #define EXCEPTION_WINE_STUB 0x80000100 /* stub entry point called */ #define EXCEPTION_WINE_ASSERTION 0x80000101 /* assertion failed */
+/* Wine extension; Windows doesn't have a name for this code. This is an + undocumented exception understood by MS VC debugger, allowing the program + to name a particular thread. Search google.com or deja.com for "0x406d1388" + for more info. */ +#define EXCEPTION_WINE_NAME_THREAD 0x406D1388 + #ifdef __cplusplus } #endif diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index ddac129bab5..05bf0c047ba 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -155,12 +155,6 @@ struct dbg_breakpoint #define CXX_EXCEPTION 0xe06d7363 #define CXX_FRAME_MAGIC 0x19930520
-/* Wine extension; Windows doesn't have a name for this code. This is an - undocumented exception understood by MS VC debugger, allowing the program - to name a particular thread. Search google.com or deja.com for "0x406d1388" - for more info. */ -#define EXCEPTION_NAME_THREAD 0x406D1388 - /* Helper structure */ typedef struct tagTHREADNAME_INFO { diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c index c51fd342496..3c1b3e85df8 100644 --- a/programs/winedbg/gdbproxy.c +++ b/programs/winedbg/gdbproxy.c @@ -63,6 +63,7 @@ #include "windef.h" #include "winbase.h" #include "tlhelp32.h" +#include "wine/exception.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(winedbg); @@ -349,7 +350,7 @@ static unsigned char signal_from_debug_event(DEBUG_EVENT* de) return SIGALRM; /* should not be here */ case EXCEPTION_INVALID_HANDLE: - case EXCEPTION_NAME_THREAD: + case EXCEPTION_WINE_NAME_THREAD: return SIGTRAP; default: ERR("Unknown exception code 0x%08x\n", ec); @@ -363,7 +364,7 @@ static BOOL handle_exception(struct gdb_context* gdbctx, EXCEPTION_DEBUG_INFO* e
switch (rec->ExceptionCode) { - case EXCEPTION_NAME_THREAD: + case EXCEPTION_WINE_NAME_THREAD: { const THREADNAME_INFO *threadname = (const THREADNAME_INFO *)rec->ExceptionInformation; struct dbg_thread *thread; diff --git a/programs/winedbg/tgt_active.c b/programs/winedbg/tgt_active.c index d4e2d7d6347..e71f4615735 100644 --- a/programs/winedbg/tgt_active.c +++ b/programs/winedbg/tgt_active.c @@ -246,7 +246,7 @@ static DWORD dbg_handle_exception(const EXCEPTION_RECORD* rec, BOOL first_chance case EXCEPTION_SINGLE_STEP: is_debug = TRUE; break; - case EXCEPTION_NAME_THREAD: + case EXCEPTION_WINE_NAME_THREAD: pThreadName = (const THREADNAME_INFO*)(rec->ExceptionInformation); if (pThreadName->dwThreadID == -1) pThread = dbg_curr_thread;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/signal_arm.c | 8 ++++++++ dlls/ntdll/signal_arm64.c | 8 ++++++++ dlls/ntdll/signal_i386.c | 8 ++++++++ dlls/ntdll/signal_x86_64.c | 8 ++++++++ 4 files changed, 32 insertions(+)
diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c index f4da2e5c71d..1b98dd5cc70 100644 --- a/dlls/ntdll/signal_arm.c +++ b/dlls/ntdll/signal_arm.c @@ -164,6 +164,14 @@ NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *conte { WARN( "Thread %04x renamed to %s\n", (DWORD)rec->ExceptionInformation[2], debugstr_a((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 { TRACE( " r0=%08x r1=%08x r2=%08x r3=%08x r4=%08x r5=%08x\n", diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c index 88e31d88f7b..078fa947c42 100644 --- a/dlls/ntdll/signal_arm64.c +++ b/dlls/ntdll/signal_arm64.c @@ -505,6 +505,14 @@ NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *conte { WARN( "Thread %04x renamed to %s\n", (DWORD)rec->ExceptionInformation[2], debugstr_a((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 { TRACE(" x0=%016lx x1=%016lx x2=%016lx x3=%016lx\n", diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index a570be10024..6ec696931e9 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -196,6 +196,14 @@ NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context ) { WARN( "Thread %04x renamed to %s\n", (DWORD)rec->ExceptionInformation[2], debugstr_a((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 { TRACE(" eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\n", diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index 7a3fd4be204..df133d6fce9 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -542,6 +542,14 @@ NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context ) { WARN( "Thread %04x renamed to %s\n", (DWORD)rec->ExceptionInformation[2], debugstr_a((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 { TRACE(" rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n",
Depending on EH_NONCONTINUABLE.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/signal_arm.c | 5 ++++ dlls/ntdll/signal_arm64.c | 5 ++++ dlls/ntdll/signal_i386.c | 5 ++++ dlls/ntdll/signal_x86_64.c | 5 ++++ include/wine/exception.h | 48 +++++++++++++++++++++++++++++++++++++ programs/winedbg/debugger.h | 9 ------- programs/winedbg/info.c | 6 ++--- 7 files changed, 71 insertions(+), 12 deletions(-)
diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c index 1b98dd5cc70..4d1969e3a9a 100644 --- a/dlls/ntdll/signal_arm.c +++ b/dlls/ntdll/signal_arm.c @@ -174,6 +174,11 @@ NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *conte } else { + if (rec->ExceptionFlags & EH_NONCONTINUABLE) + ERR( "Fatal %s exception (code=%x) raised!\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode ); + else + WARN( "Non-fatal %s exception (code=%x) raised.\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode ); + 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", diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c index 078fa947c42..800a8a98d09 100644 --- a/dlls/ntdll/signal_arm64.c +++ b/dlls/ntdll/signal_arm64.c @@ -515,6 +515,11 @@ NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *conte } else { + if (rec->ExceptionFlags & EH_NONCONTINUABLE) + ERR( "Fatal %s exception (code=%x) raised!\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode ); + else + WARN( "Non-fatal %s exception (code=%x) raised.\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode ); + 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", diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 6ec696931e9..e7481d5dc9a 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -206,6 +206,11 @@ NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context ) } else { + if (rec->ExceptionFlags & EH_NONCONTINUABLE) + ERR( "Fatal %s exception (code=%x) raised!\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode ); + else + WARN( "Non-fatal %s exception (code=%x) raised.\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode ); + 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 ); diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index df133d6fce9..5e8eec191a9 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -552,6 +552,11 @@ NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context ) } else { + if (rec->ExceptionFlags & EH_NONCONTINUABLE) + ERR( "Fatal %s exception (code=%x) raised!\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode ); + else + WARN( "Non-fatal %s exception (code=%x) raised.\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode ); + 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", diff --git a/include/wine/exception.h b/include/wine/exception.h index 3d28ff6b110..dc548d5a0fc 100644 --- a/include/wine/exception.h +++ b/include/wine/exception.h @@ -22,6 +22,7 @@ #define __WINE_WINE_EXCEPTION_H
#include <windef.h> +#include <winbase.h> #include <excpt.h>
#ifdef __cplusplus @@ -308,6 +309,53 @@ static inline EXCEPTION_REGISTRATION_RECORD *__wine_get_frame(void) for more info. */ #define EXCEPTION_WINE_NAME_THREAD 0x406D1388
+/* used for C++ exceptions in msvcrt + * parameters: + * [0] CXX_FRAME_MAGIC + * [1] pointer to exception object + * [2] pointer to type + */ +#define EXCEPTION_WINE_CXX_EXCEPTION 0xe06d7363 +#define EXCEPTION_WINE_CXX_FRAME_MAGIC 0x19930520 + +static inline const char *debugstr_exception_code( DWORD code ) +{ + switch (code) + { + case CONTROL_C_EXIT: return "CONTROL_C_EXIT"; + case DBG_CONTROL_C: return "DBG_CONTROL_C"; + case DBG_PRINTEXCEPTION_C: return "DBG_PRINTEXCEPTION_C"; + case DBG_PRINTEXCEPTION_WIDE_C: return "DBG_PRINTEXCEPTION_WIDE_C"; + case EXCEPTION_ACCESS_VIOLATION: return "EXCEPTION_ACCESS_VIOLATION"; + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED"; + case EXCEPTION_BREAKPOINT: return "EXCEPTION_BREAKPOINT"; + case EXCEPTION_DATATYPE_MISALIGNMENT: return "EXCEPTION_DATATYPE_MISALIGNMENT"; + case EXCEPTION_FLT_DENORMAL_OPERAND: return "EXCEPTION_FLT_DENORMAL_OPERAND"; + case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "EXCEPTION_FLT_DIVIDE_BY_ZERO"; + case EXCEPTION_FLT_INEXACT_RESULT: return "EXCEPTION_FLT_INEXACT_RESULT"; + case EXCEPTION_FLT_INVALID_OPERATION: return "EXCEPTION_FLT_INVALID_OPERATION"; + case EXCEPTION_FLT_OVERFLOW: return "EXCEPTION_FLT_OVERFLOW"; + case EXCEPTION_FLT_STACK_CHECK: return "EXCEPTION_FLT_STACK_CHECK"; + case EXCEPTION_FLT_UNDERFLOW: return "EXCEPTION_FLT_UNDERFLOW"; + case EXCEPTION_GUARD_PAGE: return "EXCEPTION_GUARD_PAGE"; + case EXCEPTION_ILLEGAL_INSTRUCTION: return "EXCEPTION_ILLEGAL_INSTRUCTION"; + case EXCEPTION_IN_PAGE_ERROR: return "EXCEPTION_IN_PAGE_ERROR"; + case EXCEPTION_INT_DIVIDE_BY_ZERO: return "EXCEPTION_INT_DIVIDE_BY_ZERO"; + case EXCEPTION_INT_OVERFLOW: return "EXCEPTION_INT_OVERFLOW"; + case EXCEPTION_INVALID_DISPOSITION: return "EXCEPTION_INVALID_DISPOSITION"; + case EXCEPTION_INVALID_HANDLE: return "EXCEPTION_INVALID_HANDLE"; + case EXCEPTION_NONCONTINUABLE_EXCEPTION: return "EXCEPTION_NONCONTINUABLE_EXCEPTION"; + case EXCEPTION_PRIV_INSTRUCTION: return "EXCEPTION_PRIV_INSTRUCTION"; + case EXCEPTION_SINGLE_STEP: return "EXCEPTION_SINGLE_STEP"; + case EXCEPTION_STACK_OVERFLOW: return "EXCEPTION_STACK_OVERFLOW"; + case EXCEPTION_WINE_ASSERTION: return "EXCEPTION_WINE_ASSERTION"; + case EXCEPTION_WINE_CXX_EXCEPTION: return "EXCEPTION_WINE_CXX_EXCEPTION"; + case EXCEPTION_WINE_NAME_THREAD: return "EXCEPTION_WINE_NAME_THREAD"; + case EXCEPTION_WINE_STUB: return "EXCEPTION_WINE_STUB"; + } + return "unknown"; +} + #ifdef __cplusplus } #endif diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index 05bf0c047ba..3bcf9d37f23 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -146,15 +146,6 @@ struct dbg_breakpoint struct expr* condition; };
-/* used for C++ exceptions in msvcrt - * parameters: - * [0] CXX_FRAME_MAGIC - * [1] pointer to exception object - * [2] pointer to type - */ -#define CXX_EXCEPTION 0xe06d7363 -#define CXX_FRAME_MAGIC 0x19930520 - /* Helper structure */ typedef struct tagTHREADNAME_INFO { diff --git a/programs/winedbg/info.c b/programs/winedbg/info.c index 4e8580db0d4..e1f3d269649 100644 --- a/programs/winedbg/info.c +++ b/programs/winedbg/info.c @@ -951,11 +951,11 @@ void info_win32_exception(void) case EXCEPTION_FLT_STACK_CHECK: dbg_printf("floating point stack check"); break; - case CXX_EXCEPTION: - if(rec->NumberParameters == 3 && rec->ExceptionInformation[0] == CXX_FRAME_MAGIC) + case EXCEPTION_WINE_CXX_EXCEPTION: + if(rec->NumberParameters == 3 && rec->ExceptionInformation[0] == EXCEPTION_WINE_CXX_FRAME_MAGIC) dbg_printf("C++ exception(object = 0x%08lx, type = 0x%08lx)", rec->ExceptionInformation[1], rec->ExceptionInformation[2]); - else if(rec->NumberParameters == 4 && rec->ExceptionInformation[0] == CXX_FRAME_MAGIC) + else if(rec->NumberParameters == 4 && rec->ExceptionInformation[0] == EXCEPTION_WINE_CXX_FRAME_MAGIC) dbg_printf("C++ exception(object = %p, type = %p, base = %p)", (void*)rec->ExceptionInformation[1], (void*)rec->ExceptionInformation[2], (void*)rec->ExceptionInformation[3]);