#include "crashdump.h" #include #include CrashDump::CrashDump(EXCEPTION_POINTERS* exp) : exp_(exp) { } std::string CrashDump::GetModuleByReAddr(PBYTE retAddr, PBYTE& moduleAddr) { MODULEENTRY32 M = {sizeof(M)}; HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); char moduleName[MAX_PATH]{}; if (hSnapshot != INVALID_HANDLE_VALUE && Module32First(hSnapshot, &M)) { do { if (DWORD(retAddr - M.modBaseAddr) < M.modBaseSize) { std::snprintf(moduleName, MAX_PATH, "%s", M.szExePath); moduleAddr = M.modBaseAddr; break; } } while (Module32Next(hSnapshot, &M)); } std::string name(moduleName); return name; } std::string CrashDump::GetVersion() { OSVERSIONINFO V = {sizeof(OSVERSIONINFO)}; if (!GetVersionEx((POSVERSIONINFO)&V)) { ZeroMemory(&V, sizeof(V)); V.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx((POSVERSIONINFO)&V); } if (V.dwPlatformId != VER_PLATFORM_WIN32_NT) { V.dwBuildNumber = LOWORD(V.dwBuildNumber); } char buffer[512]{}; std::snprintf(buffer, sizeof(buffer), "Windows: %ld.%ld.%ld, %s.", V.dwMajorVersion, V.dwMinorVersion, V.dwBuildNumber, V.szCSDVersion); std::string info(buffer); return info; } std::string CrashDump::GetExceptionInfo() { char moduleName[MAX_PATH]{}; PBYTE moduleAddr{}; GetModuleFileName(NULL, moduleName, MAX_PATH); if (exp_ == nullptr) { return "Not Set Exception Pointer."; } std::ostringstream oss; auto& E = exp_->ExceptionRecord; auto& C = exp_->ContextRecord; oss << "ExceptionAddr: " << E->ExceptionAddress << "\n"; oss << "ExceptionCode: " << E->ExceptionCode << "\n"; if (E->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { oss << (E->ExceptionInformation[0] ? "Write " : "Read "); oss << E->ExceptionInformation[1] << "\n"; } oss << "Instruction:"; for (int i = 0; i < 16; i++) { oss << " " << std::hex << std::setw(2) << std::setfill('0') << static_cast(PBYTE(E->ExceptionAddress)[i]); } oss << std::hex << std::setfill('0'); // 1. 基本寄存器组 oss << "\nGeneral Purpose Registers:" << "\nRAX: " << std::setw(16) << C->Rax << " RBX: " << std::setw(16) << C->Rbx << " RCX: " << std::setw(16) << C->Rcx << " RDX: " << std::setw(16) << C->Rdx << "\nRSI: " << std::setw(16) << C->Rsi << " RDI: " << std::setw(16) << C->Rdi << " RBP: " << std::setw(16) << C->Rbp << " RSP: " << std::setw(16) << C->Rsp << "\nR8: " << std::setw(16) << C->R8 << " R9: " << std::setw(16) << C->R9 << " R10: " << std::setw(16) << C->R10 << " R11: " << std::setw(16) << C->R11 << "\nR12: " << std::setw(16) << C->R12 << " R13: " << std::setw(16) << C->R13 << " R14: " << std::setw(16) << C->R14 << " R15: " << std::setw(16) << C->R15; // 2. 关键控制寄存器 oss << "\n\nControl Registers:" << "\nRIP: " << std::setw(16) << C->Rip << " EFLAGS: " << std::setw(8) << C->EFlags << " CS: " << std::setw(4) << C->SegCs << " SS: " << std::setw(4) << C->SegSs; // 3. 调试寄存器(如果有用) if (C->ContextFlags & CONTEXT_DEBUG_REGISTERS) { oss << "\n\nDebug Registers:" << "\nDR0: " << std::setw(16) << C->Dr0 << " DR1: " << std::setw(16) << C->Dr1 << " DR2: " << std::setw(16) << C->Dr2 << " DR3: " << std::setw(16) << C->Dr3 << "\nDR6: " << std::setw(16) << C->Dr6 << " DR7: " << std::setw(16) << C->Dr7; } // 4. MXCSR状态(浮点/SSE) if (C->ContextFlags & CONTEXT_FLOATING_POINT) { oss << "\n\nFPU/SSE State:" << "\nMXCSR: " << std::setw(8) << C->MxCsr; } // 5. 最后分支记录(如果可用) if (C->LastBranchToRip || C->LastBranchFromRip) { oss << "\n\nLast Branch:" << "\nFrom: " << std::setw(16) << C->LastBranchFromRip << " To: " << std::setw(16) << C->LastBranchToRip; } oss << GetCallStack(exp_) << "\n"; return oss.str(); } std::string CrashDump::GetCallStack(EXCEPTION_POINTERS* exp) { struct StackFrame { StackFrame* prev_frame; void* return_address; }; std::ostringstream oss; StackFrame* current_frame = nullptr; // 1. 初始化栈帧指针 if (exp) { // 异常情况:从异常上下文中获取栈帧 #if defined(_M_X64) || defined(__x86_64__) current_frame = reinterpret_cast(exp->ContextRecord->Rbp); #else current_frame = reinterpret_cast(exp->ContextRecord->Ebp); #endif } else { // 非异常情况:手动获取当前栈帧(编译器相关) #if defined(__GNUC__) || defined(__clang__) // GCC/Clang 内联汇编获取 EBP/RBP #if defined(__x86_64__) register void* frame_ptr asm("rbp"); #else register void* frame_ptr asm("ebp"); #endif current_frame = reinterpret_cast(frame_ptr); #elif defined(_MSC_VER) // MSVC 内置函数(如果可用) current_frame = reinterpret_cast(_AddressOfReturnAddress() - sizeof(void*)); #else return "Stack walking not supported on this compiler"; #endif } // 2. 遍历调用栈 constexpr size_t max_frames = 64; PBYTE module_addr = nullptr; for (size_t i = 0; i < max_frames && current_frame; ++i) { // 安全检查 if (IsBadReadPtr(current_frame, sizeof(StackFrame)) || IsBadCodePtr(reinterpret_cast(current_frame->return_address))) { break; } // 格式化输出 oss << "\n0x" << std::hex << std::setw(8) << std::setfill('0') << reinterpret_cast(current_frame->return_address) << " "; // 获取模块信息 std::string module_name = GetModuleByReAddr(reinterpret_cast(current_frame->return_address), module_addr); if (!module_name.empty()) { DWORD rva = static_cast(reinterpret_cast(current_frame->return_address) - module_addr); // 输出模块信息和RVA oss << " (RVA: 0x" << std::hex << std::setw(8) << std::setfill('0') << rva << ") " << module_name; } // 移动到上一栈帧 current_frame = current_frame->prev_frame; } return oss.str(); }