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;
  }
Пример #4
0
  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;
    }
  }