summaryrefslogtreecommitdiffstats
path: root/src/jdwp/jdwp_handler.cc
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2011-12-08 21:28:17 -0800
committerElliott Hughes <enh@google.com>2011-12-08 21:45:49 -0800
commit7b3cdfcca472b779cf8745fb8460935e56229f11 (patch)
treee74e88286c9f121ed1312faece45981ba4e0b14c /src/jdwp/jdwp_handler.cc
parent6f1dfe415019de95f0305de66b3afb40005fe382 (diff)
downloadandroid_art-7b3cdfcca472b779cf8745fb8460935e56229f11.tar.gz
android_art-7b3cdfcca472b779cf8745fb8460935e56229f11.tar.bz2
android_art-7b3cdfcca472b779cf8745fb8460935e56229f11.zip
More JDWP robustness.
We pass a lot more JDWP tests with this (fewer total failures than dalvik, because although dalvik implements more requests, it assumes that the debuggers only send it valid input). I've also added some of the missing constants (there are tests of modifier 12, SourceNameMatch, which was added in Java 6). Change-Id: I502e87b50fb305c5c8b061421339c8ceab104640
Diffstat (limited to 'src/jdwp/jdwp_handler.cc')
-rw-r--r--src/jdwp/jdwp_handler.cc164
1 files changed, 84 insertions, 80 deletions
diff --git a/src/jdwp/jdwp_handler.cc b/src/jdwp/jdwp_handler.cc
index a11c8056f9..9f23af1a62 100644
--- a/src/jdwp/jdwp_handler.cc
+++ b/src/jdwp/jdwp_handler.cc
@@ -194,8 +194,7 @@ static JdwpError handleVM_Version(JdwpState* state, const uint8_t* buf, int data
* been loaded by multiple class loaders.
*/
static JdwpError handleVM_ClassesBySignature(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
- size_t strLen;
- char* classDescriptor = ReadNewUtf8String(&buf, &strLen);
+ std::string classDescriptor(ReadNewUtf8String(&buf));
LOG(VERBOSE) << " Req for class by signature '" << classDescriptor << "'";
std::vector<RefTypeId> ids;
@@ -207,15 +206,15 @@ static JdwpError handleVM_ClassesBySignature(JdwpState* state, const uint8_t* bu
// Get class vs. interface and status flags.
JDWP::JdwpTypeTag typeTag;
uint32_t status;
- Dbg::GetClassInfo(ids[i], &typeTag, &status, NULL);
+ if (!Dbg::GetClassInfo(ids[i], &typeTag, &status, NULL)) {
+ return ERR_INVALID_CLASS;
+ }
expandBufAdd1(pReply, typeTag);
expandBufAddRefTypeId(pReply, ids[i]);
expandBufAdd4BE(pReply, status);
}
- free(classDescriptor);
-
return ERR_NONE;
}
@@ -324,16 +323,12 @@ static JdwpError handleVM_Exit(JdwpState* state, const uint8_t* buf, int dataLen
* string "java.util.Arrays".)
*/
static JdwpError handleVM_CreateString(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
- size_t strLen;
- char* str = ReadNewUtf8String(&buf, &strLen);
-
+ std::string str(ReadNewUtf8String(&buf));
LOG(VERBOSE) << " Req to create string '" << str << "'";
-
ObjectId stringId = Dbg::CreateString(str);
if (stringId == 0) {
return ERR_OUT_OF_MEMORY;
}
-
expandBufAddObjectId(pReply, stringId);
return ERR_NONE;
}
@@ -425,30 +420,27 @@ static JdwpError handleVM_CapabilitiesNew(JdwpState* state, const uint8_t* buf,
* Cough up the complete list of classes.
*/
static JdwpError handleVM_AllClassesWithGeneric(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
- uint32_t numClasses = 0;
- RefTypeId* classRefBuf = NULL;
+ std::vector<JDWP::RefTypeId> classes;
+ Dbg::GetClassList(classes);
- Dbg::GetClassList(&numClasses, &classRefBuf);
+ expandBufAdd4BE(pReply, classes.size());
- expandBufAdd4BE(pReply, numClasses);
-
- for (uint32_t i = 0; i < numClasses; i++) {
+ for (size_t i = 0; i < classes.size(); ++i) {
static const char genericSignature[1] = "";
JDWP::JdwpTypeTag refTypeTag;
std::string descriptor;
uint32_t status;
-
- Dbg::GetClassInfo(classRefBuf[i], &refTypeTag, &status, &descriptor);
+ if (!Dbg::GetClassInfo(classes[i], &refTypeTag, &status, &descriptor)) {
+ return ERR_INVALID_CLASS;
+ }
expandBufAdd1(pReply, refTypeTag);
- expandBufAddRefTypeId(pReply, classRefBuf[i]);
+ expandBufAddRefTypeId(pReply, classes[i]);
expandBufAddUtf8String(pReply, descriptor);
expandBufAddUtf8String(pReply, genericSignature);
expandBufAdd4BE(pReply, status);
}
- free(classRefBuf);
-
return ERR_NONE;
}
@@ -460,9 +452,11 @@ static JdwpError handleRT_Signature(JdwpState* state, const uint8_t* buf, int da
RefTypeId refTypeId = ReadRefTypeId(&buf);
LOG(VERBOSE) << StringPrintf(" Req for signature of refTypeId=0x%llx", refTypeId);
- std::string signature(Dbg::GetSignature(refTypeId));
+ std::string signature;
+ if (!Dbg::GetSignature(refTypeId, signature)) {
+ return ERR_INVALID_CLASS;
+ }
expandBufAddUtf8String(pReply, signature);
-
return ERR_NONE;
}
@@ -471,8 +465,11 @@ static JdwpError handleRT_Signature(JdwpState* state, const uint8_t* buf, int da
*/
static JdwpError handleRT_Modifiers(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
RefTypeId refTypeId = ReadRefTypeId(&buf);
- uint32_t modBits = Dbg::GetAccessFlags(refTypeId);
- expandBufAdd4BE(pReply, modBits);
+ uint32_t access_flags;
+ if (!Dbg::GetAccessFlags(refTypeId, access_flags)) {
+ return ERR_INVALID_CLASS;
+ }
+ expandBufAdd4BE(pReply, access_flags);
return ERR_NONE;
}
@@ -512,11 +509,11 @@ static JdwpError handleRT_SourceFile(JdwpState* state, const uint8_t* buf, int d
*/
static JdwpError handleRT_Status(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
RefTypeId refTypeId = ReadRefTypeId(&buf);
-
- /* get status flags */
JDWP::JdwpTypeTag typeTag;
uint32_t status;
- Dbg::GetClassInfo(refTypeId, &typeTag, &status, NULL);
+ if (!Dbg::GetClassInfo(refTypeId, &typeTag, &status, NULL)) {
+ return ERR_INVALID_CLASS;
+ }
expandBufAdd4BE(pReply, status);
return ERR_NONE;
}
@@ -526,12 +523,8 @@ static JdwpError handleRT_Status(JdwpState* state, const uint8_t* buf, int dataL
*/
static JdwpError handleRT_Interfaces(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
RefTypeId refTypeId = ReadRefTypeId(&buf);
-
LOG(VERBOSE) << StringPrintf(" Req for interfaces in %llx (%s)", refTypeId, Dbg::GetClassDescriptor(refTypeId).c_str());
-
- Dbg::OutputDeclaredInterfaces(refTypeId, pReply);
-
- return ERR_NONE;
+ return Dbg::OutputDeclaredInterfaces(refTypeId, pReply) ? ERR_NONE : ERR_INVALID_CLASS;
}
/*
@@ -539,12 +532,12 @@ static JdwpError handleRT_Interfaces(JdwpState* state, const uint8_t* buf, int d
*/
static JdwpError handleRT_ClassObject(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
RefTypeId refTypeId = ReadRefTypeId(&buf);
- ObjectId classObjId = Dbg::GetClassObject(refTypeId);
-
- LOG(VERBOSE) << StringPrintf(" RefTypeId %llx -> ObjectId %llx", refTypeId, classObjId);
-
- expandBufAddObjectId(pReply, classObjId);
-
+ ObjectId classObjectId;
+ if (!Dbg::GetClassObject(refTypeId, classObjectId)) {
+ return ERR_INVALID_CLASS;
+ }
+ LOG(VERBOSE) << StringPrintf(" RefTypeId %llx -> ObjectId %llx", refTypeId, classObjectId);
+ expandBufAddObjectId(pReply, classObjectId);
return ERR_NONE;
}
@@ -567,8 +560,8 @@ static JdwpError handleRT_SignatureWithGeneric(JdwpState* state, const uint8_t*
RefTypeId refTypeId = ReadRefTypeId(&buf);
LOG(VERBOSE) << StringPrintf(" Req for signature of refTypeId=0x%llx", refTypeId);
- std::string signature(Dbg::GetSignature(refTypeId));
- if (signature != NULL) {
+ std::string signature;
+ if (Dbg::GetSignature(refTypeId, signature)) {
expandBufAddUtf8String(pReply, signature);
} else {
LOG(WARNING) << StringPrintf("No signature for refTypeId=0x%llx", refTypeId);
@@ -591,16 +584,27 @@ static JdwpError handleRT_ClassLoader(JdwpState* state, const uint8_t* buf, int
return ERR_NONE;
}
+static std::string Describe(const RefTypeId& refTypeId) {
+ std::string signature("unknown");
+ Dbg::GetSignature(refTypeId, signature);
+ return StringPrintf("refTypeId=0x%llx (%s)", refTypeId, signature.c_str());
+}
+
/*
* Given a referenceTypeId, return a block of stuff that describes the
* fields declared by a class.
*/
static JdwpError handleRT_FieldsWithGeneric(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
RefTypeId refTypeId = ReadRefTypeId(&buf);
- LOG(VERBOSE) << StringPrintf(" Req for fields in refTypeId=0x%llx", refTypeId);
- LOG(VERBOSE) << StringPrintf(" --> '%s'", Dbg::GetSignature(refTypeId).c_str());
- Dbg::OutputDeclaredFields(refTypeId, true, pReply);
- return ERR_NONE;
+ LOG(VERBOSE) << " Req for fields in " << Describe(refTypeId);
+ return Dbg::OutputDeclaredFields(refTypeId, true, pReply) ? ERR_NONE : ERR_INVALID_CLASS;
+}
+
+// Obsolete equivalent of FieldsWithGeneric, without the generic type information.
+static JdwpError handleRT_Fields(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
+ RefTypeId refTypeId = ReadRefTypeId(&buf);
+ LOG(VERBOSE) << " Req for fields in " << Describe(refTypeId);
+ return Dbg::OutputDeclaredFields(refTypeId, false, pReply) ? ERR_NONE : ERR_INVALID_CLASS;
}
/*
@@ -609,13 +613,15 @@ static JdwpError handleRT_FieldsWithGeneric(JdwpState* state, const uint8_t* buf
*/
static JdwpError handleRT_MethodsWithGeneric(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
RefTypeId refTypeId = ReadRefTypeId(&buf);
+ LOG(VERBOSE) << " Req for methods in " << Describe(refTypeId);
+ return Dbg::OutputDeclaredMethods(refTypeId, true, pReply) ? ERR_NONE : ERR_INVALID_CLASS;
+}
- LOG(VERBOSE) << StringPrintf(" Req for methods in refTypeId=0x%llx", refTypeId);
- LOG(VERBOSE) << StringPrintf(" --> '%s'", Dbg::GetSignature(refTypeId).c_str());
-
- Dbg::OutputDeclaredMethods(refTypeId, true, pReply);
-
- return ERR_NONE;
+// Obsolete equivalent of MethodsWithGeneric, without the generic type information.
+static JdwpError handleRT_Methods(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
+ RefTypeId refTypeId = ReadRefTypeId(&buf);
+ LOG(VERBOSE) << " Req for methods in " << Describe(refTypeId);
+ return Dbg::OutputDeclaredMethods(refTypeId, false, pReply) ? ERR_NONE : ERR_INVALID_CLASS;
}
/*
@@ -623,11 +629,11 @@ static JdwpError handleRT_MethodsWithGeneric(JdwpState* state, const uint8_t* bu
*/
static JdwpError handleCT_Superclass(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
RefTypeId classId = ReadRefTypeId(&buf);
-
- RefTypeId superClassId = Dbg::GetSuperclass(classId);
-
+ RefTypeId superClassId;
+ if (!Dbg::GetSuperclass(classId, superClassId)) {
+ return ERR_INVALID_CLASS;
+ }
expandBufAddRefTypeId(pReply, superClassId);
-
return ERR_NONE;
}
@@ -680,7 +686,10 @@ static JdwpError handleCT_NewInstance(JdwpState* state, const uint8_t* buf, int
MethodId methodId = ReadMethodId(&buf);
LOG(VERBOSE) << "Creating instance of " << Dbg::GetClassDescriptor(classId);
- ObjectId objectId = Dbg::CreateObject(classId);
+ ObjectId objectId;
+ if (!Dbg::CreateObject(classId, objectId)) {
+ return ERR_INVALID_CLASS;
+ }
if (objectId == 0) {
return ERR_OUT_OF_MEMORY;
}
@@ -695,7 +704,10 @@ static JdwpError handleAT_newInstance(JdwpState* state, const uint8_t* buf, int
uint32_t length = Read4BE(&buf);
LOG(VERBOSE) << StringPrintf("Creating array %s[%u]", Dbg::GetClassDescriptor(arrayTypeId).c_str(), length);
- ObjectId objectId = Dbg::CreateArrayObject(arrayTypeId, length);
+ ObjectId objectId;
+ if (!Dbg::CreateArrayObject(arrayTypeId, length, objectId)) {
+ return ERR_INVALID_CLASS;
+ }
if (objectId == 0) {
return ERR_OUT_OF_MEMORY;
}
@@ -860,7 +872,7 @@ static JdwpError handleSR_Value(JdwpState* state, const uint8_t* buf, int dataLe
ObjectId stringObject = ReadObjectId(&buf);
std::string str(Dbg::StringToUtf8(stringObject));
- LOG(VERBOSE) << StringPrintf(" Req for str %llx --> '%s'", stringObject, str.c_str());
+ LOG(VERBOSE) << StringPrintf(" Req for str %llx --> '%s'", stringObject, PrintableString(str).c_str());
expandBufAddUtf8String(pReply, str);
@@ -1248,7 +1260,7 @@ static JdwpError handleER_Set(JdwpState* state, const uint8_t* buf, int dataLen,
* mods in JDWP doc).
*/
for (uint32_t idx = 0; idx < modifierCount; idx++) {
- uint8_t modKind = Read1(&buf);
+ JdwpModKind modKind = static_cast<JdwpModKind>(Read1(&buf));
pEvent->mods[idx].modKind = modKind;
@@ -1286,25 +1298,17 @@ static JdwpError handleER_Set(JdwpState* state, const uint8_t* buf, int dataLen,
break;
case MK_CLASS_MATCH: /* restrict events to matching classes */
{
- char* pattern;
- size_t strLen;
-
- pattern = ReadNewUtf8String(&buf, &strLen);
- LOG(VERBOSE) << StringPrintf(" ClassMatch: '%s'", pattern);
+ std::string pattern(ReadNewUtf8String(&buf));
+ LOG(VERBOSE) << StringPrintf(" ClassMatch: '%s'", pattern.c_str());
/* pattern is "java.foo.*", we want "java/foo/ *" */
- pEvent->mods[idx].classMatch.classPattern = dvmDotToSlash(pattern);
- free(pattern);
+ pEvent->mods[idx].classMatch.classPattern = dvmDotToSlash(pattern.c_str());
}
break;
case MK_CLASS_EXCLUDE: /* restrict events to non-matching classes */
{
- char* pattern;
- size_t strLen;
-
- pattern = ReadNewUtf8String(&buf, &strLen);
- LOG(VERBOSE) << StringPrintf(" ClassExclude: '%s'", pattern);
- pEvent->mods[idx].classExclude.classPattern = dvmDotToSlash(pattern);
- free(pattern);
+ std::string pattern(ReadNewUtf8String(&buf));
+ LOG(VERBOSE) << StringPrintf(" ClassExclude: '%s'", pattern.c_str());
+ pEvent->mods[idx].classExclude.classPattern = dvmDotToSlash(pattern.c_str());
}
break;
case MK_LOCATION_ONLY: /* restrict certain events based on loc */
@@ -1496,12 +1500,12 @@ static JdwpError handleCOR_ReflectedType(JdwpState* state, const uint8_t* buf, i
LOG(VERBOSE) << StringPrintf(" Req for refTypeId for class=%llx (%s)", classObjectId, Dbg::GetClassDescriptor(classObjectId).c_str());
- /* just hand the type back to them */
- if (Dbg::IsInterface(classObjectId)) {
- expandBufAdd1(pReply, TT_INTERFACE);
- } else {
- expandBufAdd1(pReply, TT_CLASS);
+ bool is_interface;
+ if (!Dbg::IsInterface(classObjectId, is_interface)) {
+ return ERR_INVALID_CLASS;
}
+
+ expandBufAdd1(pReply, is_interface ? TT_INTERFACE : TT_CLASS);
expandBufAddRefTypeId(pReply, classObjectId);
return ERR_NONE;
@@ -1587,8 +1591,8 @@ static const JdwpHandlerMap gHandlerMap[] = {
{ 2, 1, handleRT_Signature, "ReferenceType.Signature" },
{ 2, 2, handleRT_ClassLoader, "ReferenceType.ClassLoader" },
{ 2, 3, handleRT_Modifiers, "ReferenceType.Modifiers" },
- { 2, 4, NULL, "ReferenceType.Fields" },
- { 2, 5, NULL, "ReferenceType.Methods" },
+ { 2, 4, handleRT_Fields, "ReferenceType.Fields" },
+ { 2, 5, handleRT_Methods, "ReferenceType.Methods" },
{ 2, 6, handleRT_GetValues, "ReferenceType.GetValues" },
{ 2, 7, handleRT_SourceFile, "ReferenceType.SourceFile" },
{ 2, 8, NULL, "ReferenceType.NestedTypes" },