summaryrefslogtreecommitdiff
path: root/tizen/src/util/error_handler.c
diff options
context:
space:
mode:
Diffstat (limited to 'tizen/src/util/error_handler.c')
-rw-r--r--tizen/src/util/error_handler.c345
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 *)&currentFrame, 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);