示例#1
0
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;
}
示例#4
0
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());
      }
    }
  }
}