[PATCH 2/2] [WineDbg]: moved into a common function all code dealing with printing information about an exception, and use this function to implement new 'info exception' command
Eric Pouech
eric.pouech at orange.fr
Sun Nov 21 15:19:40 CST 2010
(this should make Vincent Povirk happy, from the WineConf talks)
A+
---
programs/winedbg/dbg.y | 1
programs/winedbg/debugger.h | 4 +
programs/winedbg/info.c | 157 ++++++++++++++++++++++++++++++++++++++++
programs/winedbg/tgt_active.c | 160 +++--------------------------------------
4 files changed, 173 insertions(+), 149 deletions(-)
diff --git a/programs/winedbg/dbg.y b/programs/winedbg/dbg.y
index 3fec9b7..685ca6c 100644
--- a/programs/winedbg/dbg.y
+++ b/programs/winedbg/dbg.y
@@ -291,6 +291,7 @@ info_command:
| tINFO tFRAME expr_rvalue { info_win32_frame_exceptions($3); }
| tINFO tMAPS { info_win32_virtual(dbg_curr_pid); }
| tINFO tMAPS expr_rvalue { info_win32_virtual($3); }
+ | tINFO tEXCEPTION { info_win32_exception(); }
;
maintenance_command:
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h
index 807a341..eb05cda 100644
--- a/programs/winedbg/debugger.h
+++ b/programs/winedbg/debugger.h
@@ -183,6 +183,9 @@ struct dbg_thread
struct dbg_breakpoint step_over_bp;
char name[9];
BOOL in_exception; /* TRUE if thread stopped with an exception */
+ BOOL first_chance; /* TRUE if thread stopped with a first chance exception
+ * - only valid when in_exception is TRUE
+ */
EXCEPTION_RECORD excpt_record; /* only valid when in_exception is TRUE */
struct
{
@@ -354,6 +357,7 @@ extern void info_win32_threads(void);
extern void info_win32_frame_exceptions(DWORD tid);
extern void info_win32_virtual(DWORD pid);
extern void info_win32_segments(DWORD start, int length);
+extern void info_win32_exception(void);
extern void info_wine_dbg_channel(BOOL add, const char* chnl, const char* name);
/* memory.c */
diff --git a/programs/winedbg/info.c b/programs/winedbg/info.c
index 844bcbc..8d91cc9 100644
--- a/programs/winedbg/info.c
+++ b/programs/winedbg/info.c
@@ -31,6 +31,7 @@
#include "winuser.h"
#include "tlhelp32.h"
#include "wine/debug.h"
+#include "wine/exception.h"
WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
@@ -757,3 +758,159 @@ void info_wine_dbg_channel(BOOL turn_on, const char* cls, const char* name)
if (!done) dbg_printf("Unable to find debug channel %s\n", name);
else WINE_TRACE("Changed %d channel instances\n", done);
}
+
+void info_win32_exception(void)
+{
+ const EXCEPTION_RECORD* rec;
+ ADDRESS64 addr;
+ char hexbuf[MAX_OFFSET_TO_STR_LEN];
+
+ if (!dbg_curr_thread->in_exception)
+ {
+ dbg_printf("Thread isn't in an exception\n");
+ return;
+ }
+ rec = &dbg_curr_thread->excpt_record;
+ memory_get_current_pc(&addr);
+
+ /* print some infos */
+ dbg_printf("%s: ",
+ dbg_curr_thread->first_chance ? "First chance exception" : "Unhandled exception");
+ switch (rec->ExceptionCode)
+ {
+ case EXCEPTION_BREAKPOINT:
+ dbg_printf("breakpoint");
+ break;
+ case EXCEPTION_SINGLE_STEP:
+ dbg_printf("single step");
+ break;
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ dbg_printf("divide by zero");
+ break;
+ case EXCEPTION_INT_OVERFLOW:
+ dbg_printf("overflow");
+ break;
+ case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+ dbg_printf("array bounds");
+ break;
+ case EXCEPTION_ILLEGAL_INSTRUCTION:
+ dbg_printf("illegal instruction");
+ break;
+ case EXCEPTION_STACK_OVERFLOW:
+ dbg_printf("stack overflow");
+ break;
+ case EXCEPTION_PRIV_INSTRUCTION:
+ dbg_printf("privileged instruction");
+ break;
+ case EXCEPTION_ACCESS_VIOLATION:
+ if (rec->NumberParameters == 2)
+ dbg_printf("page fault on %s access to 0x%08lx",
+ rec->ExceptionInformation[0] == EXCEPTION_WRITE_FAULT ? "write" :
+ rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT ? "execute" : "read",
+ rec->ExceptionInformation[1]);
+ else
+ dbg_printf("page fault");
+ break;
+ case EXCEPTION_DATATYPE_MISALIGNMENT:
+ dbg_printf("Alignment");
+ break;
+ case DBG_CONTROL_C:
+ dbg_printf("^C");
+ break;
+ case CONTROL_C_EXIT:
+ dbg_printf("^C");
+ break;
+ case STATUS_POSSIBLE_DEADLOCK:
+ {
+ ADDRESS64 recaddr;
+
+ recaddr.Mode = AddrModeFlat;
+ recaddr.Offset = rec->ExceptionInformation[0];
+
+ dbg_printf("wait failed on critical section ");
+ print_address(&recaddr, FALSE);
+ }
+ break;
+ case EXCEPTION_WINE_STUB:
+ {
+ char dll[32], name[64];
+ memory_get_string(dbg_curr_process,
+ (void*)rec->ExceptionInformation[0], TRUE, FALSE,
+ dll, sizeof(dll));
+ if (HIWORD(rec->ExceptionInformation[1]))
+ memory_get_string(dbg_curr_process,
+ (void*)rec->ExceptionInformation[1], TRUE, FALSE,
+ name, sizeof(name));
+ else
+ sprintf( name, "%ld", rec->ExceptionInformation[1] );
+ dbg_printf("unimplemented function %s.%s called", dll, name);
+ }
+ break;
+ case EXCEPTION_WINE_ASSERTION:
+ dbg_printf("assertion failed");
+ break;
+ case EXCEPTION_VM86_INTx:
+ dbg_printf("interrupt %02lx in vm86 mode", rec->ExceptionInformation[0]);
+ break;
+ case EXCEPTION_VM86_STI:
+ dbg_printf("sti in vm86 mode");
+ break;
+ case EXCEPTION_VM86_PICRETURN:
+ dbg_printf("PIC return in vm86 mode");
+ break;
+ case EXCEPTION_FLT_DENORMAL_OPERAND:
+ dbg_printf("denormal float operand");
+ break;
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ dbg_printf("divide by zero");
+ break;
+ case EXCEPTION_FLT_INEXACT_RESULT:
+ dbg_printf("inexact float result");
+ break;
+ case EXCEPTION_FLT_INVALID_OPERATION:
+ dbg_printf("invalid float operation");
+ break;
+ case EXCEPTION_FLT_OVERFLOW:
+ dbg_printf("floating point overflow");
+ break;
+ case EXCEPTION_FLT_UNDERFLOW:
+ dbg_printf("floating point underflow");
+ break;
+ 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)
+ dbg_printf("C++ exception(object = 0x%08lx, type = 0x%08lx)",
+ rec->ExceptionInformation[1], rec->ExceptionInformation[2]);
+ else
+ dbg_printf("C++ exception with strange parameter count %d or magic 0x%08lx",
+ rec->NumberParameters, rec->ExceptionInformation[0]);
+ break;
+ default:
+ dbg_printf("0x%08x", rec->ExceptionCode);
+ break;
+ }
+ if (rec->ExceptionFlags & EH_STACK_INVALID)
+ dbg_printf(", invalid program stack");
+
+ switch (addr.Mode)
+ {
+ case AddrModeFlat:
+ dbg_printf(" in %d-bit code (%s)",
+ be_cpu->pointer_size * 8,
+ memory_offset_to_string(hexbuf, addr.Offset, 0));
+ break;
+ case AddrModeReal:
+ dbg_printf(" in vm86 code (%04x:%04x)", addr.Segment, (unsigned) addr.Offset);
+ break;
+ case AddrMode1616:
+ dbg_printf(" in 16-bit code (%04x:%04x)", addr.Segment, (unsigned) addr.Offset);
+ break;
+ case AddrMode1632:
+ dbg_printf(" in segmented 32-bit code (%04x:%08lx)", addr.Segment, (unsigned long) addr.Offset);
+ break;
+ default: dbg_printf(" bad address");
+ }
+ dbg_printf(".\n");
+}
diff --git a/programs/winedbg/tgt_active.c b/programs/winedbg/tgt_active.c
index eb25329..376ee22 100644
--- a/programs/winedbg/tgt_active.c
+++ b/programs/winedbg/tgt_active.c
@@ -118,44 +118,18 @@ static unsigned dbg_fetch_context(void)
* or exception is silently continued(return FALSE)
* is_debug means the exception is a breakpoint or single step exception
*/
-static unsigned dbg_exception_prolog(BOOL is_debug, BOOL first_chance, const EXCEPTION_RECORD* rec)
+static unsigned dbg_exception_prolog(BOOL is_debug, const EXCEPTION_RECORD* rec)
{
ADDRESS64 addr;
BOOL is_break;
- char hexbuf[MAX_OFFSET_TO_STR_LEN];
memory_get_current_pc(&addr);
break_suspend_execution();
- dbg_curr_thread->excpt_record = *rec;
- dbg_curr_thread->in_exception = TRUE;
-
- if (!is_debug)
- {
- switch (addr.Mode)
- {
- case AddrModeFlat:
- dbg_printf(" in %d-bit code (%s)",
- be_cpu->pointer_size * 8,
- memory_offset_to_string(hexbuf, addr.Offset, 0));
- break;
- case AddrModeReal:
- dbg_printf(" in vm86 code (%04x:%04x)", addr.Segment, (unsigned) addr.Offset);
- break;
- case AddrMode1616:
- dbg_printf(" in 16-bit code (%04x:%04x)", addr.Segment, (unsigned) addr.Offset);
- break;
- case AddrMode1632:
- dbg_printf(" in segmented 32-bit code (%04x:%08lx)", addr.Segment, (unsigned long) addr.Offset);
- break;
- default: dbg_printf(" bad address");
- }
- dbg_printf(".\n");
- }
/* this will resynchronize builtin dbghelp's internal ELF module list */
SymLoadModule(dbg_curr_process->handle, 0, 0, 0, 0, 0);
- if (is_debug) break_adjust_pc(&addr, rec->ExceptionCode, first_chance, &is_break);
+ if (is_debug) break_adjust_pc(&addr, rec->ExceptionCode, dbg_curr_thread->first_chance, &is_break);
/*
* Do a quiet backtrace so that we have an idea of what the situation
* is WRT the source files.
@@ -285,131 +259,19 @@ static DWORD dbg_handle_exception(const EXCEPTION_RECORD* rec, BOOL first_chance
return DBG_EXCEPTION_NOT_HANDLED;
}
- if (!is_debug)
- {
- /* print some infos */
- dbg_printf("%s: ",
- first_chance ? "First chance exception" : "Unhandled exception");
- switch (rec->ExceptionCode)
- {
- case EXCEPTION_INT_DIVIDE_BY_ZERO:
- dbg_printf("divide by zero");
- break;
- case EXCEPTION_INT_OVERFLOW:
- dbg_printf("overflow");
- break;
- case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
- dbg_printf("array bounds");
- break;
- case EXCEPTION_ILLEGAL_INSTRUCTION:
- dbg_printf("illegal instruction");
- break;
- case EXCEPTION_STACK_OVERFLOW:
- dbg_printf("stack overflow");
- break;
- case EXCEPTION_PRIV_INSTRUCTION:
- dbg_printf("privileged instruction");
- break;
- case EXCEPTION_ACCESS_VIOLATION:
- if (rec->NumberParameters == 2)
- dbg_printf("page fault on %s access to 0x%08lx",
- rec->ExceptionInformation[0] == EXCEPTION_WRITE_FAULT ? "write" :
- rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT ? "execute" : "read",
- rec->ExceptionInformation[1]);
- else
- dbg_printf("page fault");
- break;
- case EXCEPTION_DATATYPE_MISALIGNMENT:
- dbg_printf("Alignment");
- break;
- case DBG_CONTROL_C:
- dbg_printf("^C");
- break;
- case CONTROL_C_EXIT:
- dbg_printf("^C");
- break;
- case STATUS_POSSIBLE_DEADLOCK:
- {
- ADDRESS64 addr;
+ dbg_curr_thread->excpt_record = *rec;
+ dbg_curr_thread->in_exception = TRUE;
+ dbg_curr_thread->first_chance = first_chance;
- addr.Mode = AddrModeFlat;
- addr.Offset = rec->ExceptionInformation[0];
+ if (!is_debug) info_win32_exception();
- dbg_printf("wait failed on critical section ");
- print_address(&addr, FALSE);
- }
- if (!DBG_IVAR(BreakOnCritSectTimeOut))
- {
- dbg_printf("\n");
- return DBG_EXCEPTION_NOT_HANDLED;
- }
- break;
- case EXCEPTION_WINE_STUB:
- {
- char dll[32], name[64];
- memory_get_string(dbg_curr_process,
- (void*)rec->ExceptionInformation[0], TRUE, FALSE,
- dll, sizeof(dll));
- if (HIWORD(rec->ExceptionInformation[1]))
- memory_get_string(dbg_curr_process,
- (void*)rec->ExceptionInformation[1], TRUE, FALSE,
- name, sizeof(name));
- else
- sprintf( name, "%ld", rec->ExceptionInformation[1] );
- dbg_printf("unimplemented function %s.%s called", dll, name);
- }
- break;
- case EXCEPTION_WINE_ASSERTION:
- dbg_printf("assertion failed");
- break;
- case EXCEPTION_VM86_INTx:
- dbg_printf("interrupt %02lx in vm86 mode", rec->ExceptionInformation[0]);
- break;
- case EXCEPTION_VM86_STI:
- dbg_printf("sti in vm86 mode");
- break;
- case EXCEPTION_VM86_PICRETURN:
- dbg_printf("PIC return in vm86 mode");
- break;
- case EXCEPTION_FLT_DENORMAL_OPERAND:
- dbg_printf("denormal float operand");
- break;
- case EXCEPTION_FLT_DIVIDE_BY_ZERO:
- dbg_printf("divide by zero");
- break;
- case EXCEPTION_FLT_INEXACT_RESULT:
- dbg_printf("inexact float result");
- break;
- case EXCEPTION_FLT_INVALID_OPERATION:
- dbg_printf("invalid float operation");
- break;
- case EXCEPTION_FLT_OVERFLOW:
- dbg_printf("floating point overflow");
- break;
- case EXCEPTION_FLT_UNDERFLOW:
- dbg_printf("floating point underflow");
- break;
- 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)
- dbg_printf("C++ exception(object = 0x%08lx, type = 0x%08lx)",
- rec->ExceptionInformation[1], rec->ExceptionInformation[2]);
- else
- dbg_printf("C++ exception with strange parameter count %d or magic 0x%08lx",
- rec->NumberParameters, rec->ExceptionInformation[0]);
- break;
- default:
- dbg_printf("0x%08x", rec->ExceptionCode);
- break;
- }
- }
- if( (rec->ExceptionFlags & EH_STACK_INVALID) ) {
- dbg_printf( ", invalid program stack" );
+ if (rec->ExceptionCode == STATUS_POSSIBLE_DEADLOCK && !DBG_IVAR(BreakOnCritSectTimeOut))
+ {
+ dbg_curr_thread->in_exception = FALSE;
+ return DBG_EXCEPTION_NOT_HANDLED;
}
- if (dbg_exception_prolog(is_debug, first_chance, rec))
+ if (dbg_exception_prolog(is_debug, rec))
{
dbg_interactiveP = TRUE;
return 0;
More information about the wine-patches
mailing list