From: SeokYeon Hwang Date: Fri, 4 Jul 2014 10:08:42 +0000 (+0900) Subject: emulator: some error reporting routine is refactored X-Git-Tag: Tizen_Studio_1.3_Release_p2.3.1~228^2^2~83^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bc03868a55d081601f8bad2315ce8fe791b8dfc8;p=sdk%2Femulator%2Fqemu.git emulator: some error reporting routine is refactored maru_register_exit_msg() can accept variable arguments. Remove maru_convert_path(), Add get_canonical_path(). Change-Id: I7975510cfb34a0bbb633df5a74ffce21922c0c92 Signed-off-by: SeokYeon Hwang Signed-off-by: Sooyoung Ha --- diff --git a/blockdev.c b/blockdev.c index 0144f04113..f8c63c902a 100644 --- a/blockdev.c +++ b/blockdev.c @@ -46,6 +46,10 @@ #include "trace.h" #include "sysemu/arch_init.h" +#ifdef CONFIG_MARU +#include "tizen/src/util/maru_err_table.h" +#endif + static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives); static const char *const if_name[IF_COUNT] = { @@ -288,11 +292,6 @@ static int parse_block_error_action(const char *buf, bool is_read, Error **errp) } } -#ifdef CONFIG_MARU -extern int start_simple_client(char* msg); -extern char* maru_convert_path(char* msg, const char *path); -#endif - static bool check_throttle_config(ThrottleConfig *cfg, Error **errp) { if (throttle_conflicting(cfg)) { @@ -513,14 +512,13 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, if (ret < 0) { #ifdef CONFIG_MARU - const char _msg[] = "Failed to load disk file from the following path. Check if the file is corrupted or missing.\n\n"; - char* err_msg = NULL; + char *path = get_canonical_path(file); + char *msg = g_strdup_printf("Failed to load disk file from the following path. Check if the file is corrupted or missing.\n\n%s", path); - err_msg = maru_convert_path((char*)_msg, file); - if (err_msg) { - start_simple_client(err_msg); - g_free(err_msg); - } + start_simple_client(msg); + + g_free(path); + g_free(msg); #endif error_setg(errp, "could not open disk image %s: %s", diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index 24ef874944..519b6e3c83 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -21,8 +21,7 @@ #include "virtio-9p-coth.h" #ifdef CONFIG_MARU -#include "../tizen/src/maru_err_table.h" -// extern char* maru_convert_path(char* msg, const char *path); +#include "tizen/src/util/maru_err_table.h" #endif static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features) @@ -108,13 +107,11 @@ static void virtio_9p_device_realize(DeviceState *dev, Error **errp) error_setg(errp, "Virtio-9p Failed to initialize fs-driver with id:%s" " and export path:%s", s->fsconf.fsdev_id, s->ctx.fs_root); #ifdef CONFIG_MARU - const char _msg[] = "Failed to find the file sharing path. Check if the path is correct or not.\n\n"; - char* err_msg = NULL; - err_msg = maru_convert_path((char*)_msg, s->ctx.fs_root); - maru_register_exit_msg(MARU_EXIT_UNKNOWN, err_msg); - if (err_msg) { - g_free(err_msg); - } + char *path = get_canonical_path(s->ctx.fs_root); + maru_register_exit_msg(MARU_EXIT_UNKNOWN, "Failed to find the file sharing path." + " Check if the path is correct or not.\n\n%s", path); + + g_free(path); #endif goto out; } diff --git a/hw/i386/pc.c b/hw/i386/pc.c index f48baeea8e..612bde2f2c 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -60,7 +60,7 @@ #include "acpi-build.h" #ifdef CONFIG_MARU -#include "../../tizen/src/maru_err_table.h" +#include "tizen/src/util/maru_err_table.h" #endif /* debug PC/ISA interrupts */ //#define DEBUG_IRQ @@ -734,13 +734,10 @@ static void load_linux(FWCfgState *fw_cfg, kernel_filename, strerror(errno)); #ifdef CONFIG_MARU - char *error_msg = NULL; + char *path = get_canonical_path(kernel_filename); + maru_register_exit_msg(MARU_EXIT_KERNEL_FILE_EXCEPTION, path); - error_msg = maru_convert_path(error_msg, kernel_filename); - maru_register_exit_msg(MARU_EXIT_KERNEL_FILE_EXCEPTION, error_msg); - if (error_msg) { - g_free(error_msg); - } + g_free(path); #endif exit(1); } diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c index 7819b21601..61e54ddc10 100644 --- a/hw/i386/pc_sysfw.c +++ b/hw/i386/pc_sysfw.c @@ -35,7 +35,7 @@ #include "sysemu/kvm.h" #ifdef CONFIG_MARU -#include "../../tizen/src/maru_err_table.h" +#include "tizen/src/util/maru_err_table.h" #endif #define BIOS_FILENAME "bios.bin" diff --git a/tizen/src/Makefile.objs b/tizen/src/Makefile.objs index 44bddfa55b..ba3ff7859a 100644 --- a/tizen/src/Makefile.objs +++ b/tizen/src/Makefile.objs @@ -3,14 +3,11 @@ QEMU_CFLAGS += -I$(SRC_PATH)/tizen/src # emulator base -obj-y += emulator.o emulator_legacy.o emulator_options.o emul_state.o maru_err_table.o +obj-y += emulator.o emulator_legacy.o emulator_options.o emul_state.o # utils obj-y += util/ -# mloop event -#obj-y += mloop_event.o - # maru display obj-y += display/ diff --git a/tizen/src/emulator.c b/tizen/src/emulator.c index a659db802d..2243b3ef47 100644 --- a/tizen/src/emulator.c +++ b/tizen/src/emulator.c @@ -40,7 +40,7 @@ #include "emulator_options.h" #include "util/sdb_noti_server.h" #include "util/check_gl.h" -#include "maru_err_table.h" +#include "util/maru_err_table.h" #include "util/osutil.h" #include "util/sdb.h" #include "skin/maruskin_server.h" diff --git a/tizen/src/emulator_legacy.c b/tizen/src/emulator_legacy.c index 85fa9d55e4..47b87de6b2 100644 --- a/tizen/src/emulator_legacy.c +++ b/tizen/src/emulator_legacy.c @@ -41,7 +41,7 @@ #include "guest_debug.h" #include "hw/virtio/maru_virtio_touchscreen.h" #include "util/check_gl.h" -#include "maru_err_table.h" +#include "util/maru_err_table.h" #include "display/maru_display.h" #include "util/osutil.h" #include "util/sdb.h" diff --git a/tizen/src/maru_err_table.c b/tizen/src/maru_err_table.c deleted file mode 100644 index 01f6dd1f07..0000000000 --- a/tizen/src/maru_err_table.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Error message - * - * Copyright (C) 2011, 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: - * SeokYeon Hwang - * GiWoong Kim - * YeongKyoon Lee - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - * Contributors: - * - S-Core Co., Ltd - * - */ - -#include "qemu-common.h" -#include "maru_common.h" -#include "maru_err_table.h" -#include "debug_ch.h" - -#include -#include -#include -#include - -#ifdef CONFIG_WIN32 -#include -#else -#include -#endif - - -MULTI_DEBUG_CHANNEL(qemu, backtrace); -/* This table must match the enum definition */ -static char _maru_string_table[][JAVA_MAX_COMMAND_LENGTH] = { - /* 0 */ "", - /* 1 */ "Failed to allocate memory in qemu.", - /* 2 */ "Failed to load a kernel file the following path.\ -Check if the file is corrupted or missing.\n\n", - /* 3 */ "Failed to load a bios file in bios path that mentioned on document.\ -Check if the file is corrupted or missing.\n\n", - /* 4 */ "Skin process cannot be initialized. Skin server is not ready.", - /* 5 */ "Emulator has stopped working.\n\ -A problem caused the program to stop working correctly.", - /* add here.. */ - "" -}; - - -static int maru_exit_status = MARU_EXIT_NORMAL; -static char maru_exit_msg[JAVA_MAX_COMMAND_LENGTH] = { 0, }; - -#ifdef CONFIG_WIN32 -static LPTOP_LEVEL_EXCEPTION_FILTER prevExceptionFilter; -#endif - -#ifdef CONFIG_LINUX -static pthread_spinlock_t siglock; -void maru_sighandler(int sig); -#endif - - -void maru_register_exit_msg(int maru_exit_index, char const *const additional_msg) -{ - int len = 0; - - if (maru_exit_index >= MARU_EXIT_NORMAL) { - fprintf(stderr, "Invalid error message index = %d\n", maru_exit_index); - return; - } - if (maru_exit_status != MARU_EXIT_NORMAL) { - fprintf(stderr, "The error message is already registered = %d\n", maru_exit_status); - return; - } - - maru_exit_status = maru_exit_index; - - if (maru_exit_status != MARU_EXIT_UNKNOWN) { - if (maru_exit_status == MARU_EXIT_HB_TIME_EXPIRED) { - fprintf(stderr, "Skin client could not connect to Skin server.\ -The time of internal heartbeat has expired.\n"); - } - - if (additional_msg != NULL) { - len = strlen(_maru_string_table[maru_exit_status]) - + strlen(additional_msg) + 1; - if (len > JAVA_MAX_COMMAND_LENGTH) { - len = JAVA_MAX_COMMAND_LENGTH; - } - - snprintf(maru_exit_msg, len, "%s%s", - _maru_string_table[maru_exit_status], additional_msg); - } else { - len = strlen(_maru_string_table[maru_exit_status]) + 1; - if (len > JAVA_MAX_COMMAND_LENGTH) { - len = JAVA_MAX_COMMAND_LENGTH; - } - - snprintf(maru_exit_msg, len, - "%s", _maru_string_table[maru_exit_status]); - } - } else if (additional_msg != NULL) { /* MARU_EXIT_UNKNOWN */ - len = strlen(additional_msg); - if (len >= JAVA_MAX_COMMAND_LENGTH) { - len = JAVA_MAX_COMMAND_LENGTH - 1; - } - - pstrcpy(maru_exit_msg, len + 1, additional_msg); - maru_exit_msg[len] = '\0'; - } - - fprintf(stdout, "The error message is registered = %d : %s\n", - maru_exit_status, maru_exit_msg); -} - -void maru_atexit(void) -{ - - if (maru_exit_status != MARU_EXIT_NORMAL || strlen(maru_exit_msg) != 0) { - start_simple_client(maru_exit_msg); - } - INFO("normal exit called\n"); - // dump backtrace log no matter what - maru_dump_backtrace(NULL, 0); -} - -char *maru_convert_path(char *msg, const char *path) -{ - char *current_path = NULL; - char *err_msg = NULL; -#ifdef _WIN32 - char *dos_err_msg = NULL; -#endif - int total_len = 0; - int msg_len = 0; - int cur_path_len = 0; - int path_len = 0; - int res = -1; - - if (!path) { - path = "NULL"; - res = 1; - } - else { - res = (int)g_path_is_absolute(path); - } - path_len = (strlen(path) + 1); - if (msg) { - msg_len = strlen(msg) + 1; - } - - if (!res) { - current_path = (char *)g_get_current_dir(); - cur_path_len = strlen(current_path) + strlen("/") + 1; - total_len += cur_path_len; - } - total_len += (path_len + msg_len); - - err_msg = g_malloc0(total_len * sizeof(char)); - if (!err_msg) { - fprintf(stderr, "failed to allocate a buffer for an error massage\n"); - g_free(current_path); - return NULL; - } - - if (msg) { - snprintf(err_msg, msg_len, "%s", msg); - total_len = msg_len - 1; - } else { - total_len = 0; - } - - if (!res) { - snprintf(err_msg + total_len, cur_path_len, "%s%s", current_path, "/"); - total_len += (cur_path_len - 1); - } - snprintf(err_msg + total_len, path_len, "%s", path); - -#ifdef _WIN32 - { - int i; - - dos_err_msg = g_strdup(err_msg); - if (!dos_err_msg) { - fprintf(stderr, - "failed to duplicate an error message from %p\n", err_msg); - g_free(current_path); - g_free(err_msg); - return NULL; - } - - for (i = (total_len - 1); dos_err_msg[i]; i++) { - if (dos_err_msg[i] == '/') { - dos_err_msg[i] = '\\'; - } - } - pstrcpy(err_msg, strlen(dos_err_msg) + 1, dos_err_msg); - g_free(dos_err_msg); - } -#endif - g_free(current_path); - - return err_msg; -} - -/* Print 'backtrace' */ -#ifdef _WIN32 -struct frame_layout { - void *pNext; - void *pReturnAddr; -}; - -static char *aqua_get_filename_from_path(char *path_buf) -{ - 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; -} - - -static HMODULE aqua_get_module_handle(DWORD dwAddress) -{ - MEMORY_BASIC_INFORMATION Buffer; - return VirtualQuery((LPCVOID) dwAddress, &Buffer, sizeof(Buffer)) - ? (HMODULE) Buffer.AllocationBase : (HMODULE) 0; -} -#endif - -void maru_dump_backtrace(void *ptr, int depth) -{ -#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 { - pTopFrame = (void *)((PCONTEXT)pContext)->Ebp; - } - - 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; - - ERR("\nBacktrace Dump Start :\n"); - if (pContext) { - memset(module_buf, 0, sizeof(module_buf)); - hModule = aqua_get_module_handle((DWORD)((PCONTEXT)pContext)->Eip); - 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, ((PCONTEXT)pContext)->Eip, aqua_get_filename_from_path(module_buf)); - nCount++; - } - - while (1) { - if (((void *)pCurrentFrame < pTopFrame) - || ((void *)pCurrentFrame >= (void *)0xC0000000)) { - break; - } - - memset(module_buf, 0, sizeof(module_buf)); - hModule = aqua_get_module_handle((DWORD)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, aqua_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; - } - } - 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 -} - -#ifdef CONFIG_WIN32 -static LONG maru_unhandled_exception_filter(PEXCEPTION_POINTERS pExceptionInfo){ - char module_buf[1024]; - DWORD dwException = pExceptionInfo->ExceptionRecord->ExceptionCode; - ERR("%d\n ", (int)dwException); - - PEXCEPTION_RECORD pExceptionRecord; - HMODULE hModule; - PCONTEXT pContext; - - pExceptionRecord = pExceptionInfo->ExceptionRecord; - - memset(module_buf, 0, sizeof(module_buf)); - hModule = aqua_get_module_handle((DWORD)pExceptionRecord->ExceptionAddress); - if(hModule){ - if(!GetModuleFileNameA(hModule, module_buf, sizeof(module_buf))){ - memset(module_buf, 0, sizeof(module_buf)); - } - } - - ERR("Exception [%X] occured at %s:0x%08x\n", - pExceptionRecord->ExceptionCode, - aqua_get_filename_from_path(module_buf), - pExceptionRecord->ExceptionAddress - ); - - pContext = pExceptionInfo->ContextRecord; - maru_dump_backtrace(pContext, 0); - _exit(0); - //return EXCEPTION_CONTINUE_SEARCH; -} -#endif - -#ifdef CONFIG_LINUX -void maru_sighandler(int sig) -{ - pthread_spin_lock(&siglock); - ERR("Got signal %d\n", sig); - maru_dump_backtrace(NULL, 0); - pthread_spin_unlock(&siglock); - _exit(0); -} -#endif - - -#ifndef CONFIG_DARWIN -void maru_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 - backtrace(trace, 1); - - pthread_spin_init(&siglock,0); - sa.sa_handler = (void*) maru_sighandler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - sigaction(SIGSEGV, &sa, NULL); - sigaction(SIGBUS, &sa, NULL); - sigaction(SIGILL, &sa, NULL); - sigaction(SIGFPE, &sa, NULL); - sigaction(SIGABRT, &sa, NULL); - // main thread only - sigaction(SIGTERM, &sa, NULL); - sigaction(SIGINT, &sa, NULL); -#endif -} -#endif diff --git a/tizen/src/maru_err_table.h b/tizen/src/maru_err_table.h deleted file mode 100644 index 8ad2bac01a..0000000000 --- a/tizen/src/maru_err_table.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Error message - * - * Copyright (C) 2011, 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: - * SeokYeon Hwang - * GiWoong Kim - * YeongKyoon Lee - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - * Contributors: - * - S-Core Co., Ltd - * - */ - - -#ifndef __EMUL_ERR_TABLE_H__ -#define __EMUL_ERR_TABLE_H__ - -#include "skin/maruskin_client.h" - - -/* TODO: define macro for fair of definition */ -/* This enum must match the table definition */ -enum { - /* 0 */ MARU_EXIT_UNKNOWN = 0, - /* 1 */ MARU_EXIT_MEMORY_EXCEPTION, - /* 2 */ MARU_EXIT_KERNEL_FILE_EXCEPTION, - /* 3 */ MARU_EXIT_BIOS_FILE_EXCEPTION, - /* 4 */ MARU_EXIT_SKIN_SERVER_FAILED, - /* 5 */ MARU_EXIT_HB_TIME_EXPIRED, - /* add here.. */ - MARU_EXIT_NORMAL -}; - - -void maru_register_exit_msg(int maru_exit_status, char const *const additional_msg); -void maru_atexit(void); -char *maru_convert_path(char *msg, const char *path); -void maru_dump_backtrace(void *ptr, int depth); - -void maru_register_exception_handler(void); -#endif /* __EMUL_ERR_TABLE_H__ */ diff --git a/tizen/src/skin/maruskin_client.c b/tizen/src/skin/maruskin_client.c index 243037a0a6..0c6fc22b22 100644 --- a/tizen/src/skin/maruskin_client.c +++ b/tizen/src/skin/maruskin_client.c @@ -46,7 +46,7 @@ #ifdef CONFIG_WIN32 #include -#include "maru_err_table.h" +#include "util/maru_err_table.h" #endif MULTI_DEBUG_CHANNEL(qemu, skin_client); diff --git a/tizen/src/skin/maruskin_server.c b/tizen/src/skin/maruskin_server.c index 0264db0e52..5c94ada3c8 100644 --- a/tizen/src/skin/maruskin_server.c +++ b/tizen/src/skin/maruskin_server.c @@ -34,7 +34,7 @@ #include "maruskin_server.h" #include "maruskin_operation.h" #include "display/maru_display.h" -#include "maru_err_table.h" +#include "util/maru_err_table.h" #include "ecs/ecs.h" #include "emul_state.h" diff --git a/tizen/src/util/Makefile.objs b/tizen/src/util/Makefile.objs index 2234ec0ade..762e715f6e 100644 --- a/tizen/src/util/Makefile.objs +++ b/tizen/src/util/Makefile.objs @@ -20,4 +20,7 @@ obj-$(CONFIG_DARWIN) += check_gl_cgl.o # hotplug obj-y += maru_device_hotplug.o +# error table +obj-y += maru_err_table.o + $(obj)/osutil.o: QEMU_CFLAGS += $(CURL_CFLAGS) diff --git a/tizen/src/util/maru_err_table.c b/tizen/src/util/maru_err_table.c new file mode 100644 index 0000000000..62c834de5f --- /dev/null +++ b/tizen/src/util/maru_err_table.c @@ -0,0 +1,335 @@ +/* + * Error message + * + * Copyright (C) 2011, 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * GiWoong Kim + * YeongKyoon Lee + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "qemu-common.h" +#include "maru_common.h" +#include "maru_err_table.h" +#include "debug_ch.h" + +#include +#include +#include +#include + +#ifdef CONFIG_WIN32 +#include +#else +#include +#endif + + +MULTI_DEBUG_CHANNEL(qemu, backtrace); +/* This table must match the enum definition */ +static char _maru_string_table[][JAVA_MAX_COMMAND_LENGTH] = { + /* 0 */ "", + /* 1 */ "Failed to allocate memory in qemu.", + /* 2 */ "Failed to load a kernel file the following path." + " Check if the file is corrupted or missing.\n\n", + /* 3 */ "Failed to load a bios file in bios path that mentioned on document." + " Check if the file is corrupted or missing.\n\n", + /* 4 */ "Skin process cannot be initialized. Skin server is not ready.", + /* 5 */ "Emulator has stopped working.\n" + "A problem caused the program to stop working correctly.", + /* add here.. */ + "" +}; + + +static int maru_exit_status = MARU_EXIT_NORMAL; +static char *maru_exit_msg; + +#ifdef CONFIG_WIN32 +static LPTOP_LEVEL_EXCEPTION_FILTER prevExceptionFilter; +#endif + +#ifdef CONFIG_LINUX +static pthread_spinlock_t siglock; +void maru_sighandler(int sig); +#endif + +char *get_canonical_path(char const *const path) +{ + if ((int)g_path_is_absolute(path)) { + return (char *)path; + } + + char *canonical_path; + +#ifndef _WIN32 + char *current_dir = g_get_current_dir(); + canonical_path = g_strdup_printf("%s/%s", current_dir, path); + g_free(current_dir); +#else + canonical_path = g_malloc(MAX_PATH); + GetFullPathName(path, MAX_PATH, canonical_path, NULL); +#endif + + return canonical_path; +} + +void maru_register_exit_msg(int maru_exit_index, char const *format, ...) +{ + va_list args; + + if (maru_exit_index >= MARU_EXIT_NORMAL) { + fprintf(stderr, "Invalid error message index = %d\n", + maru_exit_index); + return; + } + if (maru_exit_status != MARU_EXIT_NORMAL) { + fprintf(stderr, "The error message is already registered = %d\n", + maru_exit_status); + return; + } + + maru_exit_status = maru_exit_index; + + if (maru_exit_status == MARU_EXIT_HB_TIME_EXPIRED) { + fprintf(stderr, "Skin client could not connect to Skin server." + " The time of internal heartbeat has expired.\n"); + } + + if (!format) { + format = ""; + } + + va_start(args, format); + char *additional = g_strdup_vprintf(format, args); + va_end(args); + maru_exit_msg = g_strdup_printf("%s%s", _maru_string_table[maru_exit_status], + additional); + g_free(additional); + + if (strlen(maru_exit_msg) >= JAVA_MAX_COMMAND_LENGTH) { + maru_exit_msg[JAVA_MAX_COMMAND_LENGTH - 1] = '\0'; + } + + fprintf(stdout, "The error message is registered = %d : %s\n", + maru_exit_status, maru_exit_msg); +} + +void maru_atexit(void) +{ + + if (maru_exit_status != MARU_EXIT_NORMAL || maru_exit_msg) { + start_simple_client(maru_exit_msg); + } + g_free(maru_exit_msg); + + INFO("normal exit called\n"); + // dump backtrace log no matter what + maru_dump_backtrace(NULL, 0); +} + +/* Print 'backtrace' */ +#ifdef _WIN32 +struct frame_layout { + void *pNext; + void *pReturnAddr; +}; + +static char *aqua_get_filename_from_path(char *path_buf) +{ + 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; +} + + +static HMODULE aqua_get_module_handle(DWORD dwAddress) +{ + MEMORY_BASIC_INFORMATION Buffer; + return VirtualQuery((LPCVOID) dwAddress, &Buffer, sizeof(Buffer)) + ? (HMODULE) Buffer.AllocationBase : (HMODULE) 0; +} +#endif + +void maru_dump_backtrace(void *ptr, int depth) +{ +#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 { + pTopFrame = (void *)((PCONTEXT)pContext)->Ebp; + } + + 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; + + ERR("\nBacktrace Dump Start :\n"); + if (pContext) { + memset(module_buf, 0, sizeof(module_buf)); + hModule = aqua_get_module_handle((DWORD)((PCONTEXT)pContext)->Eip); + 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, ((PCONTEXT)pContext)->Eip, aqua_get_filename_from_path(module_buf)); + nCount++; + } + + while (1) { + if (((void *)pCurrentFrame < pTopFrame) + || ((void *)pCurrentFrame >= (void *)0xC0000000)) { + break; + } + + memset(module_buf, 0, sizeof(module_buf)); + hModule = aqua_get_module_handle((DWORD)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, aqua_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; + } + } + 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 +} + +#ifdef CONFIG_WIN32 +static LONG maru_unhandled_exception_filter(PEXCEPTION_POINTERS pExceptionInfo){ + char module_buf[1024]; + DWORD dwException = pExceptionInfo->ExceptionRecord->ExceptionCode; + ERR("%d\n ", (int)dwException); + + PEXCEPTION_RECORD pExceptionRecord; + HMODULE hModule; + PCONTEXT pContext; + + pExceptionRecord = pExceptionInfo->ExceptionRecord; + + memset(module_buf, 0, sizeof(module_buf)); + hModule = aqua_get_module_handle((DWORD)pExceptionRecord->ExceptionAddress); + if(hModule){ + if(!GetModuleFileNameA(hModule, module_buf, sizeof(module_buf))){ + memset(module_buf, 0, sizeof(module_buf)); + } + } + + ERR("Exception [%X] occured at %s:0x%08x\n", + pExceptionRecord->ExceptionCode, + aqua_get_filename_from_path(module_buf), + pExceptionRecord->ExceptionAddress + ); + + pContext = pExceptionInfo->ContextRecord; + maru_dump_backtrace(pContext, 0); + _exit(0); + //return EXCEPTION_CONTINUE_SEARCH; +} +#endif + +#ifdef CONFIG_LINUX +void maru_sighandler(int sig) +{ + pthread_spin_lock(&siglock); + ERR("Got signal %d\n", sig); + maru_dump_backtrace(NULL, 0); + pthread_spin_unlock(&siglock); + _exit(0); +} +#endif + + +#ifndef CONFIG_DARWIN +void maru_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 + backtrace(trace, 1); + + pthread_spin_init(&siglock,0); + sa.sa_handler = (void*) maru_sighandler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGBUS, &sa, NULL); + sigaction(SIGILL, &sa, NULL); + sigaction(SIGFPE, &sa, NULL); + sigaction(SIGABRT, &sa, NULL); + // main thread only + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGINT, &sa, NULL); +#endif +} +#endif diff --git a/tizen/src/util/maru_err_table.h b/tizen/src/util/maru_err_table.h new file mode 100644 index 0000000000..f27dc91013 --- /dev/null +++ b/tizen/src/util/maru_err_table.h @@ -0,0 +1,58 @@ +/* + * Error message + * + * Copyright (C) 2011, 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * GiWoong Kim + * YeongKyoon Lee + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + + +#ifndef __EMUL_ERR_TABLE_H__ +#define __EMUL_ERR_TABLE_H__ + +#include "tizen/src/skin/maruskin_client.h" + +/* TODO: define macro for fair of definition */ +/* This enum must match the table definition */ +enum { + /* 0 */ MARU_EXIT_UNKNOWN = 0, + /* 1 */ MARU_EXIT_MEMORY_EXCEPTION, + /* 2 */ MARU_EXIT_KERNEL_FILE_EXCEPTION, + /* 3 */ MARU_EXIT_BIOS_FILE_EXCEPTION, + /* 4 */ MARU_EXIT_SKIN_SERVER_FAILED, + /* 5 */ MARU_EXIT_HB_TIME_EXPIRED, + /* add here.. */ + MARU_EXIT_NORMAL +}; + + +char *get_canonical_path(char const *const path); +void maru_register_exit_msg(int maru_exit_status, char const *format, ...); +void maru_atexit(void); + +void maru_dump_backtrace(void *ptr, int depth); + +void maru_register_exception_handler(void); +#endif /* __EMUL_ERR_TABLE_H__ */ diff --git a/vl.c b/vl.c index 7c0d432da1..3cf5854d2b 100644 --- a/vl.c +++ b/vl.c @@ -132,7 +132,7 @@ int qemu_main(int argc, char **argv, char **envp); #ifdef CONFIG_MARU #include "tizen/src/maru_common.h" #include "tizen/src/emulator.h" -#include "tizen/src/maru_err_table.h" +#include "tizen/src/util/maru_err_table.h" #include "tizen/src/emul_state.h" #include "tizen/src/display/maru_display.h" #include "tizen/src/skin/maruskin_operation.h"