summaryrefslogtreecommitdiff
path: root/tizen/src/util/error_handler.c
diff options
context:
space:
mode:
authorJinhyung Jo <jinhyung.jo@samsung.com>2016-09-19 20:04:13 +0900
committerSeokYeon Hwang <syeon.hwang@samsung.com>2016-10-06 11:28:22 +0900
commit07cfe62467612339476b3a83ef61ffcb9f3ee3e9 (patch)
tree37db2e323149e1f439403256f6cce4f6fdae043c /tizen/src/util/error_handler.c
parentf569c289168ec579bcb62231d2572a80be5d6d52 (diff)
downloadqemu-07cfe62467612339476b3a83ef61ffcb9f3ee3e9.tar.gz
qemu-07cfe62467612339476b3a83ef61ffcb9f3ee3e9.tar.bz2
qemu-07cfe62467612339476b3a83ef61ffcb9f3ee3e9.zip
util: improve backtrace feature
improve & clean up the code: - correct coding convention - add backtrace feature to Mac OS X : remove #ifdef CONFIG_DARWIN ... #endif The 'backtarce' family functions first appeared in Mac OS X 10.5 - modify the Windows code using the APIs in DbgHelp - change debug channel: from debug_ch to new_debug_ch - remove some lines like redundant/unclear/unwanted/etc. - modify output form Change-Id: I8b57d996fa9daabf990932fcfb82e45a5e453636 Signed-off-by: Jinhyung Jo <jinhyung.jo@samsung.com>
Diffstat (limited to 'tizen/src/util/error_handler.c')
-rw-r--r--tizen/src/util/error_handler.c286
1 files changed, 153 insertions, 133 deletions
diff --git a/tizen/src/util/error_handler.c b/tizen/src/util/error_handler.c
index 1f91e8df85..5a41b054ea 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,60 +49,40 @@
#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;
+
+/* Windows 32 bit */
+#ifndef _WIN64
+struct frame_layout {
+ void *pNext;
+ void *pReturnAddr;
+};
static HMODULE get_module_handle(void *dwAddress)
{
MEMORY_BASIC_INFORMATION Buffer;
- return VirtualQuery((LPCVOID) dwAddress, &Buffer, sizeof(Buffer))
- ? (HMODULE) Buffer.AllocationBase : (HMODULE) 0;
+ return VirtualQuery((LPCVOID)dwAddress, &Buffer, sizeof(Buffer))
+ ? (HMODULE)Buffer.AllocationBase : (HMODULE)0;
}
-#endif
-static void dump_backtrace(void *ptr, int depth)
+static void dump_backtrace(void *ptr)
{
-#ifdef _WIN32
int nCount;
void *pTopFrame;
struct frame_layout currentFrame;
@@ -113,15 +95,11 @@ static void dump_backtrace(void *ptr, int depth)
if (!pContext) {
__asm__ __volatile__ ("movl %%ebp, %0" : "=m" (pTopFrame));
} else {
-#ifdef _WIN64
- pTopFrame = (void *)((PCONTEXT)pContext)->Rbp;
-#else
pTopFrame = (void *)((PCONTEXT)pContext)->Ebp;
-#endif
}
if (pTopFrame == NULL) {
- INFO("ebp is null, skip this for now\n");
+ LOG_INFO("ebp is null, skip this for now\n");
return ;
}
@@ -130,30 +108,23 @@ static void dump_backtrace(void *ptr, int depth)
currentFrame.pReturnAddr = ((struct frame_layout *)pTopFrame)->pReturnAddr;
pCurrentFrame = (struct frame_layout *)pTopFrame;
- ERR("\nBacktrace Dump Start :\n");
if (pContext) {
memset(module_buf, 0, sizeof(module_buf));
-#ifdef _WIN64
- hModule = get_module_handle((void *)((PCONTEXT)pContext)->Rip);
-#else
hModule = get_module_handle((void *)((PCONTEXT)pContext)->Eip);
-#endif
if (hModule) {
if (!GetModuleFileNameA(hModule, module_buf, sizeof(module_buf))) {
memset(module_buf, 0, sizeof(module_buf));
}
}
-#ifdef _WIN64
- ERR("[%02d]Addr = 0x%p : %s\n", nCount, ((PCONTEXT)pContext)->Rip, get_filename_from_path(module_buf));
-#else
- ERR("[%02d]Addr = 0x%p : %s\n", nCount, ((PCONTEXT)pContext)->Eip, get_filename_from_path(module_buf));
-#endif
+ LOG_SEVERE("#%04d 0x%08x from %s\n",
+ nCount, ((PCONTEXT)pContext)->Eip, module_buf);
nCount++;
}
while (1) {
if (((void *)pCurrentFrame < pTopFrame)
- || ((void *)pCurrentFrame >= (void *)0xC0000000)) {
+ || ((void *)pCurrentFrame >= (void *)0xC0000000)
+ || !currentFrame.pReturnAddr) {
break;
}
@@ -164,127 +135,174 @@ static void dump_backtrace(void *ptr, int depth)
memset(module_buf, 0, sizeof(module_buf));
}
}
- ERR("[%02d]Addr = 0x%p : %s\n", nCount, currentFrame.pReturnAddr, get_filename_from_path(module_buf));
+ LOG_SEVERE("#%04d 0x%08x from %s\n",
+ nCount, currentFrame.pReturnAddr, module_buf);
- if (!ReadProcessMemory(GetCurrentProcess(), currentFrame.pNext,
+ if (!ReadProcessMemory(GetCurrentProcess(), currentFrame.pNext,
(void *)&currentFrame, sizeof(struct frame_layout), NULL)) {
break;
}
pCurrentFrame = (struct frame_layout *)pCurrentFrame->pNext;
- if (depth) {
- if (!--depth) {
- break;
- }
- }
nCount++;
}
-#else
- void *trace[1024];
- int ndepth = backtrace(trace, 1024);
- ERR("Backtrace depth is %d.\n", ndepth);
-
- backtrace_symbols_fd(trace, ndepth, fileno(stderr));
-#endif
}
-static void handle_error_at_exit(void)
+#else
+
+/* Windows 64 bit */
+static void dump_backtrace(void *ptr)
{
- if (print_backtrace_at_normal_exit_enabled) {
- INFO("Stack backtrace for tracing...\n");
- INFO("This is not an error.\n");
- dump_backtrace(NULL, 0);
+ int i;
+ DWORD image;
+ STACKFRAME64 frame;
+ 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));
}
-}
-void enable_print_backtrace_at_normal_exit(void) {
- print_backtrace_at_normal_exit_enabled = true;
+ SymSetOptions(SYMOPT_LOAD_LINES);
+ SymInitialize(hProcess, NULL, TRUE);
+
+ 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;
+
+ i = 0;
+ while (1) {
+ BOOL result = StackWalk64(image, hProcess, hThread,
+ &frame, &context, NULL,
+ SymFunctionTableAccess64,
+ SymGetModuleBase64, NULL);
+ if (!result) {
+ break;
+ }
+ TCHAR buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * 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, };
+ DWORD64 dwBase = SymGetModuleBase64(hProcess, frame.AddrPC.Offset);
+ if (dwBase) {
+ HMODULE hModule = (HMODULE)((DWORD_PTR)dwBase);
+ if (!GetModuleFileNameA(hModule, pFileName, MAX_PATH)) {
+ snprintf(pFileName, MAX_PATH, "Unknown Module");
+ }
+ }
+ if (SymFromAddr(hProcess,
+ frame.AddrPC.Offset,
+ &displacement, pSymbol)) {
+ LOG_SEVERE("#%04d 0x%016x in %s from %s\n",
+ i, frame.AddrPC.Offset, pSymbol->Name, pFileName);
+ } else {
+ LOG_SEVERE("#%04d 0x%016x in ???????? from %s\n",
+ i, frame.AddrPC.Offset, pFileName);
+ }
+ i++;
+ }
+ SymCleanup(hProcess);
}
+#endif
-#ifdef CONFIG_WIN32
-static WINAPI LONG maru_unhandled_exception_filter(LPEXCEPTION_POINTERS pExceptionInfo){
- char module_buf[1024];
+static WINAPI LONG
+maru_unhandled_exception_filter(LPEXCEPTION_POINTERS pException)
+{
+ LOG_SEVERE("Exception occurred: Code[0x%x], Address[0x%016x]\n",
+ pException->ExceptionRecord->ExceptionCode,
+ pException->ExceptionRecord->ExceptionAddress);
- // print system information again
- print_system_info();
+ dump_backtrace(pException->ContextRecord);
- DWORD dwException = pExceptionInfo->ExceptionRecord->ExceptionCode;
- ERR("%d\n ", (int)dwException);
+ return EXCEPTION_CONTINUE_SEARCH;
+}
- PEXCEPTION_RECORD pExceptionRecord;
- HMODULE hModule;
- PCONTEXT pContext;
+static void register_exception_handler(void)
+{
+ prevExceptionFilter =
+ SetUnhandledExceptionFilter(maru_unhandled_exception_filter);
+}
- pExceptionRecord = pExceptionInfo->ExceptionRecord;
+#else /* END FOR WINDOWS, START FOR LINUX & DARWIN */
- 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));
- }
- }
+/* prevent an interrupt by another signal */
+QemuMutex siglock;
+/* uses in case SIGSEGV */
+struct sigaction old_sa;
- ERR("Exception [%X] occured at %s:0x%08x\n",
- pExceptionRecord->ExceptionCode,
- get_filename_from_path(module_buf),
- pExceptionRecord->ExceptionAddress
- );
+/* Print 'backtrace' */
+static void dump_backtrace(void *ptr)
+{
+ int i;
+ void *trace[1024];
+ int ndepth = backtrace(trace, 1024);
+ char **syms = backtrace_symbols(trace, ndepth);
- pContext = pExceptionInfo->ContextRecord;
- dump_backtrace(pContext, 0);
- _exit(0);
- //return EXCEPTION_CONTINUE_SEARCH;
+ LOG_SEVERE("Backtrace depth is %d\n", ndepth);
+ for (i = 0; i < ndepth; i++) {
+ LOG_SEVERE("#%04d %s\n", i, syms[i]);
+ }
+ 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 +314,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 +325,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);