76#if OGRE_CPU != OGRE_CPU_ARM
82#pragma comment(lib, "version.lib")
83#pragma warning(disable:4826)
85#include "StackWalker.h"
106typedef struct _IMAGEHLP_LINE64 {
112} IMAGEHLP_LINE64, *PIMAGEHLP_LINE64;
113typedef struct _IMAGEHLP_MODULE64 {
123 CHAR LoadedImageName[256];
124} IMAGEHLP_MODULE64, *PIMAGEHLP_MODULE64;
125typedef struct _IMAGEHLP_SYMBOL64 {
132} IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64;
139typedef struct _tagADDRESS64 {
143} ADDRESS64, *LPADDRESS64;
144typedef struct _KDHELP64 {
146 DWORD ThCallbackStack;
147 DWORD ThCallbackBStore;
151 DWORD64 KeUserCallbackDispatcher;
154} KDHELP64, *PKDHELP64;
155typedef struct _tagSTACKFRAME64 {
157 ADDRESS64 AddrReturn;
160 ADDRESS64 AddrBStore;
161 PVOID FuncTableEntry;
167} STACKFRAME64, *LPSTACKFRAME64;
170(__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(
175 LPDWORD lpNumberOfBytesRead
179(__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)(
185(__stdcall *PGET_MODULE_BASE_ROUTINE64)(
191(__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(
196#define SYMOPT_CASE_INSENSITIVE 0x00000001
197#define SYMOPT_UNDNAME 0x00000002
198#define SYMOPT_DEFERRED_LOADS 0x00000004
199#define SYMOPT_NO_CPP 0x00000008
200#define SYMOPT_LOAD_LINES 0x00000010
201#define SYMOPT_OMAP_FIND_NEAREST 0x00000020
202#define SYMOPT_LOAD_ANYTHING 0x00000040
203#define SYMOPT_IGNORE_CVREC 0x00000080
204#define SYMOPT_NO_UNQUALIFIED_LOADS 0x00000100
205#define SYMOPT_FAIL_CRITICAL_ERRORS 0x00000200
206#define SYMOPT_EXACT_SYMBOLS 0x00000400
207#define SYMOPT_ALLOW_ABSOLUTE_SYMBOLS 0x00000800
208#define SYMOPT_IGNORE_NT_SYMPATH 0x00001000
209#define SYMOPT_INCLUDE_32BIT_MODULES 0x00002000
210#define SYMOPT_PUBLICS_ONLY 0x00004000
211#define SYMOPT_NO_PUBLICS 0x00008000
212#define SYMOPT_AUTO_PUBLICS 0x00010000
213#define SYMOPT_NO_IMAGE_SEARCH 0x00020000
214#define SYMOPT_SECURE 0x00040000
215#define SYMOPT_DEBUG 0x80000000
216#define UNDNAME_COMPLETE (0x0000)
217#define UNDNAME_NAME_ONLY (0x1000)
222#ifndef INVALID_FILE_ATTRIBUTES
223#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
229#define strcpy_s strcpy
230#define strcat_s(dst, len, src) strcat(dst, src)
231#define _snprintf_s _snprintf
232#define _tcscat_s _tcscat
236#define USED_CONTEXT_FLAGS CONTEXT_FULL
239class StackWalkerInternal
242 StackWalkerInternal(
StackWalker *parent, HANDLE hProcess)
247 m_hProcess = hProcess;
262 ~StackWalkerInternal()
266 if (m_hDbhHelp != NULL)
267 FreeLibrary(m_hDbhHelp);
270 if(m_szSymPath != NULL)
274 BOOL Init(LPCSTR szSymPath)
276 if (m_parent == NULL)
282 if (GetModuleFileName(NULL, szTemp, 4096) > 0)
284 _tcscat_s(szTemp, _T(
".local"));
285 if (GetFileAttributes(szTemp) == INVALID_FILE_ATTRIBUTES)
290 if ( (m_hDbhHelp == NULL) && (GetEnvironmentVariable(_T(
"ProgramFiles"), szTemp, 4096) > 0) )
292 _tcscat_s(szTemp, _T(
"\\Debugging Tools for Windows (x86)\\dbghelp.dll"));
294 if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES)
296 m_hDbhHelp = LoadLibrary(szTemp);
300 if ( (m_hDbhHelp == NULL) && (GetEnvironmentVariable(_T(
"ProgramFiles"), szTemp, 4096) > 0) )
302 _tcscat_s(szTemp, _T(
"\\Debugging Tools for Windows (x64)\\dbghelp.dll"));
304 if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES)
306 m_hDbhHelp = LoadLibrary(szTemp);
310 if ( (m_hDbhHelp == NULL) && (GetEnvironmentVariable(_T(
"ProgramFiles"), szTemp, 4096) > 0) )
312 _tcscat_s(szTemp, _T(
"\\Debugging Tools for Windows (ia64)\\dbghelp.dll"));
314 if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES)
316 m_hDbhHelp = LoadLibrary(szTemp);
321 if ( (m_hDbhHelp == NULL) && (GetEnvironmentVariable(_T(
"ProgramFiles"), szTemp, 4096) > 0) )
323 _tcscat_s(szTemp, _T(
"\\Debugging Tools for Windows\\dbghelp.dll"));
325 if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES)
327 m_hDbhHelp = LoadLibrary(szTemp);
330#if defined _M_X64 || defined _M_IA64
332 if ( (m_hDbhHelp == NULL) && (GetEnvironmentVariable(_T(
"ProgramFiles"), szTemp, 4096) > 0) )
334 _tcscat_s(szTemp, _T(
"\\Debugging Tools for Windows 64-Bit\\dbghelp.dll"));
335 if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES)
337 m_hDbhHelp = LoadLibrary(szTemp);
343 if (m_hDbhHelp == NULL)
344 m_hDbhHelp = LoadLibrary( _T(
"dbghelp.dll") );
345 if (m_hDbhHelp == NULL)
347 pSI = (tSI) GetProcAddress(m_hDbhHelp,
"SymInitialize" );
348 pSC = (tSC) GetProcAddress(m_hDbhHelp,
"SymCleanup" );
350 pSW = (tSW) GetProcAddress(m_hDbhHelp,
"StackWalk64" );
351 pSGO = (tSGO) GetProcAddress(m_hDbhHelp,
"SymGetOptions" );
352 pSSO = (tSSO) GetProcAddress(m_hDbhHelp,
"SymSetOptions" );
354 pSFTA = (tSFTA) GetProcAddress(m_hDbhHelp,
"SymFunctionTableAccess64" );
355 pSGLFA = (tSGLFA) GetProcAddress(m_hDbhHelp,
"SymGetLineFromAddr64" );
356 pSGMB = (tSGMB) GetProcAddress(m_hDbhHelp,
"SymGetModuleBase64" );
357 pSGMI = (tSGMI) GetProcAddress(m_hDbhHelp,
"SymGetModuleInfo64" );
359 pSGSFA = (tSGSFA) GetProcAddress(m_hDbhHelp,
"SymGetSymFromAddr64" );
360 pUDSN = (tUDSN) GetProcAddress(m_hDbhHelp,
"UnDecorateSymbolName" );
361 pSLM = (tSLM) GetProcAddress(m_hDbhHelp,
"SymLoadModule64" );
362 pSGSP =(tSGSP) GetProcAddress(m_hDbhHelp,
"SymGetSearchPath" );
364 if ( pSC == NULL || pSFTA == NULL || pSGMB == NULL || pSGMI == NULL ||
365 pSGO == NULL || pSGSFA == NULL || pSI == NULL || pSSO == NULL ||
366 pSW == NULL || pUDSN == NULL || pSLM == NULL )
368 FreeLibrary(m_hDbhHelp);
375 if (szSymPath != NULL)
376 m_szSymPath = _strdup(szSymPath);
377 if (this->pSI(m_hProcess, m_szSymPath, FALSE) == FALSE)
378 this->m_parent->OnDbgHelpErr(
"SymInitialize", GetLastError(), 0);
380 DWORD symOptions = this->pSGO();
381 symOptions |= SYMOPT_LOAD_LINES;
382 symOptions |= SYMOPT_FAIL_CRITICAL_ERRORS;
385 symOptions = this->pSSO(symOptions);
388 if (this->pSGSP != NULL)
391 this->m_parent->OnDbgHelpErr(
"SymGetSearchPath", GetLastError(), 0);
393 char szUserName[1024] = {0};
395 GetUserNameA(szUserName, &dwSize);
396 this->m_parent->OnSymInit(buf, symOptions, szUserName);
437typedef struct IMAGEHLP_MODULE64_V2 {
447 CHAR LoadedImageName[256];
453 typedef BOOL (__stdcall *tSC)( IN HANDLE hProcess );
457 typedef PVOID (__stdcall *tSFTA)( HANDLE hProcess,
DWORD64 AddrBase );
461 typedef BOOL (__stdcall *tSGLFA)( IN HANDLE hProcess, IN
DWORD64 dwAddr,
462 OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE64 Line );
466 typedef DWORD64 (__stdcall *tSGMB)( IN HANDLE hProcess, IN
DWORD64 dwAddr );
470 typedef BOOL (__stdcall *tSGMI)( IN HANDLE hProcess, IN
DWORD64 dwAddr, OUT IMAGEHLP_MODULE64_V2 *ModuleInfo );
478 typedef DWORD (__stdcall *tSGO)( VOID );
482 typedef BOOL (__stdcall *tSGSFA)( IN HANDLE hProcess, IN
DWORD64 dwAddr,
483 OUT
PDWORD64 pdwDisplacement, OUT PIMAGEHLP_SYMBOL64 Symbol );
487 typedef BOOL (__stdcall *tSI)( IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess );
491 typedef DWORD64 (__stdcall *tSLM)( IN HANDLE hProcess, IN HANDLE hFile,
492 IN PSTR ImageName, IN PSTR ModuleName, IN
DWORD64 BaseOfDll, IN DWORD SizeOfDll );
496 typedef DWORD (__stdcall *tSSO)( IN DWORD SymOptions );
500 typedef BOOL (__stdcall *tSW)(
504 LPSTACKFRAME64 StackFrame,
506 PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
507 PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
508 PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
509 PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress );
513 typedef DWORD (__stdcall WINAPI *tUDSN)( PCSTR DecoratedName, PSTR UnDecoratedName,
514 DWORD UndecoratedLength, DWORD Flags );
517 typedef BOOL (__stdcall WINAPI *tSGSP)(HANDLE hProcess, PSTR SearchPath, DWORD SearchPathLength);
523 #define MAX_MODULE_NAME32 255
524 #define TH32CS_SNAPMODULE 0x00000008
525 #pragma pack( push, 8 )
526 typedef struct tagMODULEENTRY32
536 char szModule[MAX_MODULE_NAME32 + 1];
537 char szExePath[MAX_PATH];
539 typedef MODULEENTRY32 * PMODULEENTRY32;
540 typedef MODULEENTRY32 * LPMODULEENTRY32;
543 BOOL GetModuleListTH32(HANDLE hProcess, DWORD pid)
546 typedef HANDLE (__stdcall *tCT32S)(DWORD dwFlags, DWORD th32ProcessID);
548 typedef BOOL (__stdcall *tM32F)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
550 typedef BOOL (__stdcall *tM32N)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
553 const TCHAR *dllname[] = { _T(
"kernel32.dll"), _T(
"tlhelp32.dll") };
554 HINSTANCE hToolhelp = NULL;
555 tCT32S pCT32S = NULL;
561 me.dwSize =
sizeof(me);
565 for (i = 0; i<(
sizeof(dllname) /
sizeof(dllname[0])); i++ )
567 hToolhelp = LoadLibrary( dllname[i] );
568 if (hToolhelp == NULL)
570 pCT32S = (tCT32S) GetProcAddress(hToolhelp,
"CreateToolhelp32Snapshot");
571 pM32F = (tM32F) GetProcAddress(hToolhelp,
"Module32First");
572 pM32N = (tM32N) GetProcAddress(hToolhelp,
"Module32Next");
573 if ( (pCT32S != NULL) && (pM32F != NULL) && (pM32N != NULL) )
575 FreeLibrary(hToolhelp);
579 if (hToolhelp == NULL)
582 hSnap = pCT32S( TH32CS_SNAPMODULE, pid );
583 if (hSnap == (HANDLE) -1)
585 FreeLibrary(hToolhelp);
589 keepGoing = !!pM32F( hSnap, &me );
593 this->LoadModule(hProcess, me.szExePath, me.szModule, (
DWORD64) me.modBaseAddr, me.modBaseSize);
595 keepGoing = !!pM32N( hSnap, &me );
598 FreeLibrary(hToolhelp);
605 typedef struct _MODULEINFO {
609 } MODULEINFO, *LPMODULEINFO;
611 BOOL GetModuleListPSAPI(HANDLE hProcess)
614 typedef BOOL (__stdcall *tEPM)(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded );
616 typedef DWORD (__stdcall *tGMFNE)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize );
618 typedef DWORD (__stdcall *tGMBN)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize );
620 typedef BOOL (__stdcall *tGMI)(HANDLE hProcess, HMODULE hModule, LPMODULEINFO pmi, DWORD nSize );
635 const SIZE_T TTBUFLEN = 8096;
638 hPsapi = LoadLibrary( _T(
"psapi.dll") );
642 pEPM = (tEPM) GetProcAddress( hPsapi,
"EnumProcessModules" );
643 pGMFNE = (tGMFNE) GetProcAddress( hPsapi,
"GetModuleFileNameExA" );
644 pGMBN = (tGMFNE) GetProcAddress( hPsapi,
"GetModuleBaseNameA" );
645 pGMI = (tGMI) GetProcAddress( hPsapi,
"GetModuleInformation" );
646 if ( (pEPM == NULL) || (pGMFNE == NULL) || (pGMBN == NULL) || (pGMI == NULL) )
653 hMods = (HMODULE*) malloc(
sizeof(HMODULE) * (TTBUFLEN /
sizeof HMODULE));
654 tt = (
char*) malloc(
sizeof(
char) * TTBUFLEN);
655 tt2 = (
char*) malloc(
sizeof(
char) * TTBUFLEN);
656 if ( (hMods == NULL) || (tt == NULL) || (tt2 == NULL) )
659 if ( ! pEPM( hProcess, hMods, TTBUFLEN, &cbNeeded ) )
665 if ( cbNeeded > TTBUFLEN )
671 for ( i = 0; i < cbNeeded /
sizeof hMods[0]; i++ )
674 pGMI(hProcess, hMods[i], &mi,
sizeof mi );
677 pGMFNE(hProcess, hMods[i], tt, TTBUFLEN );
680 pGMBN(hProcess, hMods[i], tt2, TTBUFLEN );
682 DWORD dwRes = this->LoadModule(hProcess, tt, tt2, (
DWORD64) mi.lpBaseOfDll, mi.SizeOfImage);
683 if (dwRes != ERROR_SUCCESS)
689 if (hPsapi != NULL) FreeLibrary(hPsapi);
690 if (tt2 != NULL) free(tt2);
691 if (tt != NULL) free(tt);
692 if (hMods != NULL) free(hMods);
697 DWORD LoadModule(HANDLE hProcess, LPCSTR img, LPCSTR mod,
DWORD64 baseAddr, DWORD size)
699 CHAR *szImg = _strdup(img);
700 CHAR *szMod = _strdup(mod);
701 DWORD result = ERROR_SUCCESS;
702 if ( (szImg == NULL) || (szMod == NULL) )
703 result = ERROR_NOT_ENOUGH_MEMORY;
706 if (pSLM(hProcess, 0, szImg, szMod, baseAddr, size) == 0)
707 result = GetLastError();
709 ULONGLONG fileVersion = 0;
710 if ( (m_parent != NULL) && (szImg != NULL) )
715 VS_FIXEDFILEINFO *fInfo = NULL;
717 DWORD dwSize = GetFileVersionInfoSizeA(szImg, &dwHandle);
720 LPVOID vData = malloc(dwSize);
723 if (GetFileVersionInfoA(szImg, dwHandle, dwSize, vData) != 0)
726 TCHAR szSubBlock[] = _T(
"\\");
727 if (VerQueryValue(vData, szSubBlock, (LPVOID*) &fInfo, &len) == 0)
731 fileVersion = ((ULONGLONG)fInfo->dwFileVersionLS) + ((ULONGLONG)fInfo->dwFileVersionMS << 32);
740 IMAGEHLP_MODULE64_V2 Module;
741 const char *szSymType =
"-unknown-";
742 if (this->GetModuleInfo(hProcess, baseAddr, &Module) != FALSE)
744 switch(Module.SymType)
747 szSymType =
"-nosymbols-";
759 szSymType =
"-exported-";
762 szSymType =
"-deferred-";
771 szSymType =
"Virtual";
775 this->m_parent->
OnLoadModule(img, mod, baseAddr, size, result, szSymType, Module.LoadedImageName, fileVersion);
777 if (szImg != NULL) free(szImg);
778 if (szMod != NULL) free(szMod);
782 BOOL LoadModules(HANDLE hProcess, DWORD dwProcessId)
785 if (GetModuleListTH32(hProcess, dwProcessId))
788 return GetModuleListPSAPI(hProcess);
792 BOOL GetModuleInfo(HANDLE hProcess,
DWORD64 baseAddr, IMAGEHLP_MODULE64_V2 *pModuleInfo)
794 if(this->pSGMI == NULL)
796 SetLastError(ERROR_DLL_INIT_FAILED);
811 pModuleInfo->SizeOfStruct =
sizeof(IMAGEHLP_MODULE64_V2);
812 void *pData = malloc(4096);
815 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
818 memcpy(pData, pModuleInfo,
sizeof(IMAGEHLP_MODULE64_V2));
819 if (this->pSGMI(hProcess, baseAddr, (IMAGEHLP_MODULE64_V2*) pData) != FALSE)
822 memcpy(pModuleInfo, pData,
sizeof(IMAGEHLP_MODULE64_V2));
823 pModuleInfo->SizeOfStruct =
sizeof(IMAGEHLP_MODULE64_V2);
828 SetLastError(ERROR_DLL_INIT_FAILED);
838 this->m_hProcess = hProcess;
841 this->m_szSymPath = NULL;
848 this->m_hProcess = hProcess;
851 if (szSymPath != NULL)
853 this->m_szSymPath = _strdup(szSymPath);
857 this->m_szSymPath = NULL;
863 if (m_szSymPath != NULL)
866 if (this->
m_sw != NULL)
873 if (this->
m_sw == NULL)
875 SetLastError(ERROR_DLL_INIT_FAILED);
882 char *szSymPath = NULL;
885 const size_t nSymPathLen = 4096;
886 szSymPath = (
char*) malloc(nSymPathLen);
887 if (szSymPath == NULL)
889 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
894 if (this->m_szSymPath != NULL)
896 strcat_s(szSymPath, nSymPathLen, this->m_szSymPath);
897 strcat_s(szSymPath, nSymPathLen,
";");
900 strcat_s(szSymPath, nSymPathLen,
".;");
902 const size_t nTempLen = 1024;
903 char szTemp[nTempLen];
905 if (GetCurrentDirectoryA(nTempLen, szTemp) > 0)
907 szTemp[nTempLen-1] = 0;
908 strcat_s(szSymPath, nSymPathLen, szTemp);
909 strcat_s(szSymPath, nSymPathLen,
";");
913 if (GetModuleFileNameA(NULL, szTemp, nTempLen) > 0)
915 szTemp[nTempLen-1] = 0;
916 for (
char *p = (szTemp+strlen(szTemp)-1); p >= szTemp; --p)
919 if ( (*p ==
'\\') || (*p ==
'/') || (*p ==
':') )
925 if (strlen(szTemp) > 0)
927 strcat_s(szSymPath, nSymPathLen, szTemp);
928 strcat_s(szSymPath, nSymPathLen,
";");
931 if (GetEnvironmentVariableA(
"_NT_SYMBOL_PATH", szTemp, nTempLen) > 0)
933 szTemp[nTempLen-1] = 0;
934 strcat_s(szSymPath, nSymPathLen, szTemp);
935 strcat_s(szSymPath, nSymPathLen,
";");
937 if (GetEnvironmentVariableA(
"_NT_ALTERNATE_SYMBOL_PATH", szTemp, nTempLen) > 0)
939 szTemp[nTempLen-1] = 0;
940 strcat_s(szSymPath, nSymPathLen, szTemp);
941 strcat_s(szSymPath, nSymPathLen,
";");
943 if (GetEnvironmentVariableA(
"SYSTEMROOT", szTemp, nTempLen) > 0)
945 szTemp[nTempLen-1] = 0;
946 strcat_s(szSymPath, nSymPathLen, szTemp);
947 strcat_s(szSymPath, nSymPathLen,
";");
949 strcat_s(szTemp, nTempLen,
"\\system32");
950 strcat_s(szSymPath, nSymPathLen, szTemp);
951 strcat_s(szSymPath, nSymPathLen,
";");
956 if (GetEnvironmentVariableA(
"SYSTEMDRIVE", szTemp, nTempLen) > 0)
958 szTemp[nTempLen-1] = 0;
959 strcat_s(szSymPath, nSymPathLen,
"SRV*");
960 strcat_s(szSymPath, nSymPathLen, szTemp);
961 strcat_s(szSymPath, nSymPathLen,
"\\websymbols");
962 strcat_s(szSymPath, nSymPathLen,
"*http://msdl.microsoft.com/download/symbols;");
965 strcat_s(szSymPath, nSymPathLen,
"SRV*c:\\websymbols*http://msdl.microsoft.com/download/symbols;");
970 BOOL bRet = this->
m_sw->Init(szSymPath);
971 if (szSymPath != NULL) free(szSymPath); szSymPath = NULL;
974 this->
OnDbgHelpErr(
"Error while initializing dbghelp.dll", 0, 0);
975 SetLastError(ERROR_DLL_INIT_FAILED);
999static LPVOID s_readMemoryFunction_UserData = NULL;
1001BOOL
StackWalker::ShowCallstack(HANDLE hThread,
const CONTEXT *context, PReadProcessMemoryRoutine readMemoryFunction, LPVOID pUserData)
1005 IMAGEHLP_SYMBOL64 *pSym = NULL;
1006 StackWalkerInternal::IMAGEHLP_MODULE64_V2 Module;
1007 IMAGEHLP_LINE64 Line;
1009 bool bLastEntryCalled =
true;
1010 int curRecursionCount = 0;
1015 if (this->
m_sw->m_hDbhHelp == NULL)
1017 SetLastError(ERROR_DLL_INIT_FAILED);
1021 s_readMemoryFunction = readMemoryFunction;
1022 s_readMemoryFunction_UserData = pUserData;
1024 if (context == NULL)
1027 if (hThread == GetCurrentThread())
1035 SuspendThread(hThread);
1036 memset(&c, 0,
sizeof(CONTEXT));
1037 c.ContextFlags = USED_CONTEXT_FLAGS;
1038 if (GetThreadContext(hThread, &c) == FALSE)
1040 ResumeThread(hThread);
1050 memset(&s, 0,
sizeof(s));
1054 imageType = IMAGE_FILE_MACHINE_I386;
1055 s.AddrPC.Offset = c.Eip;
1056 s.AddrPC.Mode = AddrModeFlat;
1057 s.AddrFrame.Offset = c.Ebp;
1058 s.AddrFrame.Mode = AddrModeFlat;
1059 s.AddrStack.Offset = c.Esp;
1060 s.AddrStack.Mode = AddrModeFlat;
1062 imageType = IMAGE_FILE_MACHINE_AMD64;
1063 s.AddrPC.Offset = c.Rip;
1064 s.AddrPC.Mode = AddrModeFlat;
1065 s.AddrFrame.Offset = c.Rsp;
1066 s.AddrFrame.Mode = AddrModeFlat;
1067 s.AddrStack.Offset = c.Rsp;
1068 s.AddrStack.Mode = AddrModeFlat;
1070 imageType = IMAGE_FILE_MACHINE_IA64;
1071 s.AddrPC.Offset = c.StIIP;
1072 s.AddrPC.Mode = AddrModeFlat;
1073 s.AddrFrame.Offset = c.IntSp;
1074 s.AddrFrame.Mode = AddrModeFlat;
1075 s.AddrBStore.Offset = c.RsBSP;
1076 s.AddrBStore.Mode = AddrModeFlat;
1077 s.AddrStack.Offset = c.IntSp;
1078 s.AddrStack.Mode = AddrModeFlat;
1080#error "Platform not supported!"
1084 if (!pSym)
goto cleanup;
1086 pSym->SizeOfStruct =
sizeof(IMAGEHLP_SYMBOL64);
1089 memset(&Line, 0,
sizeof(Line));
1090 Line.SizeOfStruct =
sizeof(Line);
1092 memset(&Module, 0,
sizeof(Module));
1093 Module.SizeOfStruct =
sizeof(Module);
1099 for (frameNum = 0; ; ++frameNum )
1106 if ( ! this->
m_sw->pSW(imageType, this->m_hProcess, hThread, &s, &c,
myReadProcMem, this->m_sw->pSFTA, this->m_sw->pSGMB, NULL) )
1113 csEntry.offset = s.AddrPC.Offset;
1114 csEntry.name[0] = 0;
1115 csEntry.undName[0] = 0;
1116 csEntry.undFullName[0] = 0;
1117 csEntry.offsetFromSmybol = 0;
1118 csEntry.offsetFromLine = 0;
1119 csEntry.lineFileName[0] = 0;
1120 csEntry.lineNumber = 0;
1121 csEntry.loadedImageName[0] = 0;
1122 csEntry.moduleName[0] = 0;
1123 if (s.AddrPC.Offset == s.AddrReturn.Offset)
1127 this->
OnDbgHelpErr(
"StackWalk64-Endless-Callstack!", 0, s.AddrPC.Offset);
1130 curRecursionCount++;
1133 curRecursionCount = 0;
1134 if (s.AddrPC.Offset != 0)
1138 if (this->
m_sw->pSGSFA(this->m_hProcess, s.AddrPC.Offset, &(csEntry.offsetFromSmybol), pSym) != FALSE)
1140 strcpy_s(csEntry.name, pSym->Name);
1151 if (this->
m_sw->pSGLFA != NULL )
1153 if (this->
m_sw->pSGLFA(this->m_hProcess, s.AddrPC.Offset, &(csEntry.offsetFromLine), &Line) != FALSE)
1155 csEntry.lineNumber = Line.LineNumber;
1157 strcpy_s(csEntry.lineFileName, Line.FileName);
1166 if (this->
m_sw->GetModuleInfo(this->m_hProcess, s.AddrPC.Offset, &Module ) != FALSE)
1168 switch ( Module.SymType )
1171 csEntry.symTypeString =
"-nosymbols-";
1174 csEntry.symTypeString =
"COFF";
1177 csEntry.symTypeString =
"CV";
1180 csEntry.symTypeString =
"PDB";
1183 csEntry.symTypeString =
"-exported-";
1186 csEntry.symTypeString =
"-deferred-";
1189 csEntry.symTypeString =
"SYM";
1191#if API_VERSION_NUMBER >= 9
1193 csEntry.symTypeString =
"DIA";
1197 csEntry.symTypeString =
"Virtual";
1201 csEntry.symTypeString = NULL;
1206 strcpy_s(csEntry.moduleName, Module.ModuleName);
1207 csEntry.baseOfImage = Module.BaseOfImage;
1208 strcpy_s(csEntry.loadedImageName, Module.LoadedImageName);
1212 this->
OnDbgHelpErr(
"SymGetModuleInfo64", GetLastError(), s.AddrPC.Offset);
1219 bLastEntryCalled =
false;
1222 if (s.AddrReturn.Offset == 0)
1224 bLastEntryCalled =
true;
1226 SetLastError(ERROR_SUCCESS);
1232 if (pSym) free( pSym );
1234 if (bLastEntryCalled ==
false)
1237 if (context == NULL)
1238 ResumeThread(hThread);
1248 LPDWORD lpNumberOfBytesRead
1251 if (s_readMemoryFunction == NULL)
1254 BOOL bRet = ReadProcessMemory(hProcess, (LPVOID) qwBaseAddress, lpBuffer, nSize, &st);
1255 *lpNumberOfBytesRead = (DWORD) st;
1261 return s_readMemoryFunction(hProcess, qwBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead, s_readMemoryFunction_UserData);
1285 if ( (eType !=
lastEntry) && (entry.offset != 0) )
1287 if (entry.name[0] == 0)
1288 strcpy_s(entry.name,
"(function-name not available)");
1289 if (entry.undName[0] != 0)
1290 strcpy_s(entry.name, entry.undName);
1291 if (entry.undFullName[0] != 0)
1292 strcpy_s(entry.name, entry.undFullName);
1293 if (entry.lineFileName[0] == 0)
1295 strcpy_s(entry.lineFileName,
"(filename not available)");
1296 if (entry.moduleName[0] == 0)
1297 strcpy_s(entry.moduleName,
"(module-name not available)");
1298 _snprintf_s(buffer,
STACKWALK_MAX_NAMELEN,
"%p (%s): %s: %s\n", (LPVOID) entry.offset, entry.moduleName, entry.lineFileName, entry.name);
1301 _snprintf_s(buffer,
STACKWALK_MAX_NAMELEN,
"%s (%d): %s\n", entry.lineFileName, entry.lineNumber, entry.name);
1309 _snprintf_s(buffer,
STACKWALK_MAX_NAMELEN,
"ERROR: %s, GetLastError: %d (Address: %p)\n\n", szFuncName, gle, (LPVOID) addr);
1317 _snprintf_s(buffer,
STACKWALK_MAX_NAMELEN,
"SymInit: Symbol SearchPath: '%s', symOptions: %d, \n\n", szSearchPath, symOptions);
1322 ZeroMemory(&ver,
sizeof(OSVERSIONINFOA));
1323 ver.dwOSVersionInfoSize =
sizeof(ver);
1324 if (GetVersionExA(&ver) != FALSE)
1327 ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber,
1332 OSVERSIONINFOEXA ver;
1333 ZeroMemory(&ver,
sizeof(OSVERSIONINFOEXA));
1334 ver.dwOSVersionInfoSize =
sizeof(ver);
1335 if (GetVersionExA( (OSVERSIONINFOA*) &ver) != FALSE)
1341 ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber,
1350 OutputDebugStringA(buffer);
StackWalker(int options=RetrieveNone, LPCSTR szSymPath=NULL, DWORD dwProcessId=GetCurrentProcessId(), HANDLE hProcess=GetCurrentProcess())
StackWalkerInternal * m_sw
BOOL ShowCallstack(HANDLE hThread=GetCurrentThread(), const CONTEXT *context=NULL, PReadProcessMemoryRoutine readMemoryFunction=NULL, LPVOID pUserData=NULL)
virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry)
struct StackWalker::CallstackEntry CallstackEntry
static BOOL __stdcall myReadProcMem(HANDLE hProcess, DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead)
virtual void OnOutput(LPCSTR szText)
friend StackWalkerInternal
BOOL(__stdcall * PReadProcessMemoryRoutine)(HANDLE hProcess, DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead, LPVOID pUserData)
virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr)
virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName)
virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion)
#define GET_CURRENT_CONTEXT(c, contextFlags)
unsigned __int64 * PDWORD64