diff options
Diffstat (limited to 'tizen/src/util/error_handler.c')
-rw-r--r-- | tizen/src/util/error_handler.c | 345 |
1 files changed, 167 insertions, 178 deletions
diff --git a/tizen/src/util/error_handler.c b/tizen/src/util/error_handler.c index 1f91e8df85..959594e83c 100644 --- a/tizen/src/util/error_handler.c +++ b/tizen/src/util/error_handler.c @@ -4,6 +4,7 @@ * Copyright (C) 2015 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: + * Jinhyung Jo <jinhyung.jo@samsung.com> * SeokYeon Hwang <syeon.hwang@samsung.com> * GiWoong Kim <giwoong.kim@samsung.com> * @@ -37,6 +38,7 @@ #ifdef CONFIG_WIN32 #include <windows.h> +#include <dbghelp.h> #else #include <execinfo.h> #endif @@ -47,244 +49,229 @@ #include "emulator_common.h" #include "emulator.h" -#include "debug_ch.h" - -MULTI_DEBUG_CHANNEL(qemu, backtrace); - #ifdef CONFIG_QT #include "qt5_error_report.h" #endif -#if defined(CONFIG_WIN32) -static LPTOP_LEVEL_EXCEPTION_FILTER prevExceptionFilter; -#elif defined(CONFIG_LINUX) -static pthread_spinlock_t siglock; -#endif +#include "new_debug_ch.h" -bool print_backtrace_at_normal_exit_enabled = false; +DECLARE_DEBUG_CHANNEL(backtrace); -/* Print 'backtrace' */ -#ifdef _WIN32 -struct frame_layout { - void *pNext; - void *pReturnAddr; -}; +bool print_backtrace_at_normal_exit_enabled; -static char *get_filename_from_path(char *path_buf) +void enable_print_backtrace_at_normal_exit(void) { - char *ret_slash; - char *ret_rslash; - - ret_slash = strrchr(path_buf, '/'); - ret_rslash = strrchr(path_buf, '\\'); - - if (ret_slash || ret_rslash) { - if (ret_slash > ret_rslash) { - return ret_slash + 1; - } else{ - return ret_rslash + 1; - } - } - - return path_buf; + print_backtrace_at_normal_exit_enabled = true; } +#ifdef CONFIG_WIN32 +static LPTOP_LEVEL_EXCEPTION_FILTER prevExceptionFilter; -static HMODULE get_module_handle(void *dwAddress) -{ - MEMORY_BASIC_INFORMATION Buffer; - return VirtualQuery((LPCVOID) dwAddress, &Buffer, sizeof(Buffer)) - ? (HMODULE) Buffer.AllocationBase : (HMODULE) 0; -} -#endif - -static void dump_backtrace(void *ptr, int depth) +/* The MSDN says as followed in "Updated Platform Support" page, + (https://msdn.microsoft.com/en-us/library/windows/desktop/ + ms681408(v=vs.85).aspx) + "Where necessary, the DbgHelp library has been widened to support both 32- + and 64-bit Windows. The original function and structure definitions are + still in DbgHelp.h, but there are also updated versions of these + definitions that are compatible with 64-bit Windows. If you use the updated + functions in your code, it can be compiled for both 32- and 64-bit Windows. + Your code will also be more efficient, since the original functions simply + call the updated functions to perform the work." + However, using the updated functinos does not work on the Windows 32-bit. + IMHO, in the MinGW cross compile environment rather than the Visual Studio + it does not compile correctly. + Thus, use explicitly. +*/ +static void dump_backtrace(void *ptr) { -#ifdef _WIN32 - int nCount; - void *pTopFrame; - struct frame_layout currentFrame; - struct frame_layout *pCurrentFrame; - - char module_buf[1024]; - HMODULE hModule; - - PCONTEXT pContext = ptr; - if (!pContext) { - __asm__ __volatile__ ("movl %%ebp, %0" : "=m" (pTopFrame)); - } else { #ifdef _WIN64 - pTopFrame = (void *)((PCONTEXT)pContext)->Rbp; + STACKFRAME64 frame; #else - pTopFrame = (void *)((PCONTEXT)pContext)->Ebp; + STACKFRAME frame; #endif + int i; + DWORD image; + CONTEXT context; + HANDLE hProcess = GetCurrentProcess(); + HANDLE hThread = GetCurrentThread(); + + if (!ptr) { + ZeroMemory(&context, sizeof(CONTEXT)); + context.ContextFlags = CONTEXT_FULL; + RtlCaptureContext(&context); + } else { + CopyMemory(&context, ptr, sizeof(CONTEXT)); } - if (pTopFrame == NULL) { - INFO("ebp is null, skip this for now\n"); - return ; - } - - nCount = 0; - currentFrame.pNext = ((struct frame_layout *)pTopFrame)->pNext; - currentFrame.pReturnAddr = ((struct frame_layout *)pTopFrame)->pReturnAddr; - pCurrentFrame = (struct frame_layout *)pTopFrame; + SymInitialize(hProcess, NULL, TRUE); - ERR("\nBacktrace Dump Start :\n"); - if (pContext) { - memset(module_buf, 0, sizeof(module_buf)); #ifdef _WIN64 - hModule = get_module_handle((void *)((PCONTEXT)pContext)->Rip); + ZeroMemory(&frame, sizeof(STACKFRAME64)); + image = IMAGE_FILE_MACHINE_AMD64; + frame.AddrPC.Offset = context.Rip; + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrFrame.Offset = context.Rbp; + frame.AddrFrame.Mode = AddrModeFlat; + frame.AddrStack.Offset = context.Rsp; + frame.AddrStack.Mode = AddrModeFlat; #else - hModule = get_module_handle((void *)((PCONTEXT)pContext)->Eip); + ZeroMemory(&frame, sizeof(STACKFRAME)); + image = IMAGE_FILE_MACHINE_I386; + frame.AddrPC.Offset = context.Eip; + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrFrame.Offset = context.Ebp; + frame.AddrFrame.Mode = AddrModeFlat; + frame.AddrStack.Offset = context.Esp; + frame.AddrStack.Mode = AddrModeFlat; #endif - if (hModule) { - if (!GetModuleFileNameA(hModule, module_buf, sizeof(module_buf))) { - memset(module_buf, 0, sizeof(module_buf)); - } - } + + i = 0; + while (1) { #ifdef _WIN64 - ERR("[%02d]Addr = 0x%p : %s\n", nCount, ((PCONTEXT)pContext)->Rip, get_filename_from_path(module_buf)); + BOOL result = StackWalk64(image, hProcess, hThread, + &frame, &context, NULL, + SymFunctionTableAccess64, + SymGetModuleBase64, NULL); #else - ERR("[%02d]Addr = 0x%p : %s\n", nCount, ((PCONTEXT)pContext)->Eip, get_filename_from_path(module_buf)); + BOOL result = StackWalk(image, hProcess, hThread, + &frame, &context, NULL, + SymFunctionTableAccess, + SymGetModuleBase, NULL); #endif - nCount++; - } - - while (1) { - if (((void *)pCurrentFrame < pTopFrame) - || ((void *)pCurrentFrame >= (void *)0xC0000000)) { + if (!result) { break; } - - memset(module_buf, 0, sizeof(module_buf)); - hModule = get_module_handle(currentFrame.pReturnAddr); - if (hModule) { - if (!GetModuleFileNameA(hModule, module_buf, sizeof(module_buf))) { - memset(module_buf, 0, sizeof(module_buf)); - } - } - ERR("[%02d]Addr = 0x%p : %s\n", nCount, currentFrame.pReturnAddr, get_filename_from_path(module_buf)); - - if (!ReadProcessMemory(GetCurrentProcess(), currentFrame.pNext, - (void *)¤tFrame, sizeof(struct frame_layout), NULL)) { - break; - } - pCurrentFrame = (struct frame_layout *)pCurrentFrame->pNext; - - if (depth) { - if (!--depth) { - break; + TCHAR buffer[sizeof(SYMBOL_INFO) + (MAX_SYM_NAME - 1) * sizeof(TCHAR)]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; + pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); + pSymbol->MaxNameLen = MAX_SYM_NAME; + DWORD64 displacement = 0; + TCHAR pFileName[MAX_PATH] = {0, }; +#ifdef _WIN64 + DWORD64 dwBase = SymGetModuleBase64(hProcess, frame.AddrPC.Offset); +#else + DWORD dwBase = SymGetModuleBase(hProcess, frame.AddrPC.Offset); +#endif + if (dwBase) { + HMODULE hModule = (HMODULE)((DWORD_PTR)dwBase); + if (!GetModuleFileNameA(hModule, pFileName, MAX_PATH)) { + snprintf(pFileName, MAX_PATH, "Unknown Module"); } } - nCount++; - } + /* TODO: take the symbols for the static functions + without import .pdb */ + if (SymFromAddr(hProcess, + frame.AddrPC.Offset, + &displacement, pSymbol)) { +#ifdef _WIN64 + LOG_INFO("#%04d 0x%016I64x in %s from %s\n", #else - void *trace[1024]; - int ndepth = backtrace(trace, 1024); - ERR("Backtrace depth is %d.\n", ndepth); - - backtrace_symbols_fd(trace, ndepth, fileno(stderr)); + LOG_INFO("#%04d 0x%08x in %s from %s\n", +#endif + i, frame.AddrPC.Offset, pSymbol->Name, pFileName); + } else { +#ifdef _WIN64 + LOG_INFO("#%04d 0x%016I64x in ???????? from %s\n", +#else + LOG_INFO("#%04d 0x%08x in ???????? from %s\n", #endif + i, frame.AddrPC.Offset, pFileName); + } + i++; + } + SymCleanup(hProcess); } -static void handle_error_at_exit(void) +static WINAPI LONG +maru_unhandled_exception_filter(LPEXCEPTION_POINTERS pException) { - if (print_backtrace_at_normal_exit_enabled) { - INFO("Stack backtrace for tracing...\n"); - INFO("This is not an error.\n"); - dump_backtrace(NULL, 0); - } -} +#ifdef _WIN64 + LOG_SEVERE("Exception occurred: Code[0x%x], Address[0x%016I64x]\n", +#else + LOG_SEVERE("Exception occurred: Code[0x%x], Address[0x%08x]\n", +#endif + pException->ExceptionRecord->ExceptionCode, + pException->ExceptionRecord->ExceptionAddress); -void enable_print_backtrace_at_normal_exit(void) { - print_backtrace_at_normal_exit_enabled = true; -} + dump_backtrace(pException->ContextRecord); -#ifdef CONFIG_WIN32 -static WINAPI LONG maru_unhandled_exception_filter(LPEXCEPTION_POINTERS pExceptionInfo){ - char module_buf[1024]; + return EXCEPTION_CONTINUE_SEARCH; +} - // print system information again - print_system_info(); +static void register_exception_handler(void) +{ + prevExceptionFilter = + SetUnhandledExceptionFilter(maru_unhandled_exception_filter); +} - DWORD dwException = pExceptionInfo->ExceptionRecord->ExceptionCode; - ERR("%d\n ", (int)dwException); +#else /* END FOR WINDOWS, START FOR LINUX & DARWIN */ - PEXCEPTION_RECORD pExceptionRecord; - HMODULE hModule; - PCONTEXT pContext; +/* prevent an interrupt by another signal */ +QemuMutex siglock; +/* uses in case SIGSEGV */ +struct sigaction old_sa; - pExceptionRecord = pExceptionInfo->ExceptionRecord; +/* Print 'backtrace' */ +static void dump_backtrace(void *ptr) +{ + int i; + void *trace[1024]; + int ndepth = backtrace(trace, 1024); + char **syms = backtrace_symbols(trace, ndepth); - memset(module_buf, 0, sizeof(module_buf)); - hModule = get_module_handle(pExceptionRecord->ExceptionAddress); - if(hModule){ - if(!GetModuleFileNameA(hModule, module_buf, sizeof(module_buf))){ - memset(module_buf, 0, sizeof(module_buf)); - } + LOG_INFO("Backtrace depth is %d\n", ndepth); + for (i = 0; i < ndepth; i++) { + LOG_INFO("#%04d %s\n", i, syms[i]); } - - ERR("Exception [%X] occured at %s:0x%08x\n", - pExceptionRecord->ExceptionCode, - get_filename_from_path(module_buf), - pExceptionRecord->ExceptionAddress - ); - - pContext = pExceptionInfo->ContextRecord; - dump_backtrace(pContext, 0); - _exit(0); - //return EXCEPTION_CONTINUE_SEARCH; + free(syms); } -#endif -#ifdef CONFIG_LINUX static void maru_sighandler(int sig) { - ERR("Got signal %d\n", sig); - // print system information again - print_system_info(); - - pthread_spin_lock(&siglock); - dump_backtrace(NULL, 0); - pthread_spin_unlock(&siglock); - _exit(0); + LOG_SEVERE("Got signal: %d(%s)\n", sig, strsignal(sig)); + + qemu_mutex_lock(&siglock); + dump_backtrace(NULL); + qemu_mutex_unlock(&siglock); + qemu_mutex_destroy(&siglock); + if (sig == SIGSEGV) { + sigaction(SIGSEGV, &old_sa, NULL); + raise(SIGSEGV); + } } -#endif - -#ifndef CONFIG_DARWIN static void register_exception_handler(void) { - #ifdef CONFIG_WIN32 - prevExceptionFilter = SetUnhandledExceptionFilter(maru_unhandled_exception_filter); - #else // LINUX void *trace[1]; struct sigaction sa; - // make dummy call to explicitly load glibc library + /* make dummy call to explicitly load glibc library */ backtrace(trace, 1); - pthread_spin_init(&siglock,0); - sa.sa_handler = (void*) maru_sighandler; + qemu_mutex_init(&siglock); + sa.sa_handler = maru_sighandler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - sigaction(SIGSEGV, &sa, NULL); + /* store previous signal action */ + sigaction(SIGSEGV, &sa, &old_sa); sigaction(SIGBUS, &sa, NULL); sigaction(SIGILL, &sa, NULL); sigaction(SIGFPE, &sa, NULL); sigaction(SIGABRT, &sa, NULL); - // main thread only + /* main thread only */ sigaction(SIGTERM, &sa, NULL); sigaction(SIGINT, &sa, NULL); - #endif } -#else // CONFIG_DARWIN -static void register_exception_handler(void) +#endif /* END FOR LINUX & DARWIN */ + +static void handle_error_at_exit(void) { - // TODO: Exception handling on darwin + if (print_backtrace_at_normal_exit_enabled) { + LOG_INFO("Stack backtrace for tracing...\n"); + LOG_INFO("This is not an error\n"); + dump_backtrace(NULL); + } } -#endif #define MAX_MESSAGE_LEN 2048 static size_t message_len; @@ -296,9 +283,9 @@ static void report(const char *fmt, va_list ap) message_len = g_strlcat(message, new_message, MAX_MESSAGE_LEN); g_free(new_message); - // We are wating for '\n' + /* We are waiting for '\n' */ if (message[message_len - 1] == '\n') { -#if defined(CONFIG_QT) +#ifdef CONFIG_QT start_qt5_msgbox(CRITICAL_ICON, message); #endif @@ -307,10 +294,12 @@ static void report(const char *fmt, va_list ap) } } -static ErrorReporter error_reporter = - { .report = report }; +static ErrorReporter error_reporter = { + .report = report +}; -void init_error_handler(void) { +void init_error_handler(void) +{ register_exception_handler(); add_error_reporter(&error_reporter); |