Skyscraper 2.0
uexception.h
Go to the documentation of this file.
1//Skyscraper StackWalker interface for reporting information on unhandled exceptions
2
3// For more info about "PreventSetUnhandledExceptionFilter" see:
4// "SetUnhandledExceptionFilter" and VC8
5// http://blog.kalmbachnet.de/?postid=75
6// and
7// Unhandled exceptions in VC8 and above� for x86 and x64
8// http://blog.kalmbach-software.de/2008/04/02/unhandled-exceptions-in-vc8-and-above-for-x86-and-x64/
9
10#include <windows.h>
11#include "stackwalker.h"
12#include "globals.h"
13#include "sbs.h"
14#include "vm.h"
15#include "skyscraper.h"
16#include "enginecontext.h"
17#include "scriptproc.h"
18#include "hal.h"
19#include "textwindow.h"
20
21namespace Skyscraper {
22
25
27{
28protected:
29 virtual void OnOutput(LPCSTR szText)
30 {
31 twindow->tMain->WriteText(szText);
32 //printf("%s", szText);
33 }
34};
35
36LPTOP_LEVEL_EXCEPTION_FILTER WINAPI
38 LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
39{
40 return NULL;
41}
42
44{
45 HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
46 if (hKernel32 == NULL)
47 return FALSE;
48 void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter");
49 if(pOrgEntry == NULL)
50 return FALSE;
51
52 DWORD dwOldProtect = 0;
53 SIZE_T jmpSize = 5;
54#ifdef _M_X64
55 jmpSize = 13;
56#endif
57 BOOL bProt = VirtualProtect(pOrgEntry, jmpSize, PAGE_EXECUTE_READWRITE, &dwOldProtect);
58 BYTE newJump[20];
59 void *pNewFunc = &MyDummySetUnhandledExceptionFilter;
60#ifdef _M_IX86
61 DWORD dwOrgEntryAddr = (DWORD) pOrgEntry;
62 dwOrgEntryAddr += jmpSize; // add 5 for 5 op-codes for jmp rel32
63 DWORD dwNewEntryAddr = (DWORD) pNewFunc;
64 DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr;
65 // JMP rel32: Jump near, relative, displacement relative to next instruction.
66 newJump[0] = 0xE9; // JMP rel32
67 memcpy(&newJump[1], &dwRelativeAddr, sizeof(pNewFunc));
68#elif _M_X64
69 newJump[0] = 0x49; // MOV R15, ...
70 newJump[1] = 0xBF; // ...
71 memcpy(&newJump[2], &pNewFunc, sizeof(pNewFunc));
72 //pCur += sizeof (ULONG_PTR);
73 newJump[10] = 0x41; // JMP R15, ...
74 newJump[11] = 0xFF; // ...
75 newJump[12] = 0xE7; // ...
76#endif
77 SIZE_T bytesWritten;
78 BOOL bRet = WriteProcessMemory(GetCurrentProcess(), pOrgEntry, newJump, jmpSize, &bytesWritten);
79
80 if (bProt != FALSE)
81 {
82 DWORD dwBuf;
83 VirtualProtect(pOrgEntry, jmpSize, dwOldProtect, &dwBuf);
84 }
85 return bRet;
86}
87
88static TCHAR s_szExceptionLogFileName[_MAX_PATH] = _T("\\exceptions.log"); // default
90static LONG __stdcall CrashHandlerExceptionFilter(EXCEPTION_POINTERS* pExPtrs)
91{
92#ifdef _M_IX86
93 if (pExPtrs->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW)
94 {
95 static char MyStack[1024*128]; // be sure that we have enought space...
96 // it assumes that DS and SS are the same!!! (this is the case for Win32)
97 // change the stack only if the selectors are the same (this is the case for Win32)
98 //__asm push offset MyStack[1024*128];
99 //__asm pop esp;
100 __asm mov eax,offset MyStack[1024*128];
101 __asm mov esp,eax;
102 }
103#endif
104
105 //create text window
106 twindow = new TextWindow(NULL, -1);
107 twindow->SetTitle(wxT("Simulator Crash Report"));
108 twindow->Show(true);
109
110 //stop simulator
111 if (skyscraper)
112 skyscraper->GetVM()->Pause = true;
113
114 //print exception notice
115 CHAR lString[500];
116 sprintf_s(lString,
117 "*** Unhandled Exception\n"
118 " ExpCode: 0x%8.8X\n"
119 " ExpFlags: %d\n"
120 " ExpAddress: 0x%8.8X\n\n",
121 pExPtrs->ExceptionRecord->ExceptionCode,
122 pExPtrs->ExceptionRecord->ExceptionFlags,
123 pExPtrs->ExceptionRecord->ExceptionAddress);
124 twindow->tMain->WriteText(lString);
125
126 //print out stack trace
127 StackWalkerToConsole sw; // output to console
128 sw.ShowCallstack(GetCurrentThread(), pExPtrs->ContextRecord);
129
130 if (skyscraper)
131 {
132 twindow->tMain->WriteText(wxT("\nSimulator State Dump\n--------------------------\n"));
133 twindow->tMain->WriteText(wxString("Platform: " + skyscraper->GetVM()->Platform + "\n"));
134 twindow->tMain->WriteText(wxString("Renderer: " + skyscraper->GetVM()->GetHAL()->Renderer + "\n"));
135 twindow->tMain->WriteText(wxString("Frontend version: " + skyscraper->GetVM()->version_frontend + "\n"));
136
137 //print out simulator state
139 if (context)
140 {
141 //print out engine state
142 twindow->tMain->WriteText(wxString(context->GetSystem()->DumpState()));
143
144 //print out script processor state, if loading
145 if (context->IsLoading() == true && context->IsLoadingFinished() == false)
146 twindow->tMain->WriteText(wxString(context->GetScriptProcessor()->DumpState()));
147 }
148 }
149
150 //print instructions
151 twindow->tMain->WriteText(wxT("\n--------------------------\n"));
152 twindow->tMain->WriteText(wxString("Copy and paste the above information (select it and press CTRL-C)\nand either post it to the Skyscraper forum at http://forum.skyscrapersim.net\nor email to ryan@skyscrapersim.net\n\nPress OK to close Skyscraper\n"));
153 twindow->ShowModal();
154
155 if (twindow)
156 delete twindow;
157 twindow = 0;
158
159 FatalExit(0);
160
161 return EXCEPTION_CONTINUE_SEARCH;
162}
163
165{
166 TCHAR szModName[_MAX_PATH];
167 if (GetModuleFileName(NULL, szModName, sizeof(szModName)/sizeof(TCHAR)) != 0)
168 {
169 _tcscpy_s(s_szExceptionLogFileName, szModName);
170 _tcscat_s(s_szExceptionLogFileName, _T(".exp.log"));
171 }
173 {
174 // set global exception handler (for handling all unhandled exceptions)
175 SetUnhandledExceptionFilter(CrashHandlerExceptionFilter);
178 }
179}
180
182{
183 skyscraper = root;
184}
185
186}
std::string DumpState()
Definition sbs.cpp:2501
ScriptProcessor * GetScriptProcessor()
std::string Renderer
Definition hal.h:88
virtual void OnOutput(LPCSTR szText)
Definition uexception.h:29
HAL * GetHAL()
Definition vm.cpp:128
bool Pause
Definition vm.h:118
std::string version_frontend
Definition vm.h:129
std::string Platform
Definition vm.h:132
EngineContext * GetActiveEngine()
Definition vm.h:81
BOOL ShowCallstack(HANDLE hThread=GetCurrentThread(), const CONTEXT *context=NULL, PReadProcessMemoryRoutine readMemoryFunction=NULL, LPVOID pUserData=NULL)
TextWindow * twindow
Definition uexception.h:23
static LONG __stdcall CrashHandlerExceptionFilter(EXCEPTION_POINTERS *pExPtrs)
Definition uexception.h:90
Skyscraper * skyscraper
Definition uexception.h:24
static BOOL s_bUnhandledExeptionFilterSet
Definition uexception.h:89
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
Definition uexception.h:37
static void UnhandledExceptionSetRoot(Skyscraper *root)
Definition uexception.h:181
BOOL PreventSetUnhandledExceptionFilter()
Definition uexception.h:43
static void InitUnhandledExceptionFilter()
Definition uexception.h:164
static TCHAR s_szExceptionLogFileName[_MAX_PATH]
Definition uexception.h:88
unsigned long SIZE_T
Definition stackwalker.h:47