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;
}
diff --git a/src/debugger.h b/src/debugger.h
index ec20458..8cbfeea 100644
--- a/src/debugger.h
+++ b/src/debugger.h
@@ -141,7 +141,7 @@
static bool GetSourceFile(JDWP::RefTypeId refTypeId, std::string& source_file);
static const char* GetObjectTypeName(JDWP::ObjectId objectId);
static uint8_t GetObjectTag(JDWP::ObjectId objectId);
- static size_t GetTagWidth(int tag);
+ static size_t GetTagWidth(JDWP::JdwpTag tag);
static int GetArrayLength(JDWP::ObjectId arrayId);
static uint8_t GetArrayElementTag(JDWP::ObjectId arrayId);
@@ -164,8 +164,8 @@
static void OutputLineTable(JDWP::RefTypeId refTypeId, JDWP::MethodId methodId, JDWP::ExpandBuf* pReply);
static void OutputVariableTable(JDWP::RefTypeId refTypeId, JDWP::MethodId id, bool withGeneric, JDWP::ExpandBuf* pReply);
- static uint8_t GetFieldBasicTag(JDWP::ObjectId objId, JDWP::FieldId fieldId);
- static uint8_t GetStaticFieldBasicTag(JDWP::RefTypeId refTypeId, JDWP::FieldId fieldId);
+ static JDWP::JdwpTag GetFieldBasicTag(JDWP::FieldId fieldId);
+ static JDWP::JdwpTag GetStaticFieldBasicTag(JDWP::FieldId fieldId);
static void GetFieldValue(JDWP::ObjectId objectId, JDWP::FieldId fieldId, JDWP::ExpandBuf* pReply);
static void SetFieldValue(JDWP::ObjectId objectId, JDWP::FieldId fieldId, uint64_t value, int width);
static void GetStaticFieldValue(JDWP::RefTypeId refTypeId, JDWP::FieldId fieldId, JDWP::ExpandBuf* pReply);
@@ -224,7 +224,7 @@
static bool ConfigureStep(JDWP::ObjectId threadId, JDWP::JdwpStepSize size, JDWP::JdwpStepDepth depth);
static void UnconfigureStep(JDWP::ObjectId threadId);
- static JDWP::JdwpError 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);
+ static JDWP::JdwpError 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);
static void ExecuteMethod(DebugInvokeReq* pReq);
/* perform "late registration" of an object ID */
diff --git a/src/jdwp/jdwp.h b/src/jdwp/jdwp.h
index 1b766bd..f138880 100644
--- a/src/jdwp/jdwp.h
+++ b/src/jdwp/jdwp.h
@@ -55,6 +55,7 @@
static inline ObjectId ReadObjectId(const uint8_t** pBuf) { return Read8BE(pBuf); }
static inline RefTypeId ReadRefTypeId(const uint8_t** pBuf) { return Read8BE(pBuf); }
static inline FrameId ReadFrameId(const uint8_t** pBuf) { return Read8BE(pBuf); }
+static inline JdwpTag ReadTag(const uint8_t** pBuf) { return static_cast<JdwpTag>(Read1(pBuf)); }
static inline void SetFieldId(uint8_t* buf, FieldId val) { return Set4BE(buf, val); }
static inline void SetMethodId(uint8_t* buf, MethodId val) { return Set4BE(buf, val); }
static inline void SetObjectId(uint8_t* buf, ObjectId val) { return Set8BE(buf, val); }
diff --git a/src/jdwp/jdwp_handler.cc b/src/jdwp/jdwp_handler.cc
index c0a44e0..65b645d 100644
--- a/src/jdwp/jdwp_handler.cc
+++ b/src/jdwp/jdwp_handler.cc
@@ -118,7 +118,7 @@
}
for (uint32_t i = 0; i < numArgs; i++) {
- uint8_t typeTag = Read1(&buf);
+ JDWP::JdwpTag typeTag = ReadTag(&buf);
size_t width = Dbg::GetTagWidth(typeTag);
uint64_t value = jdwpReadValue(&buf, width);
@@ -129,7 +129,7 @@
uint32_t options = Read4BE(&buf); /* enum InvokeOptions bit flags */
LOG(VERBOSE) << StringPrintf(" options=0x%04x%s%s", options, (options & INVOKE_SINGLE_THREADED) ? " (SINGLE_THREADED)" : "", (options & INVOKE_NONVIRTUAL) ? " (NONVIRTUAL)" : "");
- uint8_t resultTag;
+ JDWP::JdwpTag resultTag;
uint64_t resultValue;
ObjectId exceptObjId;
JdwpError err = Dbg::InvokeMethod(threadId, objectId, classId, methodId, numArgs, argArray, options, &resultTag, &resultValue, &exceptObjId);
@@ -657,7 +657,7 @@
for (uint32_t i = 0; i < values; i++) {
FieldId fieldId = ReadFieldId(&buf);
- uint8_t fieldTag = Dbg::GetStaticFieldBasicTag(classId, fieldId);
+ JDWP::JdwpTag fieldTag = Dbg::GetStaticFieldBasicTag(fieldId);
size_t width = Dbg::GetTagWidth(fieldTag);
uint64_t value = jdwpReadValue(&buf, width);
@@ -805,7 +805,7 @@
for (uint32_t i = 0; i < numFields; i++) {
FieldId fieldId = ReadFieldId(&buf);
- uint8_t fieldTag = Dbg::GetFieldBasicTag(objectId, fieldId);
+ JDWP::JdwpTag fieldTag = Dbg::GetFieldBasicTag(fieldId);
size_t width = Dbg::GetTagWidth(fieldTag);
uint64_t value = jdwpReadValue(&buf, width);
@@ -1443,7 +1443,7 @@
expandBufAdd4BE(pReply, slots); /* "int values" */
for (uint32_t i = 0; i < slots; i++) {
uint32_t slot = Read4BE(&buf);
- JDWP::JdwpTag reqSigByte = static_cast<JDWP::JdwpTag>(Read1(&buf));
+ JDWP::JdwpTag reqSigByte = ReadTag(&buf);
LOG(VERBOSE) << StringPrintf(" --> slot %d '%c'", slot, reqSigByte);
@@ -1467,7 +1467,7 @@
for (uint32_t i = 0; i < slots; i++) {
uint32_t slot = Read4BE(&buf);
- JDWP::JdwpTag sigByte = static_cast<JDWP::JdwpTag>(Read1(&buf));
+ JDWP::JdwpTag sigByte = ReadTag(&buf);
size_t width = Dbg::GetTagWidth(sigByte);
uint64_t value = jdwpReadValue(&buf, width);