mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-26 04:25:51 +08:00
interpret-run.cc: Add code to properly set up variable slots when debugging.
2007-04-02 Kyle Galloway <kgallowa@redhat.com> * interpret-run.cc: Add code to properly set up variable slots when debugging. * gnu/classpath/jdwp/natVMFrame.cc (checkJVMTIError): New function. (getObjectJVMTI): New function. (setObjectJVMTI): New function. (getIntJVMTI): New function. (setIntJVMTI): New function. (getLongJVMTI): New function. (setLongJVMTI): New function. (getFloatJVMTI): New function. (setFloatJVMTI): New function. (getDoubleJVMTI): New function. (setDoubleJVMTI): New function. (getFrameDepth): New function. (getValue): Implement. (setValue): Implement. From-SVN: r123427
This commit is contained in:
parent
c6756b7257
commit
bfd6b6cb22
@ -1,3 +1,22 @@
|
||||
2007-04-02 Kyle Galloway <kgallowa@redhat.com>
|
||||
|
||||
* interpret-run.cc: Add code to properly set up variable slots
|
||||
when debugging.
|
||||
* gnu/classpath/jdwp/natVMFrame.cc (checkJVMTIError): New function.
|
||||
(getObjectJVMTI): New function.
|
||||
(setObjectJVMTI): New function.
|
||||
(getIntJVMTI): New function.
|
||||
(setIntJVMTI): New function.
|
||||
(getLongJVMTI): New function.
|
||||
(setLongJVMTI): New function.
|
||||
(getFloatJVMTI): New function.
|
||||
(setFloatJVMTI): New function.
|
||||
(getDoubleJVMTI): New function.
|
||||
(setDoubleJVMTI): New function.
|
||||
(getFrameDepth): New function.
|
||||
(getValue): Implement.
|
||||
(setValue): Implement.
|
||||
|
||||
2007-04-02 Kyle Galloway <kgallowa@redhat.com>
|
||||
|
||||
* classpath/gnu/classpath/jdwp/processor/ThreadReferenceCommandSet.java
|
||||
|
@ -8,23 +8,316 @@ This software is copyrighted work licensed under the terms of the
|
||||
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||||
details. */
|
||||
|
||||
#include <config.h>
|
||||
#include <gcj/cni.h>
|
||||
#include <jvm.h>
|
||||
#include <jvmti.h>
|
||||
#include "jvmti-int.h"
|
||||
|
||||
#include <java-interp.h>
|
||||
|
||||
#include <gnu/classpath/jdwp/VMFrame.h>
|
||||
#include <gnu/classpath/jdwp/VMVirtualMachine.h>
|
||||
#include <gnu/classpath/jdwp/exception/InvalidFrameException.h>
|
||||
#include <gnu/classpath/jdwp/exception/InvalidSlotException.h>
|
||||
#include <gnu/classpath/jdwp/exception/InvalidThreadException.h>
|
||||
#include <gnu/classpath/jdwp/exception/JdwpInternalErrorException.h>
|
||||
#include <gnu/classpath/jdwp/exception/TypeMismatchException.h>
|
||||
#include <gnu/classpath/jdwp/util/NullObject.h>
|
||||
#include <gnu/classpath/jdwp/value/ByteValue.h>
|
||||
#include <gnu/classpath/jdwp/value/BooleanValue.h>
|
||||
#include <gnu/classpath/jdwp/value/CharValue.h>
|
||||
#include <gnu/classpath/jdwp/value/DoubleValue.h>
|
||||
#include <gnu/classpath/jdwp/value/FloatValue.h>
|
||||
#include <gnu/classpath/jdwp/value/IntValue.h>
|
||||
#include <gnu/classpath/jdwp/value/LongValue.h>
|
||||
#include <gnu/classpath/jdwp/value/ObjectValue.h>
|
||||
#include <gnu/classpath/jdwp/value/ShortValue.h>
|
||||
#include <gnu/classpath/jdwp/value/Value.h>
|
||||
#include <gnu/classpath/jdwp/value/VoidValue.h>
|
||||
|
||||
using namespace java::lang;
|
||||
using namespace gnu::classpath::jdwp;
|
||||
using namespace gnu::classpath::jdwp::exception;
|
||||
|
||||
gnu::classpath::jdwp::value::Value *
|
||||
gnu::classpath::jdwp::VMFrame::getValue (MAYBE_UNUSED jint slot,
|
||||
MAYBE_UNUSED jbyte tag)
|
||||
|
||||
// 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)
|
||||
{
|
||||
return 0;
|
||||
if (jerr != JVMTI_ERROR_NONE)
|
||||
{
|
||||
char *error;
|
||||
env->GetErrorName (jerr, &error);
|
||||
String *msg = reinterpret_cast<String *> (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<jthread> (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;
|
||||
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 (MAYBE_UNUSED jint slot,
|
||||
MAYBE_UNUSED gnu::classpath::jdwp::value::Value *value)
|
||||
{
|
||||
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<jthread> (frame->thread);
|
||||
jvmtiEnv *env = _Jv_GetJDWP_JVMTIEnv ();
|
||||
|
||||
switch (sig)
|
||||
{
|
||||
case 'B':
|
||||
{
|
||||
ByteValue *val = reinterpret_cast<ByteValue *> (value);
|
||||
setIntJVMTI (env, thread, slot, depth, sig, (jint) val->getValue ());
|
||||
break;
|
||||
}
|
||||
case 'Z':
|
||||
{
|
||||
BooleanValue *val = reinterpret_cast<BooleanValue *> (value);
|
||||
setIntJVMTI (env, thread, slot, depth, sig, (jint) val->getValue ());
|
||||
break;
|
||||
}
|
||||
case 'C':
|
||||
{
|
||||
CharValue *val = reinterpret_cast<CharValue *> (value);
|
||||
setIntJVMTI (env, thread, slot, depth, sig, (jint) val->getValue ());
|
||||
break;
|
||||
}
|
||||
case 'S':
|
||||
{
|
||||
ShortValue *val = reinterpret_cast<ShortValue *> (value);
|
||||
setIntJVMTI (env, thread, slot, depth, sig, (jint) val->getValue ());
|
||||
break;
|
||||
}
|
||||
case 'I':
|
||||
{
|
||||
IntValue *val = reinterpret_cast<IntValue *> (value);
|
||||
setIntJVMTI (env, thread, slot, depth, sig, val->getValue ());
|
||||
break;
|
||||
}
|
||||
case 'J':
|
||||
{
|
||||
LongValue *val = reinterpret_cast<LongValue *> (value);
|
||||
setLongJVMTI (env, thread, slot, depth, sig, val->getValue ());
|
||||
break;
|
||||
}
|
||||
case 'F':
|
||||
{
|
||||
FloatValue *val = reinterpret_cast<FloatValue *> (value);
|
||||
setFloatJVMTI (env, thread, slot, depth, sig, val->getValue ());
|
||||
break;
|
||||
}
|
||||
case 'D':
|
||||
{
|
||||
DoubleValue *val = reinterpret_cast<DoubleValue *> (value);
|
||||
setDoubleJVMTI (env, thread, slot, depth, sig, val->getValue ());
|
||||
break;
|
||||
}
|
||||
case 'V':
|
||||
break;
|
||||
default:
|
||||
{
|
||||
ObjectValue *val = reinterpret_cast<ObjectValue *> (value);
|
||||
setObjectJVMTI (env, thread, slot, depth, sig, val->getObject());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,12 +27,91 @@ details. */
|
||||
|
||||
_Jv_word locals[meth->max_locals];
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
// This is the information needed to get and set local variables with
|
||||
// proper type checking.
|
||||
frame_desc.locals = locals;
|
||||
char locals_type[meth->max_locals];
|
||||
memset (locals_type, 'x', meth->max_locals);
|
||||
frame_desc.locals_type = locals_type;
|
||||
#endif
|
||||
|
||||
// Set all slots as invalid until they are written to.
|
||||
memset (locals_type, 'x', meth->max_locals);
|
||||
|
||||
// We need to set the local variable types for the method arguments since
|
||||
// they are valid at invocation.
|
||||
|
||||
_Jv_Method *method = meth->get_method ();
|
||||
int type_ctr = 0;
|
||||
|
||||
// If the method is non-static, we need to set the type for the "this" pointer.
|
||||
if ((method->accflags & java::lang::reflect::Modifier::STATIC) == 0)
|
||||
{
|
||||
// Set the "this" pointer for this frame
|
||||
_Jv_word *this_ptr = reinterpret_cast<_Jv_word *> (args);
|
||||
frame_desc.obj_ptr = this_ptr[0].o;
|
||||
frame_desc.locals_type[0] = 'o';
|
||||
type_ctr++;
|
||||
}
|
||||
|
||||
// Now parse the method signature to set the types of the other arguments.
|
||||
int sig_len = method->signature->len ();
|
||||
char *signature = method->signature->chars ();
|
||||
for (int i = 1; signature[i] != ')' && i <= sig_len; i++)
|
||||
{
|
||||
if (signature[i] == 'Z' || signature[i] == 'B' || signature[i] == 'C'
|
||||
|| signature[i] == 'S' || signature[i] == 'I')
|
||||
{
|
||||
frame_desc.locals_type[type_ctr] = 'i';
|
||||
type_ctr++;
|
||||
continue;
|
||||
}
|
||||
else if (signature[i] == 'F')
|
||||
{
|
||||
frame_desc.locals_type[type_ctr] = 'f';
|
||||
type_ctr++;
|
||||
continue;
|
||||
}
|
||||
else if (signature[i] == 'J')
|
||||
{
|
||||
frame_desc.locals_type[type_ctr] = 'l';
|
||||
frame_desc.locals_type[type_ctr+1] = 'x';
|
||||
type_ctr += 2;
|
||||
continue;
|
||||
}
|
||||
else if (signature[i] == 'D')
|
||||
{
|
||||
frame_desc.locals_type[type_ctr] = 'd';
|
||||
frame_desc.locals_type[type_ctr+1] = 'x';
|
||||
type_ctr += 2;
|
||||
continue;
|
||||
}
|
||||
else if (signature[i] == 'L')
|
||||
{
|
||||
frame_desc.locals_type[type_ctr] = 'o';
|
||||
type_ctr++;
|
||||
while (signature[i] != ';')
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if (signature[i] == '[')
|
||||
{
|
||||
frame_desc.locals_type[type_ctr] = 'o';
|
||||
type_ctr++;
|
||||
|
||||
// Ignore multi-dimensional arrays.
|
||||
while (signature[i] == '[')
|
||||
i++;
|
||||
|
||||
// Check for an object array
|
||||
if (signature[i] == 'L')
|
||||
{
|
||||
while (signature[i] != ';')
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define INSN_LABEL(op) &&insn_##op
|
||||
|
||||
@ -356,15 +435,6 @@ details. */
|
||||
*/
|
||||
memcpy ((void*) locals, (void*) args, meth->args_raw_size);
|
||||
|
||||
#ifdef DEBUG
|
||||
// Get the object pointer for this method, after checking that it is
|
||||
// non-static.
|
||||
_Jv_Method *method = meth->get_method ();
|
||||
|
||||
if ((method->accflags & java::lang::reflect::Modifier::STATIC) == 0)
|
||||
frame_desc.obj_ptr = locals[0].o;
|
||||
#endif
|
||||
|
||||
_Jv_word *pool_data = meth->defining_class->constants.data;
|
||||
|
||||
/* These three are temporaries for common code used by several
|
||||
|
Loading…
Reference in New Issue
Block a user