4 * Copyright (C) 2011, 2012 Samsung Electronics Co., Ltd. All rights reserved.
7 * SeokYeon Hwang <syeon.hwang@samsung.com>
8 * GiWoong Kim <giwoong.kim@samsung.com>
9 * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
32 #include "qemu-common.h"
33 #include "maru_err_table.h"
45 /* This table must match the enum definition */
46 static char _maru_string_table[][JAVA_MAX_COMMAND_LENGTH] = {
48 /* 1 */ "Failed to allocate memory in qemu.",
49 /* 2 */ "Failed to load a kernel file the following path.\
50 Check if the file is corrupted or missing.\n\n",
51 /* 3 */ "Failed to load a bios file the following path.\
52 Check if the file is corrupted or missing.\n\n",
53 /* 4 */ "Skin process cannot be initialized. Skin server is not ready.",
54 /* 5 */ "Emulator has stopped working.\n\
55 A problem caused the program to stop working correctly.",
61 static int maru_exit_status = MARU_EXIT_NORMAL;
62 static char maru_exit_msg[JAVA_MAX_COMMAND_LENGTH] = { 0, };
64 void maru_register_exit_msg(int maru_exit_index, char const *const additional_msg)
68 if (maru_exit_index >= MARU_EXIT_NORMAL) {
69 fprintf(stderr, "Invalid error message index = %d\n", maru_exit_index);
72 if (maru_exit_status != MARU_EXIT_NORMAL) {
73 fprintf(stderr, "The error message is already registered = %d\n", maru_exit_status);
77 maru_exit_status = maru_exit_index;
79 if (maru_exit_status != MARU_EXIT_UNKNOWN) {
80 if (maru_exit_status == MARU_EXIT_HB_TIME_EXPIRED) {
81 fprintf(stderr, "Skin client could not connect to Skin server.\
82 The time of internal heartbeat has expired.\n");
85 if (additional_msg != NULL) {
86 len = strlen(_maru_string_table[maru_exit_status])
87 + strlen(additional_msg) + 1;
88 if (len > JAVA_MAX_COMMAND_LENGTH) {
89 len = JAVA_MAX_COMMAND_LENGTH;
92 snprintf(maru_exit_msg, len, "%s%s",
93 _maru_string_table[maru_exit_status], additional_msg);
95 len = strlen(_maru_string_table[maru_exit_status]) + 1;
96 if (len > JAVA_MAX_COMMAND_LENGTH) {
97 len = JAVA_MAX_COMMAND_LENGTH;
100 snprintf(maru_exit_msg, len,
101 "%s", _maru_string_table[maru_exit_status]);
103 } else if (additional_msg != NULL) { /* MARU_EXIT_UNKNOWN */
104 len = strlen(additional_msg);
105 if (len >= JAVA_MAX_COMMAND_LENGTH) {
106 len = JAVA_MAX_COMMAND_LENGTH - 1;
109 pstrcpy(maru_exit_msg, len + 1, additional_msg);
110 maru_exit_msg[len] = '\0';
113 fprintf(stdout, "The error message is registered = %d : %s\n",
114 maru_exit_status, maru_exit_msg);
117 void maru_atexit(void)
119 if (maru_exit_status != MARU_EXIT_NORMAL || strlen(maru_exit_msg) != 0) {
120 maru_dump_backtrace(NULL, 0);
121 start_simple_client(maru_exit_msg);
125 char *maru_convert_path(char *msg, const char *path)
127 char *current_path = NULL;
128 char *err_msg = NULL;
130 char *dos_err_msg = NULL;
134 int cur_path_len = 0;
138 res = (int)g_path_is_absolute(path);
139 path_len = (strlen(path) + 1);
141 msg_len = strlen(msg) + 1;
145 current_path = (char *)g_get_current_dir();
146 cur_path_len = strlen(current_path) + strlen("/") + 1;
147 total_len += cur_path_len;
149 total_len += (path_len + msg_len);
151 err_msg = g_malloc0(total_len * sizeof(char));
154 snprintf(err_msg, msg_len, "%s", msg);
155 total_len = msg_len - 1;
161 snprintf(err_msg + total_len, cur_path_len, "%s%s", current_path, "/");
162 total_len += (cur_path_len - 1);
164 snprintf(err_msg + total_len, path_len, "%s", path);
170 dos_err_msg = g_strdup(err_msg);
173 "failed to duplicate an error message from %p\n", err_msg);
175 g_free(current_path);
181 for (i = (total_len - 1); dos_err_msg[i]; i++) {
182 if (dos_err_msg[i] == '/') {
183 dos_err_msg[i] = '\\';
186 pstrcpy(err_msg, strlen(dos_err_msg) + 1, dos_err_msg);
191 g_free(current_path);
197 /* Print 'backtrace' */
199 struct frame_layout {
204 static char *aqua_get_filename_from_path(char *path_buf)
209 ret_slash = strrchr(path_buf, '/');
210 ret_rslash = strrchr(path_buf, '\\');
212 if (ret_slash || ret_rslash) {
213 if (ret_slash > ret_rslash) {
214 return ret_slash + 1;
216 return ret_rslash + 1;
224 static HMODULE aqua_get_module_handle(DWORD dwAddress)
226 MEMORY_BASIC_INFORMATION Buffer;
227 return VirtualQuery((LPCVOID) dwAddress, &Buffer, sizeof(Buffer))
228 ? (HMODULE) Buffer.AllocationBase : (HMODULE) 0;
232 void maru_dump_backtrace(void *ptr, int depth)
237 struct frame_layout currentFrame;
238 struct frame_layout *pCurrentFrame;
240 char module_buf[1024];
243 PCONTEXT pContext = ptr;
245 __asm__ __volatile__ ("movl %%ebp, %0" : "=m" (pTopFrame));
247 pTopFrame = (void *)((PCONTEXT)pContext)->Ebp;
251 currentFrame.pNext = ((struct frame_layout *)pTopFrame)->pNext;
252 currentFrame.pReturnAddr = ((struct frame_layout *)pTopFrame)->pReturnAddr;
253 pCurrentFrame = (struct frame_layout *)pTopFrame;
255 fprintf(stderr, "\nBacktrace Dump Start :\n");
257 fprintf(stderr, "[%02d]Addr = 0x%p", nCount, ((PCONTEXT)pContext)->Eip);
258 memset(module_buf, 0, sizeof(module_buf));
259 hModule = aqua_get_module_handle((DWORD)((PCONTEXT)pContext)->Eip);
261 if (!GetModuleFileNameA(hModule, module_buf, sizeof(module_buf))) {
262 memset(module_buf, 0, sizeof(module_buf));
265 fprintf(stderr, " : %s\n", aqua_get_filename_from_path(module_buf));
270 if (((void *)pCurrentFrame < pTopFrame)
271 || ((void *)pCurrentFrame >= (void *)0xC0000000)) {
275 fprintf(stderr, "[%02d]Addr = 0x%p", nCount, currentFrame.pReturnAddr);
276 memset(module_buf, 0, sizeof(module_buf));
277 hModule = aqua_get_module_handle((DWORD)currentFrame.pReturnAddr);
279 if (!GetModuleFileNameA(hModule, module_buf, sizeof(module_buf))) {
280 memset(module_buf, 0, sizeof(module_buf));
283 fprintf(stderr, " : %s\n", aqua_get_filename_from_path(module_buf));
285 if (!ReadProcessMemory(GetCurrentProcess(), currentFrame.pNext,
286 (void *)¤tFrame, sizeof(struct frame_layout), NULL)) {
289 pCurrentFrame = (struct frame_layout *)pCurrentFrame->pNext;
303 fprintf(stderr, "\n Backtrace Dump Start :\n");
305 ndepth = backtrace(trace, 1024);
306 fprintf(stderr, "Backtrace depth is %d.\n", ndepth);
308 symbols = backtrace_symbols(trace, ndepth);
309 if (symbols == NULL) {
310 fprintf(stderr, "'backtrace_symbols()' return error");
314 for (i = 0; i < ndepth; i++) {
315 fprintf(stderr, "%s\n", symbols[i]);