You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
393 lines
9.7 KiB
393 lines
9.7 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
exceptn.cxx
|
|
|
|
Abstract:
|
|
|
|
Contains exception-handling code for debug version
|
|
|
|
Contents:
|
|
SetExceptionHandler
|
|
(WininetExceptionFilter)
|
|
(MapX86ProcessorFlags)
|
|
|
|
Author:
|
|
|
|
Richard L Firth (rfirth) 18-Feb-1997
|
|
|
|
Revision History:
|
|
|
|
18-Feb-1997 rfirth
|
|
Created
|
|
|
|
--*/
|
|
|
|
#include <wininetp.h>
|
|
#include "rprintf.h"
|
|
|
|
#if INET_DEBUG
|
|
|
|
//
|
|
// private prototypes
|
|
//
|
|
|
|
PRIVATE
|
|
LONG
|
|
WininetExceptionFilter(
|
|
IN PEXCEPTION_POINTERS pExPtrs
|
|
);
|
|
|
|
#if defined(_X86_)
|
|
|
|
PRIVATE
|
|
LPSTR
|
|
MapX86ProcessorFlags(
|
|
IN DWORD Flags
|
|
);
|
|
|
|
#endif // defined(_X86_)
|
|
|
|
//
|
|
// functions
|
|
//
|
|
|
|
|
|
VOID
|
|
SetExceptionHandler(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Just sets the unhandled exception filter for this process
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)WininetExceptionFilter);
|
|
}
|
|
|
|
|
|
PRIVATE
|
|
LONG
|
|
WininetExceptionFilter(
|
|
IN PEXCEPTION_POINTERS pExPtrs
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We get to look at unhandled exceptions, and dump them to the debug log
|
|
|
|
Arguments:
|
|
|
|
pExPtrs - pointer to exception pointers structure
|
|
|
|
Return Value:
|
|
|
|
LONG
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// don't bother if we are not logging
|
|
//
|
|
|
|
if (InternetDebugControlFlags & DBG_NO_DEBUG) {
|
|
return EXCEPTION_CONTINUE_SEARCH;
|
|
}
|
|
|
|
LPSTR text;
|
|
LONG disposition = EXCEPTION_EXECUTE_HANDLER;
|
|
DWORD eipOffset = 0;
|
|
|
|
switch (pExPtrs->ExceptionRecord->ExceptionCode) {
|
|
case EXCEPTION_ACCESS_VIOLATION:
|
|
text = "Access Violation";
|
|
break;
|
|
|
|
case EXCEPTION_DATATYPE_MISALIGNMENT:
|
|
text = "Data Misalignment Exception";
|
|
break;
|
|
|
|
case EXCEPTION_BREAKPOINT:
|
|
text = "Breakpoint Exception";
|
|
disposition = EXCEPTION_CONTINUE_EXECUTION;
|
|
eipOffset = 1;
|
|
break;
|
|
|
|
case EXCEPTION_SINGLE_STEP:
|
|
text = "Single Step Exception";
|
|
break;
|
|
|
|
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
|
|
text = "Array Bounds Exceeded Exception";
|
|
break;
|
|
|
|
case EXCEPTION_FLT_DENORMAL_OPERAND:
|
|
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
|
|
case EXCEPTION_FLT_INEXACT_RESULT:
|
|
case EXCEPTION_FLT_INVALID_OPERATION:
|
|
case EXCEPTION_FLT_OVERFLOW:
|
|
case EXCEPTION_FLT_STACK_CHECK:
|
|
case EXCEPTION_FLT_UNDERFLOW:
|
|
text = "Floating Point Exception";
|
|
break;
|
|
|
|
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
|
text = "Integer Divide-By-Zero Exception";
|
|
break;
|
|
|
|
case EXCEPTION_INT_OVERFLOW:
|
|
text = "Integer Overflow Exception";
|
|
break;
|
|
|
|
case EXCEPTION_PRIV_INSTRUCTION:
|
|
text = "Privileged Instruction Exception";
|
|
break;
|
|
|
|
case EXCEPTION_IN_PAGE_ERROR:
|
|
text = "In-Page Error";
|
|
break;
|
|
|
|
case EXCEPTION_ILLEGAL_INSTRUCTION:
|
|
text = "Illegal Instruction";
|
|
break;
|
|
|
|
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
|
|
text = "Non-Continuable Exception";
|
|
break;
|
|
|
|
case EXCEPTION_STACK_OVERFLOW:
|
|
text = "Stack Overflow";
|
|
break;
|
|
|
|
case EXCEPTION_INVALID_DISPOSITION:
|
|
text = "Invalid Disposition Exception";
|
|
break;
|
|
|
|
case EXCEPTION_GUARD_PAGE:
|
|
text = "Guard Page Exception";
|
|
break;
|
|
|
|
case EXCEPTION_INVALID_HANDLE:
|
|
text = "Invalid Handle Exception";
|
|
break;
|
|
|
|
case CONTROL_C_EXIT:
|
|
text = "Control-C Exception";
|
|
break;
|
|
|
|
default:
|
|
text = "Unknown Exception";
|
|
break;
|
|
}
|
|
|
|
InitSymLib();
|
|
|
|
|
|
DWORD dwCodeOffset;
|
|
// BUGBUG: Not 64b compatible
|
|
LPSTR lpszDebugSymbol = GetDebugSymbol(PtrToUlong(pExPtrs->ExceptionRecord->ExceptionAddress),
|
|
&dwCodeOffset
|
|
);
|
|
|
|
char buffer[512];
|
|
int offset;
|
|
BOOL needCrLf = FALSE;
|
|
|
|
offset = rsprintf(buffer,
|
|
"\n"
|
|
"********************************************************************************\n"
|
|
"Thread %#x\n"
|
|
"%s at %#08x",
|
|
GetCurrentThreadId(),
|
|
text,
|
|
pExPtrs->ExceptionRecord->ExceptionAddress
|
|
);
|
|
if (dwCodeOffset != (DWORD_PTR)pExPtrs->ExceptionRecord->ExceptionAddress) {
|
|
offset += rsprintf(&buffer[offset],
|
|
" (%s+%#x)\n",
|
|
lpszDebugSymbol,
|
|
dwCodeOffset
|
|
);
|
|
} else {
|
|
buffer[offset++] = ' ';
|
|
needCrLf = TRUE;
|
|
}
|
|
if (pExPtrs->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
|
|
rsprintf(&buffer[offset],
|
|
"%sing %#08x\n",
|
|
pExPtrs->ExceptionRecord->ExceptionInformation[0]
|
|
? "writ"
|
|
: "read",
|
|
pExPtrs->ExceptionRecord->ExceptionInformation[1]
|
|
);
|
|
} else if (needCrLf) {
|
|
buffer[offset++] = '\r';
|
|
buffer[offset++] = '\n';
|
|
buffer[offset] = '\0';
|
|
}
|
|
InternetDebugOut(buffer, FALSE);
|
|
|
|
#if defined(_X86_)
|
|
|
|
if ((pExPtrs->ContextRecord->ContextFlags & CONTEXT_FULL) == CONTEXT_FULL) {
|
|
rsprintf(buffer,
|
|
"\n"
|
|
"Processor Context:\n"
|
|
"eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\n"
|
|
"eip=%08x esp=%08x ebp=%08x iopl=%d %s\n"
|
|
"cs=%04x ss=%04x ds=%04x es=%04x fs=%04x gs=%04x efl=%08x\n",
|
|
pExPtrs->ContextRecord->Eax,
|
|
pExPtrs->ContextRecord->Ebx,
|
|
pExPtrs->ContextRecord->Ecx,
|
|
pExPtrs->ContextRecord->Edx,
|
|
pExPtrs->ContextRecord->Esi,
|
|
pExPtrs->ContextRecord->Edi,
|
|
pExPtrs->ContextRecord->Eip,
|
|
pExPtrs->ContextRecord->Esp,
|
|
pExPtrs->ContextRecord->Ebp,
|
|
((pExPtrs->ContextRecord->EFlags & 0x00003000) >> 12),
|
|
MapX86ProcessorFlags(pExPtrs->ContextRecord->EFlags),
|
|
pExPtrs->ContextRecord->SegCs,
|
|
pExPtrs->ContextRecord->SegSs,
|
|
pExPtrs->ContextRecord->SegDs,
|
|
pExPtrs->ContextRecord->SegEs,
|
|
pExPtrs->ContextRecord->SegFs,
|
|
pExPtrs->ContextRecord->SegGs,
|
|
pExPtrs->ContextRecord->EFlags
|
|
);
|
|
InternetDebugOut(buffer, FALSE);
|
|
}
|
|
|
|
//
|
|
// dump out the stack, debug style
|
|
//
|
|
|
|
LPBYTE Address = (LPBYTE)pExPtrs->ContextRecord->Esp;
|
|
|
|
rsprintf(buffer,
|
|
"\n"
|
|
"256 bytes of process stack at %04x:%08x:\n\n",
|
|
pExPtrs->ContextRecord->SegSs,
|
|
Address
|
|
);
|
|
InternetDebugOut(buffer, FALSE);
|
|
|
|
for (DWORD Size = 256; Size; ) {
|
|
|
|
DWORD nDumped = InternetDebugDumpFormat(Address, 16, sizeof(DWORD), buffer);
|
|
|
|
InternetDebugOut(buffer, FALSE);
|
|
Size -= nDumped;
|
|
Address += nDumped;
|
|
}
|
|
|
|
//
|
|
// dump call stack
|
|
//
|
|
|
|
LPVOID backtrace[16];
|
|
|
|
memset(&backtrace, 0, sizeof(backtrace));
|
|
|
|
x86SleazeCallStack((LPVOID *)backtrace,
|
|
ARRAY_ELEMENTS(backtrace),
|
|
(LPVOID *)pExPtrs->ContextRecord->Ebp
|
|
);
|
|
|
|
BOOL ok = FALSE;
|
|
|
|
for (int i = 0; i < ARRAY_ELEMENTS(backtrace); ++i) {
|
|
if (backtrace[i] != NULL) {
|
|
ok = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (ok) {
|
|
rsprintf(buffer,
|
|
"\n"
|
|
"Stack back-trace:\n\n"
|
|
);
|
|
InternetDebugOut(buffer, FALSE);
|
|
for (int i = 0; i < ARRAY_ELEMENTS(backtrace); ++i) {
|
|
if (backtrace[i] == NULL) {
|
|
break;
|
|
}
|
|
lpszDebugSymbol = GetDebugSymbol((DWORD)backtrace[i], &dwCodeOffset);
|
|
rsprintf(buffer,
|
|
"%08x %s+%#x\n",
|
|
backtrace[i],
|
|
lpszDebugSymbol,
|
|
dwCodeOffset
|
|
);
|
|
InternetDebugOut(buffer, FALSE);
|
|
}
|
|
}
|
|
|
|
#endif // defined(_X86_)
|
|
|
|
InternetDebugOut("\r\n********************************************************************************\r\n\r\n", FALSE);
|
|
|
|
InternetFlushDebugFile();
|
|
|
|
#if defined(_X86_)
|
|
|
|
if (disposition == EXCEPTION_CONTINUE_EXECUTION) {
|
|
pExPtrs->ContextRecord->Eip += eipOffset;
|
|
}
|
|
|
|
#endif // defined(_X86_)
|
|
|
|
return disposition;
|
|
}
|
|
|
|
#if defined(_X86_)
|
|
|
|
|
|
PRIVATE
|
|
LPSTR
|
|
MapX86ProcessorFlags(
|
|
IN DWORD Flags
|
|
)
|
|
{
|
|
//
|
|
// BUGBUG - not re-entrant
|
|
//
|
|
|
|
static char buf[32 * 3 + 1];
|
|
|
|
rsprintf(buf,
|
|
"%s %s %s %s %s %s %s %s",
|
|
(Flags & 0x00000800) ? "ov" : "nv", // Overflow: Overflow or No-overflow
|
|
(Flags & 0x00000400) ? "dn" : "up", // Direction: Up or Down
|
|
(Flags & 0x00000200) ? "ei" : "di", // Interrupts: Enabled or Disabled
|
|
(Flags & 0x00000080) ? "ng" : "pl", // Sign: Negative or Positive
|
|
(Flags & 0x00000040) ? "zr" : "nz", // Zero: Zero or Not-zero
|
|
(Flags & 0x00000010) ? "ac" : "na", // Aux-Carry: Aux-carry or No-aux-carry
|
|
(Flags & 0x00000004) ? "pe" : "po", // Parity: Parity-even or Parity-odd
|
|
(Flags & 0x00000001) ? "cy" : "nc" // Carry: Carry or No-carry
|
|
);
|
|
return buf;
|
|
}
|
|
|
|
#endif // defined(_X86_)
|
|
|
|
#endif // INET_DEBUG
|