From b7a421897254b9094268981ad6f24144af5a9d16 Mon Sep 17 00:00:00 2001 From: Alessandro Bonazzi Date: Sun, 17 Oct 2021 23:40:20 +0200 Subject: [PATCH] Patch level : 12.0 nopatch Files correlati : Commento : Aggiunto stack trace in caso di eccezione nel file stack.log --- src/xvaga/xvapp.cpp | 229 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 224 insertions(+), 5 deletions(-) diff --git a/src/xvaga/xvapp.cpp b/src/xvaga/xvapp.cpp index d17ad4ee6..50b388c27 100755 --- a/src/xvaga/xvapp.cpp +++ b/src/xvaga/xvapp.cpp @@ -5,6 +5,211 @@ #include #include +#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 + extern int xvt_main(int argc, char** argv); class TMainApp : public wxApp @@ -15,8 +220,9 @@ protected: virtual bool OnInit(); virtual int OnExit(); void OnTimer(wxTimerEvent& evt); - - DECLARE_EVENT_TABLE() +// void OnUnhandledException(); + + DECLARE_EVENT_TABLE() DECLARE_DYNAMIC_CLASS(TMainApp); }; @@ -32,13 +238,20 @@ END_EVENT_TABLE() void TMainApp::OnTimer(wxTimerEvent& evt) { - xvt_app_pre_create(); - xvt_main(argc, argv); + xvt_app_pre_create(); + xvt_main(argc, argv); } bool TMainApp::OnInit() { - wxFileName strWrk = argv[0]; +#ifdef __WXMSW__ + OSWin32_set_signal_handler(); +#else + OSLinux_set_signal_handler(); +#endif + + wxFileName strWrk = argv[0]; + //const wxString strApp = strWrk.GetName().Lower(); strWrk.MakeAbsolute(); wxString strApp = strWrk.GetFullPath().Lower(); @@ -52,6 +265,12 @@ bool TMainApp::OnInit() return true; } +/*void TMainApp::OnUnhandledException() +{ + windows_exception_handler(nullptr); +} +*/ + int TMainApp::OnExit() { delete m_sic;