88 #pragma comment(lib, "version.lib") // for "VerQueryValue" 89 #pragma warning(disable:4826) 91 #include "StackWalker.hh" 129 CHAR LoadedImageName[256];
152 DWORD ThCallbackStack;
153 DWORD ThCallbackBStore;
156 DWORD64 KiCallUserMode;
157 DWORD64 KeUserCallbackDispatcher;
158 DWORD64 SystemRangeStart;
167 PVOID FuncTableEntry;
176 (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(
178 DWORD64 qwBaseAddress,
181 LPDWORD lpNumberOfBytesRead
185 (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)(
191 (__stdcall *PGET_MODULE_BASE_ROUTINE64)(
197 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(
202 #define SYMOPT_CASE_INSENSITIVE 0x00000001 203 #define SYMOPT_UNDNAME 0x00000002 204 #define SYMOPT_DEFERRED_LOADS 0x00000004 205 #define SYMOPT_NO_CPP 0x00000008 206 #define SYMOPT_LOAD_LINES 0x00000010 207 #define SYMOPT_OMAP_FIND_NEAREST 0x00000020 208 #define SYMOPT_LOAD_ANYTHING 0x00000040 209 #define SYMOPT_IGNORE_CVREC 0x00000080 210 #define SYMOPT_NO_UNQUALIFIED_LOADS 0x00000100 211 #define SYMOPT_FAIL_CRITICAL_ERRORS 0x00000200 212 #define SYMOPT_EXACT_SYMBOLS 0x00000400 213 #define SYMOPT_ALLOW_ABSOLUTE_SYMBOLS 0x00000800 214 #define SYMOPT_IGNORE_NT_SYMPATH 0x00001000 215 #define SYMOPT_INCLUDE_32BIT_MODULES 0x00002000 216 #define SYMOPT_PUBLICS_ONLY 0x00004000 217 #define SYMOPT_NO_PUBLICS 0x00008000 218 #define SYMOPT_AUTO_PUBLICS 0x00010000 219 #define SYMOPT_NO_IMAGE_SEARCH 0x00020000 220 #define SYMOPT_SECURE 0x00040000 221 #define SYMOPT_DEBUG 0x80000000 222 #define UNDNAME_COMPLETE (0x0000) // Enable full undecoration 223 #define UNDNAME_NAME_ONLY (0x1000) // Crack only the name for primary declaration; 224 #endif // _MSC_VER < 1300 228 #ifndef INVALID_FILE_ATTRIBUTES 229 #define INVALID_FILE_ATTRIBUTES ((DWORD)-1) 235 #define strcpy_s(dst, len, src) strcpy(dst, src) 236 #define strncpy_s(dst, len, src, maxLen) strncpy(dst, len, src) 237 #define strcat_s(dst, len, src) strcat(dst, src) 238 #define _snprintf_s _snprintf 239 #define _tcscat_s _tcscat 242 static void MyStrCpy(
char* szDest,
size_t nMaxDestSize,
const char* szSrc)
244 if (nMaxDestSize <= 0)
return;
245 strncpy_s(szDest, nMaxDestSize, szSrc, _TRUNCATE);
246 szDest[nMaxDestSize-1] = 0;
250 #define USED_CONTEXT_FLAGS CONTEXT_FULL 261 m_hProcess = hProcess;
280 if (m_hDbhHelp != NULL)
281 FreeLibrary(m_hDbhHelp);
284 if(m_szSymPath != NULL)
288 BOOL Init(LPCSTR szSymPath)
290 if (m_parent == NULL)
296 if (GetModuleFileName(NULL, szTemp, 4096) > 0)
298 _tcscat_s(szTemp, _T(
".local"));
299 if (GetFileAttributes(szTemp) == INVALID_FILE_ATTRIBUTES)
304 if ( (m_hDbhHelp == NULL) && (GetEnvironmentVariable(_T(
"ProgramFiles"), szTemp, 4096) > 0) )
306 _tcscat_s(szTemp, _T(
"\\Debugging Tools for Windows (x86)\\dbghelp.dll"));
308 if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES)
310 m_hDbhHelp = LoadLibrary(szTemp);
314 if ( (m_hDbhHelp == NULL) && (GetEnvironmentVariable(_T(
"ProgramFiles"), szTemp, 4096) > 0) )
316 _tcscat_s(szTemp, _T(
"\\Debugging Tools for Windows (x64)\\dbghelp.dll"));
318 if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES)
320 m_hDbhHelp = LoadLibrary(szTemp);
324 if ( (m_hDbhHelp == NULL) && (GetEnvironmentVariable(_T(
"ProgramFiles"), szTemp, 4096) > 0) )
326 _tcscat_s(szTemp, _T(
"\\Debugging Tools for Windows (ia64)\\dbghelp.dll"));
328 if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES)
330 m_hDbhHelp = LoadLibrary(szTemp);
335 if ( (m_hDbhHelp == NULL) && (GetEnvironmentVariable(_T(
"ProgramFiles"), szTemp, 4096) > 0) )
337 _tcscat_s(szTemp, _T(
"\\Debugging Tools for Windows\\dbghelp.dll"));
339 if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES)
341 m_hDbhHelp = LoadLibrary(szTemp);
344 #if defined _M_X64 || defined _M_IA64 346 if ( (m_hDbhHelp == NULL) && (GetEnvironmentVariable(_T(
"ProgramFiles"), szTemp, 4096) > 0) )
348 _tcscat_s(szTemp, _T(
"\\Debugging Tools for Windows 64-Bit\\dbghelp.dll"));
349 if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES)
351 m_hDbhHelp = LoadLibrary(szTemp);
357 if (m_hDbhHelp == NULL)
358 m_hDbhHelp = LoadLibrary( _T(
"dbghelp.dll") );
359 if (m_hDbhHelp == NULL)
361 pSI = (tSI) GetProcAddress(m_hDbhHelp,
"SymInitialize" );
362 pSC = (tSC) GetProcAddress(m_hDbhHelp,
"SymCleanup" );
364 pSW = (tSW) GetProcAddress(m_hDbhHelp,
"StackWalk64" );
365 pSGO = (tSGO) GetProcAddress(m_hDbhHelp,
"SymGetOptions" );
366 pSSO = (tSSO) GetProcAddress(m_hDbhHelp,
"SymSetOptions" );
368 pSFTA = (tSFTA) GetProcAddress(m_hDbhHelp,
"SymFunctionTableAccess64" );
369 pSGLFA = (tSGLFA) GetProcAddress(m_hDbhHelp,
"SymGetLineFromAddr64" );
370 pSGMB = (tSGMB) GetProcAddress(m_hDbhHelp,
"SymGetModuleBase64" );
371 pSGMI = (tSGMI) GetProcAddress(m_hDbhHelp,
"SymGetModuleInfo64" );
372 pSGSFA = (tSGSFA) GetProcAddress(m_hDbhHelp,
"SymGetSymFromAddr64" );
373 pUDSN = (tUDSN) GetProcAddress(m_hDbhHelp,
"UnDecorateSymbolName" );
374 pSLM = (tSLM) GetProcAddress(m_hDbhHelp,
"SymLoadModule64" );
375 pSGSP =(tSGSP) GetProcAddress(m_hDbhHelp,
"SymGetSearchPath" );
377 if ( pSC == NULL || pSFTA == NULL || pSGMB == NULL || pSGMI == NULL ||
378 pSGO == NULL || pSGSFA == NULL || pSI == NULL || pSSO == NULL ||
379 pSW == NULL || pUDSN == NULL || pSLM == NULL )
381 FreeLibrary(m_hDbhHelp);
388 if (szSymPath != NULL)
389 m_szSymPath = _strdup(szSymPath);
390 if (this->pSI(m_hProcess, m_szSymPath, FALSE) == FALSE)
391 this->m_parent->OnDbgHelpErr(
"SymInitialize", GetLastError(), 0);
393 DWORD symOptions = this->pSGO();
394 symOptions |= SYMOPT_LOAD_LINES;
395 symOptions |= SYMOPT_FAIL_CRITICAL_ERRORS;
398 symOptions = this->pSSO(symOptions);
400 char buf[StackWalker::STACKWALK_MAX_NAMELEN] = {0};
401 if (this->pSGSP != NULL)
403 if (this->pSGSP(m_hProcess, buf, StackWalker::STACKWALK_MAX_NAMELEN) == FALSE)
404 this->m_parent->OnDbgHelpErr(
"SymGetSearchPath", GetLastError(), 0);
406 char szUserName[1024] = {0};
408 GetUserNameA(szUserName, &dwSize);
409 this->m_parent->OnSymInit(buf, symOptions, szUserName);
431 CHAR LoadedImageName[256];
433 CHAR LoadedPdbName[256];
435 CHAR CVData[MAX_PATH * 3];
459 CHAR LoadedImageName[256];
465 typedef BOOL (__stdcall *tSC)( IN HANDLE hProcess );
469 typedef PVOID (__stdcall *tSFTA)( HANDLE hProcess, DWORD64 AddrBase );
473 typedef BOOL (__stdcall *tSGLFA)( IN HANDLE hProcess, IN DWORD64 dwAddr,
474 OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE64 Line );
478 typedef DWORD64 (__stdcall *tSGMB)( IN HANDLE hProcess, IN DWORD64 dwAddr );
482 typedef BOOL (__stdcall *tSGMI)( IN HANDLE hProcess, IN DWORD64 dwAddr, OUT
IMAGEHLP_MODULE64_V3 *ModuleInfo );
486 typedef DWORD (__stdcall *tSGO)( VOID );
490 typedef BOOL (__stdcall *tSGSFA)( IN HANDLE hProcess, IN DWORD64 dwAddr,
491 OUT PDWORD64 pdwDisplacement, OUT PIMAGEHLP_SYMBOL64 Symbol );
495 typedef BOOL (__stdcall *tSI)( IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess );
499 typedef DWORD64 (__stdcall *tSLM)( IN HANDLE hProcess, IN HANDLE hFile,
500 IN PSTR ImageName, IN PSTR ModuleName, IN DWORD64 BaseOfDll, IN DWORD SizeOfDll );
504 typedef DWORD (__stdcall *tSSO)( IN DWORD SymOptions );
508 typedef BOOL (__stdcall *tSW)(
512 LPSTACKFRAME64 StackFrame,
514 PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
515 PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
516 PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
517 PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress );
521 typedef DWORD (__stdcall WINAPI *tUDSN)( PCSTR DecoratedName, PSTR UnDecoratedName,
522 DWORD UndecoratedLength, DWORD Flags );
525 typedef BOOL (__stdcall WINAPI *tSGSP)(HANDLE hProcess, PSTR SearchPath, DWORD SearchPathLength);
531 #define MAX_MODULE_NAME32 255 532 #define TH32CS_SNAPMODULE 0x00000008 533 #pragma pack( push, 8 ) 544 char szModule[MAX_MODULE_NAME32 + 1];
545 char szExePath[MAX_PATH];
551 BOOL GetModuleListTH32(HANDLE hProcess, DWORD pid)
554 typedef HANDLE (__stdcall *tCT32S)(DWORD dwFlags, DWORD th32ProcessID);
556 typedef BOOL (__stdcall *tM32F)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
558 typedef BOOL (__stdcall *tM32N)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
561 const TCHAR *dllname[] = { _T(
"kernel32.dll"), _T(
"tlhelp32.dll") };
562 HINSTANCE hToolhelp = NULL;
563 tCT32S pCT32S = NULL;
569 me.dwSize =
sizeof(me);
573 for (i = 0; i<(
sizeof(dllname) /
sizeof(dllname[0])); i++ )
575 hToolhelp = LoadLibrary( dllname[i] );
576 if (hToolhelp == NULL)
578 pCT32S = (tCT32S) GetProcAddress(hToolhelp,
"CreateToolhelp32Snapshot");
579 pM32F = (tM32F) GetProcAddress(hToolhelp,
"Module32First");
580 pM32N = (tM32N) GetProcAddress(hToolhelp,
"Module32Next");
581 if ( (pCT32S != NULL) && (pM32F != NULL) && (pM32N != NULL) )
583 FreeLibrary(hToolhelp);
587 if (hToolhelp == NULL)
590 hSnap = pCT32S( TH32CS_SNAPMODULE, pid );
591 if (hSnap == (HANDLE) -1)
593 FreeLibrary(hToolhelp);
597 keepGoing = !!pM32F( hSnap, &me );
601 this->LoadModule(hProcess, me.szExePath, me.szModule, (DWORD64) me.modBaseAddr, me.modBaseSize);
603 keepGoing = !!pM32N( hSnap, &me );
606 FreeLibrary(hToolhelp);
619 BOOL GetModuleListPSAPI(HANDLE hProcess)
622 typedef BOOL (__stdcall *tEPM)(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded );
624 typedef DWORD (__stdcall *tGMFNE)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize );
626 typedef DWORD (__stdcall *tGMBN)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize );
628 typedef BOOL (__stdcall *tGMI)(HANDLE hProcess, HMODULE hModule, LPMODULEINFO pmi, DWORD nSize );
643 const SIZE_T TTBUFLEN = 8096;
646 hPsapi = LoadLibrary( _T(
"psapi.dll") );
650 pEPM = (tEPM) GetProcAddress( hPsapi,
"EnumProcessModules" );
651 pGMFNE = (tGMFNE) GetProcAddress( hPsapi,
"GetModuleFileNameExA" );
652 pGMBN = (tGMFNE) GetProcAddress( hPsapi,
"GetModuleBaseNameA" );
653 pGMI = (tGMI) GetProcAddress( hPsapi,
"GetModuleInformation" );
654 if ( (pEPM == NULL) || (pGMFNE == NULL) || (pGMBN == NULL) || (pGMI == NULL) )
661 hMods = (HMODULE*) malloc(
sizeof(HMODULE) * (TTBUFLEN /
sizeof(HMODULE)));
662 tt = (
char*) malloc(
sizeof(
char) * TTBUFLEN);
663 tt2 = (
char*) malloc(
sizeof(
char) * TTBUFLEN);
664 if ( (hMods == NULL) || (tt == NULL) || (tt2 == NULL) )
667 if ( ! pEPM( hProcess, hMods, TTBUFLEN, &cbNeeded ) )
673 if ( cbNeeded > TTBUFLEN )
679 for ( i = 0; i < cbNeeded /
sizeof(hMods[0]); i++ )
682 pGMI(hProcess, hMods[i], &mi,
sizeof(mi));
685 pGMFNE(hProcess, hMods[i], tt, TTBUFLEN );
688 pGMBN(hProcess, hMods[i], tt2, TTBUFLEN );
690 DWORD dwRes = this->LoadModule(hProcess, tt, tt2, (DWORD64) mi.lpBaseOfDll, mi.SizeOfImage);
691 if (dwRes != ERROR_SUCCESS)
692 this->m_parent->OnDbgHelpErr(
"LoadModule", dwRes, 0);
697 if (hPsapi != NULL) FreeLibrary(hPsapi);
698 if (tt2 != NULL) free(tt2);
699 if (tt != NULL) free(tt);
700 if (hMods != NULL) free(hMods);
705 DWORD LoadModule(HANDLE hProcess, LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size)
707 CHAR *szImg = _strdup(img);
708 CHAR *szMod = _strdup(mod);
709 DWORD result = ERROR_SUCCESS;
710 if ( (szImg == NULL) || (szMod == NULL) )
711 result = ERROR_NOT_ENOUGH_MEMORY;
714 if (pSLM(hProcess, 0, szImg, szMod, baseAddr, size) == 0)
715 result = GetLastError();
717 ULONGLONG fileVersion = 0;
718 if ( (m_parent != NULL) && (szImg != NULL) )
721 if ( (this->m_parent->m_options & StackWalker::RetrieveFileVersion) != 0)
723 VS_FIXEDFILEINFO *fInfo = NULL;
725 DWORD dwSize = GetFileVersionInfoSizeA(szImg, &dwHandle);
728 LPVOID vData = malloc(dwSize);
731 if (GetFileVersionInfoA(szImg, dwHandle, dwSize, vData) != 0)
734 TCHAR szSubBlock[] = _T(
"\\");
735 if (VerQueryValue(vData, szSubBlock, (LPVOID*) &fInfo, &len) == 0)
739 fileVersion = ((ULONGLONG)fInfo->dwFileVersionLS) + ((ULONGLONG)fInfo->dwFileVersionMS << 32);
749 const char *szSymType =
"-unknown-";
750 if (this->GetModuleInfo(hProcess, baseAddr, &Module) != FALSE)
752 switch(Module.SymType)
755 szSymType =
"-nosymbols-";
767 szSymType =
"-exported-";
770 szSymType =
"-deferred-";
779 szSymType =
"Virtual";
783 LPCSTR pdbName = Module.LoadedImageName;
784 if (Module.LoadedPdbName[0] != 0)
785 pdbName = Module.LoadedPdbName;
786 this->m_parent->OnLoadModule(img, mod, baseAddr, size, result, szSymType, pdbName, fileVersion);
788 if (szImg != NULL) free(szImg);
789 if (szMod != NULL) free(szMod);
793 BOOL LoadModules(HANDLE hProcess, DWORD dwProcessId)
796 if (GetModuleListTH32(hProcess, dwProcessId))
799 return GetModuleListPSAPI(hProcess);
806 if(this->pSGMI == NULL)
808 SetLastError(ERROR_DLL_INIT_FAILED);
813 void *pData = malloc(4096);
816 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
820 static bool s_useV3Version =
true;
831 s_useV3Version =
false;
846 SetLastError(ERROR_DLL_INIT_FAILED);
852 StackWalker::StackWalker(DWORD dwProcessId, HANDLE hProcess)
854 this->m_options = OptionsAll;
855 this->m_modulesLoaded = FALSE;
856 this->m_hProcess = hProcess;
858 this->m_dwProcessId = dwProcessId;
859 this->m_szSymPath = NULL;
860 this->m_MaxRecursionCount = 1000;
862 StackWalker::StackWalker(
int options, LPCSTR szSymPath, DWORD dwProcessId, HANDLE hProcess)
864 this->m_options = options;
865 this->m_modulesLoaded = FALSE;
866 this->m_hProcess = hProcess;
868 this->m_dwProcessId = dwProcessId;
869 if (szSymPath != NULL)
871 this->m_szSymPath = _strdup(szSymPath);
872 this->m_options |= SymBuildPath;
875 this->m_szSymPath = NULL;
876 this->m_MaxRecursionCount = 1000;
879 StackWalker::~StackWalker()
881 if (m_szSymPath != NULL)
884 if (this->m_sw != NULL)
889 BOOL StackWalker::LoadModules()
891 if (this->m_sw == NULL)
893 SetLastError(ERROR_DLL_INIT_FAILED);
896 if (m_modulesLoaded != FALSE)
900 char *szSymPath = NULL;
901 if ( (this->m_options & SymBuildPath) != 0)
903 const size_t nSymPathLen = 4096;
904 szSymPath = (
char*) malloc(nSymPathLen);
905 if (szSymPath == NULL)
907 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
912 if (this->m_szSymPath != NULL)
914 strcat_s(szSymPath, nSymPathLen, this->m_szSymPath);
915 strcat_s(szSymPath, nSymPathLen,
";");
918 strcat_s(szSymPath, nSymPathLen,
".;");
920 const size_t nTempLen = 1024;
921 char szTemp[nTempLen];
923 if (GetCurrentDirectoryA(nTempLen, szTemp) > 0)
925 szTemp[nTempLen-1] = 0;
926 strcat_s(szSymPath, nSymPathLen, szTemp);
927 strcat_s(szSymPath, nSymPathLen,
";");
931 if (GetModuleFileNameA(NULL, szTemp, nTempLen) > 0)
933 szTemp[nTempLen-1] = 0;
934 for (
char *p = (szTemp+strlen(szTemp)-1); p >= szTemp; --p)
937 if ( (*p ==
'\\') || (*p ==
'/') || (*p ==
':') )
943 if (strlen(szTemp) > 0)
945 strcat_s(szSymPath, nSymPathLen, szTemp);
946 strcat_s(szSymPath, nSymPathLen,
";");
949 if (GetEnvironmentVariableA(
"_NT_SYMBOL_PATH", szTemp, nTempLen) > 0)
951 szTemp[nTempLen-1] = 0;
952 strcat_s(szSymPath, nSymPathLen, szTemp);
953 strcat_s(szSymPath, nSymPathLen,
";");
955 if (GetEnvironmentVariableA(
"_NT_ALTERNATE_SYMBOL_PATH", szTemp, nTempLen) > 0)
957 szTemp[nTempLen-1] = 0;
958 strcat_s(szSymPath, nSymPathLen, szTemp);
959 strcat_s(szSymPath, nSymPathLen,
";");
961 if (GetEnvironmentVariableA(
"SYSTEMROOT", szTemp, nTempLen) > 0)
963 szTemp[nTempLen-1] = 0;
964 strcat_s(szSymPath, nSymPathLen, szTemp);
965 strcat_s(szSymPath, nSymPathLen,
";");
967 strcat_s(szTemp, nTempLen,
"\\system32");
968 strcat_s(szSymPath, nSymPathLen, szTemp);
969 strcat_s(szSymPath, nSymPathLen,
";");
972 if ( (this->m_options & SymUseSymSrv) != 0)
974 if (GetEnvironmentVariableA(
"SYSTEMDRIVE", szTemp, nTempLen) > 0)
976 szTemp[nTempLen-1] = 0;
977 strcat_s(szSymPath, nSymPathLen,
"SRV*");
978 strcat_s(szSymPath, nSymPathLen, szTemp);
979 strcat_s(szSymPath, nSymPathLen,
"\\websymbols");
980 strcat_s(szSymPath, nSymPathLen,
"*http://msdl.microsoft.com/download/symbols;");
983 strcat_s(szSymPath, nSymPathLen,
"SRV*c:\\websymbols*http://msdl.microsoft.com/download/symbols;");
988 BOOL bRet = this->m_sw->Init(szSymPath);
989 if (szSymPath != NULL) free(szSymPath); szSymPath = NULL;
992 this->OnDbgHelpErr(
"Error while initializing dbghelp.dll", 0, 0);
993 SetLastError(ERROR_DLL_INIT_FAILED);
997 bRet = this->m_sw->LoadModules(this->m_hProcess, this->m_dwProcessId);
999 m_modulesLoaded = TRUE;
1008 static StackWalker::PReadProcessMemoryRoutine s_readMemoryFunction = NULL;
1009 static LPVOID s_readMemoryFunction_UserData = NULL;
1011 BOOL StackWalker::ShowCallstack(HANDLE hThread,
const CONTEXT *context, PReadProcessMemoryRoutine readMemoryFunction, LPVOID pUserData)
1014 CallstackEntry csEntry;
1019 bool bLastEntryCalled =
true;
1020 int curRecursionCount = 0;
1022 if (m_modulesLoaded == FALSE)
1023 this->LoadModules();
1025 if (this->m_sw->m_hDbhHelp == NULL)
1027 SetLastError(ERROR_DLL_INIT_FAILED);
1031 s_readMemoryFunction = readMemoryFunction;
1032 s_readMemoryFunction_UserData = pUserData;
1034 if (context == NULL)
1038 #if _WIN32_WINNT <= 0x0501 1040 if (hThread == GetCurrentThread())
1042 if (GetThreadId(hThread) == GetCurrentThreadId())
1045 GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, USED_CONTEXT_FLAGS);
1049 SuspendThread(hThread);
1050 memset(&c, 0,
sizeof(CONTEXT));
1051 c.ContextFlags = USED_CONTEXT_FLAGS;
1057 if (GetThreadContext(hThread, &c) == FALSE)
1059 ResumeThread(hThread);
1069 memset(&s, 0,
sizeof(s));
1073 imageType = IMAGE_FILE_MACHINE_I386;
1074 s.AddrPC.Offset = c.Eip;
1075 s.AddrPC.Mode = AddrModeFlat;
1076 s.AddrFrame.Offset = c.Ebp;
1077 s.AddrFrame.Mode = AddrModeFlat;
1078 s.AddrStack.Offset = c.Esp;
1079 s.AddrStack.Mode = AddrModeFlat;
1081 imageType = IMAGE_FILE_MACHINE_AMD64;
1082 s.AddrPC.Offset = c.Rip;
1083 s.AddrPC.Mode = AddrModeFlat;
1084 s.AddrFrame.Offset = c.Rsp;
1085 s.AddrFrame.Mode = AddrModeFlat;
1086 s.AddrStack.Offset = c.Rsp;
1087 s.AddrStack.Mode = AddrModeFlat;
1089 imageType = IMAGE_FILE_MACHINE_IA64;
1090 s.AddrPC.Offset = c.StIIP;
1091 s.AddrPC.Mode = AddrModeFlat;
1092 s.AddrFrame.Offset = c.IntSp;
1093 s.AddrFrame.Mode = AddrModeFlat;
1094 s.AddrBStore.Offset = c.RsBSP;
1095 s.AddrBStore.Mode = AddrModeFlat;
1096 s.AddrStack.Offset = c.IntSp;
1097 s.AddrStack.Mode = AddrModeFlat;
1099 #error "Platform not supported!" 1103 if (!pSym)
goto cleanup;
1106 pSym->MaxNameLength = STACKWALK_MAX_NAMELEN;
1108 memset(&Line, 0,
sizeof(Line));
1109 Line.SizeOfStruct =
sizeof(Line);
1111 memset(&Module, 0,
sizeof(Module));
1112 Module.SizeOfStruct =
sizeof(Module);
1114 for (frameNum = 0; ; ++frameNum )
1121 if ( ! this->m_sw->pSW(imageType, this->m_hProcess, hThread, &s, &c, myReadProcMem, this->m_sw->pSFTA, this->m_sw->pSGMB, NULL) )
1124 this->OnDbgHelpErr(
"StackWalk64", 0, s.AddrPC.Offset);
1128 csEntry.offset = s.AddrPC.Offset;
1129 csEntry.name[0] = 0;
1130 csEntry.undName[0] = 0;
1131 csEntry.undFullName[0] = 0;
1132 csEntry.offsetFromSmybol = 0;
1133 csEntry.offsetFromLine = 0;
1134 csEntry.lineFileName[0] = 0;
1135 csEntry.lineNumber = 0;
1136 csEntry.loadedImageName[0] = 0;
1137 csEntry.moduleName[0] = 0;
1138 if (s.AddrPC.Offset == s.AddrReturn.Offset)
1140 if ( (this->m_MaxRecursionCount > 0) && (curRecursionCount > m_MaxRecursionCount) )
1142 this->OnDbgHelpErr(
"StackWalk64-Endless-Callstack!", 0, s.AddrPC.Offset);
1145 curRecursionCount++;
1148 curRecursionCount = 0;
1149 if (s.AddrPC.Offset != 0)
1153 if (this->m_sw->pSGSFA(this->m_hProcess, s.AddrPC.Offset, &(csEntry.offsetFromSmybol), pSym) != FALSE)
1155 MyStrCpy(csEntry.name, STACKWALK_MAX_NAMELEN, pSym->Name);
1157 this->m_sw->pUDSN( pSym->Name, csEntry.undName, STACKWALK_MAX_NAMELEN, UNDNAME_NAME_ONLY );
1158 this->m_sw->pUDSN( pSym->Name, csEntry.undFullName, STACKWALK_MAX_NAMELEN, UNDNAME_COMPLETE );
1162 this->OnDbgHelpErr(
"SymGetSymFromAddr64", GetLastError(), s.AddrPC.Offset);
1166 if (this->m_sw->pSGLFA != NULL )
1168 if (this->m_sw->pSGLFA(this->m_hProcess, s.AddrPC.Offset, &(csEntry.offsetFromLine), &Line) != FALSE)
1170 csEntry.lineNumber = Line.LineNumber;
1171 MyStrCpy(csEntry.lineFileName, STACKWALK_MAX_NAMELEN, Line.FileName);
1175 this->OnDbgHelpErr(
"SymGetLineFromAddr64", GetLastError(), s.AddrPC.Offset);
1180 if (this->m_sw->GetModuleInfo(this->m_hProcess, s.AddrPC.Offset, &Module ) != FALSE)
1182 switch ( Module.SymType )
1185 csEntry.symTypeString =
"-nosymbols-";
1188 csEntry.symTypeString =
"COFF";
1191 csEntry.symTypeString =
"CV";
1194 csEntry.symTypeString =
"PDB";
1197 csEntry.symTypeString =
"-exported-";
1200 csEntry.symTypeString =
"-deferred-";
1203 csEntry.symTypeString =
"SYM";
1205 #if API_VERSION_NUMBER >= 9 1207 csEntry.symTypeString =
"DIA";
1211 csEntry.symTypeString =
"Virtual";
1215 csEntry.symTypeString = NULL;
1219 MyStrCpy(csEntry.moduleName, STACKWALK_MAX_NAMELEN, Module.ModuleName);
1220 csEntry.baseOfImage = Module.BaseOfImage;
1221 MyStrCpy(csEntry.loadedImageName, STACKWALK_MAX_NAMELEN, Module.LoadedImageName);
1225 this->OnDbgHelpErr(
"SymGetModuleInfo64", GetLastError(), s.AddrPC.Offset);
1229 CallstackEntryType et = nextEntry;
1232 bLastEntryCalled =
false;
1233 this->OnCallstackEntry(et, csEntry);
1235 if (s.AddrReturn.Offset == 0)
1237 bLastEntryCalled =
true;
1238 this->OnCallstackEntry(lastEntry, csEntry);
1239 SetLastError(ERROR_SUCCESS);
1245 if (pSym) free( pSym );
1247 if (bLastEntryCalled ==
false)
1248 this->OnCallstackEntry(lastEntry, csEntry);
1250 if (context == NULL)
1251 ResumeThread(hThread);
1256 BOOL __stdcall StackWalker::myReadProcMem(
1258 DWORD64 qwBaseAddress,
1261 LPDWORD lpNumberOfBytesRead
1264 if (s_readMemoryFunction == NULL)
1267 BOOL bRet = ReadProcessMemory(hProcess, (LPVOID) qwBaseAddress, lpBuffer, nSize, &st);
1268 *lpNumberOfBytesRead = (DWORD) st;
1274 return s_readMemoryFunction(hProcess, qwBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead, s_readMemoryFunction_UserData);
1278 void StackWalker::OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion)
1280 CHAR buffer[STACKWALK_MAX_NAMELEN];
1281 size_t maxLen = STACKWALK_MAX_NAMELEN;
1282 #if _MSC_VER >= 1400 1285 if (fileVersion == 0)
1286 _snprintf_s(buffer, maxLen,
"%s:%s (%p), size: %d (result: %d), SymType: '%s', PDB: '%s'\n", img, mod, (LPVOID)baseAddr, size, result, symType, pdbName);
1289 DWORD v4 = (DWORD) (fileVersion & 0xFFFF);
1290 DWORD v3 = (DWORD) ((fileVersion>>16) & 0xFFFF);
1291 DWORD v2 = (DWORD) ((fileVersion>>32) & 0xFFFF);
1292 DWORD v1 = (DWORD) ((fileVersion>>48) & 0xFFFF);
1293 _snprintf_s(buffer, maxLen,
"%s:%s (%p), size: %d (result: %d), SymType: '%s', PDB: '%s', fileVersion: %d.%d.%d.%d\n", img, mod, (LPVOID) baseAddr, size, result, symType, pdbName, v1, v2, v3, v4);
1295 buffer[STACKWALK_MAX_NAMELEN - 1] = 0;
1299 void StackWalker::OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry)
1301 CHAR buffer[STACKWALK_MAX_NAMELEN];
1302 size_t maxLen = STACKWALK_MAX_NAMELEN;
1303 #if _MSC_VER >= 1400 1306 if ( (eType != lastEntry) && (entry.offset != 0) )
1308 if (entry.name[0] == 0)
1309 MyStrCpy(entry.name, STACKWALK_MAX_NAMELEN,
"(function-name not available)");
1310 if (entry.undName[0] != 0)
1311 MyStrCpy(entry.name, STACKWALK_MAX_NAMELEN, entry.undName);
1312 if (entry.undFullName[0] != 0)
1313 MyStrCpy(entry.name, STACKWALK_MAX_NAMELEN, entry.undFullName);
1314 if (entry.lineFileName[0] == 0)
1316 MyStrCpy(entry.lineFileName, STACKWALK_MAX_NAMELEN,
"(filename not available)");
1317 if (entry.moduleName[0] == 0)
1318 MyStrCpy(entry.moduleName, STACKWALK_MAX_NAMELEN,
"(module-name not available)");
1319 _snprintf_s(buffer, maxLen,
"%p (%s): %s: %s\n", (LPVOID) entry.offset, entry.moduleName, entry.lineFileName, entry.name);
1322 _snprintf_s(buffer, maxLen,
"%s (%d): %s\n", entry.lineFileName, entry.lineNumber, entry.name);
1323 buffer[STACKWALK_MAX_NAMELEN-1] = 0;
1328 void StackWalker::OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr)
1330 CHAR buffer[STACKWALK_MAX_NAMELEN];
1331 size_t maxLen = STACKWALK_MAX_NAMELEN;
1332 #if _MSC_VER >= 1400 1335 _snprintf_s(buffer, maxLen,
"ERROR: %s, GetLastError: %d (Address: %p)\n", szFuncName, gle, (LPVOID) addr);
1336 buffer[STACKWALK_MAX_NAMELEN - 1] = 0;
1340 void StackWalker::OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName)
1342 CHAR buffer[STACKWALK_MAX_NAMELEN];
1343 size_t maxLen = STACKWALK_MAX_NAMELEN;
1344 #if _MSC_VER >= 1400 1347 _snprintf_s(buffer, maxLen,
"SymInit: Symbol-SearchPath: '%s', symOptions: %d, UserName: '%s'\n", szSearchPath, symOptions, szUserName);
1348 buffer[STACKWALK_MAX_NAMELEN - 1] = 0;
1351 #if _MSC_VER <= 1200 1353 ZeroMemory(&ver,
sizeof(OSVERSIONINFOA));
1354 ver.dwOSVersionInfoSize =
sizeof(ver);
1355 if (GetVersionExA(&ver) != FALSE)
1357 _snprintf_s(buffer, maxLen,
"OS-Version: %d.%d.%d (%s)\n",
1358 ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber,
1360 buffer[STACKWALK_MAX_NAMELEN - 1] = 0;
1364 OSVERSIONINFOEXA ver;
1365 ZeroMemory(&ver,
sizeof(OSVERSIONINFOEXA));
1366 ver.dwOSVersionInfoSize =
sizeof(ver);
1367 #if _MSC_VER >= 1900 1368 #pragma warning(push) 1369 #pragma warning(disable: 4996) 1371 if (GetVersionExA( (OSVERSIONINFOA*) &ver) != FALSE)
1373 _snprintf_s(buffer, maxLen,
"OS-Version: %d.%d.%d (%s) 0x%x-0x%x\n",
1374 ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber,
1375 ver.szCSDVersion, ver.wSuiteMask, ver.wProductType);
1376 buffer[STACKWALK_MAX_NAMELEN - 1] = 0;
1379 #if _MSC_VER >= 1900 1380 #pragma warning(pop) 1385 void StackWalker::OnOutput(LPCSTR buffer)
1387 OutputDebugStringA(buffer);