#include "../xvaga/wxinc.h" #include "xvt.h" #include #include #ifdef false #ifdef __WXMSW__ #include #include #include static FILE * f = nullptr; void print_stack_element(STACKFRAME frame) { //------------------------------------------------------------------ // Declare an image help symbol structure to hold symbol info and // name up to 256 chars This struct is of variable lenght though so // it must be declared as a raw byte buffer. //------------------------------------------------------------------ static char symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 255]; memset(symbolBuffer, 0, sizeof(IMAGEHLP_SYMBOL) + 255); // Cast it to a symbol struct: IMAGEHLP_SYMBOL * symbol = (IMAGEHLP_SYMBOL*)symbolBuffer; // Need to set the first two fields of this symbol before obtaining name info: symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL) + 255; symbol->MaxNameLength = 254; // The displacement from the beginning of the symbol is stored here: pretty useless unsigned displacement = 0; // Get the symbol information from the address of the instruction pointer register: if (SymGetSymFromAddr(GetCurrentProcess(), // Process to get symbol information for frame.AddrPC.Offset, // Address to get symbol for: instruction pointer register (DWORD*)& displacement, // Displacement from the beginning of the symbol: whats this for ? symbol)) // Where to save the symbol { // Add the name of the function to the function list: fprintf(f, "0x%08x %s\n", frame.AddrPC.Offset, symbol->Name); } else { // Print an unknown location: // functionNames.push_back("unknown location"); fprintf(f, "0x%08x\n", frame.AddrPC.Offset); } } void windows_print_stacktrace(CONTEXT* context) { SymInitialize(GetCurrentProcess(), 0, true); STACKFRAME frame = { 0 }; /* setup initial stack frame */ frame.AddrPC.Offset = context->Eip; frame.AddrPC.Mode = AddrModeFlat; frame.AddrStack.Offset = context->Esp; frame.AddrStack.Mode = AddrModeFlat; frame.AddrFrame.Offset = context->Ebp; frame.AddrFrame.Mode = AddrModeFlat; while (StackWalk(IMAGE_FILE_MACHINE_I386, GetCurrentProcess(), GetCurrentThread(), &frame, context, 0, SymFunctionTableAccess, SymGetModuleBase, 0)) print_stack_element(frame); SymCleanup(GetCurrentProcess()); } LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS * ExceptionInfo) { fopen_s(&f, "stack.log", xvt_fsys_file_exists("stack.log") != 0 ? "a+tc" : "wtc"); if (f != nullptr) { switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: fprintf(f, "Error: EXCEPTION_ACCESS_VIOLATION"); break; case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: fprintf(f, "Error: EXCEPTION_ARRAY_BOUNDS_EXCEEDED"); break; case EXCEPTION_BREAKPOINT: fprintf(f, "Error: EXCEPTION_BREAKPOINT"); break; case EXCEPTION_DATATYPE_MISALIGNMENT: fprintf(f, "Error: EXCEPTION_DATATYPE_MISALIGNMENT"); break; case EXCEPTION_FLT_DENORMAL_OPERAND: fprintf(f, "Error: EXCEPTION_FLT_DENORMAL_OPERAND"); break; case EXCEPTION_FLT_DIVIDE_BY_ZERO: fprintf(f, "Error: EXCEPTION_FLT_DIVIDE_BY_ZERO"); break; case EXCEPTION_FLT_INEXACT_RESULT: fprintf(f, "Error: EXCEPTION_FLT_INEXACT_RESULT"); break; case EXCEPTION_FLT_INVALID_OPERATION: fprintf(f, "Error: EXCEPTION_FLT_INVALID_OPERATION"); break; case EXCEPTION_FLT_OVERFLOW: fprintf(f, "Error: EXCEPTION_FLT_OVERFLOW"); break; case EXCEPTION_FLT_STACK_CHECK: fprintf(f, "Error: EXCEPTION_FLT_STACK_CHECK"); break; case EXCEPTION_FLT_UNDERFLOW: fprintf(f, "Error: EXCEPTION_FLT_UNDERFLOW"); break; case EXCEPTION_ILLEGAL_INSTRUCTION: fprintf(f, "Error: EXCEPTION_ILLEGAL_INSTRUCTION"); break; case EXCEPTION_IN_PAGE_ERROR: fprintf(f, "Error: EXCEPTION_IN_PAGE_ERROR"); break; case EXCEPTION_INT_DIVIDE_BY_ZERO: fprintf(f, "Error: EXCEPTION_INT_DIVIDE_BY_ZERO"); break; case EXCEPTION_INT_OVERFLOW: fprintf(f, "Error: EXCEPTION_INT_OVERFLOW"); break; case EXCEPTION_INVALID_DISPOSITION: fprintf(f, "Error: EXCEPTION_INVALID_DISPOSITION"); break; case EXCEPTION_NONCONTINUABLE_EXCEPTION: fprintf(f, "Error: EXCEPTION_NONCONTINUABLE_EXCEPTION"); break; case EXCEPTION_PRIV_INSTRUCTION: fprintf(f, "Error: EXCEPTION_PRIV_INSTRUCTION"); break; case EXCEPTION_SINGLE_STEP: fprintf(f, "Error: EXCEPTION_SINGLE_STEP"); break; case EXCEPTION_STACK_OVERFLOW: fprintf(f, "Error: EXCEPTION_STACK_OVERFLOW"); break; default: return EXCEPTION_EXECUTE_HANDLER; // per ora non mi interessa; break; } /* If this is a stack overflow then we can't walk the stack, so just show where the error happened */ if (EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode) windows_print_stacktrace(ExceptionInfo->ContextRecord); else { STACKFRAME frame = { 0 }; frame.AddrPC.Offset = ExceptionInfo->ContextRecord->Eip; frame.AddrPC.Mode = AddrModeFlat; frame.AddrStack.Offset = ExceptionInfo->ContextRecord->Esp; frame.AddrStack.Mode = AddrModeFlat; frame.AddrFrame.Offset = ExceptionInfo->ContextRecord->Ebp; frame.AddrFrame.Mode = AddrModeFlat; print_stack_element(frame); } fflush(f); } return EXCEPTION_EXECUTE_HANDLER; } static BOOL PreventSetUnhandledExceptionFilter() { HMODULE hKernelbase = LoadLibrary(_T("KernelBase.dll")); HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll")); if (hKernel32 == nullptr) return false; void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter"); if (pOrgEntry == nullptr) return false; #ifdef _M_IX86 // Code for x86: // 33 C0 xor eax,eax // C2 04 00 ret 4 unsigned char szExecute[] = { 0x33, 0xC0, 0xC2, 0x04, 0x00 }; #elif _M_X64 // 33 C0 xor eax,eax // C3 ret unsigned char szExecute[] = { 0x33, 0xC0, 0xC3 }; #else #error "The following code only works for x86 and x64!" #endif SIZE_T bytesWritten = 0; BOOL bRet = WriteProcessMemory(GetCurrentProcess(), pOrgEntry, szExecute, sizeof(szExecute), &bytesWritten); return bRet; } void OSWin32_set_signal_handler() { AddVectoredExceptionHandler(1L, windows_exception_handler); // SetUnhandledExceptionFilter(windows_exception_handler); PreventSetUnhandledExceptionFilter(); } #else void OSLinux_set_signal_handler() { } #endif #endif extern int xvt_main(int argc, char** argv); class TMainApp : public wxApp { wxSingleInstanceChecker* m_sic; protected: virtual bool OnInit(); virtual int OnExit(); void OnTimer(wxTimerEvent& evt); // void OnUnhandledException(); DECLARE_EVENT_TABLE() DECLARE_DYNAMIC_CLASS(TMainApp); }; IMPLEMENT_DYNAMIC_CLASS(TMainApp, wxApp) IMPLEMENT_APP(TMainApp) #define TIMER_ID 883 BEGIN_EVENT_TABLE(TMainApp, wxApp) EVT_TIMER(TIMER_ID, TMainApp::OnTimer) END_EVENT_TABLE() void TMainApp::OnTimer(wxTimerEvent& evt) { xvt_app_pre_create(); xvt_main(argc, argv); } bool TMainApp::OnInit() { #ifdef false #ifdef __WXMSW__ OSWin32_set_signal_handler(); #else OSLinux_set_signal_handler(); #endif #endif wxFileName strWrk = argv[0]; //const wxString strApp = strWrk.GetName().Lower(); strWrk.MakeAbsolute(); wxString strApp = strWrk.GetFullPath().Lower(); strApp.Replace("\\", "_"); strApp.Replace("/", "_"); strApp.Replace(":", "_"); m_sic = new wxSingleInstanceChecker(strApp); xvt_vobj_set_attr(NULL_WIN, ATTR_APPL_ALREADY_RUNNING, m_sic->IsAnotherRunning()); // Non eseguo direttamente xvt_main per dar modo al main event loop di partire wxTimerEvent evt(TIMER_ID); AddPendingEvent(evt); return true; } /*void TMainApp::OnUnhandledException() { windows_exception_handler(nullptr); } */ int TMainApp::OnExit() { delete m_sic; m_sic = NULL; return wxApp::OnExit(); }