📄 crash_reporter_win32.cpp
字号:
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 + -