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 [4/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...
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp Tue Mar 18 04:31:02 2008
@@ -24,6 +24,7 @@
#define LOG_DOMAIN "jvmti"
#include "cxxlog.h"
+#include "port_mutex.h"
#include "open/gc.h"
#include "jvmti_direct.h"
@@ -87,14 +88,14 @@
TIEventThread *et = p_env->event_threads[event_type - JVMTI_MIN_EVENT_TYPE_VAL];
// protect event_threads collection
- hymutex_lock(&(p_env->environment_data_lock));
+ port_mutex_lock(&(p_env->environment_data_lock));
// Find out if this environment is already registered on this thread on this event type
while (NULL != et)
{
if (et->thread == p_thread)
{
- hymutex_unlock(&(p_env->environment_data_lock));
+ port_mutex_unlock(&(p_env->environment_data_lock));
return JVMTI_ERROR_NONE;
}
et = et->next;
@@ -104,7 +105,7 @@
jvmtiError errorCode = _allocate(sizeof(TIEventThread), (unsigned char **)&newet);
if (JVMTI_ERROR_NONE != errorCode)
{
- hymutex_unlock(&(p_env->environment_data_lock));
+ port_mutex_unlock(&(p_env->environment_data_lock));
return errorCode;
}
newet->thread = p_thread;
@@ -116,7 +117,7 @@
p_env->event_threads[event_type - JVMTI_MIN_EVENT_TYPE_VAL] = newet;
// free environment lock
- hymutex_unlock(&(p_env->environment_data_lock));
+ port_mutex_unlock(&(p_env->environment_data_lock));
return JVMTI_ERROR_NONE;
}
@@ -130,14 +131,14 @@
return;
// protect event_threads collection
- hymutex_lock(&(p_env->environment_data_lock));
+ port_mutex_lock(&(p_env->environment_data_lock));
if (et->thread == p_thread)
{
VM_Global_State::loader_env->TI->removeEventSubscriber(event_type);
p_env->event_threads[event_type - JVMTI_MIN_EVENT_TYPE_VAL] = et->next;
_deallocate((unsigned char *)et);
- hymutex_unlock(&(p_env->environment_data_lock));
+ port_mutex_unlock(&(p_env->environment_data_lock));
return;
}
@@ -150,36 +151,36 @@
TIEventThread *oldet = et->next;
et->next = oldet->next;
_deallocate((unsigned char *)oldet);
- hymutex_unlock(&(p_env->environment_data_lock));
+ port_mutex_unlock(&(p_env->environment_data_lock));
return;
}
et = et->next;
}
// release protection
- hymutex_unlock(&(p_env->environment_data_lock));
+ port_mutex_unlock(&(p_env->environment_data_lock));
}
void add_event_to_global(jvmtiEnv *env, jvmtiEvent event_type)
{
TIEnv *p_env = (TIEnv *)env;
- hymutex_lock(&(p_env->environment_data_lock));
+ port_mutex_lock(&(p_env->environment_data_lock));
if(!p_env->global_events[event_type - JVMTI_MIN_EVENT_TYPE_VAL]) {
VM_Global_State::loader_env->TI->addEventSubscriber(event_type);
}
p_env->global_events[event_type - JVMTI_MIN_EVENT_TYPE_VAL] = true;
- hymutex_unlock(&(p_env->environment_data_lock));
+ port_mutex_unlock(&(p_env->environment_data_lock));
}
void remove_event_from_global(jvmtiEnv *env, jvmtiEvent event_type)
{
TIEnv *p_env = (TIEnv *)env;
- hymutex_lock(&(p_env->environment_data_lock));
+ port_mutex_lock(&(p_env->environment_data_lock));
if(p_env->global_events[event_type - JVMTI_MIN_EVENT_TYPE_VAL]) {
VM_Global_State::loader_env->TI->removeEventSubscriber(event_type);
}
p_env->global_events[event_type - JVMTI_MIN_EVENT_TYPE_VAL] = false;
- hymutex_unlock(&(p_env->environment_data_lock));
+ port_mutex_unlock(&(p_env->environment_data_lock));
}
// disable all events except VM_DEATH
@@ -2363,17 +2364,17 @@
assert(hythread_is_suspend_enabled());
// create wait loop environment
- hymutex_t event_mutex;
- UNREF IDATA stat = hymutex_create(&event_mutex, TM_MUTEX_NESTED);
+ osmutex_t event_mutex;
+ UNREF IDATA stat = port_mutex_create(&event_mutex, APR_THREAD_MUTEX_NESTED);
assert(stat == TM_ERROR_NONE);
stat = hycond_create(&ti->event_cond);
assert(stat == TM_ERROR_NONE);
// event thread loop
while(true) {
- hymutex_lock(&event_mutex);
+ port_mutex_lock(&event_mutex);
hycond_wait(&ti->event_cond, &event_mutex);
- hymutex_unlock(&event_mutex);
+ port_mutex_unlock(&event_mutex);
if(!ti->event_thread) {
// event thread is NULL,
@@ -2386,7 +2387,7 @@
}
// release wait loop environment
- stat = hymutex_destroy(&event_mutex);
+ stat = port_mutex_destroy(&event_mutex);
assert(stat == TM_ERROR_NONE);
stat = hycond_destroy(&ti->event_cond);
assert(stat == TM_ERROR_NONE);
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_heap.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_heap.cpp?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_heap.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_heap.cpp Tue Mar 18 04:31:02 2008
@@ -23,6 +23,7 @@
*/
#include "cxxlog.h"
+#include "port_mutex.h"
#include "jvmti_direct.h"
#include "jvmti_utils.h"
@@ -124,11 +125,11 @@
return JVMTI_ERROR_INVALID_OBJECT;
if (ti_env->tags == NULL) {
- hymutex_lock(&ti_env->environment_data_lock);
+ port_mutex_lock(&ti_env->environment_data_lock);
if (ti_env->tags == NULL) {
ti_env->tags = new TITags;
}
- hymutex_unlock(&ti_env->environment_data_lock);
+ port_mutex_unlock(&ti_env->environment_data_lock);
}
if (ti_env->tags == NULL) {
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_step.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_step.cpp?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_step.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_step.cpp Tue Mar 18 04:31:02 2008
@@ -19,6 +19,7 @@
* @version $Revision: $
*/
+#include "port_crash_handler.h"
#include "jvmti.h"
#include "Class.h"
#include "cxxlog.h"
@@ -104,8 +105,7 @@
// Another thread could have instrumented this location for
// prediction of invokevirtual or invokeinterface, so it is
// necessary to check that location may be instrumented
- uint8 b = *((uint8 *)ip);
- if (b == INSTRUMENTATION_BYTE)
+ if (port_is_breakpoint_set(ip))
{
bp = vm_brpt->find_breakpoint(ip);
assert(bp);
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_memory.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_memory.cpp?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_memory.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_memory.cpp Tue Mar 18 04:31:02 2008
@@ -4,6 +4,7 @@
*/
#define LOG_DOMAIN "ncai.memory"
#include "cxxlog.h"
+#include "port_memaccess.h"
#include "jvmti_break_intf.h"
#include "environment.h"
#include "jvmti_internal.h"
@@ -36,10 +37,10 @@
if (!env)
return NCAI_ERROR_INVALID_ENVIRONMENT;
- ncaiError err = ncai_read_memory(addr, size, buf);
+ int err = port_read_memory(addr, size, buf);
- if (err != NCAI_ERROR_NONE)
- return err;
+ if (err != 0)
+ return NCAI_ERROR_ACCESS_DENIED;
// Restore bytes changed by JVMTI/NCAI breakpoints
VMBreakPoints* vm_breaks = VM_Global_State::loader_env->TI->vm_brpt;
@@ -86,7 +87,12 @@
// Simple case: there are no breakpoints in specified address range
if (rewrite_count == 0)
- return ncai_write_memory(addr, size, buf);
+ {
+ if (port_write_memory(addr, size, buf) == 0)
+ return NCAI_ERROR_NONE;
+ else
+ return NCAI_ERROR_ACCESS_DENIED;
+ }
// Allocate array for address sorting
RewriteArray rwa;
@@ -114,7 +120,7 @@
assert(cur_bla);
jbyte* cbuf = (jbyte*)buf;
jbyte* cur_addr = (jbyte*)addr;
- ncaiError err = NCAI_ERROR_NONE;
+ int err = 0;
while (remain)
{
@@ -123,9 +129,9 @@
size_t offset = (size_t)cur_addr - (size_t)addr;
size_t chunk_size = cur_bla ? ((jbyte*)cur_bla->bp->addr - cur_addr)
: (end_addr - cur_addr);
- err = ncai_write_memory(cur_addr, chunk_size, cbuf + offset);
+ err = port_write_memory(cur_addr, chunk_size, cbuf + offset);
- if (err != NCAI_ERROR_NONE)
+ if (err != 0)
break;
cur_addr += chunk_size;
@@ -145,7 +151,7 @@
}
STD_FREE(rwa.array);
- return err;
+ return (err == 0) ? NCAI_ERROR_NONE : NCAI_ERROR_ACCESS_DENIED;
}
// Adding sorted item into rewrite list
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_modules.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_modules.cpp?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_modules.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_modules.cpp Tue Mar 18 04:31:02 2008
@@ -11,7 +11,7 @@
#include "cxxlog.h"
#include "environment.h"
#include "natives_support.h"
-#include "native_modules.h"
+#include "port_modules.h"
#include "open/hythread_ext.h"
#include "ncai_utils.h"
#include "ncai_direct.h"
@@ -459,7 +459,7 @@
static bool
compare_modules_by_short_name(ncaiModule module, const char* sh_name)
{
- char buf[_MAX_PATH + 1];
+ char buf[PORT_PATH_MAX + 1];
if (short_name(module->info->filename, buf) == NULL)
return false; // Error case
@@ -471,7 +471,7 @@
// Must be called under modules lock
static ncaiModule find_module_by_name(ncaiModule modules, const char* name)
{
- char name_buf[_MAX_PATH + 1];
+ char name_buf[PORT_PATH_MAX + 1];
if (short_name(name, name_buf) == NULL)
return NULL;
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_signals.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_signals.cpp?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_signals.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_signals.cpp Tue Mar 18 04:31:02 2008
@@ -8,12 +8,29 @@
#include "suspend_checker.h"
#include "jvmti_internal.h"
#include "environment.h"
+#include "port_crash_handler.h"
#include "ncai_utils.h"
#include "ncai_direct.h"
#include "ncai_internal.h"
+struct st_signal_info
+{
+ jint signal;
+ char* name;
+ size_t name_size;
+};
+
+static size_t ncai_get_signal_count();
+static st_signal_info* find_signal(jint sig);
+static jint ncai_get_min_signal();
+static jint ncai_get_max_signal();
+static char* ncai_get_signal_name(jint signal);
+static size_t ncai_get_signal_name_size(jint signal);
+bool ncai_is_signal_in_range(jint signal);
+
+
ncaiError JNICALL
ncaiGetSignalCount(ncaiEnv *env, jint* count_ptr)
{
@@ -130,4 +147,89 @@
}
}
}
+}
+
+
+
+#define STR_AND_SIZE(_x_) _x_, (strlen(_x_) + 1)
+
+static st_signal_info sig_table[] = {
+ {PORT_SIGNAL_GPF, STR_AND_SIZE("PORT_SIGNAL_GPF")},
+ {PORT_SIGNAL_STACK_OVERFLOW,STR_AND_SIZE("PORT_SIGNAL_STACK_OVERFLOW")},
+ {PORT_SIGNAL_ABORT, STR_AND_SIZE("PORT_SIGNAL_ABORT")},
+ {PORT_SIGNAL_QUIT, STR_AND_SIZE("PORT_SIGNAL_QUIT")},
+ {PORT_SIGNAL_CTRL_BREAK, STR_AND_SIZE("PORT_SIGNAL_CTRL_BREAK")},
+ {PORT_SIGNAL_CTRL_C, STR_AND_SIZE("PORT_SIGNAL_CTRL_C")},
+ {PORT_SIGNAL_BREAKPOINT, STR_AND_SIZE("PORT_SIGNAL_BREAKPOINT")},
+ {PORT_SIGNAL_ARITHMETIC, STR_AND_SIZE("PORT_SIGNAL_ARITHMETIC")},
+};
+
+static size_t ncai_get_signal_count()
+{
+ return sizeof(sig_table)/sizeof(sig_table[0]);
+}
+
+static st_signal_info* find_signal(jint sig)
+{
+ for (size_t i = 0; i < ncai_get_signal_count(); i++)
+ {
+ if (sig_table[i].signal == sig)
+ return &sig_table[i];
+ }
+
+ return NULL;
+}
+
+static jint ncai_get_min_signal()
+{
+ static int min_sig_value = sig_table[1].signal;
+
+ if (min_sig_value != sig_table[1].signal)
+ return min_sig_value;
+
+ min_sig_value = sig_table[0].signal;
+
+ for (size_t i = 1; i < ncai_get_signal_count(); i++)
+ {
+ if (sig_table[i].signal < min_sig_value)
+ min_sig_value = sig_table[i].signal;
+ }
+
+ return min_sig_value;
+}
+
+static jint ncai_get_max_signal()
+{
+ static int max_sig_value = -1;
+
+ if (max_sig_value != -1)
+ return max_sig_value;
+
+ max_sig_value = sig_table[0].signal;
+
+ for (size_t i = 1; i < ncai_get_signal_count(); i++)
+ {
+ if (sig_table[i].signal > max_sig_value)
+ max_sig_value = sig_table[i].signal;
+ }
+
+ return max_sig_value;
+}
+
+static char* ncai_get_signal_name(jint signal)
+{
+ st_signal_info* psig = find_signal(signal);
+ return psig ? psig->name : NULL;
+}
+
+static size_t ncai_get_signal_name_size(jint signal)
+{
+ st_signal_info* psig = find_signal(signal);
+ return psig ? psig->name_size : 0;
+}
+
+bool ncai_is_signal_in_range(jint signal)
+{
+ return (signal >= ncai_get_min_signal() ||
+ signal <= ncai_get_max_signal());
}
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_stack.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_stack.cpp?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_stack.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_stack.cpp Tue Mar 18 04:31:02 2008
@@ -153,14 +153,14 @@
vm_thread = jthread_get_vm_thread(thread);
}
- WalkContext context;
- if (!native_init_walk_context(&context, NULL, ®s))
+ UnwindContext context;
+ if (!port_init_unwind_context(&context, NULL, ®s))
return NCAI_ERROR_INTERNAL;
*pcount = walk_native_stack_registers(&context, ®s,
vm_thread, max_depth, frame_array);
- native_clean_walk_context(&context);
+ port_clean_unwind_context(&context);
return NCAI_ERROR_NONE;
}
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/utils/ncai_step_ia32.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/utils/ncai_step_ia32.cpp?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/utils/ncai_step_ia32.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/utils/ncai_step_ia32.cpp Tue Mar 18 04:31:02 2008
@@ -5,6 +5,7 @@
#define LOG_DOMAIN "ncai.step"
#include "cxxlog.h"
+#include "port_crash_handler.h"
#include "jvmti_break_intf.h"
#include "ncai_utils.h"
@@ -301,10 +302,9 @@
static InstructionDisassembler* get_local_disasm(void* addr)
{
VMBreakPoints* vm_brpt = VM_Global_State::loader_env->TI->vm_brpt;
- uint8* bptr = (uint8*)addr;
InstructionDisassembler* pdasm;
- if (*bptr == INSTRUMENTATION_BYTE)
+ if (port_is_breakpoint_set(addr))
{ // Address was instrumented by another thread or by breakpoint
VMBreakPoint* bp = vm_brpt->find_breakpoint(addr);
assert(bp && bp->disasm);
Copied: harmony/enhanced/drlvm/trunk/vm/vmcore/src/stack/native_stack.cpp (from r637971, harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/native_stack.cpp)
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/stack/native_stack.cpp?p2=harmony/enhanced/drlvm/trunk/vm/vmcore/src/stack/native_stack.cpp&p1=harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/native_stack.cpp&r1=637971&r2=638327&rev=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/native_stack.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/stack/native_stack.cpp Tue Mar 18 04:31:02 2008
@@ -19,16 +19,14 @@
* @version $Revision: 1.1.2.1 $
*/
-#include <string.h>
#include "lock_manager.h"
#include "m2n.h"
-#include "stack_trace.h"
+#include "compile.h"
#include "interpreter.h"
#include "interpreter_exports.h"
-#include "compile.h"
-#include "jvmti_break_intf.h"
#include "environment.h"
-#include "native_modules.h"
+#include "port_modules.h"
+#include "port_unwind.h"
#include "native_stack.h"
@@ -67,10 +65,17 @@
return buf;
}
-bool native_is_in_stack(WalkContext* context, void* sp)
+const char* native_get_stub_name_nocpy(void* ip)
{
- return (sp >= context->stack.base &&
- sp < (char*)context->stack.base + context->stack.size);
+ // Synchronizing access to dynamic code list
+ LMAutoUnlock dcll(VM_Global_State::loader_env->p_dclist_lock);
+
+ DynamicCode* code = native_find_stub(ip);
+
+ if (!code)
+ return NULL;
+
+ return code->name;
}
bool native_is_ip_stub(void* ip)
@@ -81,6 +86,41 @@
return (native_find_stub(ip) != NULL);
}
+static void native_fill_frame_info(Registers* UNREF regs, native_frame_t* UNREF frame, jint UNREF jdepth)
+{
+ frame->java_depth = jdepth;
+
+ if (!regs)
+ return;
+
+#if defined(_IPF_)
+ // Nothing
+#elif defined(_EM64T_)
+ frame->ip = (void*)regs->rip;
+ frame->frame = (void*)regs->rbp;
+ frame->stack = (void*)regs->rsp;
+#else // IA-32
+ frame->ip = (void*)regs->eip;
+ frame->frame = (void*)regs->ebp;
+ frame->stack = (void*)regs->esp;
+#endif
+}
+
+void native_get_regs_from_jit_context(JitFrameContext* jfc, Registers* regs)
+{
+#if defined(_IPF_)
+ // Nothing
+#elif defined(_EM64T_)
+ regs->rsp = jfc->rsp;
+ regs->rip = *jfc->p_rip;
+ regs->rbp = (jfc->p_rbp) ? *jfc->p_rbp : regs->rbp;
+#else // IA-32
+ regs->esp = jfc->esp;
+ regs->eip = *jfc->p_eip;
+ regs->ebp = (jfc->p_ebp) ? *jfc->p_ebp : regs->ebp;
+#endif
+}
+
/*
Now the technique for calling C handler from a signal/exception context
guarantees that all needed return addresses are present in stack, so
@@ -97,65 +137,20 @@
//////////////////////////////////////////////////////////////////////////////
//
-bool native_init_walk_context(WalkContext* 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 native_clean_walk_context(WalkContext* context)
-{
- if (!context)
- return;
-
- if (context->modules && context->clean_modules)
- {
- port_clear_modules(&context->modules);
- }
-
- context->modules = NULL;
-}
-
static int walk_native_stack_jit(
- WalkContext* context,
+ UnwindContext* context,
Registers* pregs, VM_thread* pthread,
int max_depth, native_frame_t* frame_array);
static int walk_native_stack_pure(
- WalkContext* context, Registers* pregs,
+ UnwindContext* context, Registers* pregs,
int max_depth, native_frame_t* frame_array);
static int walk_native_stack_interpreter(
- WalkContext* context,
+ UnwindContext* context,
Registers* pregs, VM_thread* pthread,
int max_depth, native_frame_t* frame_array);
-int walk_native_stack_registers(WalkContext* context, Registers* pregs,
+int walk_native_stack_registers(UnwindContext* context, Registers* pregs,
VM_thread* pthread, int max_depth, native_frame_t* frame_array)
{
if (pthread == NULL) // Pure native thread
@@ -171,7 +166,7 @@
static int walk_native_stack_jit(
- WalkContext* context,
+ UnwindContext* context,
Registers* pregs, VM_thread* pthread,
int max_depth, native_frame_t* frame_array)
{
@@ -301,20 +296,12 @@
{
Registers tmp_regs = regs;
- if (native_is_frame_exists(context, &tmp_regs))
- { // Stack frame (x86)
- if (!native_unwind_stack_frame(context, &tmp_regs))
+ if (!port_unwind_frame(context, &tmp_regs))
break;
- }
- else
- { // Stack frame does not exist, try using heuristics
- if (!native_unwind_special(context, &tmp_regs))
- break;
- }
-
+/*
VMBreakPoints* vm_breaks = VM_Global_State::loader_env->TI->vm_brpt;
vm_breaks->lock();
-/*
+
Now the technique for calling C handler from a signal/exception context
guarantees that all needed return addresses are present in stack, so
there is no need in special processing
@@ -326,7 +313,7 @@
else*/
regs = tmp_regs;
- vm_breaks->unlock();
+// vm_breaks->unlock();
}
code_type = vm_identify_eip(regs.get_ip());
@@ -354,7 +341,7 @@
static int walk_native_stack_pure(
- WalkContext* context, Registers* pregs,
+ UnwindContext* context, Registers* pregs,
int max_depth, native_frame_t* frame_array)
{
// Register context for current frame
@@ -376,19 +363,8 @@
++frame_count;
- if (native_is_frame_exists(context, ®s))
- { // Stack frame (x86)
- // Here must be special processing for breakpoint handler frames
- // But it requires VM_thread structure attached to thread
- // TODO: Investigate possibility
- if (!native_unwind_stack_frame(context, ®s))
- break;
- }
- else
- { // Stack frame does not exist, try using heuristics
- if (!native_unwind_special(context, ®s))
+ if (port_unwind_frame(context, ®s))
break;
- }
}
return frame_count;
@@ -396,7 +372,7 @@
static int walk_native_stack_interpreter(
- WalkContext* context,
+ UnwindContext* context,
Registers* pregs, VM_thread* pthread,
int max_depth, native_frame_t* frame_array)
{
@@ -426,20 +402,12 @@
void* prev_sp = regs.get_sp();
Registers tmp_regs = regs;
- if (native_is_frame_exists(context, &tmp_regs))
- { // Stack frame (x86)
- if (!native_unwind_stack_frame(context, &tmp_regs))
+ if (port_unwind_frame(context, &tmp_regs))
break;
- }
- else
- { // Stack frame does not exist, try using heuristics
- if (!native_unwind_special(context, &tmp_regs))
- break;
- }
-
+/*
VMBreakPoints* vm_breaks = VM_Global_State::loader_env->TI->vm_brpt;
vm_breaks->lock();
-/*
+
Now the technique for calling C handler from a signal/exception context
guarantees that all needed return addresses are present in stack, so
there is no need in special processing
@@ -448,7 +416,7 @@
else*/
regs = tmp_regs;
- vm_breaks->unlock();
+// vm_breaks->unlock();
bool is_java = interpreter.is_frame_in_native_frame(frame, prev_sp, regs.get_sp());
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/lock_manager.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/lock_manager.cpp?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/lock_manager.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/lock_manager.cpp Tue Mar 18 04:31:02 2008
@@ -20,37 +20,38 @@
*/
+#include "port_mutex.h"
#include "lock_manager.h"
#include "vm_threads.h"
#include "exceptions.h"
Lock_Manager::Lock_Manager()
{
- UNREF IDATA stat = hymutex_create (&lock, TM_MUTEX_NESTED);
+ UNREF IDATA stat = port_mutex_create (&lock, APR_THREAD_MUTEX_NESTED);
assert(stat==TM_ERROR_NONE);
}
Lock_Manager::~Lock_Manager()
{
- UNREF IDATA stat = hymutex_destroy (&lock);
+ UNREF IDATA stat = port_mutex_destroy (&lock);
assert(stat==TM_ERROR_NONE);
}
void Lock_Manager::_lock()
{
- UNREF IDATA stat = hymutex_lock(&lock);
+ UNREF IDATA stat = port_mutex_lock(&lock);
assert(stat==TM_ERROR_NONE);
}
bool Lock_Manager::_tryLock()
{
- IDATA stat = hymutex_trylock(&lock);
+ IDATA stat = port_mutex_trylock(&lock);
return stat==TM_ERROR_NONE;
}
void Lock_Manager::_unlock()
{
- UNREF IDATA stat = hymutex_unlock(&lock);
+ UNREF IDATA stat = port_mutex_unlock(&lock);
assert(stat==TM_ERROR_NONE);
}
@@ -93,6 +94,6 @@
bool Lock_Manager::_lock_enum_or_null(bool UNREF return_null_on_fail)
{
- IDATA stat = hymutex_lock(&lock);
+ IDATA stat = port_mutex_lock(&lock);
return stat==TM_ERROR_NONE;
}
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_generic.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_generic.cpp?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_generic.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_generic.cpp Tue Mar 18 04:31:02 2008
@@ -62,7 +62,6 @@
#include "m2n.h"
#include "exceptions.h"
#include "jit_intf.h"
-#include "exception_filter.h"
#include "vm_threads.h"
#include "jni_utils.h"
#include "object.h"
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_manager.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_manager.cpp?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_manager.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_manager.cpp Tue Mar 18 04:31:02 2008
@@ -192,7 +192,7 @@
} // vm_set_exception_registers
/**
- * Gets IP from exception registers
+ * Gets IP from exception registers for current thread
*/
void *vm_get_ip_from_regs(vm_thread_t vm_thread)
{
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_ti_monitors.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_ti_monitors.cpp?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_ti_monitors.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_ti_monitors.cpp Tue Mar 18 04:31:02 2008
@@ -21,6 +21,7 @@
*/
#include <open/hythread_ext.h>
+#include "port_mutex.h"
#include "vm_threads.h"
typedef struct ResizableArrayEntry *array_entry_t;
@@ -120,7 +121,7 @@
} // array_get
static array_t jvmti_monitor_table = 0;
-static hymutex_t jvmti_monitor_table_lock;
+static osmutex_t jvmti_monitor_table_lock;
static IDATA jthread_init_jvmti_monitor_table()
{
@@ -133,7 +134,7 @@
hythread_global_unlock();
return TM_ERROR_OUT_OF_MEMORY;
}
- status = hymutex_create(&jvmti_monitor_table_lock, TM_MUTEX_NESTED);
+ status = port_mutex_create(&jvmti_monitor_table_lock, APR_THREAD_MUTEX_NESTED);
if (status != TM_ERROR_NONE) {
hythread_global_unlock();
return status;
@@ -171,17 +172,17 @@
}
}
- status = hymutex_lock(&jvmti_monitor_table_lock);
+ status = port_mutex_lock(&jvmti_monitor_table_lock);
if (status != TM_ERROR_NONE) {
return status;
}
*mon_ptr = (jrawMonitorID)array_add(jvmti_monitor_table, monitor);
if (!(*mon_ptr)) {
- hymutex_unlock(&jvmti_monitor_table_lock);
+ port_mutex_unlock(&jvmti_monitor_table_lock);
return TM_ERROR_OUT_OF_MEMORY;
}
- status = hymutex_unlock(&jvmti_monitor_table_lock);
+ status = port_mutex_unlock(&jvmti_monitor_table_lock);
return status;
} // jthread_raw_monitor_create
@@ -206,12 +207,12 @@
}
}
- IDATA status = hymutex_lock(&jvmti_monitor_table_lock);
+ IDATA status = port_mutex_lock(&jvmti_monitor_table_lock);
if (status != TM_ERROR_NONE) {
return status;
}
array_delete(jvmti_monitor_table, (UDATA) mon_ptr);
- status = hymutex_unlock(&jvmti_monitor_table_lock);
+ status = port_mutex_unlock(&jvmti_monitor_table_lock);
return status;
} // jthread_raw_monitor_destroy
Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/crash_dump.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/crash_dump.cpp?rev=638327&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/crash_dump.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/crash_dump.cpp Tue Mar 18 04:31:02 2008
@@ -0,0 +1,509 @@
+/*
+ * 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 <ctype.h>
+
+#include "port_dso.h"
+#include "port_modules.h"
+#include "port_crash_handler.h"
+#include "port_frame_info.h"
+#include "m2n.h"
+#include "stack_iterator.h"
+#include "environment.h"
+#include "vm_threads.h"
+#include "exceptions.h"
+#include "natives_support.h"
+#include "stack_trace.h"
+#include "signals.h"
+#include "interpreter.h"
+#include "compile.h"
+#include "cci.h"
+#include "jit_intf_cpp.h"
+#include "native_stack.h"
+#include "crash_dump.h"
+
+
+#ifdef PLATFORM_POSIX
+#include <strings.h>
+#define strcmp_case strcasecmp
+#else /* Windows */
+#include <string.h>
+#define strcmp_case _stricmp
+#endif
+
+
+static void cd_init_crash_sequence();
+static void cd_cleanup_crash_sequence();
+static void cd_fill_java_method_info(Method* m, void* ip, bool is_ip_past,
+ int inl_depth, port_stack_frame_info* sfi);
+static void cd_print_module_info(Registers* regs);
+static void cd_print_threads_info();
+
+
+struct st_int_uwinfo
+{
+ bool filled;
+ FrameHandle* frame;
+ void* prev_sp;
+};
+
+struct st_jit_uwinfo
+{
+ bool filled;
+ CodeChunkInfo* cci;
+ int inline_index;
+ M2nFrame* lm2n;
+ bool is_first; // For setting is_ip_past
+};
+
+static uint32 cci_get_inlined_depth(CodeChunkInfo* cci, uint32 offset)
+{
+ ASSERT_NO_INTERPRETER
+
+ if (!cci || !cci->has_inline_info())
+ return 0;
+
+ return cci->get_jit()->get_inline_depth(cci->get_inline_info(), offset);
+}
+
+static Method* get_jit_method(CodeChunkInfo* cci, void* ip, uint32 index, bool is_first)
+{
+ Method* method = cci->get_method();
+
+ if (index == 0)
+ return method;
+
+ uint32 offset = (uint32)((POINTER_SIZE_INT)ip -
+ (POINTER_SIZE_INT)cci->get_code_block_addr());
+ uint32 inlined_depth = cci_get_inlined_depth(cci, offset);
+ bool is_ip_past = !is_first; // || (index != inlined_depth);
+
+ if (index > inlined_depth)
+ return method; // Error
+
+ Method* inl_method =
+ cci->get_jit()->get_inlined_method(cci->get_inline_info(), offset, index);
+
+ return inl_method;
+}
+
+
+static void cd_unwind_from_java(vm_thread_t vmthread,
+ CodeChunkInfo* cci, Registers* regs, bool is_ip_past, M2nFrame* m2n)
+{
+ StackIterator* si = (StackIterator*)STD_ALLOCA(si_size());
+
+ M2nFrame* last_m2n = m2n ? m2n : m2n_get_last_frame(vmthread);
+ si_fill_from_registers(si, regs, is_ip_past, last_m2n);
+
+ while (!si_is_past_end(si))
+ {
+ CodeChunkInfo* curcci = si_get_code_chunk_info(si);
+
+ if (curcci && curcci == cci &&
+ si_get_ip(si) == regs->get_ip())
+ break; // Method is found in stack iterator
+
+ si_goto_previous(si);
+ }
+
+ if (si_is_past_end(si)) // Error: method not found
+ return;
+
+ si_goto_previous(si);
+ si_copy_to_registers(si, regs);
+}
+
+static void cd_unwind_from_stub(M2nFrame* lm2n, Registers* regs)
+{
+ StackIterator* si = (StackIterator*)STD_ALLOCA(si_size());
+ si_fill_from_registers(si, regs, true, lm2n);
+ si_goto_previous(si);
+ si_copy_to_registers(si, regs);
+}
+
+
+static int unwind_compiled_frame(Registers *regs, port_stack_frame_info *sfi)
+{
+ // Suppose this callback is called by PORT for crash reasons only
+ cd_init_crash_sequence();
+
+ if (!sfi->iteration_state)
+ return (int)(interpreter_enabled() ? sizeof(st_int_uwinfo)
+ : sizeof(st_jit_uwinfo));
+
+ void* cur_ip = regs->get_ip();
+ void* cur_sp = regs->get_sp();
+
+ // For interpreter - only return additional info
+ if (interpreter_enabled())
+ {
+ vm_thread_t vmthread = get_thread_ptr();
+ st_int_uwinfo* uwinfo = (st_int_uwinfo*)sfi->iteration_state;
+
+ if (!vmthread)
+ return -1;
+
+ if (!uwinfo->filled)
+ {
+ uwinfo->frame = interpreter.interpreter_get_last_frame(vmthread);
+ uwinfo->prev_sp = cur_sp;
+ uwinfo->filled = true;
+ }
+
+ bool is_java = interpreter.is_frame_in_native_frame(uwinfo->frame, uwinfo->prev_sp, cur_sp);
+ if (is_java)
+ {
+ Method* method = (Method*)interpreter.interpreter_get_frame_method(uwinfo->frame);
+ uint8* bc_ptr = interpreter.interpreter_get_frame_bytecode_ptr(uwinfo->frame);
+ cd_fill_java_method_info(method, (void*)bc_ptr, false, -1, sfi);
+ uwinfo->frame = interpreter.interpreter_get_prev_frame(uwinfo->frame);
+ }
+
+ uwinfo->prev_sp = cur_sp;
+ return -1;
+ }
+
+ // JIT-frames
+ vm_thread_t vmthread = get_thread_ptr();
+ st_jit_uwinfo* uwinfo = (st_jit_uwinfo*)sfi->iteration_state;
+
+ if (!vmthread)
+ return -1;
+
+ if (!uwinfo->filled)
+ {
+ uwinfo->cci = NULL;
+ uwinfo->inline_index = -1;
+ uwinfo->is_first = true;
+ uwinfo->filled = true;
+ uwinfo->lm2n = NULL;
+ }
+
+ Global_Env* env = VM_Global_State::loader_env;
+ bool ip_past = !uwinfo->is_first;
+ uwinfo->is_first = false; // For the next iterations
+
+ // Stubs - return stub name as additional info
+ if (native_is_ip_stub(cur_ip))
+ {
+ sfi->method_class_name = "stub";
+ sfi->method_name = native_get_stub_name_nocpy(cur_ip);
+
+ if (uwinfo->lm2n == NULL) // Initialize
+ uwinfo->lm2n = m2n_get_last_frame(vmthread);
+
+ cd_unwind_from_stub(uwinfo->lm2n, regs);
+ uwinfo->lm2n = m2n_get_previous_frame(uwinfo->lm2n);
+
+ return 0; // Regs now contain a context for previous Java frame
+ }
+
+ CodeChunkInfo* cci = NULL;
+ Method_Handle mh = env->em_interface->LookupCodeChunk(cur_ip,
+ ip_past, NULL, NULL, (void**)&cci);
+
+ if (!mh)
+ {
+ //assert(uwinfo->inline_index == 0);// we should not miss first JITted frame
+ uwinfo->cci = NULL;
+ return -1;
+ }
+
+ if (cci == uwinfo->cci) // Continue reporting inlined methods
+ {
+ if (uwinfo->inline_index <= 0)
+ return -1; // Error: should be unwound earlier
+
+ --uwinfo->inline_index;
+ Method* m = get_jit_method(cci, cur_ip, uwinfo->inline_index, ip_past);
+ cd_fill_java_method_info(m, cur_ip, ip_past, uwinfo->inline_index, sfi);
+
+ if (uwinfo->inline_index > 0) // Simply return info from inlined method
+ return 0;
+
+ // Need to unwind JITted Java frame and update registers
+ cd_unwind_from_java(vmthread, cci, regs, ip_past, uwinfo->lm2n);
+ return 0;
+ }
+
+ // New cci
+ uint32 offset = (uint32)((POINTER_SIZE_INT)cur_ip -
+ (POINTER_SIZE_INT)cci->get_code_block_addr());
+ uint32 inlined_depth = cci_get_inlined_depth(cci, offset);
+
+ uwinfo->cci = cci;
+ uwinfo->inline_index = (int)inlined_depth;
+
+ Method* m = get_jit_method(cci, cur_ip, inlined_depth, ip_past);
+ cd_fill_java_method_info(m, cur_ip, ip_past, inlined_depth, sfi);
+
+ if (inlined_depth == 0) // Unwind right now if not inlined
+ cd_unwind_from_java(vmthread, cci, regs, ip_past, uwinfo->lm2n);
+
+ return 0;
+}
+
+
+static void crash_action(port_sigtype UNREF signum, Registers* regs, void* UNREF fault_addr)
+{
+ if (!regs) // No regs info - do not print anything
+ return;
+
+ // For the case when unwind callback was not called before
+ cd_init_crash_sequence();
+
+ // Print crashed modile info
+ cd_print_module_info(regs);
+ // Print threads info
+ cd_print_threads_info();
+
+ fflush(stderr);
+ cd_cleanup_crash_sequence();
+}
+
+
+static port_signal_handler_registration registrations[] =
+{
+ {PORT_SIGNAL_GPF, null_reference_handler},
+ {PORT_SIGNAL_STACK_OVERFLOW, stack_overflow_handler},
+ {PORT_SIGNAL_ABORT, abort_handler},
+ {PORT_SIGNAL_QUIT, ctrl_backslash_handler},
+ {PORT_SIGNAL_CTRL_BREAK, ctrl_break_handler},
+ {PORT_SIGNAL_CTRL_C, ctrl_c_handler},
+ {PORT_SIGNAL_BREAKPOINT, native_breakpoint_handler},
+ {PORT_SIGNAL_ARITHMETIC, arithmetic_handler}
+};
+
+int vm_initialize_signals()
+{
+ Boolean result = port_init_crash_handler(
+ registrations,
+ sizeof(registrations)/sizeof(registrations[0]),
+ unwind_compiled_frame);
+
+ if (!result)
+ return -1;
+
+ result = port_crash_handler_add_action(crash_action);
+
+ if (!result)
+ return -1;
+
+ unsigned flags = port_crash_handler_get_capabilities();
+
+#ifdef PLATFORM_POSIX
+ bool call_dbg = (VM_Global_State::loader_env == NULL) ||
+ get_boolean_property("vm.crash_handler", FALSE, VM_PROPERTIES);
+#else // WIN
+ bool call_dbg = (VM_Global_State::loader_env == NULL) ||
+ get_boolean_property("vm.assert_dialog", TRUE, VM_PROPERTIES);
+#endif
+ if (!call_dbg)
+ flags &= ~PORT_CRASH_CALL_DEBUGGER;
+
+ port_crash_handler_set_flags(flags);
+
+ return 0;
+}
+
+
+int vm_shutdown_signals()
+{
+ Boolean result = port_shutdown_crash_handler();
+ if (!result)
+ return -1;
+
+ return 0;
+}
+
+
+
+// Crash sequence is single-threaded, it's provided by the PORT
+static bool g_crash_initialized = false;
+static int g_disable_count;
+static bool g_unwindable;
+static native_module_t* g_modules = NULL;
+
+static void cd_init_crash_sequence()
+{
+ if (g_crash_initialized)
+ return;
+
+ VM_thread* thread = get_thread_ptr(); // Can be NULL for pure native thread
+
+ if (thread)
+ {
+ // Enable suspend to allow working with threads
+ g_disable_count = hythread_reset_suspend_disable();
+ // Acquire global lock to print threads list
+// hythread_global_lock();
+ g_unwindable = set_unwindable(false); // To call Java code
+ }
+
+ g_crash_initialized = true;
+}
+
+static void cd_cleanup_crash_sequence()
+{
+ if (!g_crash_initialized)
+ return;
+
+ VM_thread* thread = get_thread_ptr(); // Can be NULL for pure native thread
+
+ if (thread)
+ {
+ set_unwindable(g_unwindable);
+// hythread_global_unlock();
+ hythread_set_suspend_disable(g_disable_count);
+ }
+
+ g_crash_initialized = false;
+}
+
+
+static void cd_fill_java_method_info(Method* m, void* ip, bool is_ip_past,
+ int inl_depth, port_stack_frame_info* sfi)
+{
+ if (!m || !sfi)
+ return;
+
+ sfi->method_class_name = m->get_class()->get_name()->bytes;
+ sfi->method_name = m->get_name()->bytes;
+ sfi->method_signature = m->get_descriptor()->bytes;
+ sfi->source_file_name = NULL;
+ sfi->source_line_number = -1;
+
+ if (!ip)
+ return;
+
+ const char* fname = NULL;
+ int line = -1;
+
+ if (inl_depth == 0)
+ inl_depth = -1; // should pass -1 for non-inlined methods
+
+ get_file_and_line(m, ip, is_ip_past, inl_depth, &fname, &line);
+
+ if (fname)
+ {
+ sfi->source_file_name = fname;
+ sfi->source_line_number = line;
+ }
+}
+
+
+const char* cd_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 (!memcmp(short_name, PORT_DSO_PREFIX, strlen(PORT_DSO_PREFIX)))
+ nameptr += strlen(PORT_DSO_PREFIX);
+
+ char* vm_modules[] = {"java", "em", "encoder", "gc_gen", "gc_gen_uncomp", "gc_cc",
+ "harmonyvm", "hythr", "interpreter", "jitrino", "vmi"};
+
+ 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";
+ }
+
+ if (natives_is_library_loaded_slow(short_name))
+ return "JNI native library";
+
+ return "Unknown/system native module";
+}
+
+static void cd_fill_modules()
+{
+ if (g_modules)
+ return;
+
+ int count;
+ bool res = port_get_all_modules(&g_modules, &count);
+ assert(res && g_modules && count);
+}
+
+static void cd_print_module_info(Registers* regs)
+{
+ cd_fill_modules();
+
+ native_module_t* module = port_find_module(g_modules, (void*)regs->get_ip());
+ cd_parse_module_info(module, regs->get_ip());
+}
+
+
+static void cd_print_threads_info()
+{
+ VM_thread* cur_thread = get_thread_ptr();
+
+ if (!cur_thread)
+ fprintf(stderr, "\nCurrent thread is not attached to VM, ID: %d\n", port_gettid());
+
+ 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++)
+ {
+ 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);
+ }
+ }
+
+ hythread_iterator_release(&it);
+}
Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/crash_dump.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/crash_dump_os.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/crash_dump_os.cpp?rev=638327&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/crash_dump_os.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/crash_dump_os.cpp Tue Mar 18 04:31:02 2008
@@ -0,0 +1,88 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+
+#include "open/platform_types.h"
+#include "open/hythread_ext.h"
+#include "port_filepath.h"
+#include "port_dso.h"
+#include "port_modules.h"
+#include "crash_dump.h"
+
+
+static inline bool cd_is_predefined_name(const char* name)
+{
+ if (*name != '[')
+ return false;
+
+ return true;
+// return (!strcmp(name, "[heap]") ||
+// !strcmp(name, "[stack]") ||
+// !strcmp(name, "[vdso]"));
+}
+
+static inline native_segment_t* cd_find_segment(native_module_t* module, void* ip)
+{
+ for (size_t i = 0; i < module->seg_count; i++)
+ {
+ if (module->segments[i].base <= ip &&
+ (char*)module->segments[i].base + module->segments[i].size > ip)
+ return &module->segments[i];
+ }
+
+ assert(0);
+ return NULL;
+}
+
+void cd_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 = cd_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 (cd_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 = cd_get_module_type(short_name);
+
+ fprintf(stderr, "%s\n(%s)\n", module->filename, module_type);
+}
Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/crash_dump_os.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/ia32_em64t/signals_common.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/ia32_em64t/signals_common.cpp?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/ia32_em64t/signals_common.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/ia32_em64t/signals_common.cpp Tue Mar 18 04:31:02 2008
@@ -15,25 +15,8 @@
* limitations under the License.
*/
-#define LOG_DOMAIN "signals"
-#include "cxxlog.h"
-
#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/syscall.h>
-#include <stdio.h>
-#include <iostream>
-#include <fstream>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-
#include <sys/ucontext.h>
-#include <sys/wait.h>
-
-
#undef __USE_XOPEN
#include <signal.h>
@@ -42,79 +25,19 @@
#include <pthread_np.h>
#endif
#include <sys/time.h>
-#include "port_thread.h"
+#define LOG_DOMAIN "signals"
+#include "cxxlog.h"
+#include "open/platform_types.h"
#include "Class.h"
+#include "interpreter.h"
#include "environment.h"
-
-#include "open/gc.h"
-
-#include "init.h"
#include "exceptions.h"
#include "exceptions_jit.h"
-#include "vm_threads.h"
-#include "open/vm_util.h"
-#include "compile.h"
-#include "vm_stats.h"
-#include "sync_bits.h"
-
-#include "object_generic.h"
-#include "thread_manager.h"
-
-#include "exception_filter.h"
-#include "interpreter.h"
-#include "crash_handler.h"
-#include "stack_dump.h"
-#include "jvmti_break_intf.h"
-
#include "signals_common.h"
+#include "signals.h"
-static void general_crash_handler(int signum, Registers* regs);
-
-
-extern "C" {
-static void DECL_CHANDLER c_exception_handler(Registers* regs, Class* exn_class, bool java_code) {
- // this exception handler is executed *after* NT exception handler returned
- DebugUtilsTI* ti = VM_Global_State::loader_env->TI;
- // Create local copy for registers because registers in TLS can be changed
- VM_thread *thread = p_TLS_vmthread;
- assert(thread);
- assert(exn_class);
-
- exn_athrow_regs(regs, exn_class, java_code, true);
-}
-}
-
-static void throw_from_sigcontext(Registers* regs, Class* exc_clss)
-{
- DebugUtilsTI* ti = VM_Global_State::loader_env->TI;
- bool java_code = (vm_identify_eip((void*)regs->get_ip()) == VM_TYPE_JAVA);
- VM_thread* vmthread = p_TLS_vmthread;
-
- vm_set_exception_registers(vmthread, *regs);
-
- assert(exc_clss);
-
- NativeCodePtr callback = (NativeCodePtr) c_exception_handler;
- // Set up parameters and registers
- port_set_longjump_regs(callback, regs,
- 3, regs, exc_clss, (POINTER_SIZE_INT)java_code);
-}
-
-static bool java_throw_from_sigcontext(Registers* regs, Class* exc_clss)
-{
- ASSERT_NO_INTERPRETER;
- void* ip = regs->get_ip();
- VM_Code_Type vmct = vm_identify_eip(ip);
- if(vmct != VM_TYPE_JAVA) {
- return false;
- }
-
- throw_from_sigcontext(regs, exc_clss);
- return true;
-}
-
/*
* Information about stack
*/
@@ -153,11 +76,11 @@
}
#endif
-inline size_t find_guard_stack_size() {
+static inline size_t find_guard_stack_size() {
return 64*1024;
}
-inline size_t find_guard_page_size() {
+static inline size_t find_guard_page_size() {
int err;
size_t guard_size;
pthread_attr_t pthread_attr;
@@ -172,19 +95,19 @@
static size_t common_guard_stack_size;
static size_t common_guard_page_size;
-inline void* get_stack_addr() {
+static inline void* get_stack_addr() {
return jthread_self_vm_thread_unsafe()->stack_addr;
}
-inline size_t get_stack_size() {
+static inline size_t get_stack_size() {
return jthread_self_vm_thread_unsafe()->stack_size;
}
-inline size_t get_guard_stack_size() {
+static inline size_t get_guard_stack_size() {
return common_guard_stack_size;
}
-inline size_t get_guard_page_size() {
+static inline size_t get_guard_page_size() {
return common_guard_page_size;
}
@@ -361,288 +284,104 @@
}
-
-static void stack_overflow_handler(Registers* regs)
+Boolean stack_overflow_handler(port_sigtype UNREF signum, Registers* regs, void* fault_addr)
{
- Global_Env *env = VM_Global_State::loader_env;
+ TRACE2("signals", ("SOE detected at ip=%p, sp=%p",
+ regs->get_ip(), regs->get_sp()));
- vm_thread_t vm_thread = p_TLS_vmthread;
- remove_guard_stack(vm_thread);
- vm_thread->restore_guard_page = true;
+ vm_thread_t vmthread = get_thread_ptr();
+ Global_Env* env = VM_Global_State::loader_env;
+ void* saved_ip = regs->get_ip();
+ void* new_ip = NULL;
- if (java_throw_from_sigcontext(
- regs, env->java_lang_StackOverflowError_Class)) {
- return;
- } else {
- if (is_unwindable()) {
- if (hythread_is_suspend_enabled()) {
- tmn_suspend_disable();
- }
- throw_from_sigcontext(
- regs, env->java_lang_StackOverflowError_Class);
- } else {
- exn_raise_by_class(env->java_lang_StackOverflowError_Class);
- }
- }
-}
-
-
-static void null_java_reference_handler(int signum, Registers* regs, void* fault_addr)
-{
- VM_thread *vm_thread = p_TLS_vmthread;
-
- if (vm_thread && vm_thread->jvmti_thread.violation_flag)
+ if (is_in_ti_handler(vmthread, saved_ip))
{
- vm_thread->jvmti_thread.violation_flag = 0;
- regs->set_ip(vm_thread->jvmti_thread.violation_restart_address);
- return;
+ new_ip = vm_get_ip_from_regs(vmthread);
+ regs->set_ip(new_ip);
}
- Global_Env *env = VM_Global_State::loader_env;
-
- TRACE2("signals", "NPE or SOE detected at " << regs->get_ip());
+ if (!vmthread || env == NULL)
+ return FALSE; // Crash
- if (check_stack_overflow(regs, fault_addr)) {
- stack_overflow_handler(regs);
- return;
- }
+ remove_guard_stack(vmthread);
+ vmthread->restore_guard_page = true;
- if (!interpreter_enabled()) {
- if (java_throw_from_sigcontext(
- regs, env->java_lang_NullPointerException_Class)) {
- return;
- }
+ // Pass exception to NCAI exception handler
+ bool is_handled = 0;
+ ncai_process_signal_event((NativeCodePtr)regs->get_ip(),
+ (jint)signum, false, &is_handled);
+ if (is_handled)
+ {
+ if (new_ip)
+ regs->set_ip(saved_ip);
+ return TRUE;
}
- general_crash_handler(signum, regs);
-}
-
-
-static void null_java_divide_by_zero_handler(int signum, Registers* regs, void* UNREF fault_addr)
-{
- Global_Env *env = VM_Global_State::loader_env;
-
- TRACE2("signals",
- "ArithmeticException detected at " << regs->get_ip());
+ Class* exn_class = env->java_lang_StackOverflowError_Class;
- if (!interpreter_enabled()) {
- if (java_throw_from_sigcontext(
- regs, env->java_lang_ArithmeticException_Class)) {
- return;
- }
+ if (is_in_java(regs))
+ {
+ signal_throw_java_exception(regs, exn_class);
}
-
- general_crash_handler(signum, regs);
-}
-
-static void jvmti_jit_breakpoint_handler(int signum, Registers* regs, void* UNREF fault_addr)
-{
- TRACE2("signals", "JVMTI breakpoint detected at " << (void*)regs->get_ip());
-
- if (!interpreter_enabled())
+ else if (is_unwindable())
{
- regs->set_ip((void*)((POINTER_SIZE_INT)regs->get_ip() - 1));
- bool handled = jvmti_jit_breakpoint_handler(regs);
- if (handled)
- return;
+ if (hythread_is_suspend_enabled())
+ hythread_suspend_disable();
+ signal_throw_exception(regs, exn_class);
+ } else {
+ exn_raise_by_class(exn_class);
}
- general_crash_handler(signum, regs);
-}
+ if (new_ip && regs->get_ip() == new_ip)
+ regs->set_ip(saved_ip);
-/**
- * Print out the call stack of the aborted thread.
- * @note call stacks may be used for debugging
- */
-static void abort_handler(int signum, Registers* regs, void* UNREF fault_addr)
-{
- general_crash_handler(signum, regs);
+ return TRUE;
}
-static void process_crash(Registers* regs)
+Boolean null_reference_handler(port_sigtype UNREF signum, Registers* regs, void* fault_addr)
{
- // print stack trace
- sd_print_stack(regs);
-}
+ TRACE2("signals", "NPE detected at " << regs->get_ip());
-struct sig_name_t
-{
- int num;
- char* name;
-};
-
-static sig_name_t sig_names[] =
-{
- {SIGTRAP, "SIGTRAP"},
- {SIGSEGV, "SIGSEGV"},
- {SIGFPE, "SIGFPE" },
- {SIGABRT, "SIGABRT"},
- {SIGINT, "SIGINT" },
- {SIGQUIT, "SIGQUIT"}
-};
+ vm_thread_t vmthread = get_thread_ptr();
+ Global_Env* env = VM_Global_State::loader_env;
+ void* saved_ip = regs->get_ip();
+ void* new_ip = NULL;
-static const char* get_sig_name(int signum)
-{
- for (int i = 0; i < sizeof(sig_names)/sizeof(sig_names[0]); i++)
+ if (is_in_ti_handler(vmthread, saved_ip))
{
- if (signum == sig_names[i].num)
- return sig_names[i].name;
+ new_ip = vm_get_ip_from_regs(vmthread);
+ regs->set_ip(new_ip);
}
- return "unregistered";
-}
-
-static void general_crash_handler(int signum, Registers* regs)
-{
- // setup default handler
- signal(signum, SIG_DFL);
- // Print message
- fprintf(stderr, "Signal %d is reported: %s\n", signum, get_sig_name(signum));
-
- if (!is_gdb_crash_handler_enabled() ||
- !gdb_crash_handler(regs))
+ if (check_stack_overflow(regs, fault_addr))
{
- NativeCodePtr callback = (NativeCodePtr)process_crash;
- port_set_longjump_regs(callback, regs, 1, regs);
- }
-}
+ Boolean result = stack_overflow_handler(signum, regs, fault_addr);
-static void general_signal_handler(int signum, siginfo_t* info, void* context)
-{
- bool replaced = false;
- ucontext_t* uc = (ucontext_t *)context;
- void* fault_addr = info->si_addr;
- VM_thread* vm_thread = p_TLS_vmthread;
- bool violation =
- (signum == SIGSEGV) && vm_thread && vm_thread->jvmti_thread.violation_flag;
-
- Registers regs;
- port_thread_context_to_regs(®s, uc);
- void* saved_ip = regs.get_ip();
- void* new_ip = saved_ip;
- bool in_java = false;
+ if (new_ip && regs->get_ip() == new_ip)
+ regs->set_ip(saved_ip);
- if (vm_thread)
- {
- // If exception is occured in processor instruction previously
- // instrumented by breakpoint, the actual exception address will reside
- // in jvmti_jit_breakpoints_handling_buffer
- // We should replace exception address with saved address of instruction
- POINTER_SIZE_INT break_buf =
- (POINTER_SIZE_INT)vm_thread->jvmti_thread.jvmti_jit_breakpoints_handling_buffer;
- if ((POINTER_SIZE_INT)saved_ip >= break_buf &&
- (POINTER_SIZE_INT)saved_ip < break_buf + TM_JVMTI_MAX_BUFFER_SIZE)
- {
- // Breakpoints should not occur in breakpoint buffer
- assert(signum != SIGTRAP);
-
- replaced = true;
- new_ip = vm_get_ip_from_regs(vm_thread);
- regs.set_ip(new_ip);
- port_thread_regs_to_context(uc, ®s);
- }
-
- in_java = (vm_identify_eip(regs.get_ip()) == VM_TYPE_JAVA);
+ return result;
}
+ if (!vmthread || env == NULL ||
+ !is_in_java(regs) || interpreter_enabled())
+ return FALSE; // Crash
+
// Pass exception to NCAI exception handler
bool is_handled = 0;
- bool is_internal = (signum == SIGTRAP) || violation;
- ncai_process_signal_event((NativeCodePtr)regs.get_ip(),
- (jint)signum, is_internal, &is_handled);
+ ncai_process_signal_event((NativeCodePtr)regs->get_ip(),
+ (jint)signum, false, &is_handled);
if (is_handled)
- return;
-
- // delegate evident cases to crash handler
- if ((!vm_thread ||
- (!in_java && signum != SIGSEGV)) &&
- signum != SIGTRAP && signum != SIGINT && signum != SIGQUIT)
{
- regs.set_ip(saved_ip);
- general_crash_handler(signum, ®s);
- port_thread_regs_to_context(uc, ®s);
- return;
+ if (new_ip)
+ regs->set_ip(saved_ip);
+ return TRUE;
}
- switch (signum)
- {
- case SIGTRAP:
- jvmti_jit_breakpoint_handler(signum, ®s, fault_addr);
- break;
- case SIGSEGV:
- null_java_reference_handler(signum, ®s, fault_addr);
- break;
- case SIGFPE:
- null_java_divide_by_zero_handler(signum, ®s, fault_addr);
- break;
- case SIGABRT:
- abort_handler(signum, ®s, fault_addr);
- break;
- case SIGINT:
- vm_interrupt_handler(signum);
- break;
- case SIGQUIT:
- vm_dump_handler(signum);
- break;
- default:
- // Unknown signal
- assert(0);
- break;
- }
-
- // If IP was not changed in specific handler to start another handler,
- // we should restore original IP, if it's nesessary
- if (replaced && regs.get_ip() == new_ip)
- regs.set_ip((void*)saved_ip);
+ signal_throw_java_exception(regs, env->java_lang_NullPointerException_Class);
- // Update OS context
- port_thread_regs_to_context(uc, ®s);
-}
+ if (new_ip && regs->get_ip() == new_ip)
+ regs->set_ip(saved_ip);
-void initialize_signals()
-{
- struct sigaction sa;
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = &general_signal_handler;
- sigaction(SIGTRAP, &sa, NULL);
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO | SA_ONSTACK;;
- sa.sa_sigaction = &general_signal_handler;
- sigaction(SIGSEGV, &sa, NULL);
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = &general_signal_handler;
- sigaction(SIGFPE, &sa, NULL);
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = &general_signal_handler;
- sigaction(SIGINT, &sa, NULL);
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = &general_signal_handler;
- sigaction(SIGQUIT, &sa, NULL);
-
- /* install abort_handler to print out call stack on assertion failures */
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = &general_signal_handler;
- sigaction( SIGABRT, &sa, NULL);
- /* abort_handler installed */
-
- // Prepare gdb crash handler
- init_gdb_crash_handler();
-
- // Prepare general crash handler
- sd_init_crash_handler();
-
-} //initialize_signals
-
-void shutdown_signals() {
- //FIXME: should be defined in future
-} //shutdown_signals
+ return TRUE;
+}
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/include/platform_lowlevel.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/include/platform_lowlevel.h?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/include/platform_lowlevel.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/include/platform_lowlevel.h Tue Mar 18 04:31:02 2008
@@ -25,13 +25,6 @@
#include <limits.h>
//#include <ctype.h>
-inline void disable_assert_dialogs() {
- /* NOP on Linux */
-}
-
-inline void debug_break() {
- abort();
-}
#ifdef __cplusplus
extern "C" {
#endif
@@ -46,8 +39,6 @@
#define dllexport
#define __declspec(junk)
-
-#define _MAX_PATH PATH_MAX
#ifdef __cplusplus
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/include/signals_common.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/include/signals_common.h?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/include/signals_common.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/include/signals_common.h Tue Mar 18 04:31:02 2008
@@ -18,9 +18,6 @@
#ifndef _SIGNALS_COMMON_H_
#define _SIGNALS_COMMON_H_
-#include <sys/ucontext.h>
-#include "vm_core_types.h"
-
#ifdef _IPF_
#error IPF architecture is not adopted for unified signal handling
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ipf.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ipf.cpp?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ipf.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ipf.cpp Tue Mar 18 04:31:02 2008
@@ -14,145 +14,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/**
- * @author Intel, Evgueni Brevnov
- * @version $Revision: 1.1.2.2.4.4 $
- */
-
-// We use signal handlers to detect null pointer and divide by zero
-// exceptions.
-// There must be an easier way of locating the context in the signal
-// handler than what we do here.
-
-#define LOG_DOMAIN "port.old"
-#include "cxxlog.h"
#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/syscall.h>
-#include <stdio.h>
-#include <iostream.h>
-#include <fstream.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-
#include <sys/ucontext.h>
-#include <sys/wait.h>
-
#undef __USE_XOPEN
#include <signal.h>
#include <pthread.h>
-#include <sys/time.h>
+#if defined(FREEBSD)
+#include <pthread_np.h>
+#endif
+#define LOG_DOMAIN "signals"
+#include "cxxlog.h"
+#include "open/platform_types.h"
#include "Class.h"
+#include "interpreter.h"
#include "environment.h"
-
-#include "open/gc.h"
-
-#include "init.h"
#include "exceptions.h"
#include "exceptions_jit.h"
-#include "vm_threads.h"
-#include "open/vm_util.h"
-#include "compile.h"
-#include "vm_stats.h"
-#include "sync_bits.h"
-
-#include "object_generic.h"
-#include "thread_manager.h"
-
-#include "exception_filter.h"
-#include "interpreter.h"
-#include "crash_handler.h"
-#include "stack_dump.h"
-#include "jvmti_break_intf.h"
-
-
-#include <semaphore.h>
-
-void asm_exception_catch_callback() {
- // FIXME: not implemented
- fprintf(stderr, "FIXME: asm_jvmti_exception_catch_callback: not implemented\n");
- assert(0);
- abort();
-}
-
-void asm_jvmti_exception_catch_callback() {
- // FIXME: not implemented
- fprintf(stderr, "FIXME: asm_jvmti_exception_catch_callback: not implemented\n");
- assert(0);
- abort();
-}
-
-static bool java_throw_from_sigcontext(ucontext_t *uc, Class* exc_clss)
-{
- // FIXME: not implemented
- fprintf(stderr, "FIXME: java_throw_from_sigcontext: not implemented\n");
- assert(0);
- abort();
- return false;
-}
-
-void abort_handler (int signum, siginfo_t* info, void* context) {
- fprintf(stderr, "SIGABRT in VM code.\n");
- Registers regs;
- ucontext_t *uc = (ucontext_t *)context;
- port_thread_context_to_regs(®s, uc);
-
- // setup default handler
- signal(signum, SIG_DFL);
-
- if (!is_gdb_crash_handler_enabled() ||
- !gdb_crash_handler(®s))
- {
- // print stack trace
- sd_print_stack(®s);
- }
-}
-
-
-static void throw_from_sigcontext(ucontext_t *uc, Class* exc_clss) {
- // FIXME: not implemented
- fprintf(stderr, "FIXME: throw_from_sigcontext: not implemented\n");
- assert(0);
- abort();
-}
-
-void null_java_divide_by_zero_handler(int signum, siginfo_t* UNREF info, void* context)
-{
- ucontext_t *uc = (ucontext_t *)context;
- Global_Env *env = VM_Global_State::loader_env;
-
- /* Will not compile on IPF:
- * TRACE2("signals", "ArithmeticException detected at " <<
- (void *)uc->uc_mcontext.gregs[REG_EIP]);
- */
-
- if (!interpreter_enabled()) {
- if (java_throw_from_sigcontext(
- uc, env->java_lang_ArithmeticException_Class)) {
- return;
- }
- }
-
- fprintf(stderr, "SIGFPE in VM code.\n");
- Registers regs;
- port_thread_context_to_regs(®s, uc);
-
- // setup default handler
- signal(signum, SIG_DFL);
-
- if (!is_gdb_crash_handler_enabled() ||
- !gdb_crash_handler(®s))
- {
- // print stack trace
- sd_print_stack(®s);
- }
-}
+#include "signals.h"
/*
@@ -186,12 +67,12 @@
}
#endif
-inline size_t find_guard_stack_size() {
+static inline size_t find_guard_stack_size() {
return 64*1024;
}
-inline size_t find_guard_page_size() {
+static inline size_t find_guard_page_size() {
int err;
size_t guard_size;
pthread_attr_t pthread_attr;
@@ -205,19 +86,19 @@
static size_t common_guard_stack_size;
static size_t common_guard_page_size;
-inline void* get_stack_addr() {
+static inline void* get_stack_addr() {
return jthread_self_vm_thread_unsafe()->stack_addr;
}
-inline size_t get_stack_size() {
+static inline size_t get_stack_size() {
return jthread_self_vm_thread_unsafe()->stack_size;
}
-inline size_t get_guard_stack_size() {
+static inline size_t get_guard_stack_size() {
return common_guard_stack_size;
}
-inline size_t get_guard_page_size() {
+static inline size_t get_guard_page_size() {
return common_guard_page_size;
}
@@ -297,11 +178,6 @@
}
}
-size_t get_default_stack_size() {
- size_t default_stack_size = get_stack_size();
- return default_stack_size;
-}
-
bool check_available_stack_size(size_t required_size) {
size_t available_stack_size = get_available_stack_size();
@@ -329,12 +205,6 @@
return get_restore_stack_size() < available_stack_size;
}
-void remove_guard_stack() {
- vm_thread_t vm_thread = jthread_self_vm_thread_unsafe();
- assert(vm_thread);
- remove_guard_stack(vm_thread);
-}
-
void remove_guard_stack(vm_thread_t vm_thread) {
int err;
char* stack_addr = (char*) get_stack_addr();
@@ -356,7 +226,7 @@
}
-bool check_stack_overflow(siginfo_t *info, ucontext_t *uc) {
+static bool check_stack_overflow(Registers* regs, void* fault_addr) {
char* stack_addr = (char*) get_stack_addr();
size_t stack_size = get_stack_size();
size_t guard_stack_size = get_guard_stack_size();
@@ -365,264 +235,113 @@
char* guard_page_begin = stack_addr - stack_size + guard_page_size + guard_stack_size;
char* guard_page_end = guard_page_begin + guard_page_size;
- char* fault_addr = (char*)(info->si_addr);
- //char* esp_value = (char*)(uc->uc_mcontext.gregs[REG_ESP]);
-
return((guard_page_begin <= fault_addr) && (fault_addr < guard_page_end));
}
-/*
- * 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.
- */
-void stack_overflow_handler(int signum, siginfo_t* UNREF info, void* context)
+Boolean stack_overflow_handler(port_sigtype UNREF signum, Registers* regs, void* fault_addr)
{
- ucontext_t *uc = (ucontext_t *)context;
- Global_Env *env = VM_Global_State::loader_env;
+ TRACE2("signals", ("SOE detected at ip=%p, sp=%p",
+ regs->get_ip(), regs->get_sp()));
- if (java_throw_from_sigcontext(
- uc, env->java_lang_StackOverflowError_Class)) {
- return;
- } else {
- if (is_unwindable()) {
- if (hythread_is_suspend_enabled()) {
- tmn_suspend_disable();
- }
- throw_from_sigcontext(
- uc, env->java_lang_StackOverflowError_Class);
- } else {
- vm_thread_t vm_thread = p_TLS_vmthread;
- remove_guard_stack(vm_thread);
- exn_raise_by_name("java/lang/StackOverflowError");
- vm_thread->restore_guard_page = true;
- }
- }
-}
+ assert(0); // Not implemented
+ abort();
-void null_java_reference_handler(int signum, siginfo_t* UNREF info, void* context)
-{
- ucontext_t *uc = (ucontext_t *)context;
- Global_Env *env = VM_Global_State::loader_env;
- Registers regs;
- port_thread_context_to_regs(®s, uc);
+ vm_thread_t vmthread = get_thread_ptr();
+ Global_Env* env = VM_Global_State::loader_env;
+ void* saved_ip = regs->get_ip();
+ void* new_ip = NULL;
- if (!p_TLS_vmthread)
+ if (is_in_ti_handler(vmthread, saved_ip))
{
- if (!is_gdb_crash_handler_enabled() ||
- !gdb_crash_handler(®s))
- {
- // print stack trace
- sd_print_stack(®s);
- }
+ new_ip = vm_get_ip_from_regs(vmthread);
+ regs->set_ip(new_ip);
}
- /* Will not compile on IPF:
- TRACE2("signals", "NPE or SOE detected at " <<
- (void *)uc->uc_mcontext.gregs[REG_EIP]); */
-
- if (check_stack_overflow(info, uc)) {
- stack_overflow_handler(signum, info, context);
- return;
- }
-
- if (!interpreter_enabled()) {
- if (java_throw_from_sigcontext(
- uc, env->java_lang_NullPointerException_Class)) {
- return;
- }
- }
- fprintf(stderr, "SIGSEGV in VM code.\n");
+ if (!vmthread || env == NULL)
+ return FALSE; // Crash
- // setup default handler
- signal(signum, SIG_DFL);
-
- if (!is_gdb_crash_handler_enabled() ||
- !gdb_crash_handler(®s))
+ // Pass exception to NCAI exception handler
+ bool is_handled = 0;
+ ncai_process_signal_event((NativeCodePtr)regs->get_ip(),
+ (jint)signum, false, &is_handled);
+ if (is_handled)
{
- // print stack trace
- sd_print_stack(®s);
+ if (new_ip)
+ regs->set_ip(saved_ip);
+ return TRUE;
}
-}
-
-void initialize_signals() {
- struct sigaction sa;
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO | SA_ONSTACK;;
- sa.sa_sigaction = &null_java_reference_handler;
- sigaction(SIGSEGV, &sa, NULL);
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = &null_java_divide_by_zero_handler;
- sigaction(SIGFPE, &sa, NULL);
-
- signal(SIGINT, (void (*)(int)) vm_interrupt_handler);
- signal(SIGQUIT, (void (*)(int)) vm_dump_handler);
-
- /* install abort_handler to print out call stack on assertion failures */
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = &abort_handler;
- sigaction( SIGABRT, &sa, NULL);
- /* abort_handler installed */
-
- // Prepare gdb crash handler
- init_gdb_crash_handler();
-
- // Prepare general crash handler
- sd_init_crash_handler();
-
-} //initialize_signals
-
-void shutdown_signals() {
- //FIXME: should be defined in future
-} //shutdown_signals
-
-#if 0
-static sigset_t signal_set;
+ Class* exn_class = env->java_lang_StackOverflowError_Class;
-extern "C" void get_rnat_and_bspstore(uint64* res);
-extern "C" void do_flushrs();
-
-// Variables used to locate the context from the signal handler
-static int sc_nest = -1;
-static bool use_ucontext = false;
-static uint32 exam_point;
-
-bool SuspendThread(unsigned xx){ return 0; }
-bool ResumeThread(unsigned xx){ return 1; }
+ if (is_in_java(regs))
+ {
+ signal_throw_java_exception(regs, exn_class);
+ }
+ else if (is_unwindable())
+ {
+ if (hythread_is_suspend_enabled())
+ hythread_suspend_disable();
+ signal_throw_exception(regs, exn_class);
+ } else {
+ remove_guard_stack(vmthread);
+ vmthread->restore_guard_page = true;
+ exn_raise_by_class(exn_class);
+ }
-static bool linux_throw_from_sigcontext(ucontext_t *uc, Class* exc_clss)
-{
- // FIXME: not implemented
- assert(0);
- abort();
- return false;
-}
+ if (new_ip && regs->get_ip() == new_ip)
+ regs->set_ip(saved_ip);
-static void throw_from_sigcontext(ucontext_t *uc, Class* exc_clss) {
- // FIXME: not implemented
- assert(0);
- abort();
- return false;
+ return TRUE;
}
-
-/*
- * 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.
- */
-
-void null_java_reference_handler(int signum)
+Boolean null_reference_handler(port_sigtype UNREF signum, Registers* regs, void* fault_addr)
{
- uint32* top_ebp = NULL;
-//TODO: ADD correct stack handling here!!
- Global_Env *env = VM_Global_State::loader_env;
- linux_throw_from_sigcontext(top_ebp, env->java_lang_NullPointerException_Class);
-}
+ TRACE2("signals", "NPE detected at " << regs->get_ip());
+ assert(0); // Not implemented
+ abort();
-void null_java_divide_by_zero_handler(int signum)
-{
- uint32* top_ebp = NULL;
-//TODO: ADD correct stack handling here!!
- Global_Env *env = VM_Global_State::loader_env;
- linux_throw_from_sigcontext(top_ebp, env->java_lang_ArithmeticException_Class);
-}
+ vm_thread_t vmthread = get_thread_ptr();
+ Global_Env* env = VM_Global_State::loader_env;
+ void* saved_ip = regs->get_ip();
+ void* new_ip = NULL;
-/*
-See function initialize_signals() below first please.
+ if (is_in_ti_handler(vmthread, saved_ip))
+ {
+ new_ip = vm_get_ip_from_regs(vmthread);
+ regs->set_ip(new_ip);
+ }
-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.
-*/
+ if (check_stack_overflow(regs, fault_addr))
+ {
+ Boolean result = stack_overflow_handler(signum, regs, fault_addr);
-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;
- }
- }
- }
+ if (new_ip && regs->get_ip() == new_ip)
+ regs->set_ip(saved_ip);
- ebp = (uint32 *)((uint64)ebp[0]);
+ return result;
}
- 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);
+ if (!vmthread || env == NULL ||
+ !is_in_java(regs) || interpreter_enabled())
+ return FALSE; // Crash
+
+ // Pass exception to NCAI exception handler
+ bool is_handled = 0;
+ ncai_process_signal_event((NativeCodePtr)regs->get_ip(),
+ (jint)signum, false, &is_handled);
+ if (is_handled)
+ {
+ if (new_ip)
+ regs->set_ip(saved_ip);
+ return TRUE;
}
-}
+ signal_throw_java_exception(regs, env->java_lang_NullPointerException_Class);
+ if (new_ip && regs->get_ip() == new_ip)
+ regs->set_ip(saved_ip);
-#endif
+ return TRUE;
+}
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/natives_support.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/natives_support.cpp?rev=638327&r1=638326&r2=638327&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/natives_support.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/natives_support.cpp Tue Mar 18 04:31:02 2008
@@ -39,8 +39,6 @@
#include "jni_types.h"
#include "jni_utils.h"
-#include "stack_dump.h" // To update modules list on library load (in debug)
-
#define LOG_DOMAIN "natives"
#include "cxxlog.h"
@@ -298,8 +296,6 @@
returnCode = pinfo->handle;
- sd_update_modules(); // Updates modules list for crash handling (in debug)
-
NATIVES_LOAD_LIBRARY_EXIT :
#ifdef PLATFORM_NT
@@ -747,7 +743,7 @@
if (!filepointer)
return NULL;
- if (strlen(filepointer) > _MAX_PATH)
+ if (strlen(filepointer) > PORT_PATH_MAX)
return NULL;
strcpy(buf, filepointer);
@@ -762,7 +758,7 @@
// Method is stupid and slow but it works for full and partial names
bool natives_is_library_loaded_slow(const char* libname)
{
- char src_buf[_MAX_PATH + 1], cmp_buf[_MAX_PATH + 1];
+ char src_buf[PORT_PATH_MAX + 1], cmp_buf[PORT_PATH_MAX + 1];
if (short_name(libname, src_buf) == NULL)
return false; // Error case
Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/signals.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/signals.cpp?rev=638327&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/signals.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/signals.cpp Tue Mar 18 04:31:02 2008
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+#define LOG_DOMAIN "signals"
+#include "cxxlog.h"
+
+#include "open/platform_types.h"
+#include "port_crash_handler.h"
+#include "init.h"
+#include "vm_threads.h"
+#include "environment.h"
+#include "signals.h"
+
+
+Boolean abort_handler(port_sigtype UNREF signum, Registers* UNREF regs, void* fault_addr)
+{
+ TRACE2("signals", "Abort detected at " << regs->get_ip());
+ // Crash always
+ return FALSE;
+}
+
+Boolean ctrl_backslash_handler(port_sigtype UNREF signum, Registers* UNREF regs, void* UNREF fault_addr)
+{
+ TRACE2("signals", "Ctrl+\\ pressed");
+ vm_dump_handler();
+ return TRUE;
+}
+
+Boolean ctrl_break_handler(port_sigtype UNREF signum, Registers* UNREF regs, void* UNREF fault_addr)
+{
+ TRACE2("signals", "Ctrl+Break pressed");
+ vm_dump_handler();
+ return TRUE;
+}
+
+Boolean ctrl_c_handler(port_sigtype UNREF signum, Registers* UNREF regs, void* UNREF fault_addr)
+{
+ TRACE2("signals", "Ctrl+C pressed");
+ vm_interrupt_handler();
+ // Continue execution - the process will be terminated from
+ // the separate thread started in vm_interrupt_handler()
+ return TRUE;
+}
+
+Boolean native_breakpoint_handler(port_sigtype UNREF signum, Registers* regs, void* fault_addr)
+{
+ TRACE2("signals", "Native breakpoint detected at " << regs->get_ip());
+#ifdef _IPF_
+ assert(0); // Not implemented
+ abort();
+#endif
+
+ if (VM_Global_State::loader_env == NULL || interpreter_enabled())
+ return FALSE; // Crash
+
+ vm_thread_t vmthread = get_thread_ptr();
+
+ if (is_in_ti_handler(vmthread, regs->get_ip()))
+ // Breakpoints should not occur in breakpoint buffer
+ return FALSE; // Crash
+
+ // Pass exception to NCAI exception handler
+ bool is_handled = 0;
+ ncai_process_signal_event((NativeCodePtr)regs->get_ip(),
+ (jint)signum, true, &is_handled);
+ if (is_handled)
+ return TRUE;
+
+ return (Boolean)jvmti_jit_breakpoint_handler(regs);
+}
+
+Boolean arithmetic_handler(port_sigtype UNREF signum, Registers* regs, void* fault_addr)
+{
+ TRACE2("signals", "ArithmeticException detected at " << regs->get_ip());
+#ifdef _IPF_
+ assert(0); // Not implemented
+ abort();
+#endif
+
+ vm_thread_t vmthread = get_thread_ptr();
+ void* saved_ip = regs->get_ip();
+ void* new_ip = NULL;
+
+ if (is_in_ti_handler(vmthread, saved_ip))
+ {
+ new_ip = vm_get_ip_from_regs(vmthread);
+ regs->set_ip(new_ip);
+ }
+
+ // Pass exception to NCAI exception handler
+ bool is_handled = 0;
+ ncai_process_signal_event((NativeCodePtr)regs->get_ip(),
+ (jint)signum, false, &is_handled);
+ if (is_handled)
+ {
+ if (new_ip)
+ regs->set_ip(saved_ip);
+ return TRUE;
+ }
+
+ if (!vmthread || VM_Global_State::loader_env == NULL ||
+ !is_in_java(regs) || interpreter_enabled())
+ return FALSE; // Crash
+
+ signal_throw_java_exception(regs, VM_Global_State::loader_env->java_lang_ArithmeticException_Class);
+
+ if (new_ip && regs->get_ip() == new_ip)
+ regs->set_ip(saved_ip);
+
+ return TRUE;
+}