📄 stackwalker.cpp
字号:
DWORD PdbAge; // DBI age of pdb
BOOL PdbUnmatched; // loaded an unmatched pdb
BOOL DbgUnmatched; // loaded an unmatched dbg
BOOL LineNumbers; // we have line number information
BOOL GlobalSymbols; // we have internal symbol information
BOOL TypeInfo; // we have type information
// new elements: 17-Dec-2003
BOOL SourceIndexed; // pdb supports source server
BOOL Publics; // contains public symbols
};
*/
typedef struct IMAGEHLP_MODULE64_V2 {
DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64)
DWORD64 BaseOfImage; // base load address of module
DWORD ImageSize; // virtual size of the loaded module
DWORD TimeDateStamp; // date/time stamp from pe header
DWORD CheckSum; // checksum from the pe header
DWORD NumSyms; // number of symbols in the symbol table
SYM_TYPE SymType; // type of symbols loaded
CHAR ModuleName[32]; // module name
CHAR ImageName[256]; // image name
CHAR LoadedImageName[256]; // symbol file name
};
// SymCleanup()
typedef BOOL (__stdcall *tSC)( IN HANDLE hProcess );
tSC pSC;
// SymFunctionTableAccess64()
typedef PVOID (__stdcall *tSFTA)( HANDLE hProcess, DWORD64 AddrBase );
tSFTA pSFTA;
// SymGetLineFromAddr64()
typedef BOOL (__stdcall *tSGLFA)( IN HANDLE hProcess, IN DWORD64 dwAddr,
OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE64 Line );
tSGLFA pSGLFA;
// SymGetModuleBase64()
typedef DWORD64 (__stdcall *tSGMB)( IN HANDLE hProcess, IN DWORD64 dwAddr );
tSGMB pSGMB;
// SymGetModuleInfo64()
typedef BOOL (__stdcall *tSGMI)( IN HANDLE hProcess, IN DWORD64 dwAddr, OUT IMAGEHLP_MODULE64_V2 *ModuleInfo );
tSGMI pSGMI;
// // SymGetModuleInfo64()
// typedef BOOL (__stdcall *tSGMI_V3)( IN HANDLE hProcess, IN DWORD64 dwAddr, OUT IMAGEHLP_MODULE64_V3 *ModuleInfo );
// tSGMI_V3 pSGMI_V3;
// SymGetOptions()
typedef DWORD (__stdcall *tSGO)( VOID );
tSGO pSGO;
// SymGetSymFromAddr64()
typedef BOOL (__stdcall *tSGSFA)( IN HANDLE hProcess, IN DWORD64 dwAddr,
OUT PDWORD64 pdwDisplacement, OUT PIMAGEHLP_SYMBOL64 Symbol );
tSGSFA pSGSFA;
// SymInitialize()
typedef BOOL (__stdcall *tSI)( IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess );
tSI pSI;
// SymLoadModule64()
typedef DWORD64 (__stdcall *tSLM)( IN HANDLE hProcess, IN HANDLE hFile,
IN PSTR ImageName, IN PSTR ModuleName, IN DWORD64 BaseOfDll, IN DWORD SizeOfDll );
tSLM pSLM;
// SymSetOptions()
typedef DWORD (__stdcall *tSSO)( IN DWORD SymOptions );
tSSO pSSO;
// StackWalk64()
typedef BOOL (__stdcall *tSW)(
DWORD MachineType,
HANDLE hProcess,
HANDLE hThread,
LPSTACKFRAME64 StackFrame,
PVOID ContextRecord,
PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress );
tSW pSW;
// UnDecorateSymbolName()
typedef DWORD (__stdcall WINAPI *tUDSN)( PCSTR DecoratedName, PSTR UnDecoratedName,
DWORD UndecoratedLength, DWORD Flags );
tUDSN pUDSN;
typedef BOOL (__stdcall WINAPI *tSGSP)(HANDLE hProcess, PSTR SearchPath, DWORD SearchPathLength);
tSGSP pSGSP;
private:
// **************************************** ToolHelp32 ************************
#define MAX_MODULE_NAME32 255
#define TH32CS_SNAPMODULE 0x00000008
#pragma pack( push, 8 )
typedef struct tagMODULEENTRY32
{
DWORD dwSize;
DWORD th32ModuleID; // This module
DWORD th32ProcessID; // owning process
DWORD GlblcntUsage; // Global usage count on the module
DWORD ProccntUsage; // Module usage count in th32ProcessID's context
BYTE * modBaseAddr; // Base address of module in th32ProcessID's context
DWORD modBaseSize; // Size in bytes of module starting at modBaseAddr
HMODULE hModule; // The hModule of this module in th32ProcessID's context
char szModule[MAX_MODULE_NAME32 + 1];
char szExePath[MAX_PATH];
} MODULEENTRY32;
typedef MODULEENTRY32 * PMODULEENTRY32;
typedef MODULEENTRY32 * LPMODULEENTRY32;
#pragma pack( pop )
BOOL GetModuleListTH32(HANDLE hProcess, DWORD pid)
{
// CreateToolhelp32Snapshot()
typedef HANDLE (__stdcall *tCT32S)(DWORD dwFlags, DWORD th32ProcessID);
// Module32First()
typedef BOOL (__stdcall *tM32F)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
// Module32Next()
typedef BOOL (__stdcall *tM32N)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
// try both dlls...
const TCHAR *dllname[] = { _T("kernel32.dll"), _T("tlhelp32.dll") };
HINSTANCE hToolhelp = NULL;
tCT32S pCT32S = NULL;
tM32F pM32F = NULL;
tM32N pM32N = NULL;
HANDLE hSnap;
MODULEENTRY32 me;
me.dwSize = sizeof(me);
BOOL keepGoing;
size_t i;
for (i = 0; i<(sizeof(dllname) / sizeof(dllname[0])); i++ )
{
hToolhelp = LoadLibrary( dllname[i] );
if (hToolhelp == NULL)
continue;
pCT32S = (tCT32S) GetProcAddress(hToolhelp, "CreateToolhelp32Snapshot");
pM32F = (tM32F) GetProcAddress(hToolhelp, "Module32First");
pM32N = (tM32N) GetProcAddress(hToolhelp, "Module32Next");
if ( (pCT32S != NULL) && (pM32F != NULL) && (pM32N != NULL) )
break; // found the functions!
FreeLibrary(hToolhelp);
hToolhelp = NULL;
}
if (hToolhelp == NULL)
return FALSE;
hSnap = pCT32S( TH32CS_SNAPMODULE, pid );
if (hSnap == (HANDLE) -1)
return FALSE;
keepGoing = !!pM32F( hSnap, &me );
int cnt = 0;
while (keepGoing)
{
this->LoadModule(hProcess, me.szExePath, me.szModule, (DWORD64) me.modBaseAddr, me.modBaseSize);
cnt++;
keepGoing = !!pM32N( hSnap, &me );
}
CloseHandle(hSnap);
FreeLibrary(hToolhelp);
if (cnt <= 0)
return FALSE;
return TRUE;
} // GetModuleListTH32
// **************************************** PSAPI ************************
typedef struct _MODULEINFO {
LPVOID lpBaseOfDll;
DWORD SizeOfImage;
LPVOID EntryPoint;
} MODULEINFO, *LPMODULEINFO;
BOOL GetModuleListPSAPI(HANDLE hProcess)
{
// EnumProcessModules()
typedef BOOL (__stdcall *tEPM)(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded );
// GetModuleFileNameEx()
typedef DWORD (__stdcall *tGMFNE)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize );
// GetModuleBaseName()
typedef DWORD (__stdcall *tGMBN)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize );
// GetModuleInformation()
typedef BOOL (__stdcall *tGMI)(HANDLE hProcess, HMODULE hModule, LPMODULEINFO pmi, DWORD nSize );
HINSTANCE hPsapi;
tEPM pEPM;
tGMFNE pGMFNE;
tGMBN pGMBN;
tGMI pGMI;
DWORD i;
//ModuleEntry e;
DWORD cbNeeded;
MODULEINFO mi;
HMODULE *hMods = 0;
char *tt = NULL;
char *tt2 = NULL;
const SIZE_T TTBUFLEN = 8096;
int cnt = 0;
hPsapi = LoadLibrary( _T("psapi.dll") );
if (hPsapi == NULL)
return FALSE;
pEPM = (tEPM) GetProcAddress( hPsapi, "EnumProcessModules" );
pGMFNE = (tGMFNE) GetProcAddress( hPsapi, "GetModuleFileNameExA" );
pGMBN = (tGMFNE) GetProcAddress( hPsapi, "GetModuleBaseNameA" );
pGMI = (tGMI) GetProcAddress( hPsapi, "GetModuleInformation" );
if ( (pEPM == NULL) || (pGMFNE == NULL) || (pGMBN == NULL) || (pGMI == NULL) )
{
// we couldn磘 find all functions
FreeLibrary(hPsapi);
return FALSE;
}
hMods = (HMODULE*) malloc(sizeof(HMODULE) * (TTBUFLEN / sizeof HMODULE));
tt = (char*) malloc(sizeof(char) * TTBUFLEN);
tt2 = (char*) malloc(sizeof(char) * TTBUFLEN);
if ( (hMods == NULL) || (tt == NULL) || (tt2 == NULL) )
goto cleanup;
if ( ! pEPM( hProcess, hMods, TTBUFLEN, &cbNeeded ) )
{
//_ftprintf(fLogFile, _T("%lu: EPM failed, GetLastError = %lu\n"), g_dwShowCount, gle );
goto cleanup;
}
if ( cbNeeded > TTBUFLEN )
{
//_ftprintf(fLogFile, _T("%lu: More than %lu module handles. Huh?\n"), g_dwShowCount, lenof( hMods ) );
goto cleanup;
}
for ( i = 0; i < cbNeeded / sizeof hMods[0]; i++ )
{
// base address, size
pGMI(hProcess, hMods[i], &mi, sizeof mi );
// image file name
tt[0] = 0;
pGMFNE(hProcess, hMods[i], tt, TTBUFLEN );
// module name
tt2[0] = 0;
pGMBN(hProcess, hMods[i], tt2, TTBUFLEN );
DWORD dwRes = this->LoadModule(hProcess, tt, tt2, (DWORD64) mi.lpBaseOfDll, mi.SizeOfImage);
if (dwRes != ERROR_SUCCESS)
this->m_parent->OnDbgHelpErr("LoadModule", dwRes, 0);
cnt++;
}
cleanup:
if (hPsapi != NULL)
FreeLibrary(hPsapi);
if (tt2 != NULL)
free(tt2);
if (tt != NULL)
free(tt);
if (hMods != NULL)
free(hMods);
return cnt != 0;
} // GetModuleListPSAPI
DWORD LoadModule(HANDLE hProcess, LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size)
{
CHAR *szImg = _strdup(img);
CHAR *szMod = _strdup(mod);
DWORD result = ERROR_SUCCESS;
if ( (szImg == NULL) || (szMod == NULL) )
result = ERROR_NOT_ENOUGH_MEMORY;
else
{
if (pSLM(hProcess, 0, szImg, szMod, baseAddr, size) == 0)
result = GetLastError();
}
ULONGLONG fileVersion = 0;
if ( (m_parent != NULL) && (szImg != NULL) )
{
// try to retrive the file-version:
if ( (this->m_parent->m_options & StackWalker::RetrieveFileVersion) != 0)
{
VS_FIXEDFILEINFO *fInfo = NULL;
DWORD dwHandle;
DWORD dwSize = GetFileVersionInfoSizeA(szImg, &dwHandle);
if (dwSize > 0)
{
LPVOID vData = malloc(dwSize);
if (vData != NULL)
{
if (GetFileVersionInfoA(szImg, dwHandle, dwSize, vData) != 0)
{
UINT len;
TCHAR szSubBlock[] = _T("\\");
if (VerQueryValue(vData, szSubBlock, (LPVOID*) &fInfo, &len) == 0)
fInfo = NULL;
else
{
fileVersion = ((ULONGLONG)fInfo->dwFileVersionLS) + ((ULONGLONG)fInfo->dwFileVersionMS << 32);
}
}
free(vData);
}
}
}
// Retrive some additional-infos about the module
IMAGEHLP_MODULE64_V2 Module;
const char *szSymType = "-unknown-";
if (this->GetModuleInfo(hProcess, baseAddr, &Module) != FALSE)
{
switch(Module.SymType)
{
case SymNone:
szSymType = "-nosymbols-";
break;
case SymCoff:
szSymType = "COFF";
break;
case SymCv:
szSymType = "CV";
break;
case SymPdb:
szSymType = "PDB";
break;
case SymExport:
szSymType = "-exported-";
break;
case SymDeferred:
szSymType = "-deferred-";
break;
case SymSym:
szSymType = "SYM";
break;
case SymVirtual:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -