12 #include "../../common/http.h"
14 #include "../../shared/bfd.h"
21 #define ARCH_SW(x86, amd64) amd64
23 #define ARCH_SW(x86, amd64) x86
26 static void _backtrace (
struct output_buffer* ob,
struct bfd_set* set,
int depth, LPCONTEXT context)
28 char procname[MAX_PATH];
29 struct bfd_ctx* bc =
nullptr;
30 HANDLE process = GetCurrentProcess();
31 HANDLE thread = GetCurrentThread();
33 char symbol_buffer[
sizeof(IMAGEHLP_SYMBOL) + 255];
34 char module_name_raw[MAX_PATH];
36 GetModuleFileNameA(
nullptr, procname,
sizeof(procname));
40 frame.AddrPC.Offset = context->ARCH_SW(Eip, Rip);
41 frame.AddrPC.Mode = AddrModeFlat;
42 frame.AddrStack.Offset = context->ARCH_SW(Esp, Rsp);
43 frame.AddrStack.Mode = AddrModeFlat;
44 frame.AddrFrame.Offset = context->ARCH_SW(Ebp, Rbp);
45 frame.AddrFrame.Mode = AddrModeFlat;
47 while (StackWalk(ARCH_SW(IMAGE_FILE_MACHINE_I386, IMAGE_FILE_MACHINE_AMD64), process, thread, &frame, context,
48 0, SymFunctionTableAccess, SymGetModuleBase, 0)) {
49 const char* file =
nullptr;
50 const char* func =
nullptr;
52 DWORD module_base = SymGetModuleBase(process, frame.AddrPC.Offset);
53 const char* module_name =
"[unknown module]";
54 IMAGEHLP_SYMBOL* symbol = (IMAGEHLP_SYMBOL*) symbol_buffer;
60 symbol->SizeOfStruct =
sizeof(*symbol) + 255;
61 symbol->MaxNameLength = 254;
63 if (module_base && GetModuleFileNameA((HINSTANCE) module_base, module_name_raw, MAX_PATH)) {
64 module_name = module_name_raw;
65 bc = get_bc(ob, set, module_name);
69 find(bc, frame.AddrPC.Offset, &file, &func, &line);
72 if (file ==
nullptr) {
73 ARCH_SW(DWORD, DWORD64) dummy = 0;
74 if (SymGetSymFromAddr(process, frame.AddrPC.Offset, &dummy, symbol)) {
77 file =
"[unknown file]";
80 if (func ==
nullptr) {
81 output_print(ob,
"0x%x : %s : %s \n", frame.AddrPC.Offset,
84 output_print(ob,
"0x%x : %s : %s (%d) : in function (%s) \n",
85 frame.AddrPC.Offset, module_name, file, line, func);
90 static LPTOP_LEVEL_EXCEPTION_FILTER g_prev =
nullptr;
91 #define BUFFER_MAX (16*1024)
92 static char* g_output =
nullptr;
94 static LONG WINAPI exception_filter (LPEXCEPTION_POINTERS info)
96 struct output_buffer ob;
98 OSVERSIONINFOEX osInfo;
99 const char* dumpFile =
"crashdump.txt";
101 GetSystemTime(&timeInfo);
104 osInfo.dwOSVersionInfoSize =
sizeof(OSVERSIONINFOEX);
105 if (!GetVersionEx((OSVERSIONINFO*)&osInfo)) {
106 osInfo.dwOSVersionInfoSize =
sizeof(OSVERSIONINFO);
107 GetVersionEx((OSVERSIONINFO*)&osInfo);
110 output_init(&ob, g_output, BUFFER_MAX);
112 if (!SymInitialize(GetCurrentProcess(), 0, TRUE)) {
113 output_print(&ob,
"Failed to init symbol context\n");
115 struct bfd_set* set = (
struct bfd_set *)calloc(1,
sizeof(*set));
117 _backtrace(&ob, set, 128, info->ContextRecord);
120 SymCleanup(GetCurrentProcess());
124 if (crash !=
nullptr) {
125 fprintf(crash,
"======start======\n");
126 fprintf(crash,
"Date: %.4d-%.2d-%.2d\n",
127 timeInfo.wYear, timeInfo.wMonth, timeInfo.wDay);
128 fprintf(crash,
"Windows version %lu.%lu (Build %lu) %s\n",
129 osInfo.dwMajorVersion, osInfo.dwMinorVersion, osInfo.dwBuildNumber, osInfo.szCSDVersion);
131 fprintf(crash,
"%s", g_output);
132 fprintf(crash,
"======end========\n");
135 fputs(g_output, stderr);
137 const int ret = MessageBox(
nullptr,
"Would you like to upload this crash dump and your ufoconsole.log? This will help the developers to fix the problem.",
GAME_TITLE_LONG" Fatal Error", MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2);
144 static void backtrace_register (
void)
146 if (g_output ==
nullptr) {
147 g_output = (
char*)malloc(BUFFER_MAX);
148 g_prev = SetUnhandledExceptionFilter(exception_filter);
152 static void backtrace_unregister (
void)
156 SetUnhandledExceptionFilter(g_prev);
166 backtrace_register();
173 backtrace_unregister();
void Sys_BacktraceInit(void)
Win32-specific UFO header file.
void Com_UploadCrashDump(const char *crashDumpFile)
void Sys_BacktraceShutdown(void)
FILE * Sys_Fopen(const char *filename, const char *mode)