Implement static field getting/setting, and basic Eclipse support.
Eclipse uses a few new calls that I hadn't seen from any of the other
debuggers.
Change-Id: Iccb45f226431b6cd30a17f7b5ee8397e0838c1fc
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 266c1f0..9e4a76d 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1714,6 +1714,26 @@
return NULL;
}
+void ClassLinker::LookupClasses(const std::string& descriptor, std::vector<Class*>& classes) {
+ classes.clear();
+ size_t hash = StringPieceHash()(descriptor);
+ MutexLock mu(classes_lock_);
+ typedef Table::const_iterator It; // TODO: C++0x auto
+ // TODO: determine if its better to search classes_ or image_classes_ first
+ for (It it = classes_.find(hash), end = classes_.end(); it != end; ++it) {
+ Class* c = it->second;
+ if (c->GetDescriptor()->Equals(descriptor)) {
+ classes.push_back(c);
+ }
+ }
+ for (It it = image_classes_.find(hash), end = image_classes_.end(); it != end; ++it) {
+ Class* c = it->second;
+ if (c->GetDescriptor()->Equals(descriptor)) {
+ classes.push_back(c);
+ }
+ }
+}
+
void ClassLinker::VerifyClass(Class* klass) {
if (klass->IsVerified()) {
return;
diff --git a/src/class_linker.h b/src/class_linker.h
index d212c59..e408dbb 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -68,6 +68,9 @@
// by the given 'class_loader'.
Class* LookupClass(const std::string& descriptor, const ClassLoader* class_loader);
+ // Finds all the classes with the given descriptor, regardless of ClassLoader.
+ void LookupClasses(const std::string& descriptor, std::vector<Class*>& classes);
+
Class* FindPrimitiveClass(char type);
// General class unloading is not supported, this is used to prune
diff --git a/src/debugger.cc b/src/debugger.cc
index 613e27e..5b8c32c 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -471,8 +471,8 @@
}
uint32_t Dbg::GetAccessFlags(JDWP::RefTypeId id) {
- UNIMPLEMENTED(FATAL);
- return 0;
+ Class* c = gRegistry->Get<Class*>(id);
+ return c->GetAccessFlags() & kAccJavaFlagsMask;
}
bool Dbg::IsInterface(JDWP::RefTypeId classId) {
@@ -512,7 +512,7 @@
UNIMPLEMENTED(FATAL);
}
-void Dbg::GetClassInfo(JDWP::RefTypeId classId, uint8_t* pTypeTag, uint32_t* pStatus, std::string* pDescriptor) {
+void Dbg::GetClassInfo(JDWP::RefTypeId classId, JDWP::JdwpTypeTag* pTypeTag, uint32_t* pStatus, std::string* pDescriptor) {
Class* c = gRegistry->Get<Class*>(classId);
if (c->IsArrayClass()) {
*pStatus = JDWP::CS_VERIFIED | JDWP::CS_PREPARED;
@@ -531,12 +531,16 @@
}
}
-bool Dbg::FindLoadedClassBySignature(const char* classDescriptor, JDWP::RefTypeId* pRefTypeId) {
- UNIMPLEMENTED(FATAL);
- return false;
+void Dbg::FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>& ids) {
+ std::vector<Class*> classes;
+ Runtime::Current()->GetClassLinker()->LookupClasses(descriptor, classes);
+ ids.clear();
+ for (size_t i = 0; i < classes.size(); ++i) {
+ ids.push_back(gRegistry->Add(classes[i]));
+ }
}
-void Dbg::GetObjectType(JDWP::ObjectId objectId, uint8_t* pRefTypeTag, JDWP::RefTypeId* pRefTypeId) {
+void Dbg::GetObjectType(JDWP::ObjectId objectId, JDWP::JdwpTypeTag* pRefTypeTag, JDWP::RefTypeId* pRefTypeId) {
Object* o = gRegistry->Get<Object*>(objectId);
if (o->GetClass()->IsArrayClass()) {
*pRefTypeTag = JDWP::TT_ARRAY;
@@ -1017,12 +1021,12 @@
}
}
-void Dbg::GetStaticFieldValue(JDWP::RefTypeId refTypeId, JDWP::FieldId fieldId, JDWP::ExpandBuf* pReply) {
- UNIMPLEMENTED(FATAL);
+void Dbg::GetStaticFieldValue(JDWP::FieldId fieldId, JDWP::ExpandBuf* pReply) {
+ GetFieldValue(0, fieldId, pReply);
}
-void Dbg::SetStaticFieldValue(JDWP::RefTypeId refTypeId, JDWP::FieldId fieldId, uint64_t rawValue, int width) {
- UNIMPLEMENTED(FATAL);
+void Dbg::SetStaticFieldValue(JDWP::FieldId fieldId, uint64_t value, int width) {
+ SetFieldValue(0, fieldId, value, width);
}
std::string Dbg::StringToUtf8(JDWP::ObjectId strId) {
diff --git a/src/debugger.h b/src/debugger.h
index 8cbfeea..3f0f7f6 100644
--- a/src/debugger.h
+++ b/src/debugger.h
@@ -133,9 +133,9 @@
static bool IsInterface(JDWP::RefTypeId id);
static void GetClassList(uint32_t* pNumClasses, JDWP::RefTypeId** pClassRefBuf);
static void GetVisibleClassList(JDWP::ObjectId classLoaderId, uint32_t* pNumClasses, JDWP::RefTypeId** pClassRefBuf);
- static void GetClassInfo(JDWP::RefTypeId classId, uint8_t* pTypeTag, uint32_t* pStatus, std::string* pDescriptor);
- static bool FindLoadedClassBySignature(const char* classDescriptor, JDWP::RefTypeId* pRefTypeId);
- static void GetObjectType(JDWP::ObjectId objectId, uint8_t* pRefTypeTag, JDWP::RefTypeId* pRefTypeId);
+ static void GetClassInfo(JDWP::RefTypeId classId, JDWP::JdwpTypeTag* pTypeTag, uint32_t* pStatus, std::string* pDescriptor);
+ static void FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>& ids);
+ static void GetObjectType(JDWP::ObjectId objectId, JDWP::JdwpTypeTag* pRefTypeTag, JDWP::RefTypeId* pRefTypeId);
static uint8_t GetClassObjectType(JDWP::RefTypeId refTypeId);
static std::string GetSignature(JDWP::RefTypeId refTypeId);
static bool GetSourceFile(JDWP::RefTypeId refTypeId, std::string& source_file);
@@ -168,8 +168,8 @@
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);
- static void SetStaticFieldValue(JDWP::RefTypeId refTypeId, JDWP::FieldId fieldId, uint64_t rawValue, int width);
+ static void GetStaticFieldValue(JDWP::FieldId fieldId, JDWP::ExpandBuf* pReply);
+ static void SetStaticFieldValue(JDWP::FieldId fieldId, uint64_t value, int width);
static std::string StringToUtf8(JDWP::ObjectId strId);
diff --git a/src/jdwp/jdwp_handler.cc b/src/jdwp/jdwp_handler.cc
index 65b645d..ad02f64 100644
--- a/src/jdwp/jdwp_handler.cc
+++ b/src/jdwp/jdwp_handler.cc
@@ -198,34 +198,19 @@
char* classDescriptor = ReadNewUtf8String(&buf, &strLen);
LOG(VERBOSE) << " Req for class by signature '" << classDescriptor << "'";
- /*
- * TODO: if a class with the same name has been loaded multiple times
- * (by different class loaders), we're supposed to return each of them.
- *
- * NOTE: this may mangle "className".
- */
- uint32_t numClasses;
- RefTypeId refTypeId;
- if (!Dbg::FindLoadedClassBySignature(classDescriptor, &refTypeId)) {
- /* not currently loaded */
- LOG(VERBOSE) << " --> no match!";
- numClasses = 0;
- } else {
- /* just the one */
- numClasses = 1;
- }
+ std::vector<RefTypeId> ids;
+ Dbg::FindLoadedClassBySignature(classDescriptor, ids);
- expandBufAdd4BE(pReply, numClasses);
+ expandBufAdd4BE(pReply, ids.size());
- if (numClasses > 0) {
- uint8_t typeTag;
+ for (size_t i = 0; i < ids.size(); ++i) {
+ // Get class vs. interface and status flags.
+ JDWP::JdwpTypeTag typeTag;
uint32_t status;
-
- /* get class vs. interface and status flags */
- Dbg::GetClassInfo(refTypeId, &typeTag, &status, NULL);
+ Dbg::GetClassInfo(ids[i], &typeTag, &status, NULL);
expandBufAdd1(pReply, typeTag);
- expandBufAddRefTypeId(pReply, refTypeId);
+ expandBufAddRefTypeId(pReply, ids[i]);
expandBufAdd4BE(pReply, status);
}
@@ -449,7 +434,7 @@
for (uint32_t i = 0; i < numClasses; i++) {
static const char genericSignature[1] = "";
- uint8_t refTypeTag;
+ JDWP::JdwpTypeTag refTypeTag;
std::string descriptor;
uint32_t status;
@@ -495,7 +480,7 @@
* Get values from static fields in a reference type.
*/
static JdwpError handleRT_GetValues(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
- RefTypeId refTypeId = ReadRefTypeId(&buf);
+ ReadRefTypeId(&buf); // We don't need this, but we need to skip over it in the request.
uint32_t numFields = Read4BE(&buf);
LOG(VERBOSE) << " RT_GetValues " << numFields << ":";
@@ -503,7 +488,7 @@
expandBufAdd4BE(pReply, numFields);
for (uint32_t i = 0; i < numFields; i++) {
FieldId fieldId = ReadFieldId(&buf);
- Dbg::GetStaticFieldValue(refTypeId, fieldId, pReply);
+ Dbg::GetStaticFieldValue(fieldId, pReply);
}
return ERR_NONE;
@@ -529,7 +514,7 @@
RefTypeId refTypeId = ReadRefTypeId(&buf);
/* get status flags */
- uint8_t typeTag;
+ JDWP::JdwpTypeTag typeTag;
uint32_t status;
Dbg::GetClassInfo(refTypeId, &typeTag, &status, NULL);
expandBufAdd4BE(pReply, status);
@@ -662,7 +647,7 @@
uint64_t value = jdwpReadValue(&buf, width);
LOG(VERBOSE) << StringPrintf(" --> field=%x tag=%c -> %lld", fieldId, fieldTag, value);
- Dbg::SetStaticFieldValue(classId, fieldId, value, width);
+ Dbg::SetStaticFieldValue(fieldId, value, width);
}
return ERR_NONE;
@@ -764,7 +749,7 @@
ObjectId objectId = ReadObjectId(&buf);
LOG(VERBOSE) << StringPrintf(" Req for type of objectId=0x%llx", objectId);
- uint8_t refTypeTag;
+ JDWP::JdwpTypeTag refTypeTag;
RefTypeId typeId;
Dbg::GetObjectType(objectId, &refTypeTag, &typeId);