32#pragma comment (lib,"comctl32")
34DebugExceptionhandler::DebugExceptionhandler(
void)
41 #define EX(code,text) \
42 case EXCEPTION_##code: strcpy(explanation,text); return "EXCEPTION_" #code;
44 switch(exptr->ExceptionRecord->ExceptionCode)
46 case EXCEPTION_ACCESS_VIOLATION:
48 "The thread tried to read from or write to a virtual\n"
49 "address for which it does not have the appropriate access.\n"
50 "Access address 0x%08x was %s.",
51 exptr->ExceptionRecord->ExceptionInformation[1],
52 exptr->ExceptionRecord->ExceptionInformation[0]?
"written to":
"read from");
53 return "EXCEPTION_ACCESS_VIOLATION";
54 EX(ARRAY_BOUNDS_EXCEEDED,
"The thread tried to access an array element that\n"
55 "is out of bounds and the underlying hardware\n"
56 "supports bounds checking.")
57 EX(BREAKPOINT,
"A breakpoint was encountered.")
58 EX(DATATYPE_MISALIGNMENT,
"The thread tried to read or write data that is\n"
59 "misaligned on hardware that does not provide alignment.\n"
60 "For example, 16-bit values must be aligned on\n"
61 "2-byte boundaries; 32-bit values on 4-byte\n"
62 "boundaries, and so on.")
63 EX(FLT_DENORMAL_OPERAND,
"One of the operands in a floating-point operation is\n"
64 "denormal. A denormal value is one that is too small\n"
65 "to represent as a standard floating-point value.")
66 EX(FLT_DIVIDE_BY_ZERO,
"The thread tried to divide a floating-point\n"
67 "value by a floating-point divisor of zero.")
68 EX(FLT_INEXACT_RESULT,
"The result of a floating-point operation\n"
69 "cannot be represented exactly as a decimal fraction.")
70 EX(FLT_INVALID_OPERATION,
"Some strange unknown floating point operation was attempted.")
71 EX(FLT_OVERFLOW,
"The exponent of a floating-point operation is greater\n"
72 "than the magnitude allowed by the corresponding type.")
73 EX(FLT_STACK_CHECK,
"The stack overflowed or underflowed as the result\n"
74 "of a floating-point operation.")
75 EX(FLT_UNDERFLOW,
"The exponent of a floating-point operation is less\n"
76 "than the magnitude allowed by the corresponding type.")
77 EX(GUARD_PAGE,
"A guard page was accessed.")
78 EX(ILLEGAL_INSTRUCTION,
"The thread tried to execute an invalid instruction.")
79 EX(IN_PAGE_ERROR,
"The thread tried to access a page that was not\n"
80 "present, and the system was unable to load the page.\n"
81 "For example, this exception might occur if a network "
82 "connection is lost while running a program over the network.")
83 EX(INT_DIVIDE_BY_ZERO,
"The thread tried to divide an integer value by\n"
84 "an integer divisor of zero.")
85 EX(INT_OVERFLOW,
"The result of an integer operation caused a carry\n"
86 "out of the most significant bit of the result.")
87 EX(INVALID_DISPOSITION,
"An exception handler returned an invalid disposition\n"
88 "to the exception dispatcher. Programmers using a\n"
89 "high-level language such as C should never encounter\n"
91 EX(INVALID_HANDLE,
"An invalid Windows handle was used.")
92 EX(NONCONTINUABLE_EXCEPTION,
"The thread tried to continue execution after\n"
93 "a noncontinuable exception occurred.")
94 EX(PRIV_INSTRUCTION,
"The thread tried to execute an instruction whose\n"
95 "operation is not allowed in the current machine mode.")
96 EX(SINGLE_STEP,
"A trace trap or other single-instruction mechanism\n"
97 "signaled that one instruction has been executed.")
98 EX(STACK_OVERFLOW,
"The thread used up its stack.")
99 case 0xE06D7363: strcpy(explanation,
"Microsoft C++ Exception");
return "EXCEPTION_MS";
101 wsprintf(explanation,
"Unknown exception code 0x%08x",exptr->ExceptionRecord->ExceptionCode);
102 return "EXCEPTION_UNKNOWN";
108void DebugExceptionhandler::LogExceptionLocation(
Debug &dbg,
struct _EXCEPTION_POINTERS *exptr)
110 struct _CONTEXT &ctx=*exptr->ContextRecord;
114 dbg <<
"Exception occured at\n" << buf <<
".";
117void DebugExceptionhandler::LogRegisters(
Debug &dbg,
struct _EXCEPTION_POINTERS *exptr)
119 struct _CONTEXT &ctx=*exptr->ContextRecord;
121 dbg << Debug::FillChar(
'0')
123 <<
"EAX:" << Debug::Width(8) << ctx.Eax
124 <<
" EBX:" << Debug::Width(8) << ctx.Ebx
125 <<
" ECX:" << Debug::Width(8) << ctx.Ecx <<
"\n"
126 <<
"EDX:" << Debug::Width(8) << ctx.Edx
127 <<
" ESI:" << Debug::Width(8) << ctx.Esi
128 <<
" EDI:" << Debug::Width(8) << ctx.Edi <<
"\n"
129 <<
"EIP:" << Debug::Width(8) << ctx.Eip
130 <<
" ESP:" << Debug::Width(8) << ctx.Esp
131 <<
" EBP:" << Debug::Width(8) << ctx.Ebp <<
"\n"
132 <<
"Flags:" << Debug::Bin() << Debug::Width(32) << ctx.EFlags << Debug::Hex() <<
"\n"
133 <<
"CS:" << Debug::Width(4) << ctx.SegCs
134 <<
" DS:" << Debug::Width(4) << ctx.SegDs
135 <<
" SS:" << Debug::Width(4) << ctx.SegSs
136 <<
"\nES:" << Debug::Width(4) << ctx.SegEs
137 <<
" FS:" << Debug::Width(4) << ctx.SegFs
138 <<
" GS:" << Debug::Width(4) << ctx.SegGs <<
"\n" << Debug::FillChar() << Debug::Dec();
141void DebugExceptionhandler::LogFPURegisters(
Debug &dbg,
struct _EXCEPTION_POINTERS *exptr)
143 struct _CONTEXT &ctx=*exptr->ContextRecord;
145 if (!(ctx.ContextFlags&CONTEXT_FLOATING_POINT))
147 dbg <<
"FP registers not available\n";
151 FLOATING_SAVE_AREA &flt=ctx.FloatSave;
152 dbg << Debug::Bin() << Debug::FillChar(
'0')
153 <<
"CW:" << Debug::Width(16) << (flt.ControlWord&0xffff) <<
"\n"
154 <<
"SW:" << Debug::Width(16) << (flt.StatusWord&0xffff) <<
"\n"
155 <<
"TW:" << Debug::Width(16) << (flt.TagWord&0xffff) <<
"\n"
157 <<
"ErrOfs: " << Debug::Width(8) << flt.ErrorOffset
158 <<
" ErrSel: " << Debug::Width(8) << flt.ErrorSelector <<
"\n"
159 <<
"DataOfs: " << Debug::Width(8) << flt.DataOffset
160 <<
" DataSel: " << Debug::Width(8) << flt.DataSelector <<
"\n"
161 <<
"Cr0NpxState: " << Debug::Width(8) << flt.Cr0NpxState <<
"\n";
163 for (
unsigned k=0;k<SIZE_OF_80387_REGISTERS/10;++k)
165 dbg << Debug::Dec() <<
"ST(" << k <<
") ";
169 for (
unsigned i=0;i<10;i++)
170 dbg << Debug::Width(2) <<
value[i];
179 fstp qword ptr [fpVal]
182 dbg <<
" " << fpVal <<
"\n";
184 dbg << Debug::FillChar() << Debug::Dec();
191static struct _EXCEPTION_POINTERS *exPtrs;
194static char regInfo[1024],verInfo[256];
199static BOOL CALLBACK ExceptionDlgProc(HWND hWnd,
UINT uMsg, WPARAM wParam, LPARAM lParam)
206 if (LOWORD(wParam)==IDOK)
207 EndDialog(hWnd,IDOK);
215 SendDlgItemMessage(hWnd,103,WM_SETTEXT,0,(LPARAM)verInfo);
224 SendDlgItemMessage(hWnd,105,LB_ADDSTRING,0,(LPARAM)p);
232 SendDlgItemMessage(hWnd,105,WM_SETFONT,(WPARAM)CreateFont(13,0,0,0,FW_NORMAL,
234 OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
235 DEFAULT_QUALITY,FIXED_PITCH|FF_MODERN,
NULL),MAKELPARAM(
TRUE,0));
238 SendDlgItemMessage(hWnd,100,WM_SETTEXT,0,(LPARAM)
240 SendDlgItemMessage(hWnd,101,WM_SETTEXT,0,(LPARAM)regInfo);
243 struct _CONTEXT &ctx=*exPtrs->ContextRecord;
245 SendDlgItemMessage(hWnd,102,WM_SETTEXT,0,(LPARAM)regInfo);
250 list=GetDlgItem(hWnd,104);
254 c.mask=LVCF_TEXT|LVCF_WIDTH;
257 ListView_InsertColumn(list,0,&c);
263 item.pszText=
"No stack data available - check for dbghelp.dll";
265 item.iItem=ListView_InsertItem(list,&item);
271 c.mask=LVCF_TEXT|LVCF_WIDTH;
274 ListView_InsertColumn(list,0,&c);
276 c.mask=LVCF_TEXT|LVCF_WIDTH|LVCF_FMT;
280 ListView_InsertColumn(list,1,&c);
282 c.mask=LVCF_TEXT|LVCF_WIDTH;
285 ListView_InsertColumn(list,2,&c);
289 ListView_InsertColumn(list,3,&c);
293 ListView_InsertColumn(list,4,&c);
297 ListView_InsertColumn(list,5,&c);
300 for (
unsigned k=0;k<sig.Size();k++)
308 item.iItem=ListView_InsertItem(list,&item);
312 item.pszText=strtok(regInfo,
" ");
313 ListView_SetItem(list,&item);
316 item.pszText=strtok(
NULL,
",");
317 ListView_SetItem(list,&item);
320 item.pszText=strtok(
NULL,
",");
321 ListView_SetItem(list,&item);
324 item.pszText=strtok(
NULL,
":");
325 ListView_SetItem(list,&item);
328 item.pszText=strtok(
NULL,
"");
329 ListView_SetItem(list,&item);
341 static bool inExceptionFilter;
342 if (inExceptionFilter)
344 MessageBox(
NULL,
"Exception in exception handler",
"Fatal error",MB_OK);
345 return EXCEPTION_CONTINUE_SEARCH;
347 inExceptionFilter=
true;
349 if (pExPtrs->ExceptionRecord->ExceptionCode==EXCEPTION_STACK_OVERFLOW)
353 OutputDebugString(
"EA/DEBUG: EXCEPTION_STACK_OVERFLOW\n");
357 Debug &dbg=Debug::Instance;
360 ++dbg.disableAssertsEtc;
368 LogExceptionLocation(dbg,pExPtrs); dbg <<
"\n\n";
374 if (len>=
sizeof(verInfo))
375 len=
sizeof(verInfo)-1;
382 LogRegisters(dbg,pExPtrs); dbg <<
"\n";
383 LogFPURegisters(dbg,pExPtrs); dbg <<
"\n";
385 if (len>=
sizeof(regInfo))
386 len=
sizeof(regInfo)-1;
391 dbg.m_stackWalk.
StackWalk(sig,pExPtrs->ContextRecord);
394 dbg <<
"Bytes around EIP:" <<
Debug::MemDump::Char(((
char *)(pExPtrs->ContextRecord->Eip))-32,80);
403 InitCommonControls();
405 DialogBoxIndirect(
NULL,(LPDLGTEMPLATE)rcException,
NULL,ExceptionDlgProc);
408 return EXCEPTION_EXECUTE_HANDLER;
static MemDump Char(const void *startPtr, unsigned numItems, unsigned bytePerItem=1)
Repeats a given character N times.
static const char * GetExceptionType(struct _EXCEPTION_POINTERS *exptr, char *explanation)
static long __stdcall ExceptionFilter(struct _EXCEPTION_POINTERS *pExPtrs)
Debug module main class (singleton).
void WriteBuildInfo(void)
Write build information into log.
unsigned used
used buffer size
void SetPrefixAndRadix(const char *prefix, int radix)
static void GetSymbol(unsigned addr, char *buf, unsigned bufSize)
Determines symbol for given address.
static int StackWalk(Signature &sig, struct _CONTEXT *ctx=0)
Walks the stack from the given address.