void ClassTypeImpl::class_type_super_class(PacketInputStream *in, PacketOutputStream *out) { UsingFastOops fast_oops; InstanceClass::Fast clazz = in->read_class_ref(); InstanceClass::Fast superclass; if (clazz.is_null() || clazz().is_interface()) { out->write_int(0); } else { #ifdef AZZERT if (TraceDebugger) { tty->print("Superclass of class: "); JavaDebugger::print_class(&clazz); tty->print_cr(""); } #endif superclass = clazz().super(); if (superclass.is_null()) { out->write_int(0); } else { #ifdef AZZERT if (TraceDebugger) { tty->print("SuperClass = "); JavaDebugger::print_class(&superclass); tty->print_cr(", id = 0x%x", JavaDebugger::get_object_id_by_ref_nocreate(&superclass)); } #endif out->write_class(&superclass); } } out->send_packet(); }
// // Helper function for field access // jfieldID _KNI_field_lookup_helper(jclass classHandle, const char* name, const char* signature, bool is_static) { UsingFastOops fast_oops; JavaClassObj::Fast mirror = kni_read_handle(classHandle); InstanceClass::Fast ic = mirror().java_class(); InstanceClass::Fast holder(ic.obj()); GUARANTEE(ic.is_instance_class(), "sanity check"); SETUP_ERROR_CHECKER_ARG; Symbol::Fast n = SymbolTable::check_symbol_for(name _KNI_CHECK_0); Symbol::Fast s = TypeSymbol::parse((char*)signature _KNI_CHECK_0); Field field(&holder, &n, &s); #ifndef PRODUCT // If you're hit by this GUARANTEE, make sure you have use // the DontRenameNonPublicFields option in the -romconfig file for // this class. //GUARANTEE(!field.is_valid(), "Field was renamed by Romizer."); if (!field.is_valid()) { tty->print_cr("WARNING: invalid KNI field access: %s", name); } #endif // No exception check (OutOfMemoryError) done, field lookup will // fail and NULL be returned below anyway. if (!field.is_valid() || (field.is_static() != is_static) || // We do not support field IDs in super classes: (field.is_static() && !holder().equals(&ic))) { return (jfieldID)0; } else { return (jfieldID)((jint)field.offset()); } }
void ObjectReferenceImpl::common_invoke_method(PacketInputStream *in, PacketOutputStream *out, bool is_static) { UsingFastOops fastoops; SETUP_ERROR_CHECKER_ARG; Oop::Fast this_object; JavaClass::Fast this_klass; Thread::Fast invoke_thread; InstanceClass::Fast ic; Method::Fast m, sync_method; int arg_count; jbyte type_tag, modified_tag; EntryActivation::Fast entry, sync_entry; int arg_index = 0; int options; #ifdef AZZERT if (TraceDebugger) { tty->print_cr("ObjectReferenceImpl: invoke %s method starting", (is_static ? "static" : "instance")); } #endif if (!is_static) { this_object = in->read_object(); if (this_object.is_null()) { out->send_error(JDWP_Error_INVALID_OBJECT); return; } invoke_thread = in->read_thread_ref(); ic = in->read_class_ref(); } else { // Why couldn't they use the same order as static invoke? ic = in->read_class_ref(); invoke_thread = in->read_thread_ref(); } if (invoke_thread.is_null()) { out->send_error(JDWP_Error_INVALID_THREAD); return; } if ((invoke_thread().status() & THREAD_DBG_SUSPENDED_BY_EVENT) == 0) { if (TraceDebugger) { tty->print_cr("ObjectReferenceImpl: Thread not suspended by event"); } out->send_error(JDWP_Error_THREAD_NOT_SUSPENDED); return; } if (ic.is_null()) { out->send_error(JDWP_Error_INVALID_CLASS); return; } m = JavaDebugger::get_method_by_id(&ic, in->read_long()); if (m.is_null()) { out->send_error(JDWP_Error_INVALID_METHODID); return; } #ifdef AZZERT if (TraceDebugger) { tty->print("ObjectReferenceImpl: invoke method "); m().print_value_on(tty); tty->cr(); tty->print(" class ref "); ic().print_name_on(tty); tty->cr(); } #endif arg_count = in->read_int(); arg_count += (!is_static ? 1 : 0); entry = Universe::new_entry_activation(&m, arg_count JVM_NO_CHECK); Signature::Fast sig = m().signature(); SignatureStream ss(&sig, is_static); // If it's an instance method we need to push the 'this_object' rather // than one of the arguments sitting in the input stream. if (!is_static) { entry().obj_at_put(arg_index++, &this_object); ss.next(); // point at arg just past 'this' } for (; !ss.eos() && arg_index < arg_count && !ss.is_return_type(); ss.next()) { type_tag = in->read_byte(); modified_tag = type_tag; if (type_tag == JDWP_Tag_STRING || type_tag == JDWP_Tag_THREAD || type_tag == JDWP_Tag_CLASS_OBJECT) { modified_tag = JDWP_Tag_OBJECT; } if (JavaDebugger::get_tag_from_type(ss.type()) != modified_tag) { if (TraceDebugger) { tty->print_cr("ObjectReferenceImpl: invoke method: illegal arg, type %d, expected %d ", type_tag, ss.type()); } out->send_error(JDWP_Error_ILLEGAL_ARGUMENT); return; } switch(type_tag) { case JDWP_Tag_INT: entry().int_at_put(arg_index++, in->read_int()); break; case JDWP_Tag_CHAR: entry().int_at_put(arg_index++, (int)in->read_char()); break; case JDWP_Tag_SHORT: entry().int_at_put(arg_index++, (int)in->read_short()); break; case JDWP_Tag_DOUBLE: entry().double_at_put(arg_index++, in->read_double()); break; case JDWP_Tag_LONG: entry().long_at_put(arg_index++, in->read_long()); break; case JDWP_Tag_BOOLEAN: entry().int_at_put(arg_index++, (int)in->read_boolean()); break; case JDWP_Tag_OBJECT: case JDWP_Tag_ARRAY: case JDWP_Tag_STRING: case JDWP_Tag_THREAD: case JDWP_Tag_CLASS_OBJECT: { UsingFastOops fastoops2; Oop::Fast o = in->read_object(); JavaClass::Fast o_klass = o().blueprint(); JavaClass::Fast sig_klass = ss.type_klass(); if (!sig_klass().is_subtype_of(&o_klass)) { out->send_error(JDWP_Error_ILLEGAL_ARGUMENT); return; } entry().obj_at_put(arg_index++, &o); break; } default: #ifdef AZZERT tty->print_cr("Unknown argument type %d", type_tag); out->send_error(JDWP_Error_ILLEGAL_ARGUMENT); return; #endif break; } } if (arg_index < arg_count || !ss.is_return_type()) { // if arg_index < arg_count we must have reached eos // if !return_type then the actual method has more args than the debugger // thinks out->send_error(JDWP_Error_ILLEGAL_ARGUMENT); return; } options = in->read_int(); if (options & JDWP_InvokeOptions_INVOKE_SINGLE_THREADED) { ThreadReferenceImpl::resume_specific_thread(&invoke_thread, -1); } else { ThreadReferenceImpl::resume_all_threads(-1); } sync_method = Universe::dbg_class()->find_local_method(Symbols::debugger_sync_name(), Symbols::obj_obj_int_int_int_int_void_signature()); if (sync_method.is_null()) { out->send_error(JDWP_Error_ILLEGAL_ARGUMENT); return; } #ifdef AZZERT Frame fr(&invoke_thread); GUARANTEE(fr.is_java_frame(), "Must have java frame before invoking method"); #endif address* stack_pointer = (address*)invoke_thread().stack_pointer(); address ret_addr = stack_pointer[-1 * JavaStackDirection]; int is_object_return = 0; if (ret_addr == (address)shared_call_vm_oop_return) { is_object_return = 1; } sync_entry = Universe::new_entry_activation(&sync_method, 6 JVM_NO_CHECK); sync_entry().obj_at_put(0, &entry); sync_entry().obj_at_put(1, in->transport()); sync_entry().int_at_put(2, in->id()); sync_entry().int_at_put(3, options); sync_entry().int_at_put(4, ss.type()); sync_entry().int_at_put(5, is_object_return); invoke_thread().append_pending_entry(&sync_entry); }
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(); }
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(); }