annotate foosdk/sdk/foobar2000/shared/crash_info.cpp @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
1 #include "shared.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2 #include <imagehlp.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3 #include <forward_list>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5 #if SIZE_MAX == UINT32_MAX
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6 #define STACKSPEC "%08X"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7 #define PTRSPEC "%08Xh"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8 #define OFFSETSPEC "%Xh"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 #elif SIZE_MAX == UINT64_MAX
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10 #define STACKSPEC "%016llX"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11 #define PTRSPEC "%016llXh"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12 #define OFFSETSPEC "%llXh"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13 #else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 #error WTF?
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18 static volatile bool g_didSuppress = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 static critical_section g_panicHandlersSync;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 static std::forward_list<fb2k::panicHandler*> g_panicHandlers;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
21
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
22 static void callPanicHandlers() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23 insync(g_panicHandlersSync);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 for( auto i = g_panicHandlers.begin(); i != g_panicHandlers.end(); ++ i ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25 try {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26 (*i)->onPanic();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27 } catch(...) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31 void SHARED_EXPORT uAddPanicHandler(fb2k::panicHandler* p) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32 insync(g_panicHandlersSync);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 g_panicHandlers.push_front(p);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
35
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
36 void SHARED_EXPORT uRemovePanicHandler(fb2k::panicHandler* p) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
37 insync(g_panicHandlersSync);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38 g_panicHandlers.remove(p);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
40
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
41
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 enum { EXCEPTION_BUG_CHECK = 0xaa67913c };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44 #if FB2K_SUPPORT_CRASH_LOGS
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46 static const unsigned char utf8_header[3] = {0xEF,0xBB,0xBF};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
47
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
48 static __declspec(thread) char g_thread_call_stack[1024];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
49 static __declspec(thread) t_size g_thread_call_stack_length;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
50
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
51 static critical_section g_lastEventsSync;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
52 static pfc::chain_list_v2_t<pfc::string8> g_lastEvents;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53 static constexpr t_size KLastEventCount = 200;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
55 static pfc::string8 version_string;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
56
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
57 static pfc::array_t<TCHAR> DumpPathBuffer;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
59 static long crash_no = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
60
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61 // Debug timer: GetTickCount() diff since app startup.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62 // Intentionally kept as dumb as possible (originally meant to format system time nicely).
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63 // Do not want to do expensive preformat of every event that in >99% of scenarios isn't logged.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
64 // Cannot do formatting & system calls in crash handler.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
65 // So we just write amount of MS since app startup.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
66 static const uint64_t debugTimerInit = GetTickCount64();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67 static pfc::format_int_t queryDebugTimer() { return pfc::format_int( GetTickCount64() - debugTimerInit ); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
68
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
69 static pfc::string8 g_components;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
70
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
71 static void WriteFileString_internal(HANDLE hFile,const char * ptr,t_size len)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
72 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73 DWORD bah;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74 WriteFile(hFile,ptr,(DWORD)len,&bah,0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77 static HANDLE create_failure_log()
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
78 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
79 bool rv = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
80 if (DumpPathBuffer.get_size() == 0) return INVALID_HANDLE_VALUE;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
81
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
82 TCHAR * path = DumpPathBuffer.get_ptr();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
83
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
84 t_size lenWalk = _tcslen(path);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
85
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
86 if (lenWalk == 0 || path[lenWalk-1] != '\\') {path[lenWalk++] = '\\';}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
87
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
88 _tcscpy(path + lenWalk, _T("crash reports"));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
89 lenWalk += _tcslen(path + lenWalk);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
90
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
91 SetLastError(NO_ERROR);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
92 if (!CreateDirectory(path, NULL)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
93 if (GetLastError() != ERROR_ALREADY_EXISTS) return INVALID_HANDLE_VALUE;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
94 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
95 path[lenWalk++] = '\\';
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
96
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
97 TCHAR * fn_out = path + lenWalk;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
98 HANDLE hFile = INVALID_HANDLE_VALUE;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
99 unsigned attempts = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
100 for(;;) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
101 wsprintf(fn_out,TEXT("failure_%08u.txt"),++attempts);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
102 hFile = CreateFile(path,GENERIC_WRITE,0,0,CREATE_NEW,0,0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
103 if (hFile!=INVALID_HANDLE_VALUE) break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
104 if (attempts > 1000) break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
105 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
106 if (hFile!=INVALID_HANDLE_VALUE) WriteFileString_internal(hFile, (const char*)utf8_header, sizeof(utf8_header));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
107 return hFile;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
108 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
109
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
110
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
111 static void WriteFileString(HANDLE hFile,const char * str)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
112 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
113 const char * ptr = str;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
114 for(;;)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
115 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
116 const char * start = ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
117 ptr = strchr(ptr,'\n');
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
118 if (ptr)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
119 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
120 if (ptr>start) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
121 t_size len = ptr-start;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
122 if (ptr[-1] == '\r') --len;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
123 WriteFileString_internal(hFile,start,len);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
124 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
125 WriteFileString_internal(hFile,"\r\n",2);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
126 ptr++;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
127 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
128 else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
129 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
130 WriteFileString_internal(hFile,start,strlen(start));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
131 break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
132 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
133 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
134 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
135
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
136 static void WriteEvent(HANDLE hFile,const char * str) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
137 bool haveText = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
138 const char * ptr = str;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
139 bool isLineBreak = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
140 while(*ptr) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
141 const char * base = ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
142 while(*ptr && *ptr != '\r' && *ptr != '\n') ++ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
143 if (ptr > base) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
144 if (isLineBreak) WriteFileString_internal(hFile,"\r\n",2);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
145 WriteFileString_internal(hFile,base,ptr-base);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
146 isLineBreak = false; haveText = true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
147 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
148 for(;;) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
149 if (*ptr == '\n') isLineBreak = haveText;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
150 else if (*ptr != '\r') break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
151 ++ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
152 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
153 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
154 if (haveText) WriteFileString_internal(hFile,"\r\n",2);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
155 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
156
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
157 static bool read_int(t_size src, t_size* out)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
158 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
159 __try
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
160 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
161 *out = *(t_size*)src;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
162 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
163 } __except (1) { return false; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
164 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
165
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
166 static bool hexdump8(char * out,size_t address,const char * msg,int from,int to)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
167 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
168 unsigned max = (to-from)*16;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
169 if (IsBadReadPtr((const void*)(address+(from*16)),max)) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
170 out += sprintf(out,"\n%s (" PTRSPEC "):",msg,address);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
171 unsigned n;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
172 const unsigned char * src = (const unsigned char*)(address)+(from*16);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
173
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
174 for(n=0;n<max;n++)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
175 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
176 if (n%16==0)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
177 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
178 out += sprintf(out,"\n" PTRSPEC ": ",(size_t)src);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
179 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
180
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
181 out += sprintf(out," %02X",*(src++));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
182 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
183 *(out++) = '\n';
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
184 *out=0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
185 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
186 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
187
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
188 static bool hexdump_stack(char * out,size_t address,const char * msg,int from,int to)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
189 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
190 constexpr unsigned lineWords = 4;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
191 constexpr unsigned wordBytes = sizeof(size_t);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
192 constexpr unsigned lineBytes = lineWords * wordBytes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
193 const unsigned max = (to-from)*lineBytes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
194 if (IsBadReadPtr((const void*)(address+(from*lineBytes)),max)) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
195 out += sprintf(out,"\n%s (" PTRSPEC "):",msg,address);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
196 unsigned n;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
197 const unsigned char * src = (const unsigned char*)(address)+(from*16);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
198
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
199 for(n=0;n<max;n+=4)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
200 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
201 if (n % lineBytes == 0)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
202 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
203 out += sprintf(out,"\n" PTRSPEC ": ",(size_t)src);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
204 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
205
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
206 out += sprintf(out," " STACKSPEC,*(size_t*)src);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
207 src += wordBytes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
208 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
209 *(out++) = '\n';
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
210 *out=0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
211 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
212 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
213
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
214 static void call_stack_parse(size_t address,HANDLE hFile,char * temp,HANDLE hProcess)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
215 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
216 bool inited = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
217 t_size data;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
218 t_size count_done = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
219 while(count_done<1024 && read_int(address, &data))
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
220 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
221 if (!IsBadCodePtr((FARPROC)data))
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
222 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
223 bool found = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
224 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
225 IMAGEHLP_MODULE mod = {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
226 mod.SizeOfStruct = sizeof(mod);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
227 if (SymGetModuleInfo(hProcess,data,&mod))
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
228 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
229 if (!inited)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
230 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
231 WriteFileString(hFile,"\nStack dump analysis:\n");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
232 inited = true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
233 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
234 sprintf(temp, "Address: " PTRSPEC " (%s+" OFFSETSPEC ")", data, mod.ModuleName, data - mod.BaseOfImage);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
235 //sprintf(temp,"Address: %08Xh, location: \"%s\", loaded at %08Xh - %08Xh\n",data,mod.ModuleName,mod.BaseOfImage,mod.BaseOfImage+mod.ImageSize);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
236 WriteFileString(hFile,temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
237 found = true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
238 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
239 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
240
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
241
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
242 if (found)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
243 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
244 union
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
245 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
246 char buffer[128];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
247 IMAGEHLP_SYMBOL symbol;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
248 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
249 memset(buffer,0,sizeof(buffer));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
250 symbol.SizeOfStruct = sizeof(symbol);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
251 symbol.MaxNameLength = (DWORD)(buffer + sizeof(buffer) - symbol.Name);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
252 DWORD_PTR offset = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
253 if (SymGetSymFromAddr(hProcess,data,&offset,&symbol))
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
254 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
255 buffer[PFC_TABSIZE(buffer)-1]=0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
256 if (symbol.Name[0])
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
257 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
258 sprintf(temp,", symbol: \"%s\" (+" OFFSETSPEC ")",symbol.Name,offset);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
259 WriteFileString(hFile,temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
260 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
261 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
262 WriteFileString(hFile, "\n");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
263 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
264 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
265 address += sizeof(size_t);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
266 count_done++;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
267 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
268 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
269
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
270 static BOOL CALLBACK EnumModulesCallback(PCSTR ModuleName,ULONG_PTR BaseOfDll,PVOID UserContext)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
271 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
272 IMAGEHLP_MODULE mod = {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
273 mod.SizeOfStruct = sizeof(mod);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
274 if (SymGetModuleInfo(GetCurrentProcess(),BaseOfDll,&mod))
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
275 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
276 char temp[1024];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
277 char temp2[PFC_TABSIZE(mod.ModuleName)+1];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
278 strcpy(temp2,mod.ModuleName);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
279
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
280 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
281 t_size ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
282 for(ptr=strlen(temp2);ptr<PFC_TABSIZE(temp2)-1;ptr++)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
283 temp2[ptr]=' ';
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
284 temp2[ptr]=0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
285 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
286
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
287 sprintf(temp,"%s loaded at " PTRSPEC " - " PTRSPEC "\n",temp2,mod.BaseOfImage,mod.BaseOfImage+mod.ImageSize);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
288 WriteFileString((HANDLE)UserContext,temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
289 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
290 return TRUE;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
291 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
292
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
293 static bool SalvageString(t_size rptr, char* temp) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
294 __try {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
295 const char* ptr = reinterpret_cast<const char*>(rptr);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
296 t_size walk = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
297 for (; walk < 255; ++walk) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
298 char c = ptr[walk];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
299 if (c == 0) break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
300 if (c < 0x20) c = ' ';
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
301 temp[walk] = c;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
302 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
303 temp[walk] = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
304 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
305 } __except (1) { return false; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
306 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
307
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
308 static void DumpCPPExceptionData(HANDLE hFile, const ULONG_PTR* params, char* temp) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
309 t_size strPtr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
310 if (read_int(params[1] + sizeof(void*), &strPtr)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
311 if (SalvageString(strPtr, temp)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
312 WriteFileString(hFile, "Message: ");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
313 WriteFileString(hFile, temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
314 WriteFileString(hFile, "\n");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
315 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
316 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
317 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
318
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
319 static void writeFailureTxt(LPEXCEPTION_POINTERS param, HANDLE hFile, DWORD lastError) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
320 char temp[2048];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
321 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
322 t_size address = (t_size)param->ExceptionRecord->ExceptionAddress;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
323 sprintf(temp, "Illegal operation:\nCode: %08Xh, flags: %08Xh, address: " PTRSPEC "\n", param->ExceptionRecord->ExceptionCode, param->ExceptionRecord->ExceptionFlags, address);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
324 WriteFileString(hFile, temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
325
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
326 if (param->ExceptionRecord->ExceptionCode == EXCEPTION_BUG_CHECK) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
327 WriteFileString(hFile, "Bug check\n");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
328 } else if (param->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && param->ExceptionRecord->NumberParameters >= 2) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
329 sprintf(temp, "Access violation, operation: %s, address: " PTRSPEC "\n", param->ExceptionRecord->ExceptionInformation[0] ? "write" : "read", param->ExceptionRecord->ExceptionInformation[1]);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
330 WriteFileString(hFile, temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
331 } else if (param->ExceptionRecord->NumberParameters > 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
332 WriteFileString(hFile, "Additional parameters:");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
333 for (DWORD walk = 0; walk < param->ExceptionRecord->NumberParameters; ++walk) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
334 sprintf(temp, " " PTRSPEC, param->ExceptionRecord->ExceptionInformation[walk]);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
335 WriteFileString(hFile, temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
336 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
337 WriteFileString(hFile, "\n");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
338 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
339
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
340 if (param->ExceptionRecord->ExceptionCode == 0xE06D7363 && param->ExceptionRecord->NumberParameters >= 3) { //C++ exception
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
341 DumpCPPExceptionData(hFile, param->ExceptionRecord->ExceptionInformation, temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
342 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
343
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
344 if (lastError) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
345 sprintf(temp, "Last win32 error: %u\n", lastError);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
346 WriteFileString(hFile, temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
347 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
348
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
349 if (g_thread_call_stack[0] != 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
350 WriteFileString(hFile, "\nCall path:\n");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
351 WriteFileString(hFile, g_thread_call_stack);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
352 WriteFileString(hFile, "\n");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
353 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
354 WriteFileString(hFile, "\nCall path not available.\n");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
355 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
356
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
357
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
358 if (hexdump8(temp, address, "Code bytes", -4, +4)) WriteFileString(hFile, temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
359 #ifdef _M_IX86
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
360 if (hexdump_stack(temp, param->ContextRecord->Esp, "Stack", -2, +18)) WriteFileString(hFile, temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
361 sprintf(temp, "\nRegisters:\nEAX: %08X, EBX: %08X, ECX: %08X, EDX: %08X\nESI: %08X, EDI: %08X, EBP: %08X, ESP: %08X\n", param->ContextRecord->Eax, param->ContextRecord->Ebx, param->ContextRecord->Ecx, param->ContextRecord->Edx, param->ContextRecord->Esi, param->ContextRecord->Edi, param->ContextRecord->Ebp, param->ContextRecord->Esp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
362 WriteFileString(hFile, temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
363 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
364
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
365 #ifdef _M_X64
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
366 if (hexdump_stack(temp, param->ContextRecord->Rsp, "Stack", -2, +18)) WriteFileString(hFile, temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
367 sprintf(temp, "\nRegisters:\nRAX: %016llX, RBX: %016llX, RCX: %016llX, RDX: %016llX\nRSI: %016llX, RDI: %016llX, RBP: %016llX, RSP: %016llX\n", param->ContextRecord->Rax, param->ContextRecord->Rbx, param->ContextRecord->Rcx, param->ContextRecord->Rdx, param->ContextRecord->Rsi, param->ContextRecord->Rdi, param->ContextRecord->Rbp, param->ContextRecord->Rsp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
368 WriteFileString(hFile, temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
369 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
370
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
371 #ifdef _M_ARM64
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
372 if (hexdump_stack(temp, param->ContextRecord->Sp, "Stack", -2, +18)) WriteFileString(hFile, temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
373 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
374
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
375 WriteFileString(hFile, "\nTimestamp:\n");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
376 WriteFileString(hFile, queryDebugTimer() );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
377 WriteFileString(hFile, "ms\n");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
378
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
379 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
380 const HANDLE hProcess = GetCurrentProcess();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
381 if (SymInitialize(hProcess, NULL, TRUE))
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
382 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
383 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
384 IMAGEHLP_MODULE mod = {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
385 mod.SizeOfStruct = sizeof(mod);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
386 if (!IsBadCodePtr((FARPROC)address) && SymGetModuleInfo(hProcess, address, &mod))
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
387 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
388 sprintf(temp, "\nCrash location:\nModule: %s\nOffset: " OFFSETSPEC "\n", mod.ModuleName, address - mod.BaseOfImage);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
389 WriteFileString(hFile, temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
390 } else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
391 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
392 sprintf(temp, "\nUnable to identify crash location!\n");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
393 WriteFileString(hFile, temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
394 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
395 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
396
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
397 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
398 union
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
399 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
400 char buffer[128];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
401 IMAGEHLP_SYMBOL symbol;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
402 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
403 memset(buffer, 0, sizeof(buffer));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
404 symbol.SizeOfStruct = sizeof(symbol);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
405 symbol.MaxNameLength = (DWORD)(buffer + sizeof(buffer) - symbol.Name);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
406 DWORD_PTR offset = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
407 if (SymGetSymFromAddr(hProcess, address, &offset, &symbol))
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
408 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
409 buffer[PFC_TABSIZE(buffer) - 1] = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
410 if (symbol.Name[0])
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
411 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
412 sprintf(temp, "Symbol: \"%s\" (+" OFFSETSPEC ")\n", symbol.Name, offset);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
413 WriteFileString(hFile, temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
414 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
415 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
416 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
417
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
418 WriteFileString(hFile, "\nLoaded modules:\n");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
419 SymEnumerateModules(hProcess, EnumModulesCallback, hFile);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
420
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
421 #ifdef _M_IX86
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
422 call_stack_parse(param->ContextRecord->Esp, hFile, temp, hProcess);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
423 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
424
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
425 #ifdef _M_X64
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
426 call_stack_parse(param->ContextRecord->Rsp, hFile, temp, hProcess);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
427 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
428
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
429 SymCleanup(hProcess);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
430 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
431 WriteFileString(hFile, "\nFailed to get module/symbol info.\n");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
432 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
433 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
434
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
435 WriteFileString(hFile, "\nEnvironment:\n");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
436 WriteFileString(hFile, version_string);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
437
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
438 WriteFileString(hFile, "\n");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
439
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
440 if (!g_components.is_empty()) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
441 WriteFileString(hFile, "\nComponents:\n");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
442 WriteFileString(hFile, g_components);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
443 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
444
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
445 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
446 insync(g_lastEventsSync);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
447 if (g_lastEvents.get_count() > 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
448 WriteFileString(hFile, "\nRecent events:\n");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
449 for( auto & walk : g_lastEvents) WriteEvent(hFile, walk);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
450 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
451 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
452 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
453 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
454
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
455 static bool GrabOSVersion(char * out) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
456 OSVERSIONINFO ver = {}; ver.dwOSVersionInfoSize = sizeof(ver);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
457 if (!GetVersionEx(&ver)) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
458 *out = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
459 char temp[16];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
460 strcat(out,"Windows ");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
461 _itoa(ver.dwMajorVersion,temp,10); strcat(out,temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
462 strcat(out,".");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
463 _itoa(ver.dwMinorVersion,temp,10); strcat(out,temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
464 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
465 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
466
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
467 static void OnLogFileWritten() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
468 TCHAR exePath[MAX_PATH + 1] = {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
469 TCHAR params[1024];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
470 GetModuleFileName(NULL, exePath, MAX_PATH);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
471 exePath[MAX_PATH] = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
472 //unsafe...
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
473 wsprintf(params, _T("/crashed \"%s\""), DumpPathBuffer.get_ptr());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
474 ShellExecute(NULL, NULL, exePath, params, NULL, SW_SHOW);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
475 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
476
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
477 BOOL WriteMiniDumpHelper(HANDLE, LPEXCEPTION_POINTERS); //minidump.cpp
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
478
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
479
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
480 void SHARED_EXPORT uDumpCrashInfo(LPEXCEPTION_POINTERS param)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
481 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
482 if (g_didSuppress) return;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
483 const DWORD lastError = GetLastError();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
484 if (InterlockedIncrement(&crash_no) > 1) {Sleep(10000);return;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
485 HANDLE hFile = create_failure_log();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
486 if (hFile == INVALID_HANDLE_VALUE) return;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
487
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
488 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
489 _tcscpy(_tcsrchr(DumpPathBuffer.get_ptr(), '.'), _T(".dmp"));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
490 HANDLE hDump = CreateFile(DumpPathBuffer.get_ptr(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
491 if (hDump != INVALID_HANDLE_VALUE) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
492 const BOOL written = WriteMiniDumpHelper(hDump, param);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
493 CloseHandle(hDump);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
494 if (!written) { //don't bother proceeding if we don't have a valid minidump
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
495 DeleteFile(DumpPathBuffer.get_ptr());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
496 CloseHandle(hFile);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
497 _tcscpy(_tcsrchr(DumpPathBuffer.get_ptr(), '.'), _T(".txt"));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
498 DeleteFile(DumpPathBuffer.get_ptr());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
499 return;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
500 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
501 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
502 _tcscpy(_tcsrchr(DumpPathBuffer.get_ptr(), '.'), _T(".txt"));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
503 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
504
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
505 writeFailureTxt(param, hFile, lastError);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
506
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
507 CloseHandle(hFile);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
508
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
509 OnLogFileWritten();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
510 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
511
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
512 //No longer used.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
513 size_t SHARED_EXPORT uPrintCrashInfo(LPEXCEPTION_POINTERS param,const char * extra_info,char * outbase) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
514 *outbase = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
515 return 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
516 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
517
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
518
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
519 LONG SHARED_EXPORT uExceptFilterProc(LPEXCEPTION_POINTERS param) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
520 if (g_didSuppress) return UnhandledExceptionFilter(param);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
521 callPanicHandlers();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
522 if (IsDebuggerPresent()) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
523 return UnhandledExceptionFilter(param);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
524 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
525 if ( param->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
526 pfc::thread2 trd;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
527 trd.startHere( [param] {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
528 uDumpCrashInfo(param);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
529 } );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
530 trd.waitTillDone();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
531 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
532 uDumpCrashInfo(param);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
533 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
534 TerminateProcess(GetCurrentProcess(), 0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
535 return 0;// never reached
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
536 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
537 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
538
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
539 void SHARED_EXPORT uPrintCrashInfo_Init(const char * name)//called only by exe on startup
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
540 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
541 version_string = pfc::format( "App: ", name, "\nArch: ", pfc::cpuArch());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
542
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
543 SetUnhandledExceptionFilter(uExceptFilterProc);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
544 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
545 void SHARED_EXPORT uPrintCrashInfo_Suppress() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
546 g_didSuppress = true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
547 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
548
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
549 void SHARED_EXPORT uPrintCrashInfo_AddEnvironmentInfo(const char * p_info) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
550 version_string << "\n" << p_info;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
551 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
552
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
553 void SHARED_EXPORT uPrintCrashInfo_SetComponentList(const char * p_info) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
554 g_components = p_info;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
555 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
556
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
557 void SHARED_EXPORT uPrintCrashInfo_SetDumpPath(const char * p_path) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
558 pfc::stringcvt::string_os_from_utf8 temp(p_path);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
559 DumpPathBuffer.set_size(temp.length() + 256);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
560 _tcscpy(DumpPathBuffer.get_ptr(), temp.get_ptr());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
561 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
562
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
563 static HANDLE hLogFile = INVALID_HANDLE_VALUE;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
564
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
565 static void logEvent(const char* message) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
566 if ( hLogFile != INVALID_HANDLE_VALUE ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
567 DWORD wrote = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
568 WriteFile(hLogFile, message, (DWORD) strlen(message), &wrote, NULL );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
569 WriteFile(hLogFile, "\r\n", 2, &wrote, NULL);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
570 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
571 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
572
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
573 void SHARED_EXPORT uPrintCrashInfo_StartLogging(const char * path) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
574 insync(g_lastEventsSync);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
575 PFC_ASSERT(hLogFile == INVALID_HANDLE_VALUE);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
576 hLogFile = CreateFile( pfc::stringcvt::string_wide_from_utf8(path), GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
577 PFC_ASSERT(hLogFile != INVALID_HANDLE_VALUE);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
578
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
579 for( auto & walk : g_lastEvents ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
580 logEvent( walk.c_str() );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
581 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
582 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
583
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
584 void SHARED_EXPORT uPrintCrashInfo_OnEvent(const char * message, t_size length) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
585
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
586 pfc::string8 msg = pfc::format("[", queryDebugTimer(), "ms] ");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
587 msg.add_string( message, length );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
588 uOutputDebugString(msg + "\n");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
589
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
590 insync(g_lastEventsSync);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
591 logEvent(msg);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
592 while(g_lastEvents.get_count() >= KLastEventCount) g_lastEvents.remove(g_lastEvents.first());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
593 g_lastEvents.insert_last( std::move(msg) );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
594 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
595
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
596 static void callstack_add(const char * param)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
597 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
598 enum { MAX = PFC_TABSIZE(g_thread_call_stack) - 1} ;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
599 t_size len = strlen(param);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
600 if (g_thread_call_stack_length + len > MAX) len = MAX - g_thread_call_stack_length;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
601 if (len>0)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
602 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
603 memcpy(g_thread_call_stack+g_thread_call_stack_length,param,len);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
604 g_thread_call_stack_length += len;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
605 g_thread_call_stack[g_thread_call_stack_length]=0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
606 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
607 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
608
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
609 uCallStackTracker::uCallStackTracker(const char * name)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
610 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
611 param = g_thread_call_stack_length;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
612 if (g_thread_call_stack_length>0) callstack_add("=>");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
613 callstack_add(name);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
614 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
615
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
616 uCallStackTracker::~uCallStackTracker()
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
617 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
618 g_thread_call_stack_length = param;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
619 g_thread_call_stack[param]=0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
620
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
621 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
622
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
623 extern "C" {LPCSTR SHARED_EXPORT uGetCallStackPath() {return g_thread_call_stack;} }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
624
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
625 #ifdef _DEBUG
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
626 extern "C" {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
627 void SHARED_EXPORT fb2kDebugSelfTest() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
628 auto ptr = SetUnhandledExceptionFilter(NULL);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
629 PFC_ASSERT( ptr == uExceptFilterProc );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
630 SetUnhandledExceptionFilter(ptr);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
631 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
632 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
633 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
634
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
635 #else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
636
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
637 void SHARED_EXPORT uDumpCrashInfo(LPEXCEPTION_POINTERS param) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
638 void SHARED_EXPORT uPrintCrashInfo_OnEvent(const char * message, t_size length) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
639 LONG SHARED_EXPORT uExceptFilterProc(LPEXCEPTION_POINTERS param) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
640 return UnhandledExceptionFilter(param);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
641 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
642 uCallStackTracker::uCallStackTracker(const char * name) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
643 uCallStackTracker::~uCallStackTracker() {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
644 extern "C" {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
645 LPCSTR SHARED_EXPORT uGetCallStackPath() { return ""; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
646 void SHARED_EXPORT fb2kDebugSelfTest() {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
647 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
648 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
649
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
650 PFC_NORETURN void SHARED_EXPORT uBugCheck() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
651 fb2k_instacrash_scope(RaiseException(EXCEPTION_BUG_CHECK, EXCEPTION_NONCONTINUABLE, 0, NULL); );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
652 }