|
@@ -478,97 +478,97 @@ char *CrashLogWindows::AppendDecodedStac
|
|
|
return ret;
|
|
|
}
|
|
|
#endif /* _MSC_VER */
|
|
|
|
|
|
extern bool CloseConsoleLogIfActive();
|
|
|
static void ShowCrashlogWindow();
|
|
|
|
|
|
/**
|
|
|
* Stack pointer for use when 'starting' the crash handler.
|
|
|
* Not static as gcc's inline assembly needs it that way.
|
|
|
*/
|
|
|
void *_safe_esp = NULL;
|
|
|
|
|
|
static LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep)
|
|
|
{
|
|
|
if (CrashLogWindows::current != NULL) {
|
|
|
CrashLog::AfterCrashLogCleanup();
|
|
|
ExitProcess(2);
|
|
|
}
|
|
|
|
|
|
if (GamelogTestEmergency()) {
|
|
|
static const TCHAR _emergency_crash[] =
|
|
|
_T("A serious fault condition occurred in the game. The game will shut down.\n")
|
|
|
_T("As you loaded an emergency savegame no crash information will be generated.\n");
|
|
|
MessageBox(NULL, _emergency_crash, _T("Fatal Application Failure"), MB_ICONERROR);
|
|
|
ExitProcess(3);
|
|
|
}
|
|
|
|
|
|
if (SaveloadCrashWithMissingNewGRFs()) {
|
|
|
static const TCHAR _saveload_crash[] =
|
|
|
_T("A serious fault condition occurred in the game. The game will shut down.\n")
|
|
|
_T("As you loaded an savegame for which you do not have the required NewGRFs\n")
|
|
|
_T("no crash information will be generated.\n");
|
|
|
MessageBox(NULL, _saveload_crash, _T("Fatal Application Failure"), MB_ICONERROR);
|
|
|
ExitProcess(3);
|
|
|
}
|
|
|
|
|
|
CrashLogWindows *log = new CrashLogWindows(ep);
|
|
|
CrashLogWindows::current = log;
|
|
|
char *buf = log->FillCrashLog(log->crashlog, lastof(log->crashlog));
|
|
|
log->WriteCrashDump(log->crashdump_filename, lastof(log->crashdump_filename));
|
|
|
log->AppendDecodedStacktrace(buf, lastof(log->crashlog));
|
|
|
log->WriteCrashLog(log->crashlog, log->crashlog_filename, lastof(log->crashlog_filename));
|
|
|
log->WriteScreenshot(log->screenshot_filename, lastof(log->screenshot_filename));
|
|
|
|
|
|
/* Close any possible log files */
|
|
|
CloseConsoleLogIfActive();
|
|
|
|
|
|
if ((_video_driver == NULL || _video_driver->HasGUI()) && _safe_esp != NULL) {
|
|
|
if ((VideoDriver::GetInstance() == NULL || VideoDriver::GetInstance()->HasGUI()) && _safe_esp != NULL) {
|
|
|
#ifdef _M_AMD64
|
|
|
ep->ContextRecord->Rip = (DWORD64)ShowCrashlogWindow;
|
|
|
ep->ContextRecord->Rsp = (DWORD64)_safe_esp;
|
|
|
#else
|
|
|
ep->ContextRecord->Eip = (DWORD)ShowCrashlogWindow;
|
|
|
ep->ContextRecord->Esp = (DWORD)_safe_esp;
|
|
|
#endif
|
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
|
}
|
|
|
|
|
|
CrashLog::AfterCrashLogCleanup();
|
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
|
}
|
|
|
|
|
|
static void CDECL CustomAbort(int signal)
|
|
|
{
|
|
|
RaiseException(0xE1212012, 0, 0, NULL);
|
|
|
}
|
|
|
|
|
|
/* static */ void CrashLog::InitialiseCrashLog()
|
|
|
{
|
|
|
#ifdef _M_AMD64
|
|
|
CONTEXT ctx;
|
|
|
RtlCaptureContext(&ctx);
|
|
|
|
|
|
/* The stack pointer for AMD64 must always be 16-byte aligned inside a
|
|
|
* function. As we are simulating a function call with the safe ESP value,
|
|
|
* we need to subtract 8 for the imaginary return address otherwise stack
|
|
|
* alignment would be wrong in the called function. */
|
|
|
_safe_esp = (void *)(ctx.Rsp - 8);
|
|
|
#else
|
|
|
#if defined(_MSC_VER)
|
|
|
_asm {
|
|
|
mov _safe_esp, esp
|
|
|
}
|
|
|
#else
|
|
|
asm("movl %esp, __safe_esp");
|
|
|
#endif
|
|
|
#endif
|
|
|
|
|
|
/* SIGABRT is not an unhandled exception, so we need to intercept it. */
|
|
|
signal(SIGABRT, CustomAbort);
|
|
|
#if defined(_MSC_VER)
|
|
|
/* Don't show abort message as we will get the crashlog window anyway. */
|
|
|
_set_abort_behavior(0, _WRITE_ABORT_MSG);
|
|
|
#endif
|
|
|
SetUnhandledExceptionFilter(ExceptionHandler);
|
|
|
}
|