diff --git a/CMakeLists.txt b/CMakeLists.txt index 4cf2538bb..14b90e19d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -183,6 +183,8 @@ set(OLIVE_SOURCES global/clipboard.h global/config.cpp global/config.h + global/crashhandler.cpp + global/crashhandler.h global/debug.cpp global/debug.h global/global.cpp diff --git a/global/crashhandler.cpp b/global/crashhandler.cpp new file mode 100644 index 000000000..8a60435a7 --- /dev/null +++ b/global/crashhandler.cpp @@ -0,0 +1,120 @@ +#include "crashhandler.h" + +#include +#include + +#include "dialogs/crashdialog.h" + +#ifdef __GNUC__ +#ifdef Q_OS_WIN +#include +#include +#elif defined(Q_OS_LINUX) +#include +#endif +#include +#include +#endif + +#ifdef __GNUC__ +void handler(int sig) { + QStringList strings; + +#ifdef Q_OS_WIN + HANDLE process = GetCurrentProcess(); + HANDLE thread = GetCurrentThread(); + + CONTEXT context; + memset(&context, 0, sizeof(CONTEXT)); + context.ContextFlags = CONTEXT_FULL; + RtlCaptureContext(&context); + + SymInitialize(process, NULL, TRUE); + + DWORD image; + STACKFRAME64 stackframe; + ZeroMemory(&stackframe, sizeof(STACKFRAME64)); + +#ifdef _M_IX86 + image = IMAGE_FILE_MACHINE_I386; + stackframe.AddrPC.Offset = context.Eip; + stackframe.AddrPC.Mode = AddrModeFlat; + stackframe.AddrFrame.Offset = context.Ebp; + stackframe.AddrFrame.Mode = AddrModeFlat; + stackframe.AddrStack.Offset = context.Esp; + stackframe.AddrStack.Mode = AddrModeFlat; +#elif _M_X64 + image = IMAGE_FILE_MACHINE_AMD64; + stackframe.AddrPC.Offset = context.Rip; + stackframe.AddrPC.Mode = AddrModeFlat; + stackframe.AddrFrame.Offset = context.Rsp; + stackframe.AddrFrame.Mode = AddrModeFlat; + stackframe.AddrStack.Offset = context.Rsp; + stackframe.AddrStack.Mode = AddrModeFlat; +#elif _M_IA64 + image = IMAGE_FILE_MACHINE_IA64; + stackframe.AddrPC.Offset = context.StIIP; + stackframe.AddrPC.Mode = AddrModeFlat; + stackframe.AddrFrame.Offset = context.IntSp; + stackframe.AddrFrame.Mode = AddrModeFlat; + stackframe.AddrBStore.Offset = context.RsBSP; + stackframe.AddrBStore.Mode = AddrModeFlat; + stackframe.AddrStack.Offset = context.IntSp; + stackframe.AddrStack.Mode = AddrModeFlat; +#endif + + int counter = 0; + QString line_template = "[%1] %2"; + while (StackWalk64( + image, process, thread, + &stackframe, &context, NULL, + SymFunctionTableAccess64, SymGetModuleBase64, NULL)) { + + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + symbol->MaxNameLen = MAX_SYM_NAME; + + DWORD64 displacement = 0; + + + QString sym_name; + if (SymFromAddr(process, stackframe.AddrPC.Offset, &displacement, symbol)) { + sym_name = symbol->Name; + } else { + sym_name = "???"; + } + QString s = line_template.arg(QString::number(counter), sym_name); + strings.append(s); + std::cout << s.data() << std::endl << std::flush; + + counter++; + } + + SymCleanup(process); +#elif defined(Q_OS_LINUX) + void *array[10]; + size_t size; + + // get void*'s for all entries on the stack + size = backtrace(array, 10); + + // print out all the frames to stderr + fprintf(stderr, "Signal: %d\n\n", sig); + backtrace_symbols_fd(array, size, STDERR_FILENO); + + // try to show a GUI crash report + char** bt_syms = backtrace_symbols(array, size); + for (int i=0;iSetData(sig, strings); + olive::crash_dialog->exec(); + + abort(); +} +#endif diff --git a/global/crashhandler.h b/global/crashhandler.h new file mode 100644 index 000000000..da11558bd --- /dev/null +++ b/global/crashhandler.h @@ -0,0 +1,8 @@ +#ifndef CRASHHANDLER_H +#define CRASHHANDLER_H + +#ifdef __GNUC__ +void handler(int sig); +#endif + +#endif // CRASHHANDLER_H diff --git a/main.cpp b/main.cpp index 9beab8703..510cbbf77 100644 --- a/main.cpp +++ b/main.cpp @@ -21,18 +21,8 @@ #include #include -#ifdef __GNUC__ -#ifdef Q_OS_WIN -#include -#include -#elif defined(Q_OS_LINUX) -#include -#endif -#include -#include -#endif - #include "dialogs/crashdialog.h" +#include "global/crashhandler.h" #include "global/debug.h" #include "global/config.h" #include "global/global.h" @@ -46,109 +36,6 @@ extern "C" { #include } -#ifdef __GNUC__ -void handler(int sig) { - QStringList strings; - -#ifdef Q_OS_WIN - HANDLE process = GetCurrentProcess(); - HANDLE thread = GetCurrentThread(); - - CONTEXT context; - memset(&context, 0, sizeof(CONTEXT)); - context.ContextFlags = CONTEXT_FULL; - RtlCaptureContext(&context); - - SymInitialize(process, NULL, TRUE); - - DWORD image; - STACKFRAME64 stackframe; - ZeroMemory(&stackframe, sizeof(STACKFRAME64)); - -#ifdef _M_IX86 - image = IMAGE_FILE_MACHINE_I386; - stackframe.AddrPC.Offset = context.Eip; - stackframe.AddrPC.Mode = AddrModeFlat; - stackframe.AddrFrame.Offset = context.Ebp; - stackframe.AddrFrame.Mode = AddrModeFlat; - stackframe.AddrStack.Offset = context.Esp; - stackframe.AddrStack.Mode = AddrModeFlat; -#elif _M_X64 - image = IMAGE_FILE_MACHINE_AMD64; - stackframe.AddrPC.Offset = context.Rip; - stackframe.AddrPC.Mode = AddrModeFlat; - stackframe.AddrFrame.Offset = context.Rsp; - stackframe.AddrFrame.Mode = AddrModeFlat; - stackframe.AddrStack.Offset = context.Rsp; - stackframe.AddrStack.Mode = AddrModeFlat; -#elif _M_IA64 - image = IMAGE_FILE_MACHINE_IA64; - stackframe.AddrPC.Offset = context.StIIP; - stackframe.AddrPC.Mode = AddrModeFlat; - stackframe.AddrFrame.Offset = context.IntSp; - stackframe.AddrFrame.Mode = AddrModeFlat; - stackframe.AddrBStore.Offset = context.RsBSP; - stackframe.AddrBStore.Mode = AddrModeFlat; - stackframe.AddrStack.Offset = context.IntSp; - stackframe.AddrStack.Mode = AddrModeFlat; -#endif - - int counter = 0; - QString line_template = "[%1] %2"; - while (StackWalk64( - image, process, thread, - &stackframe, &context, NULL, - SymFunctionTableAccess64, SymGetModuleBase64, NULL)) { - - char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; - PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; - symbol->SizeOfStruct = sizeof(SYMBOL_INFO); - symbol->MaxNameLen = MAX_SYM_NAME; - - DWORD64 displacement = 0; - - - QString sym_name; - if (SymFromAddr(process, stackframe.AddrPC.Offset, &displacement, symbol)) { - sym_name = symbol->Name; - } else { - sym_name = "???"; - } - QString s = line_template.arg(QString::number(counter), sym_name); - strings.append(s); - qDebug() << s; - - counter++; - } - - SymCleanup(process); -#elif defined(Q_OS_LINUX) - void *array[10]; - size_t size; - - // get void*'s for all entries on the stack - size = backtrace(array, 10); - - // print out all the frames to stderr - fprintf(stderr, "Signal: %d\n\n", sig); - backtrace_symbols_fd(array, size, STDERR_FILENO); - - // try to show a GUI crash report - char** bt_syms = backtrace_symbols(array, size); - for (int i=0;iSetData(sig, strings); - olive::crash_dialog->exec(); - - abort(); -} -#endif - int main(int argc, char *argv[]) { #ifdef __GNUC__ signal(SIGSEGV, handler);