#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 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 stackName ) { return false; }