15 extern void Print(
const char* fmt, ...);
26 static LPTOP_LEVEL_EXCEPTION_FILTER old_filter;
28 static LONG WINAPI ExceptionFilter(EXCEPTION_POINTERS* info);
30 static void PrintReport(EXCEPTION_POINTERS* info);
33 static const char* GetExceptionString(DWORD dwCode);
34 static BOOL GetLogicalAddress(VOID* addr,
char* module,
int len,
35 DWORD& section, DWORD& offset);
37 static BOOL InitImageHelp();
38 static void ImageStackTrace(CONTEXT* context);
39 static void IntelStackTrace(CONTEXT* context);
44 typedef BOOL (__stdcall * SYMINITIALIZEPROC)(HANDLE, LPSTR, BOOL);
45 typedef BOOL (__stdcall * SYMCLEANUPPROC)(HANDLE);
47 typedef LPVOID (__stdcall *SYMFUNCTIONTABLEACCESSPROC)(HANDLE, DWORD);
48 typedef DWORD (__stdcall *SYMGETMODULEBASEPROC)(HANDLE, DWORD);
49 typedef BOOL (__stdcall *SYMGETSYMFROMADDRPROC)(HANDLE, DWORD, PDWORD, PIMAGEHLP_SYMBOL);
51 typedef BOOL (__stdcall * STACKWALKPROC)(DWORD,
56 PREAD_PROCESS_MEMORY_ROUTINE,
57 PFUNCTION_TABLE_ACCESS_ROUTINE,
58 PGET_MODULE_BASE_ROUTINE,
59 PTRANSLATE_ADDRESS_ROUTINE);
61 static SYMINITIALIZEPROC SymInitialize;
62 static SYMCLEANUPPROC SymCleanup;
63 static STACKWALKPROC StackTrace;
64 static SYMFUNCTIONTABLEACCESSPROC SymFunctionTableAccess;
65 static SYMGETMODULEBASEPROC SymGetModuleBase;
66 static SYMGETSYMFROMADDRPROC SymGetSymFromAddr;
71 LPTOP_LEVEL_EXCEPTION_FILTER ExceptionHandler::old_filter = 0;
73 ExceptionHandler::SYMINITIALIZEPROC ExceptionHandler::SymInitialize = 0;
74 ExceptionHandler::SYMCLEANUPPROC ExceptionHandler::SymCleanup = 0;
75 ExceptionHandler::STACKWALKPROC ExceptionHandler::StackTrace = 0;
77 ExceptionHandler::SYMFUNCTIONTABLEACCESSPROC
78 ExceptionHandler::SymFunctionTableAccess = 0;
80 ExceptionHandler::SYMGETMODULEBASEPROC
81 ExceptionHandler::SymGetModuleBase = 0;
83 ExceptionHandler::SYMGETSYMFROMADDRPROC
84 ExceptionHandler::SymGetSymFromAddr = 0;
93 old_filter = SetUnhandledExceptionFilter(ExceptionFilter);
98 SetUnhandledExceptionFilter(old_filter);
103 static bool in_filter =
false;
106 ExceptionHandler::ExceptionFilter(EXCEPTION_POINTERS* info)
109 Print(
"\n\n*********************************************\n");
110 Print(
"SECOND EXCEPTION CAUGHT: TERMINATING.\n");
111 Print(
"*********************************************\n");
121 return old_filter(info);
123 return EXCEPTION_CONTINUE_SEARCH;
129 ExceptionHandler::PrintReport(EXCEPTION_POINTERS* info)
131 EXCEPTION_RECORD* record = info->ExceptionRecord;
132 CONTEXT* context = info->ContextRecord;
133 DWORD code = record->ExceptionCode;
135 Print(
"\n*********************************************\n");
136 Print(
"FATAL EXCEPTION:\n");
138 Print(
"\nRegisters:\n");
139 Print(
"EAX: %08x\n", context->Eax);
140 Print(
"EBX: %08x\n", context->Ebx);
141 Print(
"ECX: %08x\n", context->Ecx);
142 Print(
"EDX: %08x\n", context->Edx);
143 Print(
"EDI: %08x\n", context->Edi);
144 Print(
"ESI: %08x\n", context->Esi);
145 Print(
"EBP: %08x\n", context->Ebp);
147 Print(
"CS:EIP: %04x:%08x\n", context->SegCs, context->Eip);
148 Print(
"SS:ESP: %04x:%08x\n", context->SegSs, context->Esp);
149 Print(
"DS: %04x\n", context->SegDs);
150 Print(
"ES: %04x\n", context->SegEs);
151 Print(
"FS: %04x\n", context->SegFs);
152 Print(
"GS: %04x\n", context->SegGs);
153 Print(
"Flags: %08x\n", context->EFlags );
156 Print(
"Exception Code: %08x %s\n",code, GetExceptionString(code));
157 Print(
"Exception Addr: %08x \n", record->ExceptionAddress);
159 if (code == EXCEPTION_ACCESS_VIOLATION && record->NumberParameters >= 2) {
160 if (record->ExceptionInformation[0])
161 Print(
" Program attempted to WRITE to address 0x%08x\n", record->ExceptionInformation[1]);
163 Print(
" Program attempted to READ from address 0x%08x\n", record->ExceptionInformation[1]);
166 if (InitImageHelp()) {
167 ImageStackTrace(context);
168 SymCleanup(GetCurrentProcess());
171 IntelStackTrace(context);
174 Print(
"\n*********************************************\nPROGRAM TERMINATED.\n");
180 ExceptionHandler::GetExceptionString(DWORD code)
182 #define EXCEPTION( x ) case EXCEPTION_##x: return #x;
186 EXCEPTION( DATATYPE_MISALIGNMENT )
187 EXCEPTION( BREAKPOINT )
188 EXCEPTION( SINGLE_STEP )
189 EXCEPTION( ARRAY_BOUNDS_EXCEEDED )
190 EXCEPTION( FLT_DENORMAL_OPERAND )
191 EXCEPTION( FLT_DIVIDE_BY_ZERO )
192 EXCEPTION( FLT_INEXACT_RESULT )
193 EXCEPTION( FLT_INVALID_OPERATION )
194 EXCEPTION( FLT_OVERFLOW )
195 EXCEPTION( FLT_STACK_CHECK )
196 EXCEPTION( FLT_UNDERFLOW )
197 EXCEPTION( INT_DIVIDE_BY_ZERO )
198 EXCEPTION( INT_OVERFLOW )
199 EXCEPTION( PRIV_INSTRUCTION )
200 EXCEPTION( IN_PAGE_ERROR )
201 EXCEPTION( ILLEGAL_INSTRUCTION )
202 EXCEPTION( NONCONTINUABLE_EXCEPTION )
203 EXCEPTION( STACK_OVERFLOW )
204 EXCEPTION( INVALID_DISPOSITION )
205 EXCEPTION( GUARD_PAGE )
206 EXCEPTION( INVALID_HANDLE )
209 static
char buffer[512] = { 0 };
211 FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
212 GetModuleHandle(
"NTDLL.DLL"),
213 code, 0, buffer,
sizeof(buffer), 0 );
221 ExceptionHandler::GetLogicalAddress(
void* addr,
char* mod_name,
int len, DWORD& section, DWORD& offset)
223 MEMORY_BASIC_INFORMATION mbi;
225 if (!VirtualQuery(addr, &mbi,
sizeof(mbi)))
228 DWORD hMod = (DWORD)mbi.AllocationBase;
230 if (!GetModuleFileName((HMODULE)hMod, mod_name, len))
233 PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER) hMod;
234 PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(hMod + pDosHdr->e_lfanew);
235 PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION( pNtHdr );
237 DWORD rva = (DWORD)addr - hMod;
241 for (
unsigned i = 0; i < pNtHdr->FileHeader.NumberOfSections; i++, pSection++ ) {
242 DWORD sectionStart = pSection->VirtualAddress;
243 DWORD sectionEnd = sectionStart
244 + max(pSection->SizeOfRawData, pSection->Misc.VirtualSize);
247 if ((rva >= sectionStart) && (rva <= sectionEnd)) {
252 offset = rva - sectionStart;
263 ExceptionHandler::IntelStackTrace(CONTEXT* context)
265 Print(
"\nStack Trace (Intel):\n");
266 Print(
"Address Frame Logical addr Module\n");
268 DWORD pc = context->Eip;
272 pFrame = (DWORD*)context->Ebp;
275 char mod_name[256] = { 0 };
276 DWORD section = 0, offset = 0;
278 GetLogicalAddress((
void*)pc, mod_name, 256, section, offset);
280 Print(
"%08X %08X %04X:%08X %s\n",
281 pc, pFrame, section, offset, mod_name);
285 pFrame = (PDWORD)pFrame[0];
287 if ((DWORD)pFrame & 3)
290 if (pFrame <= pPrevFrame)
294 if (IsBadWritePtr(pFrame,
sizeof(PVOID)*2))
303 void ExceptionHandler::ImageStackTrace(CONTEXT* context)
305 Print(
"\nStack Trace (Symbolic):\n");
306 Print(
"Address Frame\n");
310 memset(&sf, 0,
sizeof(sf));
314 sf.AddrPC.Offset = context->Eip;
315 sf.AddrPC.Mode = AddrModeFlat;
316 sf.AddrStack.Offset = context->Esp;
317 sf.AddrStack.Mode = AddrModeFlat;
318 sf.AddrFrame.Offset = context->Ebp;
319 sf.AddrFrame.Mode = AddrModeFlat;
322 if (!StackTrace( IMAGE_FILE_MACHINE_I386,
328 SymFunctionTableAccess,
333 if (sf.AddrFrame.Offset == 0)
336 Print(
"%08x %08x ", sf.AddrPC.Offset, sf.AddrFrame.Offset);
346 BYTE symbolBuffer[
sizeof(IMAGEHLP_SYMBOL) + 512];
347 PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)symbolBuffer;
348 pSymbol->SizeOfStruct =
sizeof(symbolBuffer);
349 pSymbol->MaxNameLength = 512;
351 DWORD symDisplacement = 0;
354 if (SymGetSymFromAddr(GetCurrentProcess(), sf.AddrPC.Offset,
355 &symDisplacement, pSymbol)) {
356 Print(
"%-40s [%04X]\n", pSymbol->Name, symDisplacement);
359 char mod_name[256] = { 0 };
360 DWORD section = 0, offset = 0;
362 GetLogicalAddress((PVOID)sf.AddrPC.Offset,
363 mod_name, 256, section, offset );
365 Print(
"%04X:%08X %s\n", section, offset, mod_name);
373 ExceptionHandler::InitImageHelp()
377 HMODULE h = LoadLibrary(
"IMAGEHLP.DLL");
379 Print(
"--- could not load IMAGEHLP.DLL (%08x) ---\n", GetLastError());
383 SymInitialize = (SYMINITIALIZEPROC) GetProcAddress(h,
"SymInitialize");
384 if (!SymInitialize) {
385 Print(
"--- could not find SymInitialize ---\n");
389 SymCleanup = (SYMCLEANUPPROC) GetProcAddress(h,
"SymCleanup");
391 Print(
"--- could not find SymCleanup ---\n");
395 StackTrace = (STACKWALKPROC) GetProcAddress(h,
"StackWalk");
397 Print(
"--- could not find StackWalk ---\n");
401 SymFunctionTableAccess = (SYMFUNCTIONTABLEACCESSPROC)
402 GetProcAddress(h,
"SymFunctionTableAccess");
404 if (!SymFunctionTableAccess) {
405 Print(
"--- could not find SymFunctionTableAccess ---\n");
409 SymGetModuleBase = (SYMGETMODULEBASEPROC) GetProcAddress(h,
"SymGetModuleBase");
410 if (!SymGetModuleBase) {
411 Print(
"--- could not find SymGetModuleBase ---\n");
415 SymGetSymFromAddr = (SYMGETSYMFROMADDRPROC) GetProcAddress(h,
"SymGetSymFromAddr");
416 if (!SymGetSymFromAddr) {
417 Print(
"--- could not find SymGetSymFromAddr ---\n");
421 if (!SymInitialize(GetCurrentProcess(), 0, TRUE)) {
422 Print(
"--- could not Initialize IMAGEHLP.DLL (%08x) ---\n", GetLastError());
426 Print(
"Loaded IMAGEHLP.DLL\n");