OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
CStackWalker Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/dev-utils/StackWalker.h>

Inheritance diagram for CStackWalker:

Public Member Functions

 CStackWalker (HANDLE hProcess=GetCurrentProcess(), WORD wPID=GetCurrentProcessId(), LPCTSTR lpSymbolPath=NULL)
 ~CStackWalker (void)
BOOL LoadSymbol ()
LPMODULE_INFO GetLoadModules ()
void GetModuleInformation (LPMODULE_INFO pmi)
void FreeModuleInformations (LPMODULE_INFO pmi)
virtual void OutputString (LPCTSTR lpszFormat,...)
LPSTACKINFO StackWalker (HANDLE hThread=GetCurrentThread(), const CONTEXT *context=NULL)
void FreeStackInformations (LPSTACKINFO psi)

Protected Member Functions

LPMODULE_INFO GetModulesTH32 ()
LPMODULE_INFO GetModulesPSAPI ()

Protected Attributes

HANDLE m_hProcess
WORD m_wPID
LPTSTR m_lpszSymbolPath
BOOL m_bSymbolLoaded

Detailed Description

Constructor & Destructor Documentation

◆ CStackWalker()

CStackWalker::CStackWalker ( HANDLE hProcess = GetCurrentProcess(),
WORD wPID = GetCurrentProcessId(),
LPCTSTR lpSymbolPath = NULL )
11 :
12 m_hProcess(hProcess),
13 m_wPID(wPID),
14 m_bSymbolLoaded(FALSE),
16{
17 if (NULL != lpSymbolPath)
18 {
19 size_t dwLength = 0;
20 StringCchLength(lpSymbolPath, MAX_SYMBOL_PATH, &dwLength);
21 m_lpszSymbolPath = new TCHAR[dwLength + 1];
22 ZeroMemory(m_lpszSymbolPath, sizeof(TCHAR) * (dwLength + 1));
23 StringCchCopy(m_lpszSymbolPath, dwLength, lpSymbolPath);
24 }
25
26}
#define MAX_SYMBOL_PATH
Definition StackWalker.h:160
HANDLE m_hProcess
Definition StackWalker.h:239
LPTSTR m_lpszSymbolPath
Definition StackWalker.h:241
BOOL m_bSymbolLoaded
Definition StackWalker.h:242
WORD m_wPID
Definition StackWalker.h:240

References m_bSymbolLoaded, m_hProcess, m_lpszSymbolPath, m_wPID, and MAX_SYMBOL_PATH.

Referenced by CBaseException::CBaseException().

Here is the caller graph for this function:

◆ ~CStackWalker()

CStackWalker::~CStackWalker ( void )
29{
30 if (NULL != m_lpszSymbolPath)
31 {
32 delete[] m_lpszSymbolPath;
33 }
34
36 {
37 SymCleanup(m_hProcess);
38 }
39}

References m_bSymbolLoaded, m_hProcess, and m_lpszSymbolPath.

Member Function Documentation

◆ FreeModuleInformations()

void CStackWalker::FreeModuleInformations ( LPMODULE_INFO pmi)
161{
162 LPMODULE_INFO head = pmi;
163 while (NULL != head)
164 {
165 pmi = pmi->pNext;
166 delete head;
167 head = pmi;
168 }
169}
struct _tag_MODULE_INFO * pNext
Definition StackWalker.h:206
struct _tag_MODULE_INFO * LPMODULE_INFO

References _tag_MODULE_INFO::pNext.

Referenced by CBaseException::ShowLoadModules().

Here is the caller graph for this function:

◆ FreeStackInformations()

void CStackWalker::FreeStackInformations ( LPSTACKINFO psi)
544{
545 LPSTACKINFO head = psi;
546 while (NULL != head)
547 {
548 psi = psi->pNext;
549 delete head;
550 head = psi;
551 }
552
553}
tagSTACKINFO * pNext
Definition StackWalker.h:217
struct tagSTACKINFO * LPSTACKINFO

References tagSTACKINFO::pNext.

Referenced by CBaseException::ShowCallstack().

Here is the caller graph for this function:

◆ GetLoadModules()

LPMODULE_INFO CStackWalker::GetLoadModules ( )
150{
152 if (NULL == pHead)
153 {
154 pHead = GetModulesPSAPI();
155 }
156
157 return pHead;
158}
LPMODULE_INFO GetModulesPSAPI()
Definition StackWalker.cpp:256
LPMODULE_INFO GetModulesTH32()
Definition StackWalker.cpp:171

References GetModulesPSAPI(), and GetModulesTH32().

Referenced by CBaseException::ShowLoadModules().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetModuleInformation()

void CStackWalker::GetModuleInformation ( LPMODULE_INFO pmi)
358{
359 //USES_CONVERSION;
360 IMAGEHLP_MODULE64 im = {0};
361 im.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
362
363 VS_FIXEDFILEINFO* pvfi = NULL;
364 DWORD dwHandle = 0;
365 DWORD dwInfoSize = 0;
366 dwInfoSize = GetFileVersionInfoSize(pmi->szModulePath, &dwHandle);
367
368 if (dwInfoSize > 0)
369 {
370 byte *lpData = new byte[dwInfoSize];
371 ZeroMemory(lpData, dwInfoSize * sizeof(byte));
372
373 if (GetFileVersionInfo(pmi->szModulePath, dwHandle, dwInfoSize, lpData) > 0 )
374 {
375 TCHAR szBlock[] = _T("\\");
376 UINT len;
377 if (VerQueryValue(lpData, szBlock, (LPVOID*)&pvfi, &len))
378 {
379 WORD v1 = HIWORD(pvfi->dwFileVersionMS);
380 WORD v2 = LOWORD(pvfi->dwFileVersionMS);
381 WORD v3 = HIWORD(pvfi->dwFileVersionLS);
382 WORD v4 = LOWORD(pvfi->dwFileVersionLS);
383 _stprintf_s(pmi->szVersion, MAX_VERSION_LENGTH, _T("%d.%d.%d.%d"), v1, v2, v3, v4);
384 }
385 }
386
387 delete[] lpData;
388 }
389
390 SymGetModuleInfo64(m_hProcess, pmi->ModuleAddress, &im);
391 StringCchCopy(pmi->szSymbolPath, MAX_PATH, textconv_helper::A2T_(im.LoadedPdbName));
392}
DWORD64 ModuleAddress
Definition StackWalker.h:200
#define MAX_VERSION_LENGTH
Definition StackWalker.h:163
TCHAR szVersion[MAX_VERSION_LENGTH]
Definition StackWalker.h:205
TCHAR szSymbolPath[MAX_PATH]
Definition StackWalker.h:204
TCHAR szModulePath[MAX_PATH]
Definition StackWalker.h:203
CA2A_ A2T_
Definition StackWalker.h:33

References m_hProcess, MAX_VERSION_LENGTH, _tag_MODULE_INFO::ModuleAddress, _tag_MODULE_INFO::szModulePath, _tag_MODULE_INFO::szSymbolPath, and _tag_MODULE_INFO::szVersion.

Referenced by GetModulesPSAPI(), and GetModulesTH32().

Here is the caller graph for this function:

◆ GetModulesPSAPI()

LPMODULE_INFO CStackWalker::GetModulesPSAPI ( )
protected
257{
258 LPMODULE_INFO pHead = NULL;
259 LPMODULE_INFO pTail = pHead;
260 typedef BOOL(WINAPI *pfnEnumProcessModules)(HANDLE hProcess, HMODULE * lphModule, DWORD cb,LPDWORD lpcbNeeded);
261 typedef DWORD(WINAPI *pfnGetModuleFileNameEx)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
262 typedef DWORD(WINAPI *pfnGetModuleBaseName)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
263 typedef BOOL(WINAPI *pfnGetModuleInformation)(HANDLE hProcess, HMODULE hModule, LPMODULEINFO pmi, DWORD nSize);
264
265 HINSTANCE hPsapi;
266 pfnEnumProcessModules EnumProcessModules = NULL;
267 pfnGetModuleFileNameEx GetModuleFileNameEx = NULL;
268 pfnGetModuleBaseName GetModuleBaseName = NULL;
269 pfnGetModuleInformation GetModuleInformation = NULL;
270
271 DWORD i;
272 //ModuleEntry e;
273 DWORD cbNeeded;
274 MODULEINFO mi;
275 HMODULE* hMods = NULL;
276 TCHAR szModuleName[MAX_MODULE_NAME32 + 1] = _T("");
277 TCHAR szModulePath[MAX_PATH] = _T("");
278
279 hPsapi = LoadLibrary(_T("psapi.dll"));
280 if (hPsapi == NULL)
281 {
282 return pHead;
283 }
284
285 EnumProcessModules = (pfnEnumProcessModules)GetProcAddress(hPsapi, "EnumProcessModules");
286#ifdef UNICODE
287 GetModuleFileNameEx = (pfnGetModuleFileNameEx)GetProcAddress(hPsapi, "GetModuleFileNameExW");
288 GetModuleBaseName = (pfnGetModuleBaseName)GetProcAddress(hPsapi, "GetModuleBaseNameW");
289#else
290 GetModuleFileNameEx = (pfnGetModuleFileNameEx)GetProcAddress(hPsapi, "GetModuleFileNameExA");
291 GetModuleBaseName = (pfnGetModuleBaseName)GetProcAddress(hPsapi, "GetModuleBaseNameA");
292#endif
293 GetModuleInformation = (pfnGetModuleInformation)GetProcAddress(hPsapi, "GetModuleInformation");
294 if ((EnumProcessModules == NULL) || (GetModuleFileNameEx == NULL) || (GetModuleBaseName == NULL) || (GetModuleInformation == NULL))
295 {
296 FreeLibrary(hPsapi);
297 return pHead;
298 }
299
300 EnumProcessModules(m_hProcess, hMods, 0, &cbNeeded);
301 hMods = new HMODULE[cbNeeded / sizeof(HMODULE)];
302 ASSERT(NULL != hMods);
303 ZeroMemory(hMods, cbNeeded);
304
305 if (!EnumProcessModules(m_hProcess, hMods, cbNeeded, &cbNeeded))
306 {
307 goto cleanup;
308 }
309
310 for (i = 0; i < cbNeeded / sizeof(HMODULE); i++)
311 {
312 GetModuleInformation(m_hProcess, hMods[i], &mi, sizeof(mi));
313 GetModuleFileNameEx(m_hProcess, hMods[i], szModulePath, MAX_PATH);
314 GetModuleBaseName(m_hProcess, hMods[i], szModuleName, MAX_MODULE_NAME32);
315 LPMODULE_INFO pmi = new MODULE_INFO;
316 ZeroMemory(pmi, sizeof(MODULE_INFO));
317 pmi->dwModSize = mi.SizeOfImage;
318 pmi->ModuleAddress = (DWORD64)mi.lpBaseOfDll;
319 StringCchCopy(pmi->szModuleName, MAX_MODULE_NAME32, szModuleName);
320 StringCchCopy(pmi->szModulePath, MAX_PATH, szModulePath);
321 this->GetModuleInformation(pmi);
322 if (pHead == NULL)
323 {
324 pHead = pmi;
325 pTail = pHead;
326 }else
327 {
328 pTail->pNext = pmi;
329 pTail = pmi;
330 }
331 }
332
333cleanup:
334 if (hPsapi != NULL)
335 {
336 FreeLibrary(hPsapi);
337 }
338 if (hMods != NULL)
339 {
340 delete[] hMods;
341 }
342
343 return pHead;
344}
struct _MODULEINFO MODULEINFO
struct _tag_MODULE_INFO MODULE_INFO
DWORD SizeOfImage
Definition StackWalker.h:191
TCHAR szModuleName[MAX_MODULE_NAME32+1]
Definition StackWalker.h:202
LPVOID lpBaseOfDll
Definition StackWalker.h:190
DWORD dwModSize
Definition StackWalker.h:201
#define ASSERT(judge)
Definition StackWalker.h:166
struct _MODULEINFO * LPMODULEINFO
#define MAX_MODULE_NAME32
Definition StackWalker.h:161
void GetModuleInformation(LPMODULE_INFO pmi)
Definition StackWalker.cpp:357

References ASSERT, _tag_MODULE_INFO::dwModSize, GetModuleInformation(), _MODULEINFO::lpBaseOfDll, m_hProcess, MAX_MODULE_NAME32, _tag_MODULE_INFO::ModuleAddress, _tag_MODULE_INFO::pNext, _MODULEINFO::SizeOfImage, _tag_MODULE_INFO::szModuleName, and _tag_MODULE_INFO::szModulePath.

Referenced by GetLoadModules().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetModulesTH32()

LPMODULE_INFO CStackWalker::GetModulesTH32 ( )
protected
172{
173 //这里为了防止加载Toolhelp.dll 影响最终结果,所以采用动态加载的方式
174 LPMODULE_INFO pHead = NULL;
175 LPMODULE_INFO pTail = pHead;
176
177 typedef HANDLE (WINAPI *pfnCreateToolhelp32Snapshot)(DWORD dwFlags, DWORD th32ProcessID);
178 typedef BOOL (WINAPI *pfnModule32First)(HANDLE hSnapshot, LPMODULEENTRY32 lpme );
179 typedef BOOL (WINAPI *pfnModule32Next)(HANDLE hSnapshot, LPMODULEENTRY32 lpme );
180
181 const TCHAR* dllname[] = {_T("kernel32.dll"), _T("tlhelp32.dll")};
182 HINSTANCE hToolhelp = NULL;
183
184 pfnCreateToolhelp32Snapshot CreateToolhelp32Snapshot = NULL;
185 pfnModule32First Module32First = NULL;
186 pfnModule32Next Module32Next = NULL;
187
188 HANDLE hSnap;
189 MODULEENTRY32 me;
190 me.dwSize = sizeof(me);
191 BOOL keepGoing;
192 size_t i;
193
194 for (i = 0; i < (sizeof(dllname) / sizeof(dllname[0])); i++)
195 {
196 hToolhelp = LoadLibrary(dllname[i]);
197 if (hToolhelp == NULL)
198 continue;
199 CreateToolhelp32Snapshot = (pfnCreateToolhelp32Snapshot)GetProcAddress(hToolhelp, "CreateToolhelp32Snapshot");
200#ifdef UNICODE
201 Module32First = (pfnModule32First)GetProcAddress(hToolhelp, "Module32FirstW");
202 Module32Next = (pfnModule32Next)GetProcAddress(hToolhelp, "Module32NextW");
203#else
204 Module32First = (pfnModule32First)GetProcAddress(hToolhelp, "Module32FirstA");
205 Module32Next = (pfnModule32Next)GetProcAddress(hToolhelp, "Module32NextA");
206#endif
207
208 if ((CreateToolhelp32Snapshot != NULL) && (Module32First != NULL) && (Module32Next != NULL))
209 break;
210
211 FreeLibrary(hToolhelp);
212 hToolhelp = NULL;
213 }
214
215 if (hToolhelp == NULL)
216 return pHead;
217
218 hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, m_wPID);
219
220 if (hSnap == INVALID_HANDLE_VALUE)
221 {
222 FreeLibrary(hToolhelp);
223 return pHead;
224 }
225
226 keepGoing = Module32First(hSnap, &me);
227
228 while (keepGoing)
229 {
230 LPMODULE_INFO pmi = new MODULE_INFO;
231 ZeroMemory(pmi, sizeof(MODULE_INFO));
232
233 pmi->dwModSize = me.modBaseSize;
234 pmi->ModuleAddress = (DWORD64)me.modBaseAddr;
235 StringCchCopy(pmi->szModuleName, MAX_MODULE_NAME32, me.szModule);
236 StringCchCopy(pmi->szModulePath, MAX_PATH, me.szExePath);
238 if (pHead == NULL)
239 {
240 pHead = pmi;
241 pTail = pHead;
242 }else
243 {
244 pTail->pNext = pmi;
245 pTail = pmi;
246 }
247
248 keepGoing = Module32Next(hSnap, &me);
249 }
250
251 CloseHandle(hSnap);
252 FreeLibrary(hToolhelp);
253 return pHead;
254}
BYTE * modBaseAddr
Definition StackWalker.h:181
MODULEENTRY32 * LPMODULEENTRY32
Definition StackWalker.h:196
TCHAR szExePath[MAX_PATH]
Definition StackWalker.h:185
DWORD dwSize
Definition StackWalker.h:176
#define TH32CS_SNAPMODULE
Definition StackWalker.h:162
TCHAR szModule[MAX_MODULE_NAME32+1]
Definition StackWalker.h:184
DWORD modBaseSize
Definition StackWalker.h:182
struct tagMODULEENTRY32 MODULEENTRY32

References _tag_MODULE_INFO::dwModSize, tagMODULEENTRY32::dwSize, GetModuleInformation(), m_wPID, MAX_MODULE_NAME32, tagMODULEENTRY32::modBaseAddr, tagMODULEENTRY32::modBaseSize, _tag_MODULE_INFO::ModuleAddress, _tag_MODULE_INFO::pNext, tagMODULEENTRY32::szExePath, tagMODULEENTRY32::szModule, _tag_MODULE_INFO::szModuleName, _tag_MODULE_INFO::szModulePath, and TH32CS_SNAPMODULE.

Referenced by GetLoadModules().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ LoadSymbol()

BOOL CStackWalker::LoadSymbol ( )
42{
43 //USES_CONVERSION;
44 //只加载一次
46 {
47 return m_bSymbolLoaded;
48 }
49
50 if (NULL != m_lpszSymbolPath)
51 {
52
54 return m_bSymbolLoaded;
55 }
56
57 //添加当前程序路径
58 TCHAR szSymbolPath[MAX_SYMBOL_PATH] = _T("");
59 StringCchCopy(szSymbolPath, MAX_SYMBOL_PATH, _T(".;"));
60
61 //添加程序所在目录
62 TCHAR szTemp[MAX_PATH] = _T("");
63 if (GetCurrentDirectory(MAX_PATH, szTemp) > 0)
64 {
65 StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, szTemp);
66 StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T(";"));
67 }
68
69 //添加程序主模块所在路径
70 ZeroMemory(szTemp, MAX_PATH * sizeof(TCHAR));
71 if (GetModuleFileName(NULL, szTemp, MAX_PATH) > 0)
72 {
73 size_t sLength = 0;
74 StringCchLength(szTemp, MAX_PATH, &sLength);
75 for (int i = sLength; i >= 0; i--)
76 {
77 if (szTemp[i] == _T('\\') || szTemp[i] == _T('/') || szTemp[i] == _T(':'))
78 {
79 szTemp[i] = _T('\0');
80 break;
81 }
82 }
83 }
84
85 StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, szTemp);
86 StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T(";"));
87
88 ZeroMemory(szTemp, MAX_PATH * sizeof(TCHAR));
89 if (GetEnvironmentVariable(_T("_NT_SYMBOL_PATH"), szTemp, MAX_PATH) > 0)
90 {
91 StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, szTemp);
92 StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T(";"));
93 }
94
95 ZeroMemory(szTemp, MAX_PATH * sizeof(TCHAR));
96 if (GetEnvironmentVariable(_T("_NT_ALTERNATE_SYMBOL_PATH"), szTemp, MAX_PATH) > 0)
97 {
98 StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, szTemp);
99 StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T(";"));
100 }
101
102 ZeroMemory(szTemp, MAX_PATH * sizeof(TCHAR));
103 if (GetEnvironmentVariable(_T("SYSTEMROOT"), szTemp, MAX_PATH) > 0)
104 {
105 StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, szTemp);
106 StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T(";"));
107 // also add the "system32"-directory:
108 StringCchCat(szTemp, MAX_PATH, _T("\\system32"));
109 StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, szTemp);
110 StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T(";"));
111 }
112
113 ZeroMemory(szTemp, MAX_PATH * sizeof(TCHAR));
114 if (GetEnvironmentVariable(_T("SYSTEMDRIVE"), szTemp, MAX_PATH) > 0)
115 {
116 StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T("SRV*"));
117 StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, szTemp);
118 StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T("\\websymbols"));
119 StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T("*http://msdl.microsoft.com/download/symbols;"));
120 }
121 else
122 {
123 StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T("SRV*c:\\websymbols*http://msdl.microsoft.com/download/symbols;"));
124 }
125
126 size_t sLength = 0;
127 StringCchLength(szSymbolPath, MAX_SYMBOL_PATH, &sLength);
128 if (sLength > 0)
129 {
130 m_lpszSymbolPath = new TCHAR[sLength + 1];
131 ZeroMemory(m_lpszSymbolPath, sizeof(TCHAR) * (sLength + 1));
132 StringCchCopy(m_lpszSymbolPath, sLength, szSymbolPath);
133 }
134
135 if (NULL != m_lpszSymbolPath)
136 {
137 m_bSymbolLoaded = SymInitialize(m_hProcess, textconv_helper::T2A_(m_lpszSymbolPath), TRUE); //这里设置为TRUE,让它在初始化符号表的同时加载符号表
138 }
139
140 DWORD symOptions = SymGetOptions();
141 symOptions |= SYMOPT_LOAD_LINES;
142 symOptions |= SYMOPT_FAIL_CRITICAL_ERRORS;
143 symOptions |= SYMOPT_DEBUG;
144 SymSetOptions(symOptions);
145
146 return m_bSymbolLoaded;
147}
CA2A_ T2A_
Definition StackWalker.h:34

References m_bSymbolLoaded, m_hProcess, m_lpszSymbolPath, and MAX_SYMBOL_PATH.

Referenced by CBaseException::ShowLoadModules(), and StackWalker().

Here is the caller graph for this function:

◆ OutputString()

void CStackWalker::OutputString ( LPCTSTR lpszFormat,
... )
virtual

Reimplemented in CBaseException.

347{
348 TCHAR szBuf[1024] = _T("");
349 va_list args;
350 va_start(args, lpszFormat);
351 _vsntprintf_s(szBuf, 1024, lpszFormat, args);
352 va_end(args);
353
354 OutputDebugString(szBuf);
355}

Referenced by StackWalker().

Here is the caller graph for this function:

◆ StackWalker()

LPSTACKINFO CStackWalker::StackWalker ( HANDLE hThread = GetCurrentThread(),
const CONTEXT * context = NULL )
395{
396 //USES_CONVERSION;
397 //加载符号表
398 LoadSymbol();
399
400 LPSTACKINFO pHead = NULL;
401 LPSTACKINFO pTail = pHead;
402
403 //获取当前线程的上下文环境
404 CONTEXT c = {0};
405 if (context == NULL)
406 {
407#if _WIN32_WINNT <= 0x0501
408 if (hThread == GetCurrentThread())
409#else
410 if (GetThreadId(hThread) == GetCurrentThreadId())
411#endif
412 {
413 GET_CURRENT_THREAD_CONTEXT(c, CONTEXT_FULL);
414 }
415 else
416 {
417 //如果不是当前线程,需要停止目标线程,以便取出正确的堆栈信息
418 SuspendThread(hThread);
419 memset(&c, 0, sizeof(CONTEXT));
420 c.ContextFlags = CONTEXT_FULL;
421 if (GetThreadContext(hThread, &c) == FALSE)
422 {
423 ResumeThread(hThread);
424 return NULL;
425 }
426 }
427 }
428 else
429 c = *context;
430
431 STACKFRAME64 sf = {};
432 DWORD imageType;
433
434//intel X86
435#ifdef _M_IX86
436 imageType = IMAGE_FILE_MACHINE_I386;
437 sf.AddrPC.Offset = c.Eip;
438 sf.AddrPC.Mode = AddrModeFlat;
439 sf.AddrFrame.Offset = c.Ebp;
440 sf.AddrFrame.Mode = AddrModeFlat;
441 sf.AddrStack.Offset = c.Esp;
442 sf.AddrStack.Mode = AddrModeFlat;
443 // AMD
444#elif _M_X64
445 imageType = IMAGE_FILE_MACHINE_AMD64;
446 sf.AddrPC.Offset = c.Rip;
447 sf.AddrPC.Mode = AddrModeFlat;
448 sf.AddrFrame.Offset = c.Rsp;
449 sf.AddrFrame.Mode = AddrModeFlat;
450 sf.AddrStack.Offset = c.Rsp;
451 sf.AddrStack.Mode = AddrModeFlat;
453#elif _M_IA64
454 imageType = IMAGE_FILE_MACHINE_IA64;
455 sf.AddrPC.Offset = c.StIIP;
456 sf.AddrPC.Mode = AddrModeFlat;
457 sf.AddrFrame.Offset = c.IntSp;
458 sf.AddrFrame.Mode = AddrModeFlat;
459 sf.AddrBStore.Offset = c.RsBSP;
460 sf.AddrBStore.Mode = AddrModeFlat;
461 sf.AddrStack.Offset = c.IntSp;
462 sf.AddrStack.Mode = AddrModeFlat;
463 // ARM64
464#elif defined(_M_ARM64)
465 imageType = IMAGE_FILE_MACHINE_ARM64;
466 sf.AddrPC.Offset = c.Pc;
467 sf.AddrPC.Mode = AddrModeFlat;
468 sf.AddrFrame.Offset = c.Fp;
469 sf.AddrFrame.Mode = AddrModeFlat;
470 sf.AddrStack.Offset = c.Sp;
471 sf.AddrStack.Mode = AddrModeFlat;
472#else
473#error "Platform not supported!"
474#endif
475
476
477 DWORD64 dwDisplayment = 0;
478 PIMAGEHLP_SYMBOL64 pSym = (PIMAGEHLP_SYMBOL64)new BYTE[sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN];
479 PIMAGEHLP_LINE64 pLine = new IMAGEHLP_LINE64;
480 while (StackWalk64(imageType, m_hProcess, hThread, &sf, &c, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
481 {
482 ZeroMemory(pSym, sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN);
483 ZeroMemory(pLine, sizeof(IMAGEHLP_LINE64));
484
485 pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
486 pSym->MaxNameLength = STACKWALK_MAX_NAMELEN;
487 pLine->SizeOfStruct = sizeof(IMAGEHLP_LINE64);
488
489 LPSTACKINFO pCallStack = new STACKINFO;
490 ZeroMemory(pCallStack, sizeof(STACKINFO));
491 pCallStack->szFncAddr = sf.AddrPC.Offset;
492 if (sf.AddrPC.Offset != 0)
493 {
494 if(SymGetSymFromAddr64(m_hProcess, sf.AddrPC.Offset, &dwDisplayment, pSym))
495 {
496 char szName[STACKWALK_MAX_NAMELEN] = "";
497 StringCchCopy(pCallStack->szFncName, STACKWALK_MAX_NAMELEN, textconv_helper::A2T_(pSym->Name));
498 UnDecorateSymbolName(pSym->Name, szName, STACKWALK_MAX_NAMELEN, UNDNAME_COMPLETE);
499 StringCchCopy(pCallStack->undFullName, STACKWALK_MAX_NAMELEN, textconv_helper::A2T_(szName));
500 ZeroMemory(szName, STACKWALK_MAX_NAMELEN * sizeof(char));
501 UnDecorateSymbolName(pSym->Name, szName, STACKWALK_MAX_NAMELEN, UNDNAME_NAME_ONLY);
502 StringCchCopy(pCallStack->undName, STACKWALK_MAX_NAMELEN, textconv_helper::A2T_(szName));
503 }else
504 {
505 //调用错误一般是487(地址无效或者没有访问的权限、在符号表中未找到指定地址的相关信息)
506 //this->OutputString(_T("Call SymGetSymFromAddr64 ,Address %08x Error:%08x\n"), sf.AddrPC.Offset, GetLastError());
507
508 StringCchCopy(pCallStack->undFullName, STACKWALK_MAX_NAMELEN, textconv_helper::A2T_("Unknown"));
509 }
510
511 if (SymGetLineFromAddr64(m_hProcess, sf.AddrPC.Offset, (DWORD*)&dwDisplayment, pLine))
512 {
513 StringCchCopy(pCallStack->szFileName, MAX_PATH, textconv_helper::A2T_(pLine->FileName));
514 pCallStack->uFileNum = pLine->LineNumber;
515 }else
516 {
517 //this->OutputString(_T("Call SymGetLineFromAddr64 ,Address %08x Error:%08x\n"), sf.AddrPC.Offset, GetLastError());
518
519 StringCchCopy(pCallStack->szFileName, MAX_PATH, textconv_helper::A2T_("Unknown file"));
520 pCallStack->uFileNum = -1;
521 }
522
523 //这里为了将获取函数信息失败的情况与正常的情况一起输出,防止用户在查看时出现误解
524 this->OutputString(_T("%08llx:%s [%s][%ld]\n"), pCallStack->szFncAddr, pCallStack->undFullName, pCallStack->szFileName, pCallStack->uFileNum);
525 if (NULL == pHead)
526 {
527 pHead = pCallStack;
528 pTail = pHead;
529 }else
530 {
531 pTail->pNext = pCallStack;
532 pTail = pCallStack;
533 }
534 }
535 }
536
537 delete[] pSym;
538 delete pLine;
539
540 return pHead;
541}
TCHAR undName[STACKWALK_MAX_NAMELEN]
Definition StackWalker.h:215
TCHAR szFileName[MAX_PATH]
Definition StackWalker.h:212
TCHAR szFncName[MAX_PATH]
Definition StackWalker.h:213
#define GET_CURRENT_THREAD_CONTEXT(c, contextFlags)
Definition StackWalker.h:278
struct tagSTACKINFO STACKINFO
#define STACKWALK_MAX_NAMELEN
Definition StackWalker.h:164
DWORD64 szFncAddr
Definition StackWalker.h:211
unsigned long uFileNum
Definition StackWalker.h:214
TCHAR undFullName[STACKWALK_MAX_NAMELEN]
Definition StackWalker.h:216
BOOL LoadSymbol()
Definition StackWalker.cpp:41
virtual void OutputString(LPCTSTR lpszFormat,...)
Definition StackWalker.cpp:346

References GET_CURRENT_THREAD_CONTEXT, LoadSymbol(), m_hProcess, OutputString(), tagSTACKINFO::pNext, STACKWALK_MAX_NAMELEN, tagSTACKINFO::szFileName, tagSTACKINFO::szFncAddr, tagSTACKINFO::szFncName, tagSTACKINFO::uFileNum, tagSTACKINFO::undFullName, and tagSTACKINFO::undName.

Referenced by CBaseException::ShowCallstack().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ m_bSymbolLoaded

BOOL CStackWalker::m_bSymbolLoaded
protected

◆ m_hProcess

HANDLE CStackWalker::m_hProcess
protected

◆ m_lpszSymbolPath

LPTSTR CStackWalker::m_lpszSymbolPath
protected

◆ m_wPID

WORD CStackWalker::m_wPID
protected

Referenced by CStackWalker(), and GetModulesTH32().


The documentation for this class was generated from the following files: