373 lines
10 KiB
C++
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;
|
|
} |