bool Thread::has_user_frames_until(int num_frames) { Frame fr(this); bool forever = (num_frames == 0); while (forever || num_frames-- > 0) { if (fr.is_entry_frame()) { break; } else { const JavaFrame jf = fr.as_JavaFrame(); const Method::Raw m = jf.method(); const JavaClass::Raw klass = m().holder(); if (!klass().is_preloaded()) { return true; } jf.caller_is(fr); } } return false; }
jboolean StepModifier::find_frame(address starting_fp, JavaFrame *frame) { JavaFrame caller(*frame); caller.caller_is(caller); while (true) { if (caller.is_entry_frame()) { EntryFrame e = caller.as_EntryFrame(); if (e.is_first_frame()) { // did not find the frame return false; } e.caller_is(caller); } else if (caller.is_java_frame()) { JavaFrame jf = caller.as_JavaFrame(); if (starting_fp == jf.fp()) { // found the frame return true; } jf.caller_is(caller); } } }
ReturnOop VMEventModifier::new_modifier(PacketInputStream *in, PacketOutputStream *out, bool& error) { UsingFastOops fast_oops; jbyte mod_kind = in->read_byte(); VMEventModifier::Fast newMod; Thread::Fast thread; newMod = allocate_modifier(); if (newMod.is_null()) { error = true; out->set_error(JDWP_Error_OUT_OF_MEMORY); return NULL; } newMod().set_mod_kind(mod_kind); #ifdef AZZERT if (TraceDebugger) { tty->print_cr("Modifier: modkind = %d", mod_kind); } #endif switch(mod_kind) { case JDWP_EventRequest_Set_Out_modifiers_Modifier_FieldOnly: // unsupported in->read_class_id(); in->read_class_id(); in->read_int(); return NULL; case JDWP_EventRequest_Set_Out_modifiers_Modifier_Conditional: // unsupported in->read_int(); return NULL; case JDWP_EventRequest_Set_Out_modifiers_Modifier_ClassExclude: // unsupported in->read_string(); return NULL; case JDWP_EventRequest_Set_Out_modifiers_Modifier_ThreadOnly: newMod().set_thread_id(in->read_thread_id()); return newMod; case JDWP_EventRequest_Set_Out_modifiers_Modifier_Count: newMod().set_count(in->read_int()); return newMod; case JDWP_EventRequest_Set_Out_modifiers_Modifier_ClassOnly: { newMod().set_clazz_id(in->read_class_id()); #ifdef AZZERT if (TraceDebugger) { tty->print_cr("Modifier: class_id = %d", newMod().clazz_id()); } #endif return newMod; } case JDWP_EventRequest_Set_Out_modifiers_Modifier_ClassMatch: { UsingFastOops fast_oops_2; int length; SETUP_ERROR_CHECKER_ARG; TypeArray::Fast ta = in->read_raw_string(length JVM_NO_CHECK); if (ta.is_null()) { // Out of memory?? Things will fall apart soon enough, // We just punt on this modifier return newMod; } for (int i = length - 1; i >= 0; i--) { if (ta().byte_at(i) == '.') { ta().byte_at_put(i, '/'); } } Symbol::Fast tmpName = Universe::new_symbol(&ta, (utf8)(ta().base_address()), length JVM_NO_CHECK); if (tmpName.is_null()) { error = true; out->set_error(JDWP_Error_OUT_OF_MEMORY); return NULL; } #ifdef AZZERT if (TraceDebugger) { tty->print("Modifier: class match = "); tmpName().print_symbol_on(tty); tty->cr(); } #endif ClassMatchModifier::Fast class_match_modifier = newMod().obj(); class_match_modifier().set_class_match_name(&tmpName); return newMod; } case JDWP_EventRequest_Set_Out_modifiers_Modifier_LocationOnly: { UsingFastOops fast_oops_3; jbyte tag = in->read_byte(); (void)tag; LocationModifier::Fast lmod = newMod.obj(); lmod().set_clazz_id(in->read_class_id()); if (lmod().clazz_id() == 0) { return NULL; /* Class ID == 0 is invalid */ } lmod().set_method_id(in->read_method_id()); lmod().set_offset(in->read_long()); #ifdef AZZERT if (TraceDebugger) { tty->print_cr("Loc: class: 0x%x, method: 0x%x, off: 0x%x", lmod().clazz_id(), (int)(lmod().method_id() & 0xFFFFFFFF), lmod().offset()); } #endif return lmod; } case JDWP_EventRequest_Set_Out_modifiers_Modifier_ExceptionOnly: { UsingFastOops fast_oops_4; ExceptionModifier::Fast emod = newMod.obj(); emod().set_clazz_id(in->read_class_id()); emod().set_sig_caught(in->read_boolean()); emod().set_sig_uncaught(in->read_boolean()); return emod; } case JDWP_EventRequest_Set_Out_modifiers_Modifier_Step: { UsingFastOops fast_oops_5; int thread_id = in->read_thread_id(); thread = JavaDebugger::get_thread_by_id(thread_id); if (!JavaDebugger::is_valid_thread(&thread) || !thread().last_java_frame_exists()) { error = true; out->set_error(JDWP_Error_INVALID_THREAD); return NULL; } Frame fr(&thread); GUARANTEE(fr.is_java_frame(), "Single step must start at JavaFrame"); JavaFrame jf = fr.as_JavaFrame(); LocationModifier::Fast loc = LocationModifier::new_location(&jf); if (loc.is_null()) { error = true; out->set_error(JDWP_Error_OUT_OF_MEMORY); return NULL; } #ifdef AZZERT if (TraceDebugger) { tty->print_cr("StepLoc: thread: 0x%x, class: 0x%x, method: 0x%x, off: 0x%x", thread_id, loc().clazz_id(), (int)(loc().method_id() & 0xFFFFFFFF), loc().offset()); } #endif loc().set_mod_kind(mod_kind); StepModifier::Fast smod = loc.obj(); smod().set_thread_id(thread_id); if (thread.is_null() /* || (thread.state() & THREAD_DEAD) */) { /* * If you try to single step after suspending because * of an uncaught exception event we'll get sent the * thread id of the thread that had the exception. * That thread is dead though. */ error = true; out->set_error(JDWP_Error_INVALID_THREAD); return NULL; } smod().set_step_size(in->read_int()); smod().set_step_depth(in->read_int()); /* query the _proxy_ for next line location */ { UsingFastOops fast_oops_6; DebuggerEvent d_event; d_event.set_event_kind((jbyte)VM_STEPINFO_EVENT); VMEvent::stepping_info_request(&d_event, in->transport(), &smod); /* * At this point, the proxy has made sure no more commands * from the debugger get sent until we get our line number * info from the proxy */ JavaDebugger::set_loop_count(1); JavaDebugger::process_command_loop(); /* * Once we get back here, then we know we've gotten the * command from the proxy with the line number info put into * the StepModifier object in the step_info_event above. */ /* setup the relevant info */ thread().set_is_stepping(true); // set the _debugger_active flag for the interpreter loop JavaDebugger::set_stepping(true); // smod = step_info_event().mods(); // smod().set_step_target_offset(stepData().step_target_offset()); smod().unlink_method(); if (smod().step_depth() == JDWP_StepDepth_OUT) { // if stepping out to the caller, we really should unlink any // compiled code from here to the caller frame, for now assume // one frame up. It could be re-compiled but we may luck out. Method::Fast m; Frame caller(jf); jf.caller_is(caller); if (!caller.is_entry_frame()) { m = caller.as_JavaFrame().method(); #if ENABLE_COMPILER if (m().has_compiled_code()) { m().unlink_compiled_code(); } #endif } } smod().set_step_starting_fp(DISTANCE(thread().stack_base(), jf.fp())); smod().set_step_starting_offset(jf.bci()); // smod().set_dup_current_line_offset(stepData().dup_current_line_offset()); // smod().set_post_dup_line_offset(stepData().post_dup_line_offset()); thread().set_step_info(&smod); } return smod; } } error = true; out->set_error(JDWP_Error_NOT_IMPLEMENTED); return NULL; }
void VMEvent::clear_impossible_to_compile(LocationModifier *mod, VMEvent *ep) { UsingFastOops fast_oops; // If we are using the compiler then we should reset the // impossible_to_compile flag for this method (and potentially one frame // up if it's a single step). // We also check the previous state of the method, if it was // "impossible_to_compile" we don't reset the flag. InstanceClass::Fast clazz; Method::Fast method, callerMethod; LocationModifier::Fast thisMod; Method::Fast m = mod->method(); // if (!m().has_compiled_code()) { // if method does not have compiled code then just return // return; // } if (m.is_null()) { // Method was removed. Most likely it was a <clinit> method return; } VMEvent::Fast epm; VMEventStream es; bool found_one = false; while (!es.at_end()) { epm = es.next(); if ((epm().event_kind() == JDWP_EventKind_BREAKPOINT || epm().event_kind() == JDWP_EventKind_SINGLE_STEP) && (ep == NULL || !epm.equals(ep))) { thisMod = get_modifier(&epm, JDWP_EventRequest_Set_Out_modifiers_Modifier_LocationOnly); if (thisMod.not_null()) { method = thisMod().method(); if (method.equals(&m)) { // another breakpoint in this method, keep impossible_to_compile set found_one = true; break; } } } } if (!found_one) { // we must have looped through the whole list and not found another // breakpoint in this method so clear the impossible_to_compile flag if (mod->rom_debug_method() != NULL) { // This method is in ROM, let's check all method pointers on the java // stack to see if any of them point to this rom_debug_method. // We may be called as a result of JVM::cleanup(). Thread doesn't have // a stack in that case. Thread *thread = Thread::current(); if (thread->last_java_fp() != NULL && thread->last_java_sp() != NULL) { Frame fr(Thread::current()); while (true) { if (fr.is_entry_frame()) { EntryFrame e = fr.as_EntryFrame(); if (e.is_first_frame()) { break; } e.caller_is(fr); } else if (fr.is_java_frame()) { JavaFrame jf = fr.as_JavaFrame(); if (jf.method() == mod->rom_debug_method()) { MethodDesc *md = (MethodDesc *)mod->method(); // fix up the stored bcp in this frame int bci = jf.bci_with_flags(); jf.set_raw_method(md); Method::Raw m = jf.method(); jf.set_raw_bcp((address)(bci + m().code_base())); } jf.caller_is(fr); } } } } // We also check the previous state of the method, if it was // "impossible_to_compile" we don't reset the flag. if (mod->compile_state() == true) { // Method was compilable so set entry to default m().set_default_entry(false); } else { if (ep->event_kind() == JDWP_EventKind_BREAKPOINT) { // May have been a special native method like String.charAt. // Just replace the entry with what we had saved earlier GUARANTEE(!ObjectHeap::contains((OopDesc*)mod->saved_method_entry()), "ROM method entry is in heap"); m().variable_part()->set_execution_entry(mod->saved_method_entry()); } } } }