ReturnOop LocationModifier::get_dup_rom_method(Method *in_rom_method) { VMEventStream es; VMEvent::Raw ep; LocationModifier::Raw mod; Method::Raw sm; ep = es.next_by_kind(JDWP_EventKind_BREAKPOINT); while(!ep.is_null()) { mod = VMEvent::get_modifier(&ep, JDWP_EventRequest_Set_Out_modifiers_Modifier_LocationOnly); if (!mod.is_null()) { sm = mod().method(); if (!sm.is_null() && sm.obj() == in_rom_method->obj()) { return mod().rom_debug_method(); } } ep = es.next_by_kind(JDWP_EventKind_BREAKPOINT); } return NULL; }
void LocationModifier::find_and_set_rom_method_id(Method *debug_rom_method) { VMEventStream es; VMEvent::Raw ep; LocationModifier::Raw mod; Method::Raw dm; ep = es.next_by_kind(JDWP_EventKind_BREAKPOINT); while(!ep.is_null()) { mod = VMEvent::get_modifier(&ep, JDWP_EventRequest_Set_Out_modifiers_Modifier_LocationOnly); if (!mod.is_null()) { dm = mod().rom_debug_method(); if (!dm.is_null() && dm.obj() == debug_rom_method->obj()) { set_method_id(mod().method_id()); break; } } ep = es.next_by_kind(JDWP_EventKind_BREAKPOINT); } }
address get_rom_debug_method(Thread *thread, OopDesc *md) { (void)thread; // always passed from interpreter but not used here. VMEventStream es; Method::Raw m = md; VMEvent::Raw ep; LocationModifier::Raw mod; ep = es.next_by_kind(JDWP_EventKind_BREAKPOINT); while(!ep.is_null()) { mod = VMEvent::get_modifier(&ep, JDWP_EventRequest_Set_Out_modifiers_Modifier_LocationOnly); if (!mod.is_null() && mod().method_id() == JavaDebugger::get_method_id(&m)) { Method::Raw dm = mod().rom_debug_method(); if (!dm.is_null()) { return (address)((char *)dm.obj()); } } ep = es.next_by_kind(JDWP_EventKind_BREAKPOINT); } return (address)md; }
void handle_single_step(Thread *thread) { UsingFastOops fast_oops; julong offset; bool sendEvent = false; /* if the proxy has returned -1 it means that we have reached * the end of a function and we must look up stack for the * calling function * */ JavaFrame frame(thread); GUARANTEE(frame.is_java_frame(), "single step not in JavaFrame!"); #if !ENABLE_ROM_JAVA_DEBUGGER // Don't allow step events if we are in a ROM method GUARANTEE(UseROM, "Sanity"); Method::Raw m = frame.method(); if (ROM::in_any_loaded_bundle(m.obj())) { return; } #endif offset = frame.bci(); StepModifier::Fast sm = thread->step_info(); if (sm.is_null()) { // Huh? this can't be. Turn off single stepping for this thread thread->set_is_stepping(false); return; } address starting_fp = DERIVED(address, sm().step_starting_fp(), thread->stack_base()); if (sm().step_target_offset() == -1) { /* * Wait for the frame to change and that will mean we popped up to * the calling frame. (Or we called down to another frame, maybe... * should look into that possibility) */ if (starting_fp != frame.fp()) { sendEvent = true; /* the frame has changed but we don't know whether we * have gone into a function or gone up one. * if we look up the call stack and find the frame * that originally set the request then we stepped * into a function, otherwise we stepped out */ if (sm().step_depth() == JDWP_StepDepth_OVER || sm().step_depth() == JDWP_StepDepth_OUT) { if (StepModifier::find_frame(starting_fp, &frame)) { sendEvent = false; } } } } else { switch (sm().step_size()) { case JDWP_StepSize_LINE: /* stepping by line can have two effects: we stay in the same * frame or the frame changes */ if (starting_fp == frame.fp()) { /* if the frame is the same and we are not running to the * end of a function we need to see if we have reached * the location we are looking for */ if (sm().step_depth() != JDWP_StepDepth_OUT) { if (offset == sm().step_target_offset()) { /* we reached the exact offset we were looking for */ sendEvent = true; break; } else if (offset < sm().step_starting_offset()) { /* we ended up before the offset were the stepping * request was initiated. we jumped back */ sendEvent = true; break; } else if (offset > sm().step_target_offset() && offset > sm().step_starting_offset()) { if (sm().dup_current_line_offset() == -1) { /* We stepped beyond the target and there's no * duplicate offset information * (like there would be in a for or while loop). * Most likely a break in a switch case. * However, we checked to see if our starting offset * is equal to our current, if so don't issue * an event otherwise we'll be in an infinite loop. */ sendEvent = true; break; } else if (offset >= sm().dup_current_line_offset()) { /* * We are after the location we were looking for; * we jumped forward. However, we may be at the end * of a for/while loop where we do the loop * test. We check to see if we are in the line after * the for/do end line. If not, we just continue. */ if (sm().post_dup_line_offset() != -1) { /* * There is a line after the duplicate line * so check to see if we've past it. If * post_dup_line_offset == -1 then there is no line * after the duplicate so we continue until we * either jump back or return from this method */ if (offset >= sm().post_dup_line_offset()) { /* we were beyond the end of the loop */ sendEvent = true; break; } } } } } } else { /* the frame has changed but we don't know whether we * have gone into a function or gone up one. * if we look up the call stack and find the frame * that originally set the request then we stepped * into a function, otherwise we stepped out */ sendEvent = true; if (sm().step_depth() == JDWP_StepDepth_OVER || sm().step_depth() == JDWP_StepDepth_OUT) { if (StepModifier::find_frame(starting_fp, &frame)) { sendEvent = false; } } } break; /* stepping by bytecode */ case JDWP_StepSize_MIN: if (sm().step_depth() == JDWP_StepDepth_OVER) { // if we are stepping by bytecode then if we are in the // same frame as we started in, send the event. // if we are not in the same frame then see if we are deeper in the // call stack. If so then don't send the event since we are in // Step Over mode. if (starting_fp == frame.fp()) { sendEvent = true; } else { sendEvent = true; /* If we are deeper in the call stack do not break... */ if (StepModifier::find_frame(starting_fp, &frame)) { sendEvent = false; } } } else if (sm().step_depth() == JDWP_StepDepth_OUT) { // in this case, we want to send the event only if we've popped // up one frame (i.e. to the caller of the starting frame) if (starting_fp != frame.fp()) { sendEvent = true; /* If we are deeper in the call stack do not break... */ if (StepModifier::find_frame(starting_fp, &frame)) { sendEvent = false; } } } else { sendEvent = true; } break; } } if (sendEvent) { UsingFastOops fast_oops_2; Method::Fast m = frame.method(); InstanceClass::Fast ic = m().holder(); if (m().bytecode_at_raw(frame.bci()) == Bytecodes::_breakpoint) { // Don't single step into a breakpoint return; } if (JavaDebugger::get_method_id(&ic, &m) == -1) { // Most likely this method was removed from the ROM because the // ROM was built without MakeROMDebuggable. There's no sense in // sending an event since we can't identify the method to the // debugger return; } DebuggerEvent d_event(JDWP_EventKind_SINGLE_STEP, JavaDebugger::get_thread_id_by_ref(Thread::current()), JavaDebugger::get_object_id_by_ref(&ic), JavaDebugger::get_method_id(&ic, &m), (jlong)frame.bci()); d_event.set_step_size(sm().step_size()); d_event.set_step_depth(sm().step_depth()); VMEvent::send_event(&d_event); return; } else { return; } }