Files
Sun1602/Tools/CrashInfomationReport/CrashReport/PDBProcess.cpp
T
2022-10-26 12:25:11 +08:00

373 lines
10 KiB
C++

#include "StdAfx.h"
#include "PDBProcess.h"
#define MakePtr( cast , ptr , AddValue ) (cast)( (DWORD_PTR)(ptr)+(DWORD_PTR)(AddValue))
CPDBProcess::CPDBProcess(void) :
dwLoadAddress_(0),
dwCharacteristics_(0),
FullFileName_(L"")
{
memset( &ImageModuleInfo_, 0, sizeof( IMAGEHLP_MODULE ) );;
memset( &LoadImageFile_, 0, sizeof( LOADED_IMAGE ) );
memset( &pdbprocess_File_Name_,0,sizeof(char)*256);
}
CPDBProcess::~CPDBProcess(void)
{
}
bool CPDBProcess::LoadFile( const TCHAR* SymbolName )
{
// CString FileFormatChange;
// FileFormatChange.Format(L"%s",SymbolName);
//
// CString ExeFileName;
// FileFormatChange = FileFormatChange.MakeReverse();
//
// int Len = FileFormatChange.Find('\\');
// int TotalLen = FileFormatChange.GetLength();
// int DeleteLen = TotalLen - Len; //얼만큼 글자를 뽑을것인가?
//
// //경로 재 설정.
// FileFormatChange = FileFormatChange.MakeReverse();
// FileFormatChange = FileFormatChange.Left(DeleteLen-1);
//
// FileFormatChange = FileFormatChange.MakeReverse();
// Len = FileFormatChange.Find('\\');
// TotalLen = FileFormatChange.GetLength();
// DeleteLen = TotalLen - Len; //얼만큼 글자를 뽑을것인가?
// FileFormatChange = FileFormatChange.MakeReverse();
// FileFormatChange = FileFormatChange.Left(DeleteLen);
//
// //현재 실행파일이 존재 하는 경로 조합
// FullFileName_ = FileFormatChange += L"client\\GameClient.exe";
if(!LoadImageFile(SymbolName))
return false;
CHAR szTemp[MAX_PATH];
WideCharToMultiByte ( CP_ACP, 0, SymbolName, -1, szTemp, MAX_PATH, NULL, NULL );
strcpy(pdbprocess_File_Name_,szTemp);
DWORD64 bRet = SymLoadModule64(HandlePdb_, NULL, szTemp, NULL, dwLoadAddress_, 0 );
IMAGEHLP_MODULE64 cModInfo;
memset( &cModInfo, 0, sizeof( IMAGEHLP_MODULE64 ) );
cModInfo.SizeOfStruct = sizeof( IMAGEHLP_MODULE64 );
DWORD dwError = GetLastError();
BOOL bResult = ::SymGetModuleInfo64(HandlePdb_, (DWORD64)bRet, &cModInfo );
dwError = GetLastError();
if( SymNone == cModInfo.SymType )
{
return false;
}
ImageModuleInfo_ = cModInfo;
CMapStringToPtr mapModule;
if( !GetModules( SymbolName, mapModule ) )
return FALSE;
mapModule.RemoveKey( SymbolName );
std::vector<CString> teststring;
CString strDllName;
LPVOID pPtr;
POSITION mlPos = mapModule.GetStartPosition();
while( mlPos )
{
mapModule.GetNextAssoc( mlPos, strDllName, pPtr );
if(!LoadImageFile(strDllName))
continue;
WideCharToMultiByte ( CP_ACP, 0, strDllName, -1, szTemp, MAX_PATH, NULL, NULL );
strcpy(pdbprocess_File_Name_,szTemp);
DWORD64 bRet = SymLoadModule64(HandlePdb_, NULL, szTemp, NULL, dwLoadAddress_, 0 );
IMAGEHLP_MODULE64 cModInfo;
memset( &cModInfo, 0, sizeof( IMAGEHLP_MODULE64 ) );
cModInfo.SizeOfStruct = sizeof( IMAGEHLP_MODULE64 );
DWORD dwError = GetLastError();
BOOL bResult = ::SymGetModuleInfo64(HandlePdb_, bRet, &cModInfo );
dwError = GetLastError();
if( SymNone == cModInfo.SymType )
{
continue;
}
}
WideCharToMultiByte ( CP_ACP, 0, SymbolName, -1, szTemp, MAX_PATH, NULL, NULL );
strcpy(pdbprocess_File_Name_,szTemp);
return true;
}
void CPDBProcess::Clean()
{
// UnMapAndLoad ( &LoadImageFile_ ) ;
}
const int nSymbolSize = 1024;
bool CPDBProcess::OnSearch( DWORD ExceptionAddr , sExceptionInfomation& ExceptionInfo )
{
int nSymbolMax = sizeof ( IMAGEHLP_SYMBOL ) + nSymbolSize;
IMAGEHLP_SYMBOL* pImageSymbol = (IMAGEHLP_SYMBOL*)new BYTE[ nSymbolMax ];
memset( pImageSymbol, NULL, nSymbolMax );
pImageSymbol->SizeOfStruct = nSymbolMax;
pImageSymbol->MaxNameLength = nSymbolSize;
IMAGEHLP_LINE cImageLine;
DWORD64 dwFnDispl = 0;
DWORD dwSrcDispl = 0;
CString strModule;
int iRes = AddressInfo( ExceptionAddr, strModule, *pImageSymbol, dwFnDispl, cImageLine, dwSrcDispl,ExceptionInfo );
return true;
}
bool CPDBProcess::OnSearch( const char* ExceptionAddr,sExceptionInfomation& ExceptionInfo )
{
DWORD dwordExceptionAddr = GetHexValue(ExceptionAddr);
return OnSearch(dwordExceptionAddr,ExceptionInfo);
}
void CPDBProcess::OnInitation()
{
srand ( (unsigned)time ( NULL ) ) ;
HandlePdb_ = (HANDLE)1;
#pragma warning ( disable : 4312 )
BOOL bRet = SymInitialize ( HandlePdb_, NULL, FALSE );
#pragma warning ( default : 4312 )
DWORD dwOpts = SymGetOptions ( ) ;
SymSetOptions ( dwOpts | SYMOPT_DEBUG | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST );
return;
}
bool CPDBProcess::LoadImageFile( const TCHAR* ImageFile )
{
LOADED_IMAGE File_Image;
CHAR szTemp[MAX_PATH];
WideCharToMultiByte ( CP_ACP, 0, ImageFile, -1, szTemp, MAX_PATH, NULL, NULL );
if ( ( FALSE == MapAndLoad ( szTemp, NULL, &File_Image, TRUE, TRUE ) ) ||
( IMAGE_NT_SIGNATURE != File_Image.FileHeader->Signature ) )
{
return true;
}
LoadImageFile_ = File_Image;
dwLoadAddress_ = LoadImageFile_.FileHeader->OptionalHeader.ImageBase ;
dwCharacteristics_ = LoadImageFile_.Characteristics ;
return true;
}
int CPDBProcess::AddressInfo( DWORD dwAddress, CString& strModule, IMAGEHLP_SYMBOL& cImageSymbol,
DWORD dwFnDispl, IMAGEHLP_LINE& cImageLine, DWORD dwSrcDispl,sExceptionInfomation& ExceptionInfo )
{
BOOL bSymFound = TRUE ;
BOOL bLineFound = TRUE ;
DWORD64 test;
DWORD test2;
BYTE arrSymBuffer[1024];
ZeroMemory(arrSymBuffer, sizeof(arrSymBuffer));
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)arrSymBuffer;
pSymbol->SizeOfStruct = sizeof(*pSymbol);
pSymbol->MaxNameLen = sizeof(arrSymBuffer) - sizeof(*pSymbol) + 1;
BOOL bRet = SymFromAddr ( HandlePdb_, (DWORD64)dwAddress,
&test ,pSymbol );
int info = GetLastError();
IMAGEHLP_LINE64 il;
ZeroMemory(&il, sizeof(il));
il.SizeOfStruct = sizeof(il);
bRet = SymGetLineFromAddr64(HandlePdb_, (DWORD64)dwAddress, &test2, &il);
info = GetLastError();
MultiByteToWideChar(CP_ACP,MB_COMPOSITE,il.FileName,-1,ExceptionInfo.ExceptionFileName,256);
MultiByteToWideChar(CP_ACP,MB_COMPOSITE,pSymbol->Name,-1,ExceptionInfo.ExceptionFuntionName,256);
ExceptionInfo.FileSourceLine = il.LineNumber;
return bRet;
}
BOOL CPDBProcess::GetModules( LPCTSTR pModuleName, CMapStringToPtr& ModuleList )
{
CString strName ( pModuleName ) ;
strName.MakeUpper() ;
ModuleList[strName] = NULL ;
HINSTANCE hModule = LoadLibraryEx ( pModuleName, NULL, DONT_RESOLVE_DLL_REFERENCES );
if ( !hModule )
{
return ( FALSE ) ;
}
PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER)hModule ;
if ( IsBadReadPtr ( pDOSHeader, sizeof ( IMAGE_DOS_HEADER ) ) || IMAGE_DOS_SIGNATURE != pDOSHeader->e_magic )
{
FreeLibrary ( hModule ) ;
SetLastErrorEx ( ERROR_INVALID_PARAMETER , SLE_ERROR ) ;
return ( FALSE ) ;
}
PIMAGE_NT_HEADERS pNTHeader = MakePtr ( PIMAGE_NT_HEADERS, pDOSHeader, pDOSHeader->e_lfanew ) ;
if ( IsBadReadPtr ( pNTHeader, sizeof ( IMAGE_NT_HEADERS ) ) || IMAGE_NT_SIGNATURE != pNTHeader->Signature )
{
FreeLibrary ( hModule ) ;
SetLastErrorEx ( ERROR_INVALID_PARAMETER , SLE_ERROR ) ;
return ( FALSE ) ;
}
DWORD dwVirtualAddr = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = MakePtr ( PIMAGE_IMPORT_DESCRIPTOR, pDOSHeader, dwVirtualAddr );
if ( !pImportDesc )
{
FreeLibrary ( hModule ) ;
return ( FALSE ) ;
}
BuildSearchPathString ( ) ;
LPVOID pPtr;
while ( pImportDesc->Name )
{
PSTR pModName = MakePtr ( PSTR, pDOSHeader, pImportDesc->Name );
if(IsBadReadPtr(pModName,sizeof(PSTR)))
{
return true;
}
WCHAR szTemp[MAX_PATH];
MultiByteToWideChar ( CP_THREAD_ACP, 0, pModName, -1, szTemp, MAX_PATH );
CString szModName = szTemp;
if ( SearchForModule ( szModName ) )
{
szModName.MakeUpper ( ) ;
if ( !ModuleList.Lookup ( szModName , pPtr ) )
{
ModuleList[szModName] = NULL ;
if ( !GetModules ( szModName , ModuleList) )
{
FreeLibrary ( hModule ) ;
return FALSE;
}
}
}
pImportDesc++;
}
FreeLibrary ( hModule ) ;
return TRUE;
}
BOOL CPDBProcess::SearchForModule( CString& fullpath )
{
CString strName ;
CString szExt ;
int i = fullpath.Find ( _T ( '.' ) ) ;
if ( -1 != i )
{
strName = fullpath.Left ( i ) ;
szExt = fullpath.Mid ( i ) ;
}
else
{
strName = fullpath ;
szExt = _T ( '.' ) ;
}
TCHAR szBuff [ MAX_PATH + 1 ];
LPTSTR pFilePart ;
DWORD len = SearchPath ( m_szSearchPath, strName, szExt, MAX_PATH, szBuff, &pFilePart );
if ( ( len > 0 ) && ( len < MAX_PATH ) )
{
fullpath = szBuff ;
return ( TRUE ) ;
}
else
{
fullpath = strName + szExt ;
return ( FALSE ) ;
}
}
void CPDBProcess::BuildSearchPathString( void )
{
TCHAR szCurrPath[ MAX_PATH ] ;
_tcscpy ( szCurrPath , FullFileName_.GetBuffer() ) ;
TCHAR * pSlash = _tcsrchr ( szCurrPath , _T ( '\\' ) ) ;
if ( NULL != pSlash )
{
*pSlash = _T ( '\0' ) ;
}
m_szSearchPath += szCurrPath ;
m_szSearchPath += _T ( ";" ) ;
// Add the current working directory.
_tgetcwd ( szCurrPath , MAX_PATH ) ;
m_szSearchPath += szCurrPath ;
m_szSearchPath += _T ( ";" ) ;
// Add %SYSTEMROOT%\System32.
GetSystemDirectory ( szCurrPath , MAX_PATH ) ;
m_szSearchPath += szCurrPath ;
m_szSearchPath += _T ( ";" ) ;
// Add %SYSTEMROOT%\System
GetWindowsDirectory ( szCurrPath , MAX_PATH ) ;
_tcscat ( szCurrPath , _T ( "SYSTEM" ) ) ;
m_szSearchPath += szCurrPath ;
m_szSearchPath += _T ( ";" ) ;
// Add %SYSTEMROOT%
GetWindowsDirectory ( szCurrPath , MAX_PATH ) ;
m_szSearchPath += szCurrPath ;
m_szSearchPath += _T ( ";" ) ;
// Finally, get the real PATH.
CString cTemp ;
cTemp.GetEnvironmentVariable ( _T ( "PATH" ) ) ;
m_szSearchPath += cTemp ;
}
bool CPDBProcess::StackWalker( void* DumpProcess,std::vector<CString> stackName )
{
return false;
}