- Improved gameloop unhandled exception handler to retrieve the line and source file (if PDB is available) and display in the fault screen instead of the location of the fault handler (by tazpn)

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5166 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Wanne
2012-04-06 08:39:16 +00:00
parent bfe4a7b08e
commit 3c1940a260
2 changed files with 237 additions and 10 deletions
+222 -5
View File
@@ -1166,6 +1166,7 @@ static void ERLogStackWalk(HWFILE fdump, EXCEPTION_POINTERS* pExPtrs)
#define TRAP_EDITED(f) f.Reserved[1]
#define SAVE_TRAP(f) f.Reserved[2]
CONTEXT Context;
DWORD dwDisplacement = 0;
char *szSymName;
IMAGEHLP_MODULE mi;
@@ -1173,6 +1174,8 @@ static void ERLogStackWalk(HWFILE fdump, EXCEPTION_POINTERS* pExPtrs)
DWORD i;
HANDLE hProc = (HANDLE)GetCurrentProcess();
memcpy( &Context, pExPtrs->ContextRecord, sizeof( CONTEXT ) );
if (!ERLoadImageHlpDLL())
return;
@@ -1187,22 +1190,22 @@ static void ERLogStackWalk(HWFILE fdump, EXCEPTION_POINTERS* pExPtrs)
ZeroMemory( &stFrame, sizeof(stFrame) );
stFrame.AddrPC.Offset = pExPtrs->ContextRecord->Eip ;
stFrame.AddrPC.Offset = Context.Eip ;
stFrame.AddrPC.Mode = AddrModeFlat ;
stFrame.AddrStack.Offset = pExPtrs->ContextRecord->Esp ;
stFrame.AddrStack.Offset = Context.Esp ;
stFrame.AddrStack.Mode = AddrModeFlat ;
stFrame.AddrFrame.Offset = pExPtrs->ContextRecord->Ebp ;
stFrame.AddrFrame.Offset = Context.Ebp ;
stFrame.AddrFrame.Mode = AddrModeFlat ;
ErrorLog(fdump, "FramePtr ReturnAd Param#1 Param#2 Param#3 Param#4 Function Name\r\n");
for (i=0; i<100; i++)
for (i=0; i<15; i++)
{
if (!ERStackWalk( IMAGE_FILE_MACHINE_I386,
hProc,
GetCurrentThread(),
&stFrame,
pExPtrs->ContextRecord,
&Context,
NULL,
ERSymFunctionTableAccess,
ERSymGetModuleBase,
@@ -1226,6 +1229,8 @@ static void ERLogStackWalk(HWFILE fdump, EXCEPTION_POINTERS* pExPtrs)
stFrame.Params[3]
);
memset(&mi, 0, sizeof(mi));
mi.SizeOfStruct = sizeof(mi);
if (ERSymGetModuleInfo(hProc, stFrame.AddrPC.Offset, &mi )) {
ErrorLog(fdump, "%s!", mi.ModuleName );
}
@@ -1288,6 +1293,218 @@ static void ERLogStackWalk(HWFILE fdump, EXCEPTION_POINTERS* pExPtrs)
}
#endif //_IMAGEHLP_
//************************************
// Method: ERLogStackWalk
// FullName: ERLogStackWalk
// Access: public static
// Returns: LPCSTR (Free with LocalFree)
// Qualifier:
// Parameter: EXCEPTION_POINTERS * pExPtrs
//************************************
LPCSTR ERStackWalk(EXCEPTION_POINTERS* pExPtrs)
{
#if defined(_IMAGEHLP_) && defined(_X86_)
CONTEXT Context;
DWORD dwDisplacement = 0;
char *szSymName;
IMAGEHLP_MODULE mi;
STACKFRAME stFrame;
DWORD i;
HANDLE hProc = (HANDLE)GetCurrentProcess();
if (!ERLoadImageHlpDLL())
return NULL;
std::stringstream ss;
HMODULE hModule = GetModuleHandle(NULL);
memcpy( &Context, pExPtrs->ContextRecord, sizeof( CONTEXT ) );
ERSymInitialize(hProc, NULL, TRUE);
memset(g_sym, 0, MAX_SYMNAME_SIZE + sizeof(IMAGEHLP_SYMBOL) ) ;
g_sym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
g_sym->MaxNameLength = MAX_SYMNAME_SIZE;
ZeroMemory( &stFrame, sizeof(stFrame) );
stFrame.AddrPC.Offset = Context.Eip ;
stFrame.AddrPC.Mode = AddrModeFlat ;
stFrame.AddrStack.Offset = Context.Esp ;
stFrame.AddrStack.Mode = AddrModeFlat ;
stFrame.AddrFrame.Offset = Context.Ebp ;
stFrame.AddrFrame.Mode = AddrModeFlat ;
for (i=0; i<100; i++)
{
if (!ERStackWalk( IMAGE_FILE_MACHINE_I386,
hProc,
GetCurrentThread(),
&stFrame,
&Context,
NULL,
ERSymFunctionTableAccess,
ERSymGetModuleBase,
NULL))
{
break;
}
if (ERSymGetSymFromAddr(hProc, stFrame.AddrPC.Offset, &dwDisplacement, g_sym)) {
szSymName = g_sym->Name;
}
else {
szSymName = "<nosymbols>";
}
memset(&mi, 0, sizeof(mi));
mi.SizeOfStruct = sizeof(mi);
if (ERSymGetModuleInfo(hProc, stFrame.AddrPC.Offset, &mi )) {
if (mi.BaseOfImage != (DWORD)hModule)
{
ss << mi.ModuleName << "!";
}
}
ss << szSymName << " ";
ER_IMAGEHLP_LINE64 lineInfo;
ZeroMemory( &lineInfo, sizeof(lineInfo) );
lineInfo.SizeOfStruct = sizeof(lineInfo);
dwDisplacement = 0;
if ( ERSymGetLineFromAddr(hProc, stFrame.AddrPC.Offset, &dwDisplacement, &lineInfo) )
{
LPSTR pFileName = strrchr(lineInfo.FileName, '\\');
if (pFileName) ++pFileName;
if (!pFileName) pFileName = lineInfo.FileName;
ss << " \t" << pFileName << ":" << lineInfo.LineNumber << " ";
}
ss << std::endl;
}
ss << std::endl;
ERSymCleanup(hProc);
std::string str = ss.str();
LPSTR lpResult = (LPSTR)LocalAlloc(LPTR, str.length()+1);
strcpy(lpResult, str.c_str());
return lpResult;
#else
return NULL;
#endif //_IMAGEHLP_
}
//************************************
// Method: ERGetFirstModuleException
// FullName: ERGetFirstModuleException
// Access: public
// Returns: BOOL
// Qualifier:
// Parameter: EXCEPTION_POINTERS * pExPtrs
// Parameter: HMODULE hModule
// Parameter: LPSTR funcName
// Parameter: INT funcNameLen
// Parameter: LPSTR sourceName
// Parameter: INT sourceNameLen
// Parameter: INT * lpLineNum
//************************************
BOOL ERGetFirstModuleException(
EXCEPTION_POINTERS* pExPtrs
, HMODULE hModule
, LPSTR funcName, INT funcNameLen
, LPSTR sourceName, INT sourceNameLen
, INT *lpLineNum
)
{
#if defined(_IMAGEHLP_) && defined(_X86_)
CONTEXT Context;
DWORD dwDisplacement = 0;
char *szSymName;
IMAGEHLP_MODULE mi;
STACKFRAME stFrame;
DWORD i;
HANDLE hProc = (HANDLE)GetCurrentProcess();
BOOL bFound = FALSE;
if (!ERLoadImageHlpDLL())
return FALSE;
memcpy( &Context, pExPtrs->ContextRecord, sizeof( CONTEXT ) );
if (hModule == NULL)
hModule = GetModuleHandle(NULL);
ERSymInitialize(hProc, NULL, TRUE);
memset(g_sym, 0, MAX_SYMNAME_SIZE + sizeof(IMAGEHLP_SYMBOL) ) ;
g_sym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
g_sym->MaxNameLength = MAX_SYMNAME_SIZE;
ZeroMemory( &stFrame, sizeof(stFrame) );
stFrame.AddrPC.Offset = Context.Eip ;
stFrame.AddrPC.Mode = AddrModeFlat ;
stFrame.AddrStack.Offset = Context.Esp ;
stFrame.AddrStack.Mode = AddrModeFlat ;
stFrame.AddrFrame.Offset = Context.Ebp ;
stFrame.AddrFrame.Mode = AddrModeFlat ;
for (i=0; i<15; i++)
{
if (!ERStackWalk( IMAGE_FILE_MACHINE_I386,
hProc,
GetCurrentThread(),
&stFrame,
&Context,
NULL,
ERSymFunctionTableAccess,
ERSymGetModuleBase,
NULL))
{
break;
}
if (ERSymGetSymFromAddr(hProc, stFrame.AddrPC.Offset, &dwDisplacement, g_sym)) {
szSymName = g_sym->Name;
}
else {
szSymName = "<nosymbols>";
}
memset(&mi, 0, sizeof(mi));
mi.SizeOfStruct = sizeof(mi);
if (!ERSymGetModuleInfo(hProc, stFrame.AddrPC.Offset, &mi ))
continue;
if (mi.BaseOfImage != (DWORD)hModule)
continue;
ER_IMAGEHLP_LINE64 lineInfo;
ZeroMemory( &lineInfo, sizeof(lineInfo) );
lineInfo.SizeOfStruct = sizeof(lineInfo);
dwDisplacement = 0;
if ( ERSymGetLineFromAddr(hProc, stFrame.AddrPC.Offset, &dwDisplacement, &lineInfo) )
{
LPSTR pFileName = strrchr(lineInfo.FileName, '\\');
if (pFileName) ++pFileName;
if (!pFileName) pFileName = lineInfo.FileName;
if (funcName) lstrcpyn(funcName,szSymName, funcNameLen);
if (sourceName) lstrcpyn(sourceName,pFileName, sourceNameLen);
if (lpLineNum) *lpLineNum = lineInfo.LineNumber;
bFound = TRUE;
break;
}
}
ERSymCleanup(hProc);
return bFound;
#else
return FALSE;
#endif //_IMAGEHLP_
}
void ERLogModules(HWFILE fdump)
{
#ifdef _USE_PSAPI_
+15 -5
View File
@@ -1862,15 +1862,25 @@ static void PopulateSectionFromCommandLine(vfs::PropertyContainer &oProps, vfs::
static LONG __stdcall SGPExceptionFilter(int exceptionCount, EXCEPTION_POINTERS* pExceptInfo)
{
#ifdef ENABLE_EXCEPTION_HANDLING
extern BOOL ERGetFirstModuleException(EXCEPTION_POINTERS*, HMODULE, LPSTR, INT, LPSTR, INT, INT *);
extern STR GetExceptionString( DWORD uiExceptionCode );
CHAR funcName[64], sourceName[MAX_PATH];
INT lineNum = 0;
if (exceptionCount >= 1)
{
// the exception handler writer can fail with exceptions too
__try
{
bool showAssert = true;
__try{
// the exception handler writer can fail with exceptions too
RecordExceptionInfo(pExceptInfo);
LPCSTR exceptMsg = GetExceptionString(pExceptInfo->ExceptionRecord->ExceptionCode);
if ( ERGetFirstModuleException(pExceptInfo, NULL, funcName, _countof(funcName), sourceName, _countof(sourceName), &lineNum ) )
{
_FailMessage(exceptMsg, lineNum, funcName, sourceName);
showAssert = false;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {}
AssertMsg(FALSE, "Unhanded exception processing GameLoop unable to recover.");
if (showAssert) AssertMsg(FALSE, "Unhanded exception processing GameLoop unable to recover.");
}
#endif