You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by gs...@apache.org on 2008/03/18 12:31:10 UTC
svn commit: r638327 [2/5] - in /harmony/enhanced/drlvm/trunk: make/vm/
vm/em/src/ vm/gc_gen/src/common/ vm/include/open/ vm/interpreter/src/
vm/port/include/ vm/port/src/crash_handler/
vm/port/src/crash_handler/em64t/ vm/port/src/crash_handler/ia32/ vm...
Copied: harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/linux/stack_dump_os.cpp (from r637971, harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/stack_dump_platf.cpp)
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/linux/stack_dump_os.cpp?p2=harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/linux/stack_dump_os.cpp&p1=harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/stack_dump_platf.cpp&r1=637971&r2=638327&rev=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/stack_dump_platf.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/linux/stack_dump_os.cpp Tue Mar 18 04:31:02 2008
@@ -16,57 +16,24 @@
*/
#include <sys/types.h>
-#include <sys/wait.h>
#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/wait.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <assert.h>
+#include <ctype.h>
-#include "open/hythread_ext.h"
-#include "native_stack.h"
-#include "port_filepath.h"
#include "port_dso.h"
-#include "port_thread.h"
+#include "port_malloc.h"
#include "stack_dump.h"
-static hymutex_t g_lock;
-static const char* g_curdir = NULL;
-static const char* g_cmdline = NULL;
-
-
-bool sd_initialize(hymutex_t** p_lock)
-{
- static int initialized = 0;
-
- if (!initialized)
- {
- IDATA err = hymutex_create(&g_lock, APR_THREAD_MUTEX_NESTED);
-
- if (err != APR_SUCCESS)
- return false;
-
- initialized = true;
- }
-
- if (p_lock)
- *p_lock = &g_lock;
-
- return true;
-}
-
-
-static bool sd_is_predefined_name(const char* name)
-{
- if (*name != '[')
- return false;
+static char* g_curdir = NULL;
+static char* g_cmdline = NULL;
- return true;
-// return (!strcmp(name, "[heap]") ||
-// !strcmp(name, "[stack]") ||
-// !strcmp(name, "[vdso]"));
-}
static inline native_segment_t* sd_find_segment(native_module_t* module, void* ip)
{
@@ -81,48 +48,10 @@
return NULL;
}
-void sd_parse_module_info(native_module_t* module, void* ip)
-{
- fprintf(stderr, "\nCrashed module:\n");
-
- if (!module)
- { // Unknown address
- fprintf(stderr, "Unknown address 0x%"W_PI_FMT"\n",
- (POINTER_SIZE_INT)ip);
- return;
- }
-
- native_segment_t* segment = sd_find_segment(module, ip);
-
- if (!module->filename)
- {
- fprintf(stderr, "Unknown memory region 0x%"W_PI_FMT":0x%"W_PI_FMT"%s\n",
- (size_t)segment->base, (size_t)segment->base + segment->size,
- (segment->type == SEGMENT_TYPE_CODE) ? "" : " without execution rights");
- return;
- }
-
- if (sd_is_predefined_name(module->filename))
- { // Special memory region
- fprintf(stderr, "%s memory region 0x%"W_PI_FMT":0x%"W_PI_FMT"%s\n",
- module->filename,
- (size_t)segment->base, (size_t)segment->base + segment->size,
- (segment->type == SEGMENT_TYPE_CODE) ? "" : " without execution rights");
- return;
- }
-
- // Common shared module
- const char* short_name = port_filepath_basename(module->filename);
- const char* module_type = sd_get_module_type(short_name);
-
- fprintf(stderr, "%s\n(%s)\n", module->filename, module_type);
-}
-
-
-void sd_get_c_method_info(MethodInfo* info, native_module_t* module, void* ip)
+void sd_get_c_method_info(CFunInfo* info, native_module_t* module, void* ip)
{
- *info->method_name = 0;
- *info->file_name = 0;
+ *info->name = 0;
+ *info->filename = 0;
info->line = -1;
if (!module || !module->filename)
@@ -154,7 +83,7 @@
else
{
close(po[1]);
- char buf[sizeof(info->method_name) + sizeof(info->file_name)];
+ char buf[sizeof(info->name) + sizeof(info->filename)];
int status;
wait(&status);
int count = read(po[0], buf, sizeof(buf) - 1);
@@ -177,7 +106,7 @@
if (buf[i] == '\n')
{ // Function name is limited by '\n'
buf[i] = '\0';
- strncpy(info->method_name, buf, sizeof(info->method_name));
+ strncpy(info->name, buf, sizeof(info->name));
break;
}
}
@@ -193,7 +122,7 @@
return;
buf[i] = '\0';
- strncpy(info->file_name, fn, sizeof(info->file_name));
+ strncpy(info->filename, fn, sizeof(info->filename));
info->line = atoi(buf + i + 1); // Line number
@@ -202,11 +131,6 @@
}
}
-int sd_get_cur_tid()
-{
- return gettid();
-}
-
void sd_init_crash_handler()
{
// Get current directory
@@ -251,15 +175,24 @@
}
}
-void sd_print_cwdcmdenv()
+void sd_cleanup_crash_handler()
{
- fprintf(stderr, "\nWorking directory:\n%s\n", g_curdir ? g_curdir : "'null'");
+ STD_FREE(g_curdir);
+ STD_FREE(g_cmdline);
+}
+void sd_print_cmdline_cwd()
+{
fprintf(stderr, "\nCommand line:\n");
for (const char* ptr = g_cmdline; *ptr; ptr += strlen(ptr) + 1)
fprintf(stderr, "%s ", ptr);
fprintf(stderr, "\n");
+ fprintf(stderr, "\nWorking directory:\n%s\n", g_curdir ? g_curdir : "'null'");
+}
+
+void sd_print_environment()
+{
fprintf(stderr, "\nEnvironment variables:\n");
for (char** env = environ; *env; ++env)
fprintf(stderr, "%s\n", *env);
Added: harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/native_unwind.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/native_unwind.cpp?rev=638327&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/native_unwind.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/native_unwind.cpp Tue Mar 18 04:31:02 2008
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @author Ilya Berezhniuk
+ * @version $Revision: 1.1.2.1 $
+ */
+
+#include <string.h>
+#include "port_modules.h"
+#include "native_unwind.h"
+
+
+//////////////////////////////////////////////////////////////////////////////
+/// Helper functions
+
+bool native_is_in_stack(UnwindContext* context, void* sp)
+{
+ return (sp >= context->stack.base &&
+ sp < (char*)context->stack.base + context->stack.size);
+}
+
+/// Helper functions
+//////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+
+bool port_init_unwind_context(UnwindContext* context, native_module_t* modules, Registers* regs)
+{
+ if (!context)
+ return false;
+
+ if (!modules)
+ {
+ int mod_count;
+ native_module_t* mod_list = NULL;
+
+ if (!port_get_all_modules(&mod_list, &mod_count))
+ return false;
+
+ context->clean_modules = true;
+ context->modules = mod_list;
+ }
+ else
+ {
+ context->clean_modules = false;
+ context->modules = modules;
+ }
+
+ if (!native_get_stack_range(context, regs, &context->stack))
+ {
+ if (context->clean_modules)
+ port_clear_modules(&context->modules);
+ return false;
+ }
+
+ return true;
+}
+
+void port_clean_unwind_context(UnwindContext* context)
+{
+ if (!context)
+ return;
+
+ if (context->modules && context->clean_modules)
+ {
+ port_clear_modules(&context->modules);
+ }
+
+ context->modules = NULL;
+}
+
+bool port_unwind_frame(UnwindContext* context, Registers* regs)
+{
+// if (native_is_frame_exists(context, regs))
+// { // Stack frame (x86)
+// return native_unwind_stack_frame(context, regs);
+// }
+// else
+ { // Stack frame does not exist, try using heuristics
+ return native_unwind_special(context, regs);
+ }
+}
Propchange: harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/native_unwind.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Modified: harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/port_crash_handler.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/port_crash_handler.cpp?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/port_crash_handler.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/port_crash_handler.cpp Tue Mar 18 04:31:02 2008
@@ -16,15 +16,22 @@
*/
#include <assert.h>
+#include <stdlib.h>
+#include "port_malloc.h"
+#include "port_mutex.h"
+#include "stack_dump.h"
+#include "signals_internal.h"
#include "port_crash_handler.h"
-static port_signal_handler signal_callbacks[PORT_SIGNAL_MAX] =
+static port_signal_handler signal_callbacks[] =
{
NULL, // PORT_SIGNAL_GPF
NULL, // PORT_SIGNAL_STACK_OVERFLOW
NULL, // PORT_SIGNAL_ABORT
- NULL, // PORT_SIGNAL_TRAP
- NULL, // PORT_SIGNAL_PRIV_INSTR
+ NULL, // PORT_SIGNAL_QUIT
+ NULL, // PORT_SIGNAL_CTRL_BREAK
+ NULL, // PORT_SIGNAL_CTRL_C
+ NULL, // PORT_SIGNAL_BREAKPOINT
NULL // PORT_SIGNAL_ARITHMETIC
};
@@ -36,32 +43,70 @@
static crash_additional_actions *crash_actions = NULL;
-static unisigned crash_output_flags;
+static unsigned crash_output_flags;
-Boolean port_init_crash_handler(port_signal_handler_registration *registrations,
- unsigned count)
+static osmutex_t g_mutex;
+
+static port_unwind_compiled_frame g_unwind_callback = NULL;
+
+
+Boolean port_init_crash_handler(
+ port_signal_handler_registration *registrations,
+ unsigned count,
+ port_unwind_compiled_frame unwind_callback)
{
- if (initialize_signals() == FALSE)
+ if (initialize_signals() != 0)
return FALSE;
- for (int iii = 0; iii < count; iii++)
+ if (init_private_tls_data() != 0)
+ return FALSE;
+
+ port_mutex_create(&g_mutex, APR_THREAD_MUTEX_NESTED);
+
+ sd_init_crash_handler();
+
+ for (unsigned iii = 0; iii < count; iii++)
{
- assert(registrations[iii]->signum >= PORT_SIGNAL_MIN);
- assert(registrations[iii]->signum <= PORT_SIGNAL_MAX);
- signal_callbacks[registrations[iii]->signum] = registrations[iii]->callback;
+ assert(registrations[iii].signum >= PORT_SIGNAL_MIN);
+ assert(registrations[iii].signum <= PORT_SIGNAL_MAX);
+ signal_callbacks[registrations[iii].signum] = registrations[iii].callback;
}
+ g_unwind_callback = unwind_callback;
+
return TRUE;
}
-void port_crash_handler_set_flags(port_crash_handler_flags flags)
+unsigned port_crash_handler_get_capabilities()
+{
+ // Return the features we currently support
+ return (port_crash_handler_flags)
+ (PORT_CRASH_CALL_DEBUGGER |
+ PORT_CRASH_DUMP_TO_STDERR |
+ PORT_CRASH_STACK_DUMP |
+ PORT_CRASH_DUMP_ALL_THREADS |
+ PORT_CRASH_PRINT_COMMAND_LINE |
+ PORT_CRASH_PRINT_ENVIRONMENT |
+ PORT_CRASH_PRINT_MODULES |
+ PORT_CRASH_PRINT_REGISTERS |
+ PORT_CRASH_DUMP_PROCESS_CORE);
+
+}
+
+void port_crash_handler_set_flags(unsigned flags)
{
crash_output_flags = flags;
}
+unsigned port_crash_handler_get_flags()
+{
+ return crash_output_flags;
+}
+
Boolean port_crash_handler_add_action(port_crash_handler_action action)
{
- crash_additional_actions *a = STD_MALLOC(sizeof(crash_additional_actions));
+ crash_additional_actions *a =
+ (crash_additional_actions*)STD_MALLOC(sizeof(crash_additional_actions));
if (NULL == a)
return FALSE;
@@ -73,9 +118,12 @@
Boolean port_shutdown_crash_handler()
{
- if (shutdown_signals() == FALSE)
+ if (shutdown_signals() != 0)
return FALSE;
+ if (free_private_tls_data() != 0)
+ return FALSE;
+
for (crash_additional_actions *a = crash_actions; NULL != a;)
{
crash_additional_actions *next = a->next;
@@ -83,5 +131,48 @@
a = next;
}
+ sd_cleanup_crash_handler();
+
+ port_mutex_destroy(&g_mutex);
+
return TRUE;
+}
+
+/* Returns 0 when execution should be continued with (updated) Registers
+ Returns 1 when crash occured and process should invoke a debugger
+ Returns -1 when crash occured and process should be terminated */
+int port_process_signal(port_sigtype signum, Registers *regs, void* fault_addr, Boolean iscrash)
+{
+ if (!iscrash)
+ {
+ assert(signum >= PORT_SIGNAL_MIN);
+ assert(signum <= PORT_SIGNAL_MAX);
+
+ if (signal_callbacks[signum] != NULL)
+ {
+ Boolean cres = signal_callbacks[signum](signum, regs, fault_addr);
+
+ if (cres) // signal was processed
+ return 0;
+ }
+ }
+
+ // CRASH
+ port_mutex_lock(&g_mutex);
+
+ sd_print_crash_info(signum, regs, g_unwind_callback);
+
+ for (crash_additional_actions* action = crash_actions;
+ action; action = action->next)
+ {
+ action->action(signum, regs, fault_addr);
+ }
+
+ if ((crash_output_flags & PORT_CRASH_CALL_DEBUGGER) != 0)
+ {
+ port_mutex_unlock(&g_mutex);
+ return 1;
+ }
+
+ return -1;
}
Copied: harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/stack_dump.cpp (from r637971, harmony/enhanced/drlvm/trunk/vm/vmcore/src/stack/stack_dump.cpp)
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/stack_dump.cpp?p2=harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/stack_dump.cpp&p1=harmony/enhanced/drlvm/trunk/vm/vmcore/src/stack/stack_dump.cpp&r1=637971&r2=638327&rev=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/stack/stack_dump.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/stack_dump.cpp Tue Mar 18 04:31:02 2008
@@ -14,28 +14,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/**
- * @author Vladimir Nenashev
- * @version $Revision$
- */
#include <ctype.h>
-#include "vm_threads.h"
+#include <assert.h>
+#include <string.h>
+// offsetof macro
+#if defined(WIN32)
+#include <stddef.h>
+#else
+#include <objalloc.h>
+#endif
+
#include "port_malloc.h"
-#include "port_dso.h"
-#include "jit_intf_cpp.h"
-#include "Class.h"
-#include "class_member.h"
-#include "exceptions.h"
-#include "stack_trace.h"
-#include "interpreter_exports.h"
-#include "cci.h"
-#include "m2n.h"
-#include "native_stack.h"
-#include "native_modules.h"
-#include "natives_support.h"
-#include "exception_filter.h"
+#include "port_unwind.h"
+#include "port_modules.h"
+#include "port_crash_handler.h"
+#include "port_frame_info.h"
#include "stack_dump.h"
@@ -52,461 +47,222 @@
assert(res && g_modules && count);
}
-#ifdef SD_UPDATE_MODULES
-// Is called to update modules info
-void sd_update_modules()
-{
- hymutex_t* sd_lock;
- bool res = sd_initialize(&sd_lock);
-
- if (!res)
- return;
-
- hymutex_lock(sd_lock);
- if (g_modules)
- port_clear_modules(&g_modules);
+// "%s::%s (%s): %s:%d" - class::name (signature): file:line
+static const char* vm_fmt_tbl[] = {
+// method_class_name is present
+ "%s::%s (%s): %s:%d\n",
+ "%s::%s (%s)\n", // No sourcefile
+ "%s::%s: %s:%d\n", // No signature
+ "%s::%s\n", // No signature no sourcefile
+// method_class_name is absent
+ "%s (%s): %s:%d\n",
+ "%s (%s)\n", // No sourcefile
+ "%s: %s:%d\n", // No signature
+ "%s\n", // No signature no sourcefile
+};
- int count;
- res = port_get_all_modules(&g_modules, &count);
- assert(res && g_modules && count);
-
- hymutex_unlock(sd_lock);
-}
-#endif // SD_UPDATE_MODULES
-
-
-static char* sd_construct_java_method_name(Method* m, char* buf)
+static void sd_print_vm_line(FILE* file, int count, port_stack_frame_info* fi)
{
- if (!m || !buf)
- {
- *buf = 0;
- return NULL;
- }
-
- char* ptr = buf;
+ if (!fi->method_name)
+ return;
- const char* err_str = "<--Truncated: too long name";
- size_t err_len = strlen(err_str);
+ if (count >= 0)
+ fprintf(file, "%3d: ", count);
+ else
+ fprintf(file, " "); // additional VM info - indent
- size_t remain = SD_MNAME_LENGTH - 1;
- const char* cname = m->get_class()->get_name()->bytes;
- size_t clen = m->get_class()->get_name()->len;
- const char* mname = m->get_name()->bytes;
- size_t mlen = m->get_name()->len;
- const char* descr = m->get_descriptor()->bytes;
- size_t dlen = m->get_descriptor()->len;
+ const void* args[5] = {fi->method_class_name, fi->method_name,
+ fi->method_signature, fi->source_file_name,
+ (const void*)(size_t)fi->source_line_number};
+ const void** pargs = args;
+ int fmt_num = 0;
- if (clen + 1 > remain)
+ if (!fi->method_class_name)
{
- size_t len = remain - err_len;
- memcpy(ptr, cname, len);
- strcpy(ptr + len, err_str);
- return buf;
+ fmt_num += 4;
+ pargs++;
}
-
- memcpy(ptr, cname, clen);
- ptr += clen;
- *ptr++ = '.';
- remain -= clen + 1;
-
- if (mlen > remain)
+ if (!fi->method_signature)
{
- if (remain > err_len)
- memcpy(ptr, mname, remain - err_len);
-
- strcpy(ptr + remain - err_len, err_str);
- return buf;
+ fmt_num += 2;
+ args[2] = args[3];
+ args[3] = args[4];
}
+ if (!fi->source_file_name)
+ fmt_num += 1;
- memcpy(ptr, mname, mlen);
- ptr += mlen;
- remain -= mlen;
-
- if (dlen > remain)
- {
- if (remain > err_len)
- memcpy(ptr, descr, remain - err_len);
-
- strcpy(ptr + remain - err_len, err_str);
- return buf;
- }
-
- strcpy(ptr, descr);
- return buf;
+ fprintf(file, vm_fmt_tbl[fmt_num],
+ pargs[0], pargs[1], pargs[2], pargs[3], pargs[4]);
}
-static void sd_get_java_method_info(MethodInfo* info, Method* m, void* ip,
- bool is_ip_past, int inl_depth)
-{
- *info->method_name = 0;
- *info->file_name = 0;
- info->line = -1;
- if (!m || !method_get_class(m))
- return;
-
- if (!sd_construct_java_method_name(m, info->method_name))
+static void sd_print_c_line(FILE* file, int count, CFunInfo* cfi)
+{
+ if (!cfi->name)
return;
- const char* fname = NULL;
- get_file_and_line(m, ip, is_ip_past, inl_depth, &fname, &info->line);
-
- if (fname)
- {
- if (strlen(fname) >= sizeof(info->file_name))
- {
- memcpy(info->file_name, fname, sizeof(info->file_name));
- info->file_name[sizeof(info->file_name) - 1] = 0;
- }
- else
- strcpy(info->file_name, fname);
- }
+ fprintf(file, "%3d: %s (%s:%d)\n",
+ count, cfi->name,
+ cfi->filename ? cfi->filename : "??",
+ cfi->line);
}
-static void sd_print_line(int count, MethodInfo* m) {
- fprintf(stderr, "%3d: %s (%s:%d)\n",
- count,
- *m->method_name ? m->method_name : "??",
- *m->file_name ? m->file_name : "??",
- m->line);
+static void sd_print_modules()
+{
+ sd_fill_modules(); // Fill modules table if needed
+ fprintf(stderr, "\nLoaded modules:\n\n");
+ port_dump_modules(g_modules, stderr);
}
-static void sd_print_stack_jit(VM_thread* thread,
- native_frame_t* frames, jint num_frames)
+static void sd_print_stack(Registers* regs, port_unwind_compiled_frame unwind)
{
- jint frame_num = 0;
- jint count = 0;
- StackIterator* si = NULL;
-
- if (thread)
- si = si_create_from_native(thread);
-
- while ((si && !si_is_past_end(si)) || frame_num < num_frames)
+ if (!regs)
{
- MethodInfo m;
- void* cur_ip = frames[frame_num].ip;
-
- if (frame_num < num_frames && frames[frame_num].java_depth < 0)
- {
- if (native_is_ip_stub(cur_ip)) // Generated stub
- {
- char buf[81];
- char* stub_name =
- native_get_stub_name(cur_ip, buf, sizeof(buf));
-
- fprintf(stderr, "%3d: 0x%"W_PI_FMT": stub '%s'\n",
- count++, (POINTER_SIZE_INT)cur_ip,
- stub_name ? stub_name : "??");
- ++frame_num;
- continue;
- }
-
- // pure native frame
- native_module_t* module = port_find_module(g_modules, cur_ip);
- sd_get_c_method_info(&m, module, cur_ip);
- sd_print_line(count++, &m);
- ++frame_num;
- continue;
- }
+ fprintf(stderr, "No stack trace due to registers info absence\n");
+ return;
+ }
- // Java/JNI frame, look into stack iterator
+ fprintf(stderr, "\nStack trace:\n");
- // If iterator is exhausted
- if (si_is_past_end(si) ||
- (si_is_native(si) && !m2n_get_previous_frame(si_get_m2n(si))))
- break;
+ Registers locregs = *regs;
+ UnwindContext uwcontext;
+ bool hasnative = false;
- if (si_is_native(si) && frame_num < num_frames)
- {
- // Print information from native stack trace for JNI frames
- native_module_t* module = port_find_module(g_modules, cur_ip);
- sd_get_c_method_info(&m, module, cur_ip);
- sd_print_line(count, &m);
- }
- else if (si_is_native(si) && frame_num >= num_frames)
- {
- // Print information about JNI frames from iterator
- // when native stack trace is not available
- Method* method = m2n_get_method(si_get_m2n(si));
- void* ip = m2n_get_ip(si_get_m2n(si));
- sd_get_java_method_info(&m, method, ip, false, -1);
- sd_print_line(count, &m);
- }
- else // !si_is_native(si)
- {
- // Print information about Java method from iterator
- CodeChunkInfo* cci = si_get_code_chunk_info(si);
- Method* method = cci->get_method();
- void* ip = (void*)si_get_ip(si);
-
- uint32 inlined_depth = si_get_inline_depth(si);
- uint32 offset = (uint32)((POINTER_SIZE_INT)ip -
- (POINTER_SIZE_INT)cci->get_code_block_addr());
- bool is_ip_past = (frame_num != 0);
-
- if (inlined_depth)
- {
- for (uint32 i = inlined_depth; i > 0; i--)
- {
- Method* inl_method = cci->get_jit()->get_inlined_method(
- cci->get_inline_info(), offset, i);
-
- sd_get_java_method_info(&m, inl_method, ip, is_ip_past, i);
- sd_print_line(count++, &m);
-
- if (frame_num < num_frames)
- ++frame_num; // Go to the next native frame
- }
- }
+ if (port_init_unwind_context(&uwcontext, g_modules, &locregs))
+ hasnative = true;
- sd_get_java_method_info(&m, method, ip, is_ip_past, -1);
- sd_print_line(count, &m);
- }
+ port_stack_frame_info uwinfo;
- ++count;
- si_goto_previous(si);
+ int framenum = 0;
+ int uwresult = -1;
- if (frame_num < num_frames)
- ++frame_num; // Go to the next native frame
+ // Prepare VM-specific struct for stack iteration
+ if (unwind)
+ {
+ memset(&uwinfo, 0, sizeof(port_stack_frame_info));
+ uwresult = unwind(&locregs, &uwinfo);
}
- if (si)
- si_free(si);
-}
-
-static void sd_print_stack_interpreter(VM_thread* thread,
- native_frame_t* frames, jint num_frames)
-{
- FrameHandle* frame = interpreter.interpreter_get_last_frame(thread);
- jint frame_num = 0;
- jint count = 0;
-
- while (frame || frame_num < num_frames)
+ if (uwresult > 0)
{
- MethodInfo m;
+ uwinfo.iteration_state = STD_ALLOCA(uwresult);
+ memset(uwinfo.iteration_state, 0, uwresult);
+ uwresult = unwind(&locregs, &uwinfo);
+ assert(uwresult <= 0);
+ }
- if (frame_num < num_frames && frames[frame_num].java_depth < 0)
- { // pure native frame
- native_module_t* module = port_find_module(g_modules, frames[frame_num].ip);
- sd_get_c_method_info(&m, module, frames[frame_num].ip);
- sd_print_line(count++, &m);
- ++frame_num;
+ while (true)
+ {
+ // Unwinding with VM callback
+ if (unwind && uwresult == 0)
+ {
+ sd_print_vm_line(stderr, framenum++, &uwinfo);
+ // Cleanup frame info except 'iteration_state'
+ memset(&uwinfo, 0, offsetof(port_stack_frame_info, iteration_state));
+ // Try unwinding by the callback for next iteration
+ uwresult = unwind(&locregs, &uwinfo);
continue;
}
- // Java/JNI frame, look into stack iterator
-
- Method* method = (Method*)interpreter.interpreter_get_frame_method(frame);
- uint8* bc_ptr = interpreter.interpreter_get_frame_bytecode_ptr(frame);
-
- // Print information from native stack trace
- // when method is not available or is native
- if (frame_num < num_frames &&
- (!method || method_is_native(method)))
- {
- native_module_t* module = port_find_module(g_modules, frames[frame_num].ip);
- sd_get_c_method_info(&m, module, frames[frame_num].ip);
- sd_print_line(count, &m);
+ // Print native frame info
+ CFunInfo cfi = {0};
+ native_module_t* module = port_find_module(g_modules, locregs.get_ip());
+ sd_get_c_method_info(&cfi, module, locregs.get_ip());
+ sd_print_c_line(stderr, framenum++, &cfi);
+
+ if (unwind && uwresult < 0 && uwinfo.method_name)
+ { // VM has not unwound but has provided additional frame info
+ sd_print_vm_line(stderr, -1, &uwinfo); // Print as additional info
}
- // Print information about method from iterator
- // when is Java method or when native stack trace is not available
- if (method &&
- (!method_is_native(method) || frame_num >= num_frames))
- {
- sd_get_java_method_info(&m, method, (void*)bc_ptr, false, -1);
- sd_print_line(count, &m);
- }
-
- ++count;
- frame = interpreter.interpreter_get_prev_frame(frame);
-
- if (frame_num < num_frames)
- ++frame_num; // Go to the next native frame
- }
-}
-
-const char* sd_get_module_type(const char* short_name)
-{
- char name[256];
-
- if (strlen(short_name) > 255)
- return "Too long short name";
-
- strcpy(name, short_name);
- char* dot = strchr(name, '.');
-
- // Strip suffix/extension
- if (dot)
- *dot = 0;
-
- // Strip prefix
- char* nameptr = name;
+ if (!hasnative) // Native unwinding is not initialized
+ break;
- if (!memcmp(short_name, PORT_DSO_PREFIX, strlen(PORT_DSO_PREFIX)))
- nameptr += strlen(PORT_DSO_PREFIX);
+ // Try native unwinding
+ bool nativeres = port_unwind_frame(&uwcontext, &locregs);
- char* vm_modules[] = {"java", "em", "encoder", "gc_gen", "gc_gen_uncomp", "gc_cc",
- "harmonyvm", "hythr", "interpreter", "jitrino", "vmi"};
+ if (!nativeres)
+ break; // Neither VM calback nor native unwinding can unwind the frame
- for (size_t i = 0; i < sizeof(vm_modules)/sizeof(vm_modules[0]); i++)
- {
- if (!strcmp_case(name, vm_modules[i]))
- return "VM native code";
+ // Cleanup frame info except 'iteration_state'
+ memset(&uwinfo, 0, offsetof(port_stack_frame_info, iteration_state));
+ // Try unwinding by the callback for next iteration
+ uwresult = unwind(&locregs, &uwinfo);
}
- if (natives_is_library_loaded_slow(short_name))
- return "JNI native library";
+ if (hasnative)
+ port_clean_unwind_context(&uwcontext);
- return "Unknown/system native module";
+ fprintf(stderr, "<end of stack trace>\n");
+ fflush(stderr);
}
-static void sd_print_module_info(Registers* regs)
+struct sig_name_t
{
-#ifdef SD_UPDATE_MODULES
- sd_fill_modules(); // Fill modules table if needed
-#endif
+ int num;
+ char* name;
+};
- native_module_t* module = port_find_module(g_modules, (void*)regs->get_ip());
- sd_parse_module_info(module, (void*)regs->get_ip());
-}
-
-static void sd_print_modules()
+static sig_name_t sig_names[] =
{
- fprintf(stderr, "\nLoaded modules:\n\n");
- port_dump_modules(g_modules, stderr);
-}
-
+ {PORT_SIGNAL_GPF, "GENERAL_PROTECTION_FAULT"},
+ {PORT_SIGNAL_STACK_OVERFLOW, "STACK_OVERFLOW"},
+ {PORT_SIGNAL_ABORT, "ABORT" },
+ {PORT_SIGNAL_QUIT, "QUIT"},
+ {PORT_SIGNAL_CTRL_C, "CTRL_C" },
+ {PORT_SIGNAL_CTRL_BREAK, "CTRL_BREAK" },
+ {PORT_SIGNAL_BREAKPOINT, "BREAKPOINT"},
+ {PORT_SIGNAL_ARITHMETIC, "ARITHMETIC_EXCEPTION" },
+ {PORT_SIGNAL_UNKNOWN, "UNKNOWN"}
+};
-static void sd_print_threads_info(VM_thread* cur_thread)
+static const char* get_sig_name(int signum)
{
- if (!cur_thread)
- fprintf(stderr, "\nCurrent thread is not attached to VM, ID: %d\n", sd_get_cur_tid());
-
- fprintf(stderr, "\nVM attached threads:\n\n");
-
- hythread_iterator_t it = hythread_iterator_create(NULL);
- int count = (int)hythread_iterator_size (it);
-
- for (int i = 0; i < count; i++)
+ for (int i = 0; i < sizeof(sig_names)/sizeof(sig_names[0]); i++)
{
- hythread_t thread = hythread_iterator_next(&it);
- VM_thread* vm_thread = jthread_get_vm_thread(thread);
-
- if (!vm_thread)
- continue;
-
- jthread java_thread = jthread_get_java_thread(thread);
- JNIEnv* jni_env = vm_thread->jni_env;
-
- if (cur_thread && java_thread)
- {
- jclass cl = GetObjectClass(jni_env, java_thread);
- jmethodID id = jni_env->GetMethodID(cl, "getName","()Ljava/lang/String;");
- jstring name = jni_env->CallObjectMethod(java_thread, id);
- char* java_name = (char*)jni_env->GetStringUTFChars(name, NULL);
-
- fprintf(stderr, "%s[%p] '%s'\n",
- (cur_thread && vm_thread == cur_thread) ? "--->" : " ",
- thread->os_handle, java_name);
-
- jni_env->ReleaseStringUTFChars(name, java_name);
- }
- else
- {
- fprintf(stderr, "%s[%p]\n",
- (cur_thread && vm_thread == cur_thread) ? "--->" : " ",
- thread->os_handle);
- }
+ if (signum == sig_names[i].num)
+ return sig_names[i].name;
}
- hythread_iterator_release(&it);
+ return "unknown signal";
}
-
-void sd_print_stack(Registers* regs)
+static void print_name_and_context(int signum, Registers* regs)
{
- hymutex_t* sd_lock;
- int disable_count;
- bool unwindable;
-
- VM_thread* thread = get_thread_ptr(); // Can be NULL for pure native thread
-
- // Enable suspend to allow working with threads
- if (thread)
- disable_count = hythread_reset_suspend_disable();
+ // Print signal name
+ fprintf(stderr, "\nSignal reported: %s\n", get_sig_name(signum));
- // Acquire global lock to print threads list and stop other crashed threads
- hythread_global_lock();
-
- if (!sd_initialize(&sd_lock))
- return;
+ // Print register state
+ if (regs)
+ print_reg_state(regs);
+ else
+ fprintf(stderr, "\nRegisters info is absent\n");
+}
- hymutex_lock(sd_lock);
- if (thread)
- unwindable = set_unwindable(false); // To call Java code
- // Print register info
- print_reg_state(regs);
+void sd_print_crash_info(int signum, Registers* regs, port_unwind_compiled_frame unwind)
+{
+ // Print signal name and register info
+ if (port_crash_handler_get_flags() & PORT_CRASH_PRINT_REGISTERS)
+ print_name_and_context(signum, regs);
- // Print crashed modile info
- sd_print_module_info(regs);
+ // Print command line and working directory
+ if (port_crash_handler_get_flags() & PORT_CRASH_PRINT_COMMAND_LINE)
+ sd_print_cmdline_cwd();
// Print program environment info
- sd_print_cwdcmdenv();
+ if (port_crash_handler_get_flags() & PORT_CRASH_PRINT_ENVIRONMENT)
+ sd_print_environment();
// Print the whole list of modules
- sd_print_modules();
-
- native_frame_t* frames = NULL;
-
- // Print threads info
- sd_print_threads_info(thread);
-
- // We are trying to get native stack trace using walk_native_stack_registers
- // function and get corresponding Java methods for stack trace from
- // JIT/interpreter stack iterator.
- // When native stack trace is not complete (for example, when
- // walk_native_stack_registers cannot unwind frames in release build),
- // we will use JIT/interpreter stack iterator to complete stack trace.
-
- WalkContext context;
-
- if (native_init_walk_context(&context, g_modules, regs))
- {
- jint num_frames =
- walk_native_stack_registers(&context, regs, thread, -1, NULL);
-
- if (num_frames)
- frames = (native_frame_t*)STD_ALLOCA(sizeof(native_frame_t)*num_frames);
-
- if (num_frames && frames)
- walk_native_stack_registers(&context, regs, thread, num_frames, frames);
- else
- num_frames = 0; // Consider native stack trace empty
-
- fprintf(stderr, "\nStack trace:\n");
-
- if (interpreter_enabled() && thread)
- sd_print_stack_interpreter(thread, frames, num_frames);
- else // It should be used also for threads without VM_thread structure
- sd_print_stack_jit(thread, frames, num_frames);
-
- fprintf(stderr, "<end of stack trace>\n");
- fflush(stderr);
- }
-
- if (thread)
- set_unwindable(unwindable);
-
- // Do not unlock to prevent other threads from printing crash stack
- //hymutex_unlock(sd_lock);
+ if (port_crash_handler_get_flags() & PORT_CRASH_PRINT_MODULES)
+ sd_print_modules();
- hythread_global_unlock();
- if (thread)
- hythread_set_suspend_disable(disable_count);
+ // Print stack of crashed module
+ if (port_crash_handler_get_flags() & PORT_CRASH_STACK_DUMP)
+ sd_print_stack(regs, unwind);
}
Copied: harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/win/native_unwind_os.cpp (from r637971, harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/native_stack_os.cpp)
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/win/native_unwind_os.cpp?p2=harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/win/native_unwind_os.cpp&p1=harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/native_stack_os.cpp&r1=637971&r2=638327&rev=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/native_stack_os.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/win/native_unwind_os.cpp Tue Mar 18 04:31:02 2008
@@ -16,11 +16,12 @@
*/
-#include "native_modules.h"
-#include "native_stack.h"
+#include "open/hythread_ext.h" // for correct Windows.h inclusion
+#include "port_modules.h"
+#include "native_unwind.h"
-bool native_is_in_code(WalkContext* context, void* ip)
+bool native_is_in_code(UnwindContext* context, void* ip)
{
if (!ip)
return false;
@@ -37,7 +38,7 @@
PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)) != 0);
}
-bool native_get_stack_range(WalkContext* context, Registers* regs, native_segment_t* seg)
+bool native_get_stack_range(UnwindContext* context, Registers* regs, native_segment_t* seg)
{
MEMORY_BASIC_INFORMATION mem_info;
Copied: harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/win/stack_dump_os.cpp (from r637971, harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/stack_dump_platf.cpp)
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/win/stack_dump_os.cpp?p2=harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/win/stack_dump_os.cpp&p1=harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/stack_dump_platf.cpp&r1=637971&r2=638327&rev=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/stack_dump_platf.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/win/stack_dump_os.cpp Tue Mar 18 04:31:02 2008
@@ -15,10 +15,10 @@
* limitations under the License.
*/
-#include "open/hythread_ext.h"
-#include "native_stack.h"
+#include <string.h>
+#include "open/hythread_ext.h" // for correct Windows.h inclusion
+#include "port_malloc.h"
#include "stack_dump.h"
-#include "port_filepath.h"
#ifndef NO_DBGHELP
#include <dbghelp.h>
@@ -26,10 +26,9 @@
#endif
-static hymutex_t g_lock;
-static const char* g_curdir = NULL;
-static const char* g_cmdline = NULL;
-static const char* g_environ = NULL;
+static char* g_curdir = NULL;
+static char* g_cmdline = NULL;
+static char* g_environ = NULL;
#ifndef NO_DBGHELP
typedef BOOL (WINAPI *SymFromAddr_type)
@@ -49,111 +48,80 @@
OUT PDWORD pdwDisplacement,
OUT PIMAGEHLP_LINE Line );
+typedef BOOL (WINAPI *MiniDumpWriteDump_type)
+ (HANDLE hProcess,
+ DWORD ProcessId,
+ HANDLE hFile,
+ MINIDUMP_TYPE DumpType,
+ PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
+ PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
+ PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
+
static SymFromAddr_type g_SymFromAddr = NULL;
static SymGetLineFromAddr64_type g_SymGetLineFromAddr64 = NULL;
static SymGetLineFromAddr_type g_SymGetLineFromAddr = NULL;
#endif // #ifndef NO_DBGHELP
-bool sd_initialize(hymutex_t** p_lock)
-{
- static int initialized = 0;
-
- if (!initialized)
- {
- IDATA err = hymutex_create(&g_lock, APR_THREAD_MUTEX_NESTED);
-
- if (err != APR_SUCCESS)
- return false;
+void create_minidump(LPEXCEPTION_POINTERS exp)
+{
#ifndef NO_DBGHELP
-// Preventive initialization does not work
-// if (!SymInitialize(GetCurrentProcess(), NULL, TRUE))
-// return false;
+ MINIDUMP_EXCEPTION_INFORMATION mei = {GetCurrentThreadId(), exp, TRUE};
+ MiniDumpWriteDump_type mdwd = NULL;
- HMODULE hdbghelp = ::LoadLibrary("dbghelp");
+ HMODULE hdbghelp = ::LoadLibrary("dbghelp");
- if (hdbghelp)
- {
- SymSetOptions(SYMOPT_LOAD_LINES);
- g_SymFromAddr = (SymFromAddr_type)::GetProcAddress(hdbghelp, "SymFromAddr");
- g_SymGetLineFromAddr64 = (SymGetLineFromAddr64_type)::GetProcAddress(hdbghelp, "SymGetLineFromAddr64");
- g_SymGetLineFromAddr = (SymGetLineFromAddr_type)::GetProcAddress(hdbghelp, "SymGetLineFromAddr");
- }
-#endif // #ifndef NO_DBGHELP
+ if (hdbghelp)
+ mdwd = (MiniDumpWriteDump_type)::GetProcAddress(hdbghelp, "MiniDumpWriteDump");
- initialized = true;
+ if (!mdwd)
+ {
+ fprintf(stderr, "\nFailed to open DbgHelp library\n");
+ fflush(stderr);
+ return;
}
- if (p_lock)
- *p_lock = &g_lock;
-
- return true;
-}
-
-
-static const char* sd_get_region_access_info(MEMORY_BASIC_INFORMATION* pinfo)
-{
- if ((pinfo->State & MEM_COMMIT) == 0)
- return "not committed";
-
- if ((pinfo->Protect & PAGE_GUARD) != 0)
- return "guard page occured";
+ char filename[24];
+ sprintf(filename, "minidump_%d.dmp", GetCurrentProcessId());
- if ((pinfo->Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ |
- PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY |
- PAGE_READWRITE | PAGE_READONLY)) != 0)
- return "";
+ HANDLE file = CreateFile(filename, GENERIC_WRITE, 0, 0,
+ CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
- if ((pinfo->Protect & (PAGE_READWRITE | PAGE_READONLY)) != 0)
- return "without execution rights";
-
- return "without read rights";;
-}
-
-void sd_parse_module_info(native_module_t* module, void* ip)
-{
- fprintf(stderr, "\nCrashed module:\n");
-
- if (module)
+ if (file == INVALID_HANDLE_VALUE)
{
- native_segment_t* segment = module->segments;
+ fprintf(stderr, "\nFailed to create minidump file: %s\n", filename);
+ fflush(stderr);
+ return;
+ }
- assert(module->filename);
+ SymInitialize(GetCurrentProcess(), NULL, TRUE);
- if (!module->filename)
- { // We should not reach this code
- fprintf(stderr, "Unknown memory region 0x%"W_PI_FMT":0x%"W_PI_FMT"%s\n",
- (size_t)segment->base, (size_t)segment->base + segment->size,
- (segment->type == SEGMENT_TYPE_CODE) ? "" : " without execution rights");
- return;
- }
+ BOOL res = mdwd(GetCurrentProcess(), GetCurrentProcessId(),
+ file, MiniDumpNormal, &mei, 0, 0);
- // Common shared module
- const char* short_name = port_filepath_basename(module->filename);
- const char* module_type = sd_get_module_type(short_name);
- fprintf(stderr, "%s\n(%s)\n", module->filename, module_type);
- return;
+ if (!res)
+ {
+ fprintf(stderr, "\nFailed to create minidump\n");
+ fflush(stderr);
+ }
+ else
+ {
+ char dir[_MAX_PATH];
+ GetCurrentDirectory(_MAX_PATH, dir);
+ fprintf(stderr, "\nMinidump is generated:\n%s\\%s\n", dir, filename);
+ fflush(stderr);
}
- // module == NULL
- size_t start_addr, end_addr, region_size;
- MEMORY_BASIC_INFORMATION mem_info;
-
- VirtualQuery(ip, &mem_info, sizeof(mem_info));
- start_addr = (size_t)mem_info.BaseAddress;
- region_size = (size_t)mem_info.RegionSize;
- end_addr = start_addr + region_size;
-
- fprintf(stderr, "Memory region 0x%"W_PI_FMT":0x%"W_PI_FMT" %s\n",
- start_addr, end_addr, sd_get_region_access_info(&mem_info));
+ CloseHandle(file);
+#endif // #ifndef NO_DBGHELP
}
-void sd_get_c_method_info(MethodInfo* info, native_module_t* UNREF module, void* ip)
+void sd_get_c_method_info(CFunInfo* info, native_module_t* module, void* ip)
{
- *info->method_name = 0;
- *info->file_name = 0;
+ *info->name = 0;
+ *info->filename = 0;
info->line = -1;
#ifndef NO_DBGHELP
@@ -170,7 +138,7 @@
if (g_SymFromAddr &&
g_SymFromAddr(GetCurrentProcess(), (DWORD64)(POINTER_SIZE_INT)ip, &funcDispl, pSymb))
{
- strcpy(info->method_name, pSymb->Name);
+ strcpy(info->name, pSymb->Name);
}
if (g_SymGetLineFromAddr64)
@@ -184,7 +152,7 @@
&offset, &lineinfo))
{
info->line = lineinfo.LineNumber;
- strncpy(info->file_name, lineinfo.FileName, sizeof(info->file_name));
+ strncpy(info->filename, lineinfo.FileName, sizeof(info->filename));
return;
}
}
@@ -200,20 +168,31 @@
&offset, &lineinfo))
{
info->line = lineinfo.LineNumber;
- strncpy(info->file_name, lineinfo.FileName, sizeof(info->file_name));
+ strncpy(info->filename, lineinfo.FileName, sizeof(info->filename));
}
}
#endif // #ifndef NO_DBGHELP
}
-int sd_get_cur_tid()
-{
- return GetCurrentThreadId();
-}
-
void sd_init_crash_handler()
{
+#ifndef NO_DBGHELP
+// Preventive initialization does not work
+// if (!SymInitialize(GetCurrentProcess(), NULL, TRUE))
+// return false;
+
+ HMODULE hdbghelp = ::LoadLibrary("dbghelp");
+
+ if (hdbghelp)
+ {
+ SymSetOptions(SYMOPT_LOAD_LINES);
+ g_SymFromAddr = (SymFromAddr_type)::GetProcAddress(hdbghelp, "SymFromAddr");
+ g_SymGetLineFromAddr64 = (SymGetLineFromAddr64_type)::GetProcAddress(hdbghelp, "SymGetLineFromAddr64");
+ g_SymGetLineFromAddr = (SymGetLineFromAddr_type)::GetProcAddress(hdbghelp, "SymGetLineFromAddr");
+ }
+#endif // #ifndef NO_DBGHELP
+
// Get current directory
DWORD required = GetCurrentDirectory(0, NULL);
char* ptr = (char*)STD_MALLOC(required);
@@ -256,11 +235,21 @@
FreeEnvironmentStrings((char*)env_block);
}
-void sd_print_cwdcmdenv()
+void sd_cleanup_crash_handler()
+{
+ STD_FREE(g_curdir);
+ STD_FREE(g_cmdline);
+ STD_FREE(g_environ);
+}
+
+void sd_print_cmdline_cwd()
{
- fprintf(stderr, "\nWorking directory:\n%s\n", g_curdir ? g_curdir : "'null'");
fprintf(stderr, "\nCommand line:\n%s\n", g_cmdline);
+ fprintf(stderr, "\nWorking directory:\n%s\n", g_curdir ? g_curdir : "'null'");
+}
+void sd_print_environment()
+{
fprintf(stderr, "\nEnvironment variables:\n");
const char* penv = (char*)g_environ;
Copied: harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess.cpp (from r637971, harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/utils/ncai_memory_linux.cpp)
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess.cpp?p2=harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess.cpp&p1=harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/utils/ncai_memory_linux.cpp&r1=637971&r2=638327&rev=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/utils/ncai_memory_linux.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess.cpp Tue Mar 18 04:31:02 2008
@@ -1,3 +1,19 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
/**
* @author Ilya Berezhniuk
* @version $Revision$
@@ -5,283 +21,98 @@
#include <sys/mman.h>
#include <limits.h>
+#include "port_general.h"
#include "port_vmem.h"
-#ifdef _IA32_
-#include "encoder.h"
-#include "jit_intf_cpp.h"
-#endif // #ifdef _IA32_
-#include "nogc.h"
-#include "dump.h"
-#include "ncai_direct.h"
-#include "ncai_internal.h"
+#include "port_barriers.h"
+#include "signals_internal.h"
+#include "port_memaccess.h"
-typedef void* (__cdecl *get_return_address_stub_type)();
+extern "C" void port_memcpy_asm(void* dst, const void* src, size_t size,
+ void** prestart_addr, void* memcpyaddr);
-#ifdef _IA32_
-static get_return_address_stub_type gen_get_return_address_stub()
+static int memcpy_internal(void* dst, const void* src, size_t size, int from)
{
- static get_return_address_stub_type addr = NULL;
-
- if (addr)
- return addr;
-
- const int stub_size = 0x04;
- char *stub = (char *)malloc_fixed_code_for_jit(stub_size, DEFAULT_CODE_ALIGNMENT, CODE_BLOCK_HEAT_COLD, CAA_Allocate);
-#ifdef _DEBUG
- memset(stub, 0xcc /*int 3*/, stub_size);
-#endif
- char *ss = stub;
-
- M_Base_Opnd m1(esp_reg, 0);
- ss = mov(ss, eax_opnd, m1);
- ss = ret(ss);
-
- addr = (get_return_address_stub_type)stub;
- assert(ss - stub <= stub_size);
-
- /*
- The following code will be generated:
+ port_tls_data tlsdata;
- mov eax,dword ptr [esp]
- ret
- */
-
- DUMP_STUB(stub, "get_return_address", ss - stub);
-
- return addr;
-}
-#endif // #ifdef _IA32_
-
-
-ncaiError ncai_read_memory_internal(void* addr, size_t size, void* buf, bool UNUSED calc_pass = false)
-{
-#ifndef _IA32_
- // SIGSEGV processing is not implemented for EM64T/IPF
- memcpy(buf, addr, size);
- return NCAI_ERROR_NONE;
-#else // #ifndef _IA32_
-
-static void* read_memory_1st_label = NULL;
-static void* read_memory_2nd_label = NULL;
-
- char dummy_str[3];
-
- if (calc_pass)
+ if (!get_private_tls_data())
{
- addr = dummy_str;
- buf = dummy_str;
- *dummy_str = 'a'; // To avoid warnings
- size = 1;
+ if (set_private_tls_data(&tlsdata) != 0)
+ return -1;
}
- jvmti_thread_t jvmti_thread = &p_TLS_vmthread->jvmti_thread;
+ tlsdata.violation_flag = 1;
- unsigned char* src_ptr = (unsigned char*)addr;
- unsigned char* dest_ptr = (unsigned char*)buf;
+ void* memcpyaddr = (void*)&memcpy;
+ port_memcpy_asm(dst, src, size, &tlsdata.restart_address, memcpyaddr);
- jvmti_thread->violation_flag = 1;
- jvmti_thread->violation_restart_address = read_memory_1st_label;
-
- size_t i;
- for (i = 0; i < size; i++)
+ if (tlsdata.violation_flag == 1)
{
- *dest_ptr = *src_ptr;
-
- void* label = (gen_get_return_address_stub())();
- read_memory_1st_label = label;
-
- if (jvmti_thread->violation_flag == 0)
- break;
-
- ++src_ptr;
- ++dest_ptr;
+ pthread_setspecific(port_tls_key, NULL);
+ return 0;
}
- if (jvmti_thread->violation_flag == 0 || calc_pass)
- {
- if (!calc_pass)
- {
- size_t* page_sizes = port_vmem_page_sizes();
- size_t page_size = page_sizes[0];
-
- POINTER_SIZE_INT start =
- ((POINTER_SIZE_INT)addr + i) & ~(page_size - 1);
- POINTER_SIZE_INT pastend =
- ((POINTER_SIZE_INT)addr + size + page_size - 1) & ~(page_size - 1);
-
- int result = mprotect((void*)start, pastend - start,
- PROT_READ | PROT_WRITE | PROT_EXEC);
-
- if (result == EAGAIN)
- {
- timespec delay = {0, 10};
- nanosleep(&delay, NULL);
- result = mprotect((void*)start, pastend - start,
- PROT_READ | PROT_WRITE | PROT_EXEC);
- }
-
- if (result != 0)
- return NCAI_ERROR_ACCESS_DENIED;
- }
-
- if (calc_pass)
- ++size;
-
- jvmti_thread->violation_flag = 1;
- jvmti_thread->violation_restart_address = read_memory_2nd_label;
-
- for (; i < size; i++)
- {
- *dest_ptr++ = *src_ptr++;
-
- void* label = (gen_get_return_address_stub())();
- read_memory_2nd_label = label;
-
- if (jvmti_thread->violation_flag == 0)
- return NCAI_ERROR_ACCESS_DENIED;
- }
- }
-
- jvmti_thread->violation_flag = 0;
- return NCAI_ERROR_NONE;
-#endif // #ifndef _IA32_
-}
-
-
-ncaiError ncai_read_memory(void* addr, size_t size, void* buf)
-{
- if (!buf || !addr)
- return NCAI_ERROR_NULL_POINTER;
-
- if (size == 0)
- return NCAI_ERROR_ILLEGAL_ARGUMENT;
-
- if (p_TLS_vmthread == NULL)
- return NCAI_ERROR_INTERNAL;
-
- if (ncai_read_memory_internal(NULL, 0, NULL, true) != NCAI_ERROR_NONE)
- return NCAI_ERROR_INTERNAL;
-
- return ncai_read_memory_internal(addr, size, buf, false);
-}
-
+ // Try changing memory access
+ size_t* page_sizes = port_vmem_page_sizes();
+ size_t page_size = page_sizes[0];
-static ncaiError ncai_write_memory_internal(void* addr, size_t size, void* buf, bool UNUSED calc_pass = false)
-{
-#ifndef _IA32_
- // SIGSEGV processing is not implemented for EM64T/IPF
- memcpy(addr, buf, size);
- return NCAI_ERROR_NONE;
-#else // #ifndef _IA32_
+ const void* addr = from ? src : dst;
-static void* write_memory_1st_label = NULL;
-static void* write_memory_2nd_label = NULL;
+ POINTER_SIZE_INT start =
+ (POINTER_SIZE_INT)addr & ~(page_size - 1);
+ POINTER_SIZE_INT pastend =
+ ((POINTER_SIZE_INT)addr + size + page_size - 1) & ~(page_size - 1);
- char dummy_str[3];
+ int result = mprotect((void*)start, pastend - start,
+ PROT_READ | PROT_WRITE | PROT_EXEC);
- if (calc_pass)
+ if (result == EAGAIN)
{
- addr = dummy_str;
- buf = dummy_str;
- *dummy_str = 'a'; // To avoid warnings
- size = 1;
+ timespec delay = {0, 10};
+ nanosleep(&delay, NULL);
+ result = mprotect((void*)start, pastend - start,
+ PROT_READ | PROT_WRITE | PROT_EXEC);
}
- jvmti_thread_t jvmti_thread = &p_TLS_vmthread->jvmti_thread;
+ if (result != 0)
+ return -1;
- unsigned char* src_ptr = (unsigned char*)buf;
- unsigned char* dest_ptr = (unsigned char*)addr;
+ tlsdata.violation_flag = 1;
- jvmti_thread->violation_flag = 1;
- jvmti_thread->violation_restart_address = write_memory_1st_label;
+ port_memcpy_asm(dst, src, size, &tlsdata.restart_address, memcpyaddr);
- size_t i;
- for (i = 0; i < size; i++)
- {
- *dest_ptr = *src_ptr;
-
- void* label = (gen_get_return_address_stub())();
- write_memory_1st_label = label;
+ pthread_setspecific(port_tls_key, NULL);
+ return (tlsdata.violation_flag == 1) ? 0 : -1;
+}
- if (jvmti_thread->violation_flag == 0)
- break;
- ++src_ptr;
- ++dest_ptr;
- }
+int port_read_memory(void* addr, size_t size, void* buf)
+{
+ if (!buf || !addr)
+ return -1;
- if (jvmti_thread->violation_flag == 0 || calc_pass)
- {
- if (!calc_pass)
- {
- size_t* page_sizes = port_vmem_page_sizes();
- size_t page_size = page_sizes[0];
-
- POINTER_SIZE_INT start =
- ((POINTER_SIZE_INT)addr + i) & ~(page_size - 1);
- POINTER_SIZE_INT pastend =
- ((POINTER_SIZE_INT)addr + size + page_size - 1) & ~(page_size - 1);
-
- int result = mprotect((void*)start, pastend - start,
- PROT_READ | PROT_WRITE | PROT_EXEC);
-
- if (result == EAGAIN)
- {
- timespec delay = {0, 10};
- nanosleep(&delay, NULL);
- result = mprotect((void*)start, pastend - start,
- PROT_READ | PROT_WRITE | PROT_EXEC);
- }
-
- if (result != 0)
- return NCAI_ERROR_ACCESS_DENIED;
- }
-
- if (calc_pass)
- ++size;
-
- jvmti_thread->violation_flag = 1;
- jvmti_thread->violation_restart_address = write_memory_2nd_label;
-
- for (; i < size; i++)
- {
- *dest_ptr++ = *src_ptr++;
-
- void* label = (gen_get_return_address_stub())();
- write_memory_2nd_label = label;
-
- if (jvmti_thread->violation_flag == 0)
- return NCAI_ERROR_ACCESS_DENIED;
- }
- }
+ if (size == 0)
+ return 0;
-#ifdef _IPF_
- asm volatile ("mf" ::: "memory");
-#else
- __asm__("mfence");
-#endif
-
- jvmti_thread->violation_flag = 0;
- return NCAI_ERROR_NONE;
-#endif // #ifndef _IA32_
+ return memcpy_internal(buf, addr, size, 1);
}
-ncaiError ncai_write_memory(void* addr, size_t size, void* buf)
+int port_write_memory(void* addr, size_t size, void* buf)
{
if (!buf || !addr)
- return NCAI_ERROR_NULL_POINTER;
+ return -1;
if (size == 0)
- return NCAI_ERROR_ILLEGAL_ARGUMENT;
+ return 0;
- if (p_TLS_vmthread == NULL)
- return NCAI_ERROR_INTERNAL;
+ int result = memcpy_internal(addr, buf, size, 0);
- if (ncai_write_memory_internal(NULL, 0, NULL, true) != NCAI_ERROR_NONE)
- return NCAI_ERROR_INTERNAL;
+ if (result == 0)
+ {
+ port_rw_barrier();
+ }
- return ncai_write_memory_internal(addr, size, buf, false);
+ return result;
}
Added: harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess_em64t.s
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess_em64t.s?rev=638327&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess_em64t.s (added)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess_em64t.s Tue Mar 18 04:31:02 2008
@@ -0,0 +1,42 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+ .text
+ .align 16
+
+// port_memcpy_asm(void* dst, const void* src, size_t size,
+// void** prestart_addr, void* memcpyaddr);
+// 1st arg (RDI) - dest
+// 2nd arg (RSI) - src
+// 3rd arg (RDX) - len
+// 4th arg (RCX) - address of restart_address storage
+// 5th arg (R8) - address of memcpy - to avoid PIC problems in GNU asm
+
+.globl port_memcpy_asm
+ .type port_memcpy_asm, @function
+port_memcpy_asm:
+ pushq %rbx
+ callq precall
+precall:
+ popq %rax
+ addq $(preret - precall), %rax
+ movq %rax, (%rcx)
+
+ callq *%r8
+
+preret:
+ popq %rbx
+ ret
Added: harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess_ia32.s
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess_ia32.s?rev=638327&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess_ia32.s (added)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess_ia32.s Tue Mar 18 04:31:02 2008
@@ -0,0 +1,49 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+ .text
+ .align 4
+
+// port_memcpy_asm(void* dst, const void* src, size_t size,
+// void** prestart_addr, void* memcpyaddr);
+// 1st arg (EBP + 8) - dest
+// 2nd arg (EBP + 12) - src
+// 3rd arg (EBP + 16) - len
+// 4th arg (EBP + 20) - address of restart_address storage
+// 5th arg (EBP + 24) - address of memcpy - not used on x86
+
+.globl port_memcpy_asm
+ .type port_memcpy_asm, @function
+port_memcpy_asm:
+ pushl %ebp
+ movl %esp, %ebp
+ subl $20, %esp
+
+ movl 20(%ebp), %eax
+ movl $preret, (%eax)
+
+ movl 8(%ebp), %eax
+ movl %eax, (%esp)
+ movl 12(%ebp), %eax
+ movl %eax, 4(%esp)
+ movl 16(%ebp), %eax
+ movl %eax, 8(%esp)
+ call memcpy
+
+preret:
+ addl $20, %esp
+ popl %ebp
+ ret
Added: harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess_ipf.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess_ipf.cpp?rev=638327&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess_ipf.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess_ipf.cpp Tue Mar 18 04:31:02 2008
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @author Ilya Berezhniuk
+ * @version $Revision$
+ */
+
+#include <string.h>
+#include "port_memaccess.h"
+
+
+int port_read_memory(void* addr, size_t size, void* buf)
+{
+ if (!buf || !addr)
+ return -1;
+
+ if (size == 0)
+ return 0;
+
+ memcpy(buf, addr, size);
+
+ return 0;
+}
+
+int port_write_memory(void* addr, size_t size, void* buf)
+{
+ if (!buf || !addr)
+ return -1;
+
+ if (size == 0)
+ return 0;
+
+ memcpy(addr, buf, size);
+ asm volatile ("mf" ::: "memory");
+
+ return 0;
+}
Propchange: harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess_ipf.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Copied: harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/win/memaccess.cpp (from r637971, harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/utils/ncai_memory_win.cpp)
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/win/memaccess.cpp?p2=harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/win/memaccess.cpp&p1=harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/utils/ncai_memory_win.cpp&r1=637971&r2=638327&rev=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/utils/ncai_memory_win.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/win/memaccess.cpp Tue Mar 18 04:31:02 2008
@@ -1,49 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
/**
* @author Ilya Berezhniuk
* @version $Revision$
*/
-#include "ncai_direct.h"
-#include "ncai_internal.h"
+
+#include "open/platform_types.h"
+#include <windows.h>
+#include "port_memaccess.h"
-ncaiError ncai_read_memory(void* addr, size_t size, void* buf)
+int port_read_memory(void* addr, size_t size, void* buf)
{
if (!buf || !addr)
- return NCAI_ERROR_NULL_POINTER;
+ return -1;
if (size == 0)
- return NCAI_ERROR_ILLEGAL_ARGUMENT;
+ return 0;
SIZE_T bytes_read;
BOOL result = ReadProcessMemory(GetCurrentProcess(),
addr, buf, size, &bytes_read);
- assert(bytes_read == size);
- if (!result)
- return NCAI_ERROR_ACCESS_DENIED;
+ if (!result || bytes_read != size)
+ return -1;
- return NCAI_ERROR_NONE;
+ return 0;
}
-ncaiError ncai_write_memory(void* addr, size_t size, void* buf)
+int port_write_memory(void* addr, size_t size, void* buf)
{
if (!buf || !addr)
- return NCAI_ERROR_NULL_POINTER;
+ return -1;
if (size == 0)
- return NCAI_ERROR_ILLEGAL_ARGUMENT;
+ return 0;
SIZE_T bytes_written;
BOOL result = WriteProcessMemory(GetCurrentProcess(),
addr, buf, size, &bytes_written);
- assert(bytes_written == size);
- if (!result)
- return NCAI_ERROR_ACCESS_DENIED;
+ if (!result || bytes_written != size)
+ return -1;
FlushInstructionCache(GetCurrentProcess(), addr, size);
- return NCAI_ERROR_NONE;
+ return 0;
}
Modified: harmony/enhanced/drlvm/trunk/vm/port/src/modules/linux/native_modules_os.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/modules/linux/native_modules_os.c?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/modules/linux/native_modules_os.c (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/modules/linux/native_modules_os.c Tue Mar 18 04:31:02 2008
@@ -26,7 +26,7 @@
#include <unistd.h>
#include "open/types.h"
#include "port_malloc.h"
-#include "native_modules.h"
+#include "port_modules.h"
typedef struct _raw_module raw_module;
Modified: harmony/enhanced/drlvm/trunk/vm/port/src/modules/native_modules.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/modules/native_modules.c?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/modules/native_modules.c (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/modules/native_modules.c Tue Mar 18 04:31:02 2008
@@ -18,7 +18,7 @@
#include <stdio.h>
#include "open/types.h"
#include "port_malloc.h"
-#include "native_modules.h"
+#include "port_modules.h"
native_module_t* port_find_module(native_module_t* modules, void* code_ptr)
Modified: harmony/enhanced/drlvm/trunk/vm/port/src/modules/win/native_modules_os.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/modules/win/native_modules_os.c?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/modules/win/native_modules_os.c (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/modules/win/native_modules_os.c Tue Mar 18 04:31:02 2008
@@ -20,11 +20,12 @@
*/
#include "port_malloc.h"
-#include "native_modules.h"
+#include "port_modules.h"
#include <memory.h>
#include <Windows.h>
#include <Tlhelp32.h>
+
static native_module_t* fill_module(MODULEENTRY32 src);
Added: harmony/enhanced/drlvm/trunk/vm/port/src/signals/include/signals_internal.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/include/signals_internal.h?rev=638327&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/include/signals_internal.h (added)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/include/signals_internal.h Tue Mar 18 04:31:02 2008
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _SIGNALS_INTERNAL_H_
+#define _SIGNALS_INTERNAL_H_
+
+#include "port_general.h"
+#include "port_thread.h"
+#include "open/platform_types.h"
+#include "open/hythread_ext.h" /* For windows.h */
+
+
+/* Thread-specific structure */
+typedef struct
+{
+ /* Previous crash handling stage to restart crash processing */
+ int crash_stage;
+
+#ifndef WIN32 /* UNIX */
+ /* Flag and restart address for memory access violation detection */
+ int violation_flag;
+ void* restart_address;
+#endif /* UNIX */
+
+#ifdef WIN32
+ Boolean assert_dialog;
+#endif
+
+ /* Flag to produce minidump/core on the second exception catch */
+ Boolean produce_core;
+
+} port_tls_data;
+
+
+#ifdef WIN32
+typedef DWORD port_tls_key_t;
+#else
+typedef pthread_key_t port_tls_key_t;
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern port_tls_key_t port_tls_key;
+
+int init_private_tls_data();
+int free_private_tls_data();
+
+PORT_INLINE port_tls_data* get_private_tls_data()
+{
+#ifdef WIN32
+ return (port_tls_data*)TlsGetValue(port_tls_key);
+#else
+ return (port_tls_data*)pthread_getspecific(port_tls_key);
+#endif
+}
+
+PORT_INLINE int set_private_tls_data(port_tls_data* data)
+{
+#ifdef WIN32
+ return TlsSetValue(port_tls_key, data) ? 0 : -1;
+#else
+ return pthread_setspecific(port_tls_key, data);
+#endif
+}
+
+
+#define INSTRUMENTATION_BYTE_HLT 0xf4 // HLT instruction
+#define INSTRUMENTATION_BYTE_CLI 0xfa // CLI instruction
+#define INSTRUMENTATION_BYTE_INT3 0xcc // INT 3 instruction
+
+#ifdef WINNT
+#define INSTRUMENTATION_BYTE INSTRUMENTATION_BYTE_CLI
+#else
+#define INSTRUMENTATION_BYTE INSTRUMENTATION_BYTE_INT3
+#endif
+
+
+#ifdef WIN32
+
+/**
+ * Assembler wrapper for clearing CLD flag - bug in VEHs
+ * appeared in debug prolog.
+ */
+LONG NTAPI vectored_exception_handler(LPEXCEPTION_POINTERS nt_exception);
+
+/* Internal exception handler */
+LONG NTAPI vectored_exception_handler_internal(LPEXCEPTION_POINTERS nt_exception);
+
+#else /* UNIX */
+
+//
+
+#endif /* WIN32 */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SIGNALS_INTERNAL_H_ */
Propchange: harmony/enhanced/drlvm/trunk/vm/port/src/signals/include/signals_internal.h
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_common.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_common.cpp?rev=638327&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_common.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_common.cpp Tue Mar 18 04:31:02 2008
@@ -0,0 +1,179 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h>
+#undef __USE_XOPEN
+#include <signal.h>
+
+#include "open/platform_types.h"
+#include "port_crash_handler.h"
+#include "stack_dump.h"
+#include "../linux/include/gdb_crash_handler.h"
+#include "signals_internal.h"
+
+
+port_tls_key_t port_tls_key;
+
+int init_private_tls_data()
+{
+ return (pthread_key_create(&port_tls_key, NULL) == 0) ? 0 : -1;
+}
+
+int free_private_tls_data()
+{
+ return (pthread_key_delete(port_tls_key) == 0) ? 0 : -1;
+}
+
+
+static void c_handler(Registers* pregs, size_t signum, void* fault_addr)
+{ // this exception handler is executed *after* VEH handler returned
+ int result;
+ Registers regs = *pregs;
+
+ // Check if SIGSEGV is produced by port_read/write_memory
+ port_tls_data* tlsdata = get_private_tls_data();
+ if (tlsdata && tlsdata->violation_flag)
+ {
+ tlsdata->violation_flag = 0;
+ pregs->set_ip(tlsdata->restart_address);
+ return;
+ }
+
+ switch ((int)signum)
+ {
+ case SIGSEGV:
+ result = port_process_signal(PORT_SIGNAL_GPF, pregs, fault_addr, FALSE);
+ break;
+ case SIGFPE:
+ result = port_process_signal(PORT_SIGNAL_ARITHMETIC, pregs, fault_addr, FALSE);
+ break;
+ case SIGTRAP:
+ // Correct return address
+ pregs->set_ip((void*)((POINTER_SIZE_INT)pregs->get_ip() - 1));
+ result = port_process_signal(PORT_SIGNAL_BREAKPOINT, pregs, fault_addr, FALSE);
+ break;
+ case SIGINT:
+ result = port_process_signal(PORT_SIGNAL_CTRL_C, pregs, fault_addr, FALSE);
+ break;
+ case SIGQUIT:
+ result = port_process_signal(PORT_SIGNAL_QUIT, pregs, fault_addr, FALSE);
+ break;
+ default:
+ result = port_process_signal(PORT_SIGNAL_UNKNOWN, pregs, fault_addr, TRUE);
+ }
+
+ if (result == 0)
+ return;
+
+ // We've got a crash
+ if (result > 0)
+ { // result > 0 - invoke debugger
+ bool result = gdb_crash_handler(®s);
+ // Continue with exiting process if not sucessful...
+ }
+
+ // result < 0 - exit process
+ if ((port_crash_handler_get_flags() & PORT_CRASH_DUMP_PROCESS_CORE) != 0)
+ { // Return to the same place to produce the same crash and generate core
+ signal(signum, SIG_DFL); // setup default handler
+ return;
+ }
+ // No core needed - simply terminate
+ _exit(-1);
+}
+
+static void general_signal_handler(int signum, siginfo_t* info, void* context)
+{
+ Registers regs;
+ // Convert OS context to Registers
+ port_thread_context_to_regs(®s, (ucontext_t*)context);
+ // Prepare registers for transfering control out of signal handler
+ void* callback = (void*)&c_handler;
+ port_set_longjump_regs(callback, ®s, 3,
+ ®s, (void*)(size_t)signum, info->si_addr);
+ // Convert prepared Registers back to OS context
+ port_thread_regs_to_context((ucontext_t*)context, ®s);
+ // Return from signal handler to go to C handler
+}
+
+
+struct sig_reg
+{
+ int signal;
+ int flags;
+ bool set_up;
+};
+
+static sig_reg signals_used[] =
+{
+ { SIGTRAP, SA_SIGINFO, false },
+ { SIGSEGV, SA_SIGINFO | SA_ONSTACK, false },
+ { SIGFPE, SA_SIGINFO, false },
+ { SIGINT, SA_SIGINFO, false },
+ { SIGQUIT, SA_SIGINFO, false },
+ { SIGABRT, SA_SIGINFO, false }
+};
+
+static struct sigaction old_actions[sizeof(signals_used)/sizeof(signals_used[0])];
+
+
+static void restore_signals()
+{
+ for (size_t i = 0; i < sizeof(signals_used)/sizeof(signals_used[0]); i++)
+ {
+ if (!signals_used[i].set_up)
+ continue;
+
+ signals_used[i].set_up = false;
+ sigaction(signals_used[i].signal, &old_actions[i], NULL);
+ }
+}
+
+int initialize_signals()
+{
+ struct sigaction sa;
+
+ for (size_t i = 0; i < sizeof(signals_used)/sizeof(signals_used[0]); i++)
+ {
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = signals_used[i].flags;
+ sa.sa_sigaction = &general_signal_handler;
+
+ if (0 != sigaction(signals_used[i].signal, &sa, &old_actions[i]))
+ {
+ restore_signals();
+ return -1;
+ }
+ }
+
+ // Prepare gdb crash handler
+ if (!init_gdb_crash_handler())
+ {
+ restore_signals();
+ return -1;
+ }
+
+ return 0;
+
+} //initialize_signals
+
+int shutdown_signals()
+{
+ cleanup_gdb_crash_handler();
+ restore_signals();
+ return 0;
+} //shutdown_signals
Propchange: harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_common.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_ipf.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_ipf.cpp?rev=638327&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_ipf.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_ipf.cpp Tue Mar 18 04:31:02 2008
@@ -0,0 +1,283 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h>
+#undef __USE_XOPEN
+#include <signal.h>
+
+#include "open/platform_types.h"
+#include "port_crash_handler.h"
+#include "stack_dump.h"
+#include "../linux/include/gdb_crash_handler.h"
+#include "signals_internal.h"
+
+
+port_tls_key_t port_tls_key;
+
+int init_private_tls_data()
+{
+ return (pthread_key_create(&port_tls_key, NULL) == 0) ? 0 : -1;
+}
+
+int free_private_tls_data()
+{
+ return (pthread_key_delete(port_tls_key) == 0) ? 0 : -1;
+}
+
+
+/* Out-of-signal-handler signal processing is not implemented for IPF
+
+static void c_handler(Registers* pregs, size_t signum, void* fault_addr)
+{ // this exception handler is executed *after* VEH handler returned
+}
+*/
+
+static void general_signal_handler(int signum, siginfo_t* info, void* context)
+{
+ Registers regs;
+/* Not implemented
+ // Check if SIGSEGV is produced by port_read/write_memory
+ port_tls_data* tlsdata = get_private_tls_data();
+ if (tlsdata && tlsdata->violation_flag)
+ {
+ tlsdata->violation_flag = 0;
+ pregs->set_ip(tlsdata->restart_address);
+ return;
+ }
+*/
+ // Convert OS context to Registers
+ port_thread_context_to_regs(®s, (ucontext_t*)context);
+
+ void* fault_addr = info->si_addr;
+ int result;
+
+ switch ((int)signum)
+ {
+ case SIGSEGV:
+ result = port_process_signal(PORT_SIGNAL_GPF, ®s, fault_addr, FALSE);
+ break;
+ case SIGFPE:
+ result = port_process_signal(PORT_SIGNAL_ARITHMETIC, ®s, fault_addr, FALSE);
+ break;
+ case SIGTRAP:
+ // Correct return address - FIXME ??? probably not needed on IPF
+ regs.set_ip((void*)((POINTER_SIZE_INT)regs.get_ip() - 1));
+ result = port_process_signal(PORT_SIGNAL_BREAKPOINT, ®s, fault_addr, FALSE);
+ break;
+ case SIGINT:
+ result = port_process_signal(PORT_SIGNAL_CTRL_C, ®s, fault_addr, FALSE);
+ break;
+ case SIGQUIT:
+ result = port_process_signal(PORT_SIGNAL_QUIT, ®s, fault_addr, FALSE);
+ break;
+ default:
+ result = port_process_signal(PORT_SIGNAL_UNKNOWN, ®s, fault_addr, TRUE);
+ }
+
+ if (result == 0)
+ return;
+
+ // We've got a crash
+ if (result > 0)
+ { // result > 0 - invoke debugger
+ bool result = gdb_crash_handler(®s);
+ // Continue with exiting process if not sucessful...
+ }
+
+ // Convert Registers back to OS context
+ port_thread_regs_to_context((ucontext_t*)context, ®s);
+
+ // result < 0 - exit process
+ if ((port_crash_handler_get_flags() & PORT_CRASH_DUMP_PROCESS_CORE) != 0)
+ { // Return to the same place to produce the same crash and generate core
+ signal(signum, SIG_DFL); // setup default handler
+ return;
+ }
+ // No core needed - simply terminate
+ _exit(-1);
+}
+
+
+struct sig_reg
+{
+ int signal;
+ int flags;
+ bool set_up;
+};
+
+static sig_reg signals_used[] =
+{
+ { SIGTRAP, SA_SIGINFO, false },
+ { SIGSEGV, SA_SIGINFO | SA_ONSTACK, false },
+ { SIGFPE, SA_SIGINFO, false },
+ { SIGINT, SA_SIGINFO, false },
+ { SIGQUIT, SA_SIGINFO, false },
+ { SIGABRT, SA_SIGINFO, false }
+};
+
+static struct sigaction old_actions[sizeof(signals_used)/sizeof(signals_used[0])];
+
+
+static void restore_signals()
+{
+ for (size_t i = 0; i < sizeof(signals_used)/sizeof(signals_used[0]); i++)
+ {
+ if (!signals_used[i].set_up)
+ continue;
+
+ signals_used[i].set_up = false;
+ sigaction(signals_used[i].signal, &old_actions[i], NULL);
+ }
+}
+
+int initialize_signals()
+{
+ struct sigaction sa;
+
+ for (size_t i = 0; i < sizeof(signals_used)/sizeof(signals_used[0]); i++)
+ {
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = signals_used[i].flags;
+ sa.sa_sigaction = &general_signal_handler;
+
+ if (0 != sigaction(signals_used[i].signal, &sa, &old_actions[i]))
+ {
+ restore_signals();
+ return -1;
+ }
+ }
+
+ // Prepare gdb crash handler
+ if (!init_gdb_crash_handler())
+ {
+ restore_signals();
+ return -1;
+ }
+
+ return 0;
+
+} //initialize_signals
+
+int shutdown_signals() {
+ cleanup_gdb_crash_handler();
+ restore_signals();
+ return 0;
+} //shutdown_signals
+
+#if 0
+
+// Variables used to locate the context from the signal handler
+static int sc_nest = -1;
+static bool use_ucontext = false;
+static uint32 exam_point;
+
+/*
+ * We find the true signal stack frame set-up by kernel,which is located
+ * by locate_sigcontext() below; then change its content according to
+ * exception handling semantics, so that when the signal handler is
+ * returned, application can continue its execution in Java exception handler.
+ */
+
+/*
+See function initialize_signals() below first please.
+
+Two kinds of signal contexts (and stack frames) are tried in
+locate_sigcontext(), one is sigcontext, which is the way of
+Linux kernel implements( see Linux kernel source
+arch/i386/kernel/signal.c for detail); the other is ucontext,
+used in some other other platforms.
+
+The sigcontext locating in Linux is not so simple as expected,
+because it involves not only the kernel, but also glibc/linuxthreads,
+which VM is linked against. In glibc/linuxthreads, user-provided
+signal handler is wrapped by linuxthreads signal handler, i.e.
+the signal handler really registered in system is not the one
+provided by user. So when Linux kernel finishes setting up signal
+stack frame and returns to user mode for singal handler execution,
+locate_sigcontext() is not the one being invoked immediately. It's
+called by linuxthreads function. That means the user stack viewed by
+locate_sigcontext() is NOT NECESSARILY the signal frame set-up by
+kernel, we need find the true one according to glibc/linuxthreads
+specific signal implementation in different versions.
+
+Because locate_sigcontext() uses IA32 physical register epb for
+call stack frame, compilation option `-fomit-frame-pointer' MUST
+not be used when gcc compiles it; and as gcc info, `-O2' will do
+`-fomit-frame-pointer' by default, although we haven't seen that
+in our experiments.
+*/
+
+volatile void locate_sigcontext(int signum)
+{
+ sigcontext *sc, *found_sc;
+ uint32 *ebp = NULL;
+ int i;
+
+//TODO: ADD correct stack handling here!!
+
+#define SC_SEARCH_WIDTH 3
+ for (i = 0; i < SC_SEARCH_WIDTH; i++) {
+ sc = (sigcontext *)(ebp + 3 );
+ if (sc->sc_ip == ((uint32)exam_point)) { // found
+ sc_nest = i;
+ use_ucontext = false;
+ found_sc = sc;
+ // we will try to find the real sigcontext setup by Linux kernel,
+ // because if we want to change the execution path after the signal
+ // handling, we must modify the sigcontext used by kernel.
+ // LinuxThreads in glibc 2.1.2 setups a sigcontext for our singal
+ // handler, but we should not modify it, because kernel doesn't use
+ // it when resumes the application. Then we must find the sigcontext
+ // setup by kernel, and modify it in singal handler.
+ // but, with glibc 2.2.3, it's useless to modify only the sigcontext
+ // setup by Linux kernel, because LinuxThreads does a interesting
+ // copy after our signal handler returns, which destroys the
+ // modification we have just done in the handler. So with glibc 2.2.3,
+ // what we need do is simply to modify the sigcontext setup by
+ // LinuxThreads, which will be copied to overwrite the one setup by
+ // kernel. Really complicated..., not really. We use a simple trick
+ // to overcome the changes in glibc from version to version, that is,
+ // we modify both sigcontexts setup by kernel and LinuxThreads. Then
+ // it will always work.
+
+ } else { // not found
+ struct ucontext *uc;
+ uc = (struct ucontext *)((uint64)ebp[4]);
+ if ((ebp < (uint32 *)uc) && ((uint32 *)uc < ebp + 0x100)) {
+ sc = (sigcontext *)&uc->uc_mcontext;
+ if (sc->sc_ip == ((uint32)exam_point)) { // found
+ sc_nest = i;
+ use_ucontext = true;
+ found_sc = sc;
+ break;
+ }
+ }
+ }
+
+ ebp = (uint32 *)((uint64)ebp[0]);
+ }
+
+ if (sc_nest < 0) {
+ printf("cannot locate sigcontext.\n");
+ printf("Please add or remove any irrelevant statement(e.g. add a null printf) in VM source code, then rebuild it. If problem remains, please submit a bug report. Thank you very much\n");
+ exit(1);
+ }
+}
+
+
+
+#endif
Propchange: harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_ipf.cpp
------------------------------------------------------------------------------
svn:eol-style = native