Fix a bunch of JDWP bugs.
Most of these were broken in dalvikvm too.
Bug: http://code.google.com/p/android/issues/detail?id=20856
Change-Id: I88bc89e00a19edc21953cd4f42833f35bb5456a8
diff --git a/src/debugger.cc b/src/debugger.cc
index ef3ac88..4c47e00 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -160,11 +160,11 @@
return JDWP::JT_STRING;
} else if (c->IsClassClass()) {
return JDWP::JT_CLASS_OBJECT;
- } else if (c->InstanceOf(class_linker->FindSystemClass("Ljava/lang/Thread;"))) {
+ } else if (class_linker->FindSystemClass("Ljava/lang/Thread;")->IsAssignableFrom(c)) {
return JDWP::JT_THREAD;
- } else if (c->InstanceOf(class_linker->FindSystemClass("Ljava/lang/ThreadGroup;"))) {
+ } else if (class_linker->FindSystemClass("Ljava/lang/ThreadGroup;")->IsAssignableFrom(c)) {
return JDWP::JT_THREAD_GROUP;
- } else if (c->InstanceOf(class_linker->FindSystemClass("Ljava/lang/ClassLoader;"))) {
+ } else if (class_linker->FindSystemClass("Ljava/lang/ClassLoader;")->IsAssignableFrom(c)) {
return JDWP::JT_CLASS_LOADER;
} else {
return JDWP::JT_OBJECT;
@@ -464,13 +464,48 @@
return true;
}
-bool Dbg::GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId& superclassId) {
+static Array* DecodeArray(JDWP::RefTypeId id, JDWP::JdwpError& status) {
Object* o = gRegistry->Get<Object*>(id);
- if (o == NULL || !o->IsClass()) {
- return false;
+ if (o == NULL) {
+ status = JDWP::ERR_INVALID_OBJECT;
+ return NULL;
}
- superclassId = gRegistry->Add(o->AsClass()->GetSuperClass());
- return true;
+ if (!o->IsArrayInstance()) {
+ status = JDWP::ERR_INVALID_ARRAY;
+ return NULL;
+ }
+ status = JDWP::ERR_NONE;
+ return o->AsArray();
+}
+
+// TODO: this should probably be used everywhere we're converting a RefTypeId to a Class*.
+static Class* DecodeClass(JDWP::RefTypeId id, JDWP::JdwpError& status) {
+ Object* o = gRegistry->Get<Object*>(id);
+ if (o == NULL) {
+ status = JDWP::ERR_INVALID_OBJECT;
+ return NULL;
+ }
+ if (!o->IsClass()) {
+ status = JDWP::ERR_INVALID_CLASS;
+ return NULL;
+ }
+ status = JDWP::ERR_NONE;
+ return o->AsClass();
+}
+
+JDWP::JdwpError Dbg::GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId& superclassId) {
+ JDWP::JdwpError status;
+ Class* c = DecodeClass(id, status);
+ if (c == NULL) {
+ return status;
+ }
+ if (c->IsInterface()) {
+ // http://code.google.com/p/android/issues/detail?id=20856
+ superclassId = NULL;
+ } else {
+ superclassId = gRegistry->Add(c->GetSuperClass());
+ }
+ return JDWP::ERR_NONE;
}
JDWP::ObjectId Dbg::GetClassLoader(JDWP::RefTypeId id) {
@@ -630,34 +665,33 @@
}
}
-int Dbg::GetArrayLength(JDWP::ObjectId arrayId) {
- Object* o = gRegistry->Get<Object*>(arrayId);
- Array* a = o->AsArray();
- return a->GetLength();
-}
-
-uint8_t Dbg::GetArrayElementTag(JDWP::ObjectId arrayId) {
- Object* o = gRegistry->Get<Object*>(arrayId);
- Array* a = o->AsArray();
- std::string descriptor(ClassHelper(a->GetClass()).GetDescriptor());
- JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor.c_str() + 1);
- if (!IsPrimitiveTag(tag)) {
- tag = TagFromClass(a->GetClass()->GetComponentType());
+JDWP::JdwpError Dbg::GetArrayLength(JDWP::ObjectId arrayId, int& length) {
+ JDWP::JdwpError status;
+ Array* a = DecodeArray(arrayId, status);
+ if (a == NULL) {
+ return status;
}
- return tag;
+ length = a->GetLength();
+ return JDWP::ERR_NONE;
}
-bool Dbg::OutputArray(JDWP::ObjectId arrayId, int offset, int count, JDWP::ExpandBuf* pReply) {
- Object* o = gRegistry->Get<Object*>(arrayId);
- Array* a = o->AsArray();
+JDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId arrayId, int offset, int count, JDWP::ExpandBuf* pReply) {
+ JDWP::JdwpError status;
+ Array* a = DecodeArray(arrayId, status);
+ if (a == NULL) {
+ return status;
+ }
if (offset < 0 || count < 0 || offset > a->GetLength() || a->GetLength() - offset < count) {
LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count;
- return false;
+ return JDWP::ERR_INVALID_LENGTH;
}
std::string descriptor(ClassHelper(a->GetClass()).GetDescriptor());
JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor.c_str() + 1);
+ expandBufAdd1(pReply, tag);
+ expandBufAdd4BE(pReply, count);
+
if (IsPrimitiveTag(tag)) {
size_t width = GetTagWidth(tag);
const uint8_t* src = reinterpret_cast<uint8_t*>(a->GetRawData());
@@ -684,16 +718,19 @@
}
}
- return true;
+ return JDWP::ERR_NONE;
}
-bool Dbg::SetArrayElements(JDWP::ObjectId arrayId, int offset, int count, const uint8_t* src) {
- Object* o = gRegistry->Get<Object*>(arrayId);
- Array* a = o->AsArray();
+JDWP::JdwpError Dbg::SetArrayElements(JDWP::ObjectId arrayId, int offset, int count, const uint8_t* src) {
+ JDWP::JdwpError status;
+ Array* a = DecodeArray(arrayId, status);
+ if (a == NULL) {
+ return status;
+ }
if (offset < 0 || count < 0 || offset > a->GetLength() || a->GetLength() - offset < count) {
LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count;
- return false;
+ return JDWP::ERR_INVALID_LENGTH;
}
std::string descriptor(ClassHelper(a->GetClass()).GetDescriptor());
JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor.c_str() + 1);
@@ -726,7 +763,7 @@
}
}
- return true;
+ return JDWP::ERR_NONE;
}
JDWP::ObjectId Dbg::CreateString(const std::string& str) {
@@ -1047,7 +1084,7 @@
}
}
-void Dbg::SetFieldValue(JDWP::ObjectId objectId, JDWP::FieldId fieldId, uint64_t value, int width) {
+JDWP::JdwpError Dbg::SetFieldValue(JDWP::ObjectId objectId, JDWP::FieldId fieldId, uint64_t value, int width) {
Object* o = gRegistry->Get<Object*>(objectId);
Field* f = FromFieldId(fieldId);
@@ -1060,16 +1097,23 @@
f->Set32(o, value);
}
} else {
- f->SetObject(o, gRegistry->Get<Object*>(value));
+ Object* v = gRegistry->Get<Object*>(value);
+ Class* field_type = FieldHelper(f).GetType();
+ if (!field_type->IsAssignableFrom(v->GetClass())) {
+ return JDWP::ERR_INVALID_OBJECT;
+ }
+ f->SetObject(o, v);
}
+
+ return JDWP::ERR_NONE;
}
void Dbg::GetStaticFieldValue(JDWP::FieldId fieldId, JDWP::ExpandBuf* pReply) {
GetFieldValue(0, fieldId, pReply);
}
-void Dbg::SetStaticFieldValue(JDWP::FieldId fieldId, uint64_t value, int width) {
- SetFieldValue(0, fieldId, value, width);
+JDWP::JdwpError Dbg::SetStaticFieldValue(JDWP::FieldId fieldId, uint64_t value, int width) {
+ return SetFieldValue(0, fieldId, value, width);
}
std::string Dbg::StringToUtf8(JDWP::ObjectId strId) {