|
7 | 7 | #include "MessageDlg.h" |
8 | 8 | #include "Common.h" |
9 | 9 | #include "TrafficMonitor.h" |
| 10 | +#include <sstream> |
10 | 11 |
|
11 | 12 | #pragma comment(lib, "Dbghelp.lib") |
12 | 13 |
|
@@ -47,14 +48,106 @@ class CCrashReport |
47 | 48 | ::CloseHandle(hDumpFile); |
48 | 49 | } |
49 | 50 |
|
50 | | - void ShowCrashInfo() |
| 51 | + //根据地址获取模块路径 |
| 52 | + std::wstring GetModulePath(DWORD64 address) |
| 53 | + { |
| 54 | + // 获取模块信息 |
| 55 | + HMODULE hModule = NULL; |
| 56 | + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)address, &hModule)) |
| 57 | + { |
| 58 | + TCHAR moduleName[MAX_PATH]; |
| 59 | + if (GetModuleFileName(hModule, moduleName, MAX_PATH)) |
| 60 | + { |
| 61 | + return moduleName; |
| 62 | + } |
| 63 | + } |
| 64 | + return L"Unknown Module"; |
| 65 | + } |
| 66 | + |
| 67 | + //获取崩溃堆栈信息 |
| 68 | + std::wstring GetStackTrace(EXCEPTION_POINTERS* pExceptionInfo) |
| 69 | + { |
| 70 | + std::wstringstream stream; |
| 71 | + |
| 72 | + // 初始化符号处理 |
| 73 | + if (!SymInitialize(GetCurrentProcess(), NULL, TRUE)) |
| 74 | + { |
| 75 | + stream << L"Failed to initialize symbol handler.\r\n"; |
| 76 | + return stream.str(); |
| 77 | + } |
| 78 | + |
| 79 | + // RAII 确保 SymCleanup 被调用 |
| 80 | + struct SymCleanupHelper { |
| 81 | + ~SymCleanupHelper() { SymCleanup(GetCurrentProcess()); } |
| 82 | + } cleanupHelper; |
| 83 | + |
| 84 | + STACKFRAME64 stackFrame = {}; |
| 85 | + CONTEXT context = *pExceptionInfo->ContextRecord; |
| 86 | + |
| 87 | + // 初始化堆栈帧 |
| 88 | +#if defined _M_IX86 |
| 89 | + DWORD machineType = IMAGE_FILE_MACHINE_I386; |
| 90 | +#elif defined _M_ARM64EC |
| 91 | + DWORD machineType = IMAGE_FILE_MACHINE_ARM64; |
| 92 | +#else |
| 93 | + DWORD machineType = IMAGE_FILE_MACHINE_AMD64; |
| 94 | +#endif |
| 95 | + stackFrame.AddrPC.Offset = context.Rip; |
| 96 | + stackFrame.AddrPC.Mode = AddrModeFlat; |
| 97 | + stackFrame.AddrFrame.Offset = context.Rbp; |
| 98 | + stackFrame.AddrFrame.Mode = AddrModeFlat; |
| 99 | + stackFrame.AddrStack.Offset = context.Rsp; |
| 100 | + stackFrame.AddrStack.Mode = AddrModeFlat; |
| 101 | + |
| 102 | + // 遍历堆栈帧 |
| 103 | + while (StackWalk64(machineType, GetCurrentProcess(), GetCurrentThread(), &stackFrame, &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) { |
| 104 | + if (stackFrame.AddrPC.Offset == 0) break; |
| 105 | + |
| 106 | + // 获取符号信息 |
| 107 | + BYTE symbolBuffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; |
| 108 | + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer; |
| 109 | + pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); |
| 110 | + pSymbol->MaxNameLen = MAX_SYM_NAME; |
| 111 | + |
| 112 | + DWORD64 displacement = 0; |
| 113 | + if (SymFromAddr(GetCurrentProcess(), stackFrame.AddrPC.Offset, &displacement, pSymbol)) { |
| 114 | + stream << L"Function: " << CCommon::AsciiToUnicode(pSymbol->Name) << L" (Displacement: " << displacement << L")\r\n"; |
| 115 | + } |
| 116 | + else { |
| 117 | + stream << L"Unknown Function at address: " << (void*)stackFrame.AddrPC.Offset << L"\r\n"; |
| 118 | + } |
| 119 | + |
| 120 | + std::wstring modulePath = GetModulePath(stackFrame.AddrPC.Offset); |
| 121 | + if (!modulePath.empty()) |
| 122 | + stream << L"Module Path: " << modulePath << L"\r\n"; |
| 123 | + |
| 124 | + // 获取源代码行信息 |
| 125 | + IMAGEHLP_LINE64 line = {}; |
| 126 | + line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); |
| 127 | + DWORD lineDisplacement = 0; |
| 128 | + if (SymGetLineFromAddr64(GetCurrentProcess(), stackFrame.AddrPC.Offset, &lineDisplacement, &line)) { |
| 129 | + stream << L"File: " << CCommon::AsciiToUnicode(line.FileName) << L" (Line: " << line.LineNumber << L")\r\n"; |
| 130 | + } |
| 131 | + } |
| 132 | + return stream.str(); |
| 133 | + } |
| 134 | + |
| 135 | + void ShowCrashInfo(EXCEPTION_POINTERS* pEP) |
51 | 136 | { |
52 | 137 | CMessageDlg dlg; |
53 | 138 | dlg.SetWindowTitle(APP_NAME); |
54 | 139 | dlg.SetInfoText(CCommon::LoadText(IDS_ERROR_MESSAGE)); |
55 | 140 |
|
56 | 141 | CString info = CCommon::LoadTextFormat(IDS_CRASH_INFO, { m_dumpFile }); |
57 | 142 | info += _T("\r\n"); |
| 143 | + //在崩溃信息中调用堆栈 |
| 144 | + std::wstring stack_trace = GetStackTrace(pEP); |
| 145 | + if (!stack_trace.empty()) |
| 146 | + { |
| 147 | + info += _T("Stack trace:\r\n"); |
| 148 | + info += stack_trace.c_str(); |
| 149 | + info += _T("\r\n"); |
| 150 | + } |
58 | 151 | info += theApp.GetSystemInfoString(); |
59 | 152 | dlg.SetMessageText(info); |
60 | 153 |
|
@@ -105,7 +198,7 @@ namespace CRASHREPORT |
105 | 198 | ::SetErrorMode(0); //使用默认的 |
106 | 199 | CCrashReport cr; |
107 | 200 | cr.CreateMiniDump(pEP); |
108 | | - cr.ShowCrashInfo(); |
| 201 | + cr.ShowCrashInfo(pEP); |
109 | 202 | return EXCEPTION_CONTINUE_SEARCH; |
110 | 203 | } |
111 | 204 |
|
|
0 commit comments