diff --git a/vm/vmcore/include/jvmti_break_intf.h b/vm/vmcore/include/jvmti_break_intf.h index 7927a6b..6fb69bd 100644 --- a/vm/vmcore/include/jvmti_break_intf.h +++ b/vm/vmcore/include/jvmti_break_intf.h @@ -219,6 +219,9 @@ private: Lock_Manager m_lock; }; +// Address of this function is used for stack unwinding througn breakpoint +void process_native_breakpoint_event(); + // Callback function for native breakpoint processing bool jvmti_jit_breakpoint_handler(Registers *regs); diff --git a/vm/vmcore/include/native_stack.h b/vm/vmcore/include/native_stack.h index c52811d..ec521e1 100644 --- a/vm/vmcore/include/native_stack.h +++ b/vm/vmcore/include/native_stack.h @@ -25,6 +25,7 @@ #define _NATIVE_STACK_H_ #include "jni.h" #include "stack_iterator.h" #include "native_modules.h" +#include "vm_threads.h" #ifdef __cplusplus extern "C" { @@ -53,6 +54,7 @@ bool native_is_frame_valid(native_module int native_test_unwind_special(native_module_t* modules, void* sp); bool native_unwind_special(native_module_t* modules, void* stack, void** ip, void** sp, void** bp, bool is_last); +void native_unwind_interrupted_frame(VM_thread* pthread, void** p_ip, void** p_bp, void** p_sp); bool native_is_ip_in_modules(native_module_t* modules, void* ip); bool native_is_ip_stub(void* ip); diff --git a/vm/vmcore/include/vm_core_types.h b/vm/vmcore/include/vm_core_types.h index c4d5c9b..2cfa3c6 100644 --- a/vm/vmcore/include/vm_core_types.h +++ b/vm/vmcore/include/vm_core_types.h @@ -71,6 +71,7 @@ struct Registers { void reset_ip() { ip = 0; } void* get_ip() { return (void*)ip; } + void set_ip(void* src_ip) { ip = (uint64)src_ip; } }; //Registers #else // !_IPF_ @@ -100,6 +101,7 @@ struct Registers { void reset_ip() { rip = 0; } void* get_ip() { return (void*)rip; } + void set_ip(void* src_ip) { rip = (uint64)src_ip; } }; //Registers #else // ! _EM64T_ @@ -118,6 +120,7 @@ struct Registers { void reset_ip() { eip = 0; } void* get_ip() { return (void*)eip; } + void set_ip(void* src_ip) { eip = (uint32)src_ip; } }; //Registers #endif // _EM64T_ diff --git a/vm/vmcore/src/jvmti/jvmti_break_intf.cpp b/vm/vmcore/src/jvmti/jvmti_break_intf.cpp index 4a9ec9e..7da89b2 100644 --- a/vm/vmcore/src/jvmti/jvmti_break_intf.cpp +++ b/vm/vmcore/src/jvmti/jvmti_break_intf.cpp @@ -584,17 +584,12 @@ VMBreakPoints::process_native_breakpoint // When we get here we know already that breakpoint occurred in JITted code, // JVMTI handles it, and registers context is saved for us in TLS VM_thread *vm_thread = p_TLS_vmthread; + lock(); Registers regs = vm_thread->jvmti_saved_exception_registers; - -#if _IA32_ && PLATFORM_POSIX && INSTRUMENTATION_BYTE == INSTRUMENTATION_BYTE_INT3 - // Int3 exception address points to the instruction after it - regs.eip -= 1; -#endif //_IA32_ && PLATFORM_POSIX && INSTRUMENTATION_BYTE == INSTRUMENTATION_BYTE_INT3 NativeCodePtr addr = (NativeCodePtr)regs.get_ip(); TRACE2("jvmti.break", "Native breakpoint occured: " << addr); - lock(); VMBreakPoint* bp = find_breakpoint(addr); if (NULL == bp) { // breakpoint could be deleted by another thread @@ -1302,7 +1297,7 @@ static bool clear_native_breakpoint(VMBr // Native breakpoints ////////////////////////////////////////////////////////////////////////////// -static void process_native_breakpoint_event() +void process_native_breakpoint_event() { DebugUtilsTI *ti = VM_Global_State::loader_env->TI; ti->vm_brpt->process_native_breakpoint(); @@ -1327,13 +1322,12 @@ #endif // Now it is necessary to set up a transition to // process_native_breakpoint_event from the exception/signal handler VM_thread *vm_thread = p_TLS_vmthread; + // Store possibly corrected location + regs->set_ip((void*)native_location); // Copy original registers to TLS vm_thread->jvmti_saved_exception_registers = *regs; -#ifndef _EM64T_ - regs->eip = (POINTER_SIZE_INT)process_native_breakpoint_event; -#else - regs->rip = (POINTER_SIZE_INT)process_native_breakpoint_event; -#endif + // Set return address for exception handler + regs->set_ip((void*)process_native_breakpoint_event); return true; } diff --git a/vm/vmcore/src/util/em64t/base/native_stack_em64t.cpp b/vm/vmcore/src/util/em64t/base/native_stack_em64t.cpp index 583fce9..36a8f29 100644 --- a/vm/vmcore/src/util/em64t/base/native_stack_em64t.cpp +++ b/vm/vmcore/src/util/em64t/base/native_stack_em64t.cpp @@ -66,3 +66,10 @@ bool native_unwind_special(native_module { return false; // Not implemented } + +void native_unwind_interrupted_frame(VM_thread* pthread, void** p_ip, void** p_bp, void** p_sp) +{ // Not implemented yet + *p_ip = NULL; + *p_bp = NULL; + *p_sp = NULL; +} diff --git a/vm/vmcore/src/util/ia32/base/native_stack_ia32.cpp b/vm/vmcore/src/util/ia32/base/native_stack_ia32.cpp index b4f5508..e34f377 100644 --- a/vm/vmcore/src/util/ia32/base/native_stack_ia32.cpp +++ b/vm/vmcore/src/util/ia32/base/native_stack_ia32.cpp @@ -56,7 +56,7 @@ void native_get_sp_from_si_jit_context(S bool native_is_out_of_stack(void* value) { // FIXME: Invalid criterion - return (value < (void*)0x10000) || (value > (void*)0x80000000); + return (value < (void*)0x10000) || (value > (void*)0xC0000000); } bool native_is_frame_valid(native_module_t* modules, void* bp, void* sp) @@ -182,3 +182,11 @@ bool native_unwind_special(native_module return true; } + +void native_unwind_interrupted_frame(VM_thread* pthread, void** p_ip, void** p_bp, void** p_sp) +{ + Registers* pregs = &pthread->jvmti_saved_exception_registers; + *p_ip = (void*)pregs->eip; + *p_bp = (void*)pregs->ebp; + *p_sp = (void*)pregs->esp; +} diff --git a/vm/vmcore/src/util/ipf/base/native_stack_ipf.cpp b/vm/vmcore/src/util/ipf/base/native_stack_ipf.cpp index 78a8966..8320afd 100644 --- a/vm/vmcore/src/util/ipf/base/native_stack_ipf.cpp +++ b/vm/vmcore/src/util/ipf/base/native_stack_ipf.cpp @@ -59,3 +59,10 @@ bool native_unwind_special(native_module { return false; // Not implemented } + +void native_unwind_interrupted_frame(VM_thread* pthread, void** p_ip, void** p_bp, void** p_sp) +{ // Not implemented yet + *p_ip = NULL; + *p_bp = NULL; + *p_sp = NULL; +} diff --git a/vm/vmcore/src/util/native_stack.cpp b/vm/vmcore/src/util/native_stack.cpp index b0e0a25..2a5545d 100644 --- a/vm/vmcore/src/util/native_stack.cpp +++ b/vm/vmcore/src/util/native_stack.cpp @@ -26,6 +26,8 @@ #include "stack_trace.h" #include "interpreter.h" #include "interpreter_exports.h" #include "compile.h" +#include "jvmti_break_intf.h" +#include "environment.h" #include "native_modules.h" #include "native_stack.h" @@ -88,6 +90,12 @@ bool native_is_ip_stub(void* ip) return false; } + +static bool native_is_ip_in_breakpoint_handler(void* ip) +{ + return (ip >= &process_native_breakpoint_event && + ip < &jvmti_jit_breakpoint_handler); +} /// Helper functions ////////////////////////////////////////////////////////////////////////////// @@ -143,14 +151,19 @@ static int walk_native_stack_jit(Registe si = si_create_from_native(pthread); - if (is_java) + if (is_java || + // Frame was pushed already by breakpoint handler + (si_is_native(si) && si_get_m2n(si) && m2n_is_suspended_frame(si_get_m2n(si)))) + { si_goto_previous(si); + } jint inline_index = -1; jint inline_count; CodeChunkInfo* cci = NULL; bool is_stub = false; int special_count = 0; + bool flag_breakpoint = false; while (1) { @@ -197,7 +210,7 @@ static int walk_native_stack_jit(Registe else { inline_index = -1; - // Ge to previous stack frame from StackIterator + // Go to previous stack frame from StackIterator si_goto_previous(si); native_get_ip_bp_from_si_jit_context(si, &ip, &bp);//??? native_get_sp_from_si_jit_context(si, &sp); @@ -238,7 +251,25 @@ static int walk_native_stack_jit(Registe if (native_is_frame_valid(modules, bp, sp)) { // Simply bp-based frame, let's unwind it - native_unwind_bp_based_frame(bp, &ip, &bp, &sp); + void *tmp_ip, *tmp_bp, *tmp_sp; + native_unwind_bp_based_frame(bp, &tmp_ip, &tmp_bp, &tmp_sp); + + VMBreakPoints* vm_breaks = VM_Global_State::loader_env->TI->vm_brpt; + vm_breaks->lock(); + + if (native_is_ip_in_breakpoint_handler(tmp_ip)) + { + native_unwind_interrupted_frame(pthread, &ip, &bp, &sp); + flag_breakpoint = true; + } + else + { + ip = tmp_ip; + bp = tmp_bp; + sp = tmp_sp; + } + + vm_breaks->unlock(); } else { // Is not bp-based frame @@ -266,9 +297,10 @@ static int walk_native_stack_jit(Registe code_type = vm_identify_eip(ip); is_java = (code_type == VM_TYPE_JAVA); - // If we've reached Java without native stub - if (is_java && !is_stub) + // If we've reached Java without native stub (or breakpoint handler frame) + if (is_java && !is_stub && !flag_breakpoint) break; // then stop processing + flag_breakpoint = false; // ^^ Native ^^ ///////////////////////// } @@ -280,6 +312,8 @@ static int walk_native_stack_jit(Registe STD_FREE(plm2n); } + si_free(si); + return frame_count; }