void GetExceptionInfo(str::Str<char>& s, EXCEPTION_POINTERS *excPointers) { if (!excPointers) return; EXCEPTION_RECORD *excRecord = excPointers->ExceptionRecord; DWORD excCode = excRecord->ExceptionCode; s.AppendFmt("Exception: %08X %s\r\n", (int)excCode, ExceptionNameFromCode(excCode)); s.AppendFmt("Faulting IP: "); GetAddressInfo(s, (DWORD64)excRecord->ExceptionAddress); if ((EXCEPTION_ACCESS_VIOLATION == excCode) || (EXCEPTION_IN_PAGE_ERROR == excCode)) { int readWriteFlag = (int)excRecord->ExceptionInformation[0]; DWORD64 dataVirtAddr = (DWORD64)excRecord->ExceptionInformation[1]; if (0 == readWriteFlag) { s.Append("Fault reading address "); AppendAddress(s, dataVirtAddr); } else if (1 == readWriteFlag) { s.Append("Fault writing address "); AppendAddress(s, dataVirtAddr); } else if (8 == readWriteFlag) { s.Append("DEP violation at address "); AppendAddress(s, dataVirtAddr); } else { s.Append("unknown readWriteFlag: %d", readWriteFlag); } s.Append("\r\n"); } PCONTEXT ctx = excPointers->ContextRecord; s.AppendFmt("\r\nRegisters:\r\n"); #ifdef _WIN64 s.AppendFmt("RAX:%016I64X RBX:%016I64X RCX:%016I64X\r\nRDX:%016I64X RSI:%016I64X RDI:%016I64X\r\n" "R8: %016I64X\r\nR9: %016I64X\r\nR10:%016I64X\r\nR11:%016I64X\r\nR12:%016I64X\r\nR13:%016I64X\r\nR14:%016I64X\r\nR15:%016I64X\r\n", ctx->Rax, ctx->Rbx, ctx->Rcx, ctx->Rdx, ctx->Rsi, ctx->Rdi, ctx->R9,ctx->R10,ctx->R11,ctx->R12,ctx->R13,ctx->R14,ctx->R15); s.AppendFmt("CS:RIP:%04X:%016I64X\r\n", ctx->SegCs, ctx->Rip); s.AppendFmt("SS:RSP:%04X:%016X RBP:%08X\r\n", ctx->SegSs, ctx->Rsp, ctx->Rbp); s.AppendFmt("DS:%04X ES:%04X FS:%04X GS:%04X\r\n", ctx->SegDs, ctx->SegEs, ctx->SegFs, ctx->SegGs); s.AppendFmt("Flags:%08X\r\n", ctx->EFlags); #else s.AppendFmt("EAX:%08X EBX:%08X ECX:%08X\r\nEDX:%08X ESI:%08X EDI:%08X\r\n", ctx->Eax, ctx->Ebx, ctx->Ecx, ctx->Edx, ctx->Esi, ctx->Edi); s.AppendFmt("CS:EIP:%04X:%08X\r\n", ctx->SegCs, ctx->Eip); s.AppendFmt("SS:ESP:%04X:%08X EBP:%08X\r\n", ctx->SegSs, ctx->Esp, ctx->Ebp); s.AppendFmt("DS:%04X ES:%04X FS:%04X GS:%04X\r\n", ctx->SegDs, ctx->SegEs, ctx->SegFs, ctx->SegGs); s.AppendFmt("Flags:%08X\r\n", ctx->EFlags); #endif s.Append("\r\nCrashed thread:\r\n"); // it's not really for current thread, but it seems to work GetCallstack(s, *ctx, GetCurrentThread()); }
static void GetAddressInfo(str::Str<char>& s, DWORD64 addr) { static const int MAX_SYM_LEN = 512; char buf[sizeof(SYMBOL_INFO) + MAX_SYM_LEN * sizeof(char)]; SYMBOL_INFO *symInfo = (SYMBOL_INFO*)buf; memset(buf, 0, sizeof(buf)); symInfo->SizeOfStruct = sizeof(SYMBOL_INFO); symInfo->MaxNameLen = MAX_SYM_LEN; DWORD64 symDisp = 0; char *symName = nullptr; BOOL ok = _SymFromAddr(GetCurrentProcess(), addr, &symDisp, symInfo); if (ok) symName = &(symInfo->Name[0]); char module[MAX_PATH] = { 0 }; DWORD section; DWORD_PTR offset; if (GetAddrInfo((void*)addr, module, sizeof(module), section, offset)) { str::ToLower(module); const char *moduleShort = path::GetBaseName(module); AppendAddress(s, addr); s.AppendFmt(" %02X:", section); AppendAddress(s, offset); s.AppendFmt(" %s", moduleShort); if (symName) { s.AppendFmt("!%s+0x%x", symName, (int)symDisp); } else if (symDisp != 0) { s.AppendFmt("+0x%x", (int)symDisp); } IMAGEHLP_LINE64 line; line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); DWORD disp; if (_SymGetLineFromAddr64(GetCurrentProcess(), addr, &disp, &line)) { s.AppendFmt(" %s+%d", line.FileName, line.LineNumber); } } else { AppendAddress(s, addr); } s.Append("\r\n"); }