Implement field getting and setting.
This lets you use "dump" and "set <object>.<field> = <value>".
Change-Id: I47aee563b26e04f4931ac1cf3de2cd2e38db35a7
diff --git a/src/debugger.cc b/src/debugger.cc
index 49a7c5e..613e27e 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -475,9 +475,9 @@
return 0;
}
-bool Dbg::IsInterface(JDWP::RefTypeId id) {
- UNIMPLEMENTED(FATAL);
- return false;
+bool Dbg::IsInterface(JDWP::RefTypeId classId) {
+ Class* c = gRegistry->Get<Class*>(classId);
+ return c->IsInterface();
}
void Dbg::GetClassList(uint32_t* pClassCount, JDWP::RefTypeId** pClasses) {
@@ -581,7 +581,7 @@
return TagFromObject(o);
}
-size_t Dbg::GetTagWidth(int tag) {
+size_t Dbg::GetTagWidth(JDWP::JdwpTag tag) {
switch (tag) {
case JDWP::JT_VOID:
return 0;
@@ -748,6 +748,14 @@
#endif
}
+Field* FromFieldId(JDWP::FieldId fid) {
+#ifdef MOVING_GARBAGE_COLLECTOR
+ UNIMPLEMENTED(FATAL);
+#else
+ return reinterpret_cast<Field*>(static_cast<uintptr_t>(fid));
+#endif
+}
+
Method* FromMethodId(JDWP::MethodId mid) {
#ifdef MOVING_GARBAGE_COLLECTOR
UNIMPLEMENTED(FATAL);
@@ -958,22 +966,55 @@
JDWP::Set4BE(expandBufGetBuffer(pReply) + variable_count_offset, context.variable_count);
}
-uint8_t Dbg::GetFieldBasicTag(JDWP::ObjectId objId, JDWP::FieldId fieldId) {
- UNIMPLEMENTED(FATAL);
- return 0;
+JDWP::JdwpTag Dbg::GetFieldBasicTag(JDWP::FieldId fieldId) {
+ return BasicTagFromDescriptor(FromFieldId(fieldId)->GetTypeDescriptor());
}
-uint8_t Dbg::GetStaticFieldBasicTag(JDWP::RefTypeId refTypeId, JDWP::FieldId fieldId) {
- UNIMPLEMENTED(FATAL);
- return 0;
+JDWP::JdwpTag Dbg::GetStaticFieldBasicTag(JDWP::FieldId fieldId) {
+ return BasicTagFromDescriptor(FromFieldId(fieldId)->GetTypeDescriptor());
}
void Dbg::GetFieldValue(JDWP::ObjectId objectId, JDWP::FieldId fieldId, JDWP::ExpandBuf* pReply) {
- UNIMPLEMENTED(FATAL);
+ Object* o = gRegistry->Get<Object*>(objectId);
+ Field* f = FromFieldId(fieldId);
+
+ JDWP::JdwpTag tag = BasicTagFromDescriptor(f->GetTypeDescriptor());
+
+ if (IsPrimitiveTag(tag)) {
+ expandBufAdd1(pReply, tag);
+ if (tag == JDWP::JT_BOOLEAN || tag == JDWP::JT_BYTE) {
+ expandBufAdd1(pReply, f->Get32(o));
+ } else if (tag == JDWP::JT_CHAR || tag == JDWP::JT_SHORT) {
+ expandBufAdd2BE(pReply, f->Get32(o));
+ } else if (tag == JDWP::JT_FLOAT || tag == JDWP::JT_INT) {
+ expandBufAdd4BE(pReply, f->Get32(o));
+ } else if (tag == JDWP::JT_DOUBLE || tag == JDWP::JT_LONG) {
+ expandBufAdd8BE(pReply, f->Get64(o));
+ } else {
+ LOG(FATAL) << "unknown tag: " << tag;
+ }
+ } else {
+ Object* value = f->GetObject(o);
+ expandBufAdd1(pReply, TagFromObject(value));
+ expandBufAddObjectId(pReply, gRegistry->Add(value));
+ }
}
void Dbg::SetFieldValue(JDWP::ObjectId objectId, JDWP::FieldId fieldId, uint64_t value, int width) {
- UNIMPLEMENTED(FATAL);
+ Object* o = gRegistry->Get<Object*>(objectId);
+ Field* f = FromFieldId(fieldId);
+
+ JDWP::JdwpTag tag = BasicTagFromDescriptor(f->GetTypeDescriptor());
+
+ if (IsPrimitiveTag(tag)) {
+ if (tag == JDWP::JT_DOUBLE || tag == JDWP::JT_LONG) {
+ f->Set64(o, value);
+ } else {
+ f->Set32(o, value);
+ }
+ } else {
+ f->SetObject(o, gRegistry->Get<Object*>(value));
+ }
}
void Dbg::GetStaticFieldValue(JDWP::RefTypeId refTypeId, JDWP::FieldId fieldId, JDWP::ExpandBuf* pReply) {
@@ -1376,7 +1417,7 @@
UNIMPLEMENTED(FATAL);
}
-JDWP::JdwpError Dbg::InvokeMethod(JDWP::ObjectId threadId, JDWP::ObjectId objectId, JDWP::RefTypeId classId, JDWP::MethodId methodId, uint32_t numArgs, uint64_t* argArray, uint32_t options, uint8_t* pResultTag, uint64_t* pResultValue, JDWP::ObjectId* pExceptObj) {
+JDWP::JdwpError Dbg::InvokeMethod(JDWP::ObjectId threadId, JDWP::ObjectId objectId, JDWP::RefTypeId classId, JDWP::MethodId methodId, uint32_t numArgs, uint64_t* argArray, uint32_t options, JDWP::JdwpTag* pResultTag, uint64_t* pResultValue, JDWP::ObjectId* pExceptObj) {
UNIMPLEMENTED(FATAL);
return JDWP::ERR_NONE;
}