⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 crash_reporter_win32.cpp

📁 这是一款2d游戏引擎
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		if ( stackframe.AddrPC.Offset == 0 )
		{
			_snprintf(stringBuffer, 1024, "(-nosymbols- PC == 0)\r\n" );
			WriteFile(hFile, stringBuffer, strlen(stringBuffer), &bytesWritten, 0);
		}
		else
		{
			// we seem to have a valid PC

			// show procedure info (SymGetSymFromAddr())
			if ( ! ptrSymGetSymFromAddr( hProcess, stackframe.AddrPC.Offset, &offsetFromSymbol, pSym ) )
			{
				if ( GetLastError() != 487 )
				{
					_snprintf(stringBuffer, 1024, "SymGetSymFromAddr(): gle = %lu\r\n", GetLastError() );
					WriteFile(hFile, stringBuffer, strlen(stringBuffer), &bytesWritten, 0);
				}
			}
			else
			{
				// UnDecorateSymbolName()
				ptrUnDecorateSymbolName( pSym->Name, undName, MAXNAMELEN, UNDNAME_NAME_ONLY );
				ptrUnDecorateSymbolName( pSym->Name, undFullName, MAXNAMELEN, UNDNAME_COMPLETE );
				_snprintf(stringBuffer, 1024, "%s", undName );
				WriteFile(hFile, stringBuffer, strlen(stringBuffer), &bytesWritten, 0);
				if ( offsetFromSymbol != 0 )
				{
					_snprintf(stringBuffer, 1024, " %+ld bytes", (long) offsetFromSymbol );
					WriteFile(hFile, stringBuffer, strlen(stringBuffer), &bytesWritten, 0);
				}
				WriteFile(hFile, "\r\n", 2, &bytesWritten, 0 );
				_snprintf(stringBuffer, 1024, "    Sig:  %s\r\n", pSym->Name );
				WriteFile(hFile, stringBuffer, strlen(stringBuffer), &bytesWritten, 0);
				_snprintf(stringBuffer, 1024, "    Decl: %s\r\n", undFullName );
				WriteFile(hFile, stringBuffer, strlen(stringBuffer), &bytesWritten, 0);
			}

			// show line number info, NT5.0-method (SymGetLineFromAddr())
			if ( ptrSymGetLineFromAddr != 0 )
			{ // yes, we have SymGetLineFromAddr()
				if ( ! ptrSymGetLineFromAddr( hProcess, stackframe.AddrPC.Offset, &offsetFromSymbol, &Line ) )
				{
					if ( GetLastError() != 487 )
					{
						_snprintf(stringBuffer, 1024, "SymGetLineFromAddr(): gle = %lu\r\n", GetLastError() );
						WriteFile(hFile, stringBuffer, strlen(stringBuffer), &bytesWritten, 0);
					}
				}
				else
				{
					_snprintf(stringBuffer, 1024, "    Line: %s(%lu) %+ld bytes\r\n",
						Line.FileName, Line.LineNumber, offsetFromSymbol );
					WriteFile(hFile, stringBuffer, strlen(stringBuffer), &bytesWritten, 0);
				}
			}

			// show module info (SymGetModuleInfo())
			if ( ! ptrSymGetModuleInfo( hProcess, stackframe.AddrPC.Offset, &Module ) )
			{
				_snprintf(stringBuffer, 1024, "SymGetModuleInfo): gle = %lu\r\n", GetLastError() );
				WriteFile(hFile, stringBuffer, strlen(stringBuffer), &bytesWritten, 0);
			}
			else
			{ // got module info OK
				char ty[80];
				switch ( Module.SymType )
				{
				case SymNone:
					strcpy( ty, "-nosymbols-" );
					break;
				case SymCoff:
					strcpy( ty, "COFF" );
					break;
				case SymCv:
					strcpy( ty, "CV" );
					break;
				case SymPdb:
					strcpy( ty, "PDB" );
					break;
				case SymExport:
					strcpy( ty, "-exported-" );
					break;
				case SymDeferred:
					strcpy( ty, "-deferred-" );
					break;
				case SymSym:
					strcpy( ty, "SYM" );
					break;
				default:
					_snprintf( ty, sizeof ty, "symtype=%ld", (long) Module.SymType );
					break;
				}

				_snprintf(stringBuffer, 1024, "    Mod:  %s[%s], base: %08lxh\r\n",
					Module.ModuleName, Module.ImageName, Module.BaseOfImage );
				WriteFile(hFile, stringBuffer, strlen(stringBuffer), &bytesWritten, 0);
				_snprintf(stringBuffer, 1024, "    Sym:  type: %s, file: %s\r\n",
					ty, Module.LoadedImageName );
				WriteFile(hFile, stringBuffer, strlen(stringBuffer), &bytesWritten, 0);
			}
		}

		// no return address means no deeper stackframe
		if ( stackframe.AddrReturn.Offset == 0 ) break;

		frameNum++;
	}

	_snprintf(stringBuffer, 1024, "-- End stack trace --\r\n");
	WriteFile(hFile, stringBuffer, strlen(stringBuffer), &bytesWritten, 0);

	CloseHandle(hFile);

	ptrSymCleanup(hProcess);

	// todo: signal CL_CrashReporter::sig_crash here
/*
	hFile = CreateFile(
		fileName,
		GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);

	int pos = 0;
	DWORD bytesRead;
	ReadFile(hFile, stringBuffer, 1024, &bytesRead, 0);
	stringBuffer[bytesRead] = 0;
	while (bytesRead > 0)
	{
		char *ptrNewline = strstr(stringBuffer, "\r\n");
		if (ptrNewline)
		{
			ptrNewline[0] = 0;
			CL_Log::log("debug", stringBuffer);
			pos += ptrNewline-stringBuffer+2;
			SetFilePointer(hFile, pos, 0, FILE_BEGIN);
		}

		ReadFile(hFile, stringBuffer, 1024, &bytesRead, 0);
		stringBuffer[bytesRead] = 0;
	}

	CloseHandle(hFile);
*/

	return 0;
}

void CL_CrashReporter_Win32::enumAndLoadModuleSymbols( HANDLE hProcess, DWORD pid )
{
	ModuleList modules;
	ModuleListIter it;
	char *img, *mod;

	// fill in module list
	fillModuleList( modules, pid, hProcess );

	for ( it = modules.begin(); it != modules.end(); ++ it )
	{
		// unfortunately, SymLoadModule() wants writeable strings
		img = new char[(*it).imageName.size() + 1];
		strcpy( img, (*it).imageName.c_str() );
		mod = new char[(*it).moduleName.size() + 1];
		strcpy( mod, (*it).moduleName.c_str() );

		ptrSymLoadModule( hProcess, 0, img, mod, (*it).baseAddress, (*it).size );
/*		if ( ptrSymLoadModule( hProcess, 0, img, mod, (*it).baseAddress, (*it).size ) == 0 )
			printf( "Error %lu loading symbols for \"%s\"\n",
				GetLastError(), (*it).moduleName.c_str() );
		else
			printf( "Symbols loaded: \"%s\"\n", (*it).moduleName.c_str() );
*/
		delete [] img;
		delete [] mod;
	}
}



bool CL_CrashReporter_Win32::fillModuleList( ModuleList& modules, DWORD pid, HANDLE hProcess )
{
	// try toolhelp32 first
	if ( fillModuleListTH32( modules, pid ) )
		return true;
	// nope? try psapi, then
	return fillModuleListPSAPI( modules, pid, hProcess );
}



// miscellaneous toolhelp32 declarations; we cannot #include the header
// because not all systems may have it
#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 CL_CrashReporter_Win32::fillModuleListTH32( ModuleList& modules, 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 );

	// I think the DLL is called tlhelp32.dll on Win9X, so we try both
	const char *dllname[] = { "kernel32.dll", "tlhelp32.dll" };
	HINSTANCE hToolhelp;
	tCT32S pCT32S;
	tM32F pM32F;
	tM32N pM32N;

	HANDLE hSnap;
	MODULEENTRY32 me = { sizeof me };
	bool keepGoing;
	ModuleEntry e;
	int i;

	#define lenof(a) (sizeof(a) / sizeof((a)[0]))
	for ( i = 0; i < lenof( dllname ); ++ i )
	{
		hToolhelp = LoadLibraryA( dllname[i] );
		if ( hToolhelp == 0 )
			continue;
		pCT32S = (tCT32S) GetProcAddress( hToolhelp, "CreateToolhelp32Snapshot" );
		pM32F = (tM32F) GetProcAddress( hToolhelp, "Module32First" );
		pM32N = (tM32N) GetProcAddress( hToolhelp, "Module32Next" );
		if ( pCT32S != 0 && pM32F != 0 && pM32N != 0 )
			break; // found the functions!
		FreeLibrary( hToolhelp );
		hToolhelp = 0;
	}

	if ( hToolhelp == 0 ) // nothing found?
		return false;

	hSnap = pCT32S( TH32CS_SNAPMODULE, pid );
	if ( hSnap == (HANDLE) -1 )
		return false;

	keepGoing = !!pM32F( hSnap, &me );
	while ( keepGoing )
	{
		// here, we have a filled-in MODULEENTRY32
//		printf( "%08lXh %6lu %-15.15s %s\n", me.modBaseAddr, me.modBaseSize, me.szModule, me.szExePath );
		e.imageName = me.szExePath;
		e.moduleName = me.szModule;
		e.baseAddress = (DWORD) me.modBaseAddr;
		e.size = me.modBaseSize;
		modules.push_back( e );
		keepGoing = !!pM32N( hSnap, &me );
	}

	CloseHandle( hSnap );

	FreeLibrary( hToolhelp );

	return modules.size() != 0;
}



// miscellaneous psapi declarations; we cannot #include the header
// because not all systems may have it
typedef struct _MODULEINFO {
    LPVOID lpBaseOfDll;
    DWORD SizeOfImage;
    LPVOID EntryPoint;
} MODULEINFO, *LPMODULEINFO;



bool CL_CrashReporter_Win32::fillModuleListPSAPI( ModuleList& modules, DWORD pid, 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() -- redundant, as GMFNE() has the same prototype, but who cares?
	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;

	int i;
	ModuleEntry e;
	DWORD cbNeeded;
	MODULEINFO mi;
	HMODULE *hMods = 0;
	char *tt = 0;

	hPsapi = LoadLibrary( "psapi.dll" );
	if ( hPsapi == 0 )
		return false;

	modules.clear();

	pEPM = (tEPM) GetProcAddress( hPsapi, "EnumProcessModules" );
	pGMFNE = (tGMFNE) GetProcAddress( hPsapi, "GetModuleFileNameExA" );
	pGMBN = (tGMFNE) GetProcAddress( hPsapi, "GetModuleBaseNameA" );
	pGMI = (tGMI) GetProcAddress( hPsapi, "GetModuleInformation" );
	if ( pEPM == 0 || pGMFNE == 0 || pGMBN == 0 || pGMI == 0 )
	{
		// yuck. Some API is missing.
		FreeLibrary( hPsapi );
		return false;
	}

	hMods = new HMODULE[TTBUFLEN / sizeof HMODULE];
	tt = new char[TTBUFLEN];
	// not that this is a sample. Which means I can get away with
	// not checking for errors, but you cannot. :)

	if ( ! pEPM( hProcess, hMods, TTBUFLEN, &cbNeeded ) )
	{
//		printf( "EPM failed, gle = %lu\n", GetLastError() );
		goto cleanup;
	}

	if ( cbNeeded > TTBUFLEN )
	{
//		printf( "More than %lu module handles. Huh?\n", lenof( hMods ) );
		goto cleanup;
	}

	for ( i = 0; i < cbNeeded / sizeof hMods[0]; ++ i )
	{
		// for each module, get:
		// base address, size
		pGMI( hProcess, hMods[i], &mi, sizeof mi );
		e.baseAddress = (DWORD) mi.lpBaseOfDll;
		e.size = mi.SizeOfImage;
		// image file name
		tt[0] = '\0';
		pGMFNE( hProcess, hMods[i], tt, TTBUFLEN );
		e.imageName = tt;
		// module name
		tt[0] = '\0';
		pGMBN( hProcess, hMods[i], tt, TTBUFLEN );
		e.moduleName = tt;
//		printf( "%08lXh %6lu %-15.15s %s\n", e.baseAddress,
//			e.size, e.moduleName.c_str(), e.imageName.c_str() );

		modules.push_back( e );
	}

cleanup:
	if ( hPsapi )
		FreeLibrary( hPsapi );
	delete [] tt;
	delete [] hMods;

	return modules.size() != 0;
}

HINSTANCE CL_CrashReporter_Win32::moduleImagehlp = 0;

HINSTANCE CL_CrashReporter_Win32::moduleDbghlp = 0;

CL_CrashReporter_Win32::TypeSymCleanup CL_CrashReporter_Win32::ptrSymCleanup = 0;

CL_CrashReporter_Win32::TypeSymFunctionTableAccess CL_CrashReporter_Win32::ptrSymFunctionTableAccess = 0;

CL_CrashReporter_Win32::TypeSymGetLineFromAddr CL_CrashReporter_Win32::ptrSymGetLineFromAddr = 0;

CL_CrashReporter_Win32::TypeSymGetModuleBase CL_CrashReporter_Win32::ptrSymGetModuleBase = 0;

CL_CrashReporter_Win32::TypeSymGetModuleInfo CL_CrashReporter_Win32::ptrSymGetModuleInfo = 0;

CL_CrashReporter_Win32::TypeSymGetOptions CL_CrashReporter_Win32::ptrSymGetOptions = 0;

CL_CrashReporter_Win32::TypeSymGetSymFromAddr CL_CrashReporter_Win32::ptrSymGetSymFromAddr = 0;

CL_CrashReporter_Win32::TypeSymInitialize CL_CrashReporter_Win32::ptrSymInitialize = 0;

CL_CrashReporter_Win32::TypeSymLoadModule CL_CrashReporter_Win32::ptrSymLoadModule = 0;

CL_CrashReporter_Win32::TypeSymSetOptions CL_CrashReporter_Win32::ptrSymSetOptions = 0;

CL_CrashReporter_Win32::TypeStackWalk CL_CrashReporter_Win32::ptrStackWalk = 0;

CL_CrashReporter_Win32::TypeUnDecorateSymbolName CL_CrashReporter_Win32::ptrUnDecorateSymbolName = 0;

CL_CrashReporter_Win32::TypeMiniDumpWriteDump CL_CrashReporter_Win32::ptrMiniDumpWriteDump = 0;

_se_translator_function CL_CrashReporter_Win32::ptrOldFilter = 0;

std::string CL_CrashReporter_Win32::userSearchPath;

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -