// natFrame.cc -- native support for VMFrame.java /* Copyright (C) 2006, 2007 Free Software Foundation This file is part of libgcj. This software is copyrighted work licensed under the terms of the Libgcj License. Please consult the file "LIBGCJ_LICENSE" for details. */ #include #include #include #include #include "jvmti-int.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace java::lang; using namespace gnu::classpath::jdwp; using namespace gnu::classpath::jdwp::exception; // All the jvmti GetLocalXX and SetLocalXX functions return the same potential // errors, so this function handles them all and throws the appropriate JDWP // exception. static void checkJVMTIError (jvmtiEnv *env, jthread thread, jvmtiError jerr, jint slot, jbyte sig) { if (jerr != JVMTI_ERROR_NONE) { char *error; env->GetErrorName (jerr, &error); String *msg = reinterpret_cast (JvNewStringUTF (error)); env->Deallocate ((unsigned char *) error); if (jerr == JVMTI_ERROR_INVALID_THREAD) throw new InvalidThreadException ((jlong) thread); else if (jerr == JVMTI_ERROR_NO_MORE_FRAMES) throw new InvalidFrameException (msg); else if (jerr == JVMTI_ERROR_INVALID_SLOT) throw new InvalidSlotException (slot); else if (jerr == JVMTI_ERROR_TYPE_MISMATCH) throw new TypeMismatchException (sig); else throw new JdwpInternalErrorException (msg); } } static jobject getObjectJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, jbyte sig) { jobject value; jvmtiError jerr = env->GetLocalObject (thread, depth, slot, &value); checkJVMTIError (env, thread, jerr, slot, sig); return value; } static void setObjectJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, jbyte sig, jobject value) { if (value->getClass ()->isAssignableFrom (&util::NullObject::class$)) value = NULL; jvmtiError jerr = env->SetLocalObject (thread, depth, slot, value); checkJVMTIError (env, thread, jerr, slot, sig); } static jint getIntJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, jbyte sig) { jint value; jvmtiError jerr = env->GetLocalInt (thread, depth, slot, &value); checkJVMTIError (env, thread, jerr, slot, sig); return value; } static void setIntJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, jbyte sig, jint value) { jvmtiError jerr = env->SetLocalInt (thread, depth, slot, value); checkJVMTIError (env, thread, jerr, slot, sig); } static jlong getLongJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, jbyte sig) { jlong value; jvmtiError jerr = env->GetLocalLong (thread, depth, slot, &value); checkJVMTIError (env, thread, jerr, slot, sig); return value; } static void setLongJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, jbyte sig, jlong value) { jvmtiError jerr = env->SetLocalLong (thread, depth, slot, value); checkJVMTIError (env, thread, jerr, slot, sig); } static jfloat getFloatJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, jbyte sig) { jfloat value; jvmtiError jerr = env->GetLocalFloat (thread, depth, slot, &value); checkJVMTIError (env, thread, jerr, slot, sig); return value; } static void setFloatJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, jbyte sig, jfloat value) { jvmtiError jerr = env->SetLocalFloat (thread, depth, slot, value); checkJVMTIError (env, thread, jerr, slot, sig); } static jdouble getDoubleJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, jbyte sig) { jdouble value; jvmtiError jerr = env->GetLocalDouble (thread, depth, slot, &value); checkJVMTIError (env, thread, jerr, slot, sig); return value; } static void setDoubleJVMTI (jvmtiEnv *env, jthread thread, jint slot, jint depth, jbyte sig, jdouble value) { jvmtiError jerr = env->SetLocalDouble (thread, depth, slot, value); checkJVMTIError (env, thread, jerr, slot, sig); } // This is necessary since JVMTI requires a stack depth as a parameter in all // its local variable functions. Since JDWP needs frameids, we have to run // through the call stack to translate these ids into the parameters JVMTI // wants. static jint getFrameDepth (_Jv_Frame *frame) { jint depth = 0; _Jv_Frame *top_frame = (_Jv_Frame *) frame->thread->frame; jint num_frames = VMVirtualMachine::getFrameCount (frame->thread); while (frame != top_frame) { top_frame = top_frame->next; depth++; if (depth >= num_frames || top_frame == NULL) throw new InvalidFrameException ((jlong) frame); } return depth; } using namespace gnu::classpath::jdwp::value; Value * gnu::classpath::jdwp::VMFrame::getValue (jint slot, jbyte sig) { _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (id); jint depth = getFrameDepth (frame); jthread thread = reinterpret_cast (frame->thread); jvmtiEnv *env = _Jv_GetJDWP_JVMTIEnv (); Value *value = NULL; switch (sig) { case 'B': value = new ByteValue ((jbyte) getIntJVMTI (env, thread, slot, depth, sig)); break; case 'Z': value = new BooleanValue ((jboolean) getIntJVMTI (env, thread, slot, depth, sig)); break; case 'C': value = new CharValue ((jchar) getIntJVMTI (env, thread, slot, depth, sig)); break; case 'S': value = new ShortValue ((jshort) getIntJVMTI (env, thread, slot, depth, sig)); break; case 'I': value = new IntValue (getIntJVMTI (env, thread, slot, depth, sig)); break; case 'J': value = new LongValue (getLongJVMTI (env, thread, slot, depth, sig)); break; case 'F': value = new FloatValue (getFloatJVMTI (env, thread, slot, depth, sig)); break; case 'D': value = new DoubleValue (getDoubleJVMTI (env, thread, slot, depth, sig)); break; case 'V': value = new VoidValue (); break; case '[': { Object *obj = getObjectJVMTI (env, thread, slot, depth, sig); if (obj == NULL) obj = new util::NullObject (); value = new ArrayValue (obj); break; } default: Object *obj = getObjectJVMTI (env, thread, slot, depth, sig); if (obj == NULL) obj = new util::NullObject (); value = new ObjectValue (obj); break; } return value; } void gnu::classpath::jdwp::VMFrame::setValue (jint slot, Value* value) { jbyte sig = value->getTag (); _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (id); jint depth = getFrameDepth (frame); jthread thread = reinterpret_cast (frame->thread); jvmtiEnv *env = _Jv_GetJDWP_JVMTIEnv (); switch (sig) { case 'B': { ByteValue *val = reinterpret_cast (value); setIntJVMTI (env, thread, slot, depth, sig, (jint) val->getValue ()); break; } case 'Z': { BooleanValue *val = reinterpret_cast (value); setIntJVMTI (env, thread, slot, depth, sig, (jint) val->getValue ()); break; } case 'C': { CharValue *val = reinterpret_cast (value); setIntJVMTI (env, thread, slot, depth, sig, (jint) val->getValue ()); break; } case 'S': { ShortValue *val = reinterpret_cast (value); setIntJVMTI (env, thread, slot, depth, sig, (jint) val->getValue ()); break; } case 'I': { IntValue *val = reinterpret_cast (value); setIntJVMTI (env, thread, slot, depth, sig, val->getValue ()); break; } case 'J': { LongValue *val = reinterpret_cast (value); setLongJVMTI (env, thread, slot, depth, sig, val->getValue ()); break; } case 'F': { FloatValue *val = reinterpret_cast (value); setFloatJVMTI (env, thread, slot, depth, sig, val->getValue ()); break; } case 'D': { DoubleValue *val = reinterpret_cast (value); setDoubleJVMTI (env, thread, slot, depth, sig, val->getValue ()); break; } case 'V': break; case '[': { ArrayValue *val = reinterpret_cast (value); setObjectJVMTI (env, thread, slot, depth, sig, val->getObject ()); break; } default: { ObjectValue *val = reinterpret_cast (value); setObjectJVMTI (env, thread, slot, depth, sig, val->getObject()); break; } } }