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 ReferenceTypeImpl::static_field_getter_setter(PacketInputStream *in, 
                         PacketOutputStream *out,
                         bool is_setter)
{
  UsingFastOops fast_oops;

  InstanceClass::Fast clazz = in->read_class_ref(); 
  jint num = in->read_int();
  int i;

#ifdef AZZERT
  if (TraceDebugger) {
    tty->print_cr("Static %s: class=0x%lx, count=%ld",
                  (is_setter ? "Set" : "Get"), 
                  clazz.obj(), num);
  }
#endif

  // Prevent compiler warnings
  clazz = clazz;

  // Create a buffered output stream so we can asynchronously send an error
  // Calculate the size based on half of the items being 'longs'
  if (!is_setter) { 
    out->write_int(num);
  }

  for (i = 0; i < num; i++) {
    UsingFastOops fast_oops_2;

    InstanceClass::Fast field_clazz = in->read_class_ref();
    TypeArray::Fast fields;
    jint field_id = in->read_int();
    char type_tag;

    if (field_clazz.is_null()) {
      out->send_error(JDWP_Error_INVALID_FIELDID);
      return;
    }
    fields = field_clazz().fields();
    if (fields.is_null()) {
      out->send_error(JDWP_Error_INVALID_FIELDID);
      return;
    }
    if (field_id >= fields().length() / Field::NUMBER_OF_SLOTS) {
      out->send_error(JDWP_Error_INVALID_FIELDID);
      return;
    }
    Field field(&field_clazz, field_id * Field::NUMBER_OF_SLOTS);
    if (!field.is_static() || (is_setter && field.is_final())) { 
      out->send_error(JDWP_Error_INVALID_FIELDID);
      return;
    }

    type_tag = (field.type() < T_OBJECT ) 
      ? JavaDebugger::get_tag_from_type(field.type())
      : JDWP_Tag_OBJECT;
    Oop::Fast p;
#if ENABLE_ISOLATES
    // Statics don't live at the end of the JavaClassDesc, we need to
    // find the correct task mirror for this task
    {
      SETUP_ERROR_CHECKER_ARG;
      TaskGCContext tmp(in->transport()->task_id());
      TaskMirror::Fast tm = field_clazz().task_mirror_no_check();
      if (!TaskMirrorDesc::is_initialized_mirror((TaskMirrorDesc*)tm.obj())) {
        GUARANTEE(field_clazz().is_interface(),
                  "Non-interface class not initialized");
        if (field_clazz().is_interface()) {
          SAVE_CURRENT_EXCEPTION;
          // If an interface contains only non-object data then
          // it will not get initialized since javac will only
          // create a reference to the interface class if you
          // are accessing some static object like a static array
          // We need to at least initialized the statics
          tm = task_barrier(Thread::current(), field_clazz.obj() JVM_NO_CHECK);
          if (tm.is_null()) {
            // oome
            RESTORE_CURRENT_EXCEPTION;
            out->send_error(JDWP_Error_OUT_OF_MEMORY);
            return;
          }
          RESTORE_CURRENT_EXCEPTION;
        }
      }
      p = tm();
    }
#else
    p = field_clazz();
#endif
    if (is_setter) {
      ObjectReferenceImpl::read_value_to_address(in, &p,
                                                 field.offset(),
                                                 type_tag, true);
    } else { 
      ObjectReferenceImpl::write_value_from_address(out, &p,
                                                    field.offset(),
                                                    type_tag, true, true);
    }
#ifdef AZZERT
    if (TraceDebugger) { 
      tty->print("    ");     
      JavaDebugger::print_class(&field_clazz);
      tty->print(".");  
      JavaDebugger::print_field(&field);
      tty->print(": ");
      ObjectReferenceImpl::print_value_from_address(&p, 
                                                    field.offset(),
                                                    type_tag);
      tty->print_cr("");
    }
#endif
  }
  out->send_packet();
}
void ObjectReferenceImpl::object_field_getter_setter(PacketInputStream *in, 
                         PacketOutputStream *out, 
                         bool is_setter)
{
  UsingFastOops fast_oops;
  int i;

  Oop::Fast object = in->read_object();
  jint num = in->read_int();
  if (object.is_null()) {
    out->send_error(JDWP_Error_INVALID_OBJECT);
    return;
  }

  // Create a buffered output stream so we can asynchronously send an error
  // Calculate the size based on half of the items being 'longs'
#ifdef AZZERT
  if (TraceDebugger) {
    tty->print_cr("Object %s, objectID=%ld, object=0x%lx, count=%ld",
                  (is_setter ? "Set" : "Get"), 
                  JavaDebugger::get_object_id_by_ref_nocreate(&object), 
                  object.obj(), num);
  }
#endif
  if (!is_setter) { 
    out->write_int(num);
  }

  for (i = 0; i < num; i++) {
    UsingFastOops fast_oops_2;

    InstanceClass::Fast fieldClazz = in->read_class_ref();
    TypeArray::Fast fields;  
    jint field_id = in->read_int();

    if (fieldClazz.is_null()) {
      out->send_error(JDWP_Error_INVALID_FIELDID);
      return;
    }
    fields = fieldClazz().fields();
    if (fields.is_null()) {
      out->send_error(JDWP_Error_INVALID_FIELDID);
      return;
    }
    if (field_id >=fields().length() / Field::NUMBER_OF_SLOTS) {
      out->send_error(JDWP_Error_INVALID_FIELDID);
      return;
    }
    Field field(&fieldClazz, field_id * Field::NUMBER_OF_SLOTS);
    char type_tag = (field.type() < T_OBJECT) 
      ? JavaDebugger::get_tag_from_type(field.type()) 
      : JDWP_Tag_OBJECT;
    if (is_setter) { 
      read_value_to_address(in, &object, field.offset(), type_tag, false);
    } else { 
      write_value_from_address(out, &object, field.offset(), type_tag, true, false);
    }
#ifdef AZZERT
    if (TraceDebugger) {
      //AccessFlags field_access_flags = field.access_flags();
      tty->print("    ");  
      JavaDebugger::print_class(&fieldClazz), 
        tty->print(".");
      JavaDebugger::print_field(&field);
      tty->print(": ");
      print_value_from_address(&object, field.offset(), type_tag);
      tty->print_cr("");
    }
#endif
  }
  out->send_packet();
}
Beispiel #4
0
void VMEvent::exception_event(Throwable *exception,
                                   JavaFrame *catch_frame,
                                   DebuggerEvent *d_event, int catch_offset)
{
  check_notify_wanted(Dbg_EventKind_EXCEPTION);

  UsingFastOops fast_oops;

  VMEvent::Fast ep, ep_2;
  jlong throw_offset = 0;
  int event_count = 0;
  jbyte suspend_policy = JDWP_SuspendPolicy_NONE;
  InstanceClass::Fast ic;
  LocationModifier::Fast location;
  Method::Fast catch_method;
  Method::Fast throw_method;
  int data_len = JDWP_EVENT_LEN;

  ep = ep_2 = get_event_request(d_event, event_count, suspend_policy);
  if (ep.is_null()) {
    return;
  }
  // Flush any packets waiting in the queue.  This helps avoid a race
  // condition where we may have a resume command in the queue for a
  // previous event, we send this event, process the resume command
  // out of order
  JavaDebugger::dispatch(0);

  // Calculate packet length
  data_len += (JDWP_EVENT_EXCEPTION_LEN * event_count);

  Transport::Fast transport = ep().transport();
  PacketOutputStream out(&transport, data_len, JDWP_COMMAND_SET(Event),
                         JDWP_COMMAND(Event, Composite));
  // Create a buffered output stream so we can asynchronously send an error
  // Calculate the size based on half of the items being 'longs'
  UsingFastOops fast_oops_2;

  Thread::Fast thread = JavaDebugger::get_thread_by_id(d_event->thread_id());
  VMEventModifier::deoptimize_frame(&thread, true);


  VMEvent::Fast info_event = find_event((jbyte)VM_EXCEPTION_INFO_EVENT);
  if (!info_event.is_null()) {
    location = get_modifier(&info_event,
        JDWP_EventRequest_Set_Out_modifiers_Modifier_LocationOnly);
    GUARANTEE(!location.is_null(), "No location modifier in info event");
    throw_method = location().method();
    throw_offset = location().offset();
    remove_event_request(&info_event);
  } else {
    UsingFastOops fast_oops_3;
    ObjArray::Fast trace, methods;
    TypeArray::Fast offsets;
    trace = exception->backtrace();
    if (!trace.is_null()) {
      methods = trace().obj_at(0);
      offsets = trace().obj_at(1);
      if (!methods.is_null() && !offsets.is_null()) {
        throw_method = methods().obj_at(0);
        throw_offset = (jlong)(offsets().int_at(0));
      }
    }
  }

  DEBUGGER_EVENT(("Exception"));
  out.write_byte(suspend_policy);
  out.write_int(event_count);
  while (ep.not_null()) {
    out.write_byte(JDWP_EventKind_EXCEPTION);        
    out.write_int(ep().event_id());

    // thread with exception
    out.write_int(d_event->thread_id());

    // location of exception throw
    if (throw_method.not_null()) {
      ic = throw_method().holder();
    }
    DebuggerEvent throw_event(JDWP_EventKind_EXCEPTION,
                              0, // don't need thread
                              JavaDebugger::get_object_id_by_ref(&ic),
                              JavaDebugger::get_method_id(&ic, &throw_method),
                              (jlong)throw_offset);
    throw_event.write_as_location(&out);

    // thrown exception 
    out.write_byte('L');
    out.write_object(exception);

    // location of catch, or 0 if not caught

    if (catch_frame == NULL) {
      LocationModifier::write_null_location(&out);
    } else {
      catch_method = catch_frame->method();
      ic = catch_method().holder();
      DebuggerEvent catch_event(JDWP_EventKind_EXCEPTION,
                                0, // don't need thread
                                JavaDebugger::get_object_id_by_ref(&ic),
                                JavaDebugger::get_method_id(&ic, &catch_method),
                                (jlong)catch_offset);
      catch_event.write_as_location(&out);
    }
    ep = ep().send_next();
  }
  out.send_packet();
  JavaDebugger::process_suspend_policy(suspend_policy, &thread,
                                      true);
}