summaryrefslogtreecommitdiffstats
path: root/dexdump
diff options
context:
space:
mode:
authorDan Bornstein <danfuzz@android.com>2010-11-11 12:26:58 -0800
committerDan Bornstein <danfuzz@android.com>2010-11-11 12:58:00 -0800
commit4a6b4825a5d3ac267e359897a5fb4d132a82c935 (patch)
tree7f01b3ededa7a5b642d1a6fea50135a9c95ad362 /dexdump
parente192bb82fc3c0f5d0fe2f42e7479eb48fc3ae855 (diff)
downloadandroid_dalvik-4a6b4825a5d3ac267e359897a5fb4d132a82c935.tar.gz
android_dalvik-4a6b4825a5d3ac267e359897a5fb4d132a82c935.tar.bz2
android_dalvik-4a6b4825a5d3ac267e359897a5fb4d132a82c935.zip
Add the new instruction formats.
This just adds new elements to the enum and adds code to InstrUtils and dexdump which knows how to decode them. In dexdump, I took advantage of the new index type table to simplify how all the index-bearing instructions get dumped, to the point where adding the new formats was really just a matter of picking the right switch cases to add new labels to. Change-Id: I9094b0d568e7c71ee237672bbea8c319274c6697
Diffstat (limited to 'dexdump')
-rw-r--r--dexdump/DexDump.c302
1 files changed, 163 insertions, 139 deletions
diff --git a/dexdump/DexDump.c b/dexdump/DexDump.c
index b9c8bd1f3..4fb3878c9 100644
--- a/dexdump/DexDump.c
+++ b/dexdump/DexDump.c
@@ -694,11 +694,153 @@ const char* getClassDescriptor(DexFile* pDexFile, u4 classIdx)
}
/*
+ * Helper for dumpInstruction(), which builds the string
+ * representation for the index in the given instruction. This will
+ * first try to use the given buffer, but if the result won't fit,
+ * then this will allocate a new buffer to hold the result. A pointer
+ * to the buffer which holds the full result is always returned, and
+ * this can be compared with the one passed in, to see if the result
+ * needs to be free()d.
+ */
+static char* indexString(DexFile* pDexFile,
+ const DecodedInstruction* pDecInsn, char* buf, size_t bufSize)
+{
+ int outSize;
+ u4 index;
+ u4 width;
+
+ /* TODO: Make the index *always* be in field B, to simplify this code. */
+ switch (dexGetInstrFormat(gInstrInfo.formats, pDecInsn->opCode)) {
+ case kFmt20bc:
+ case kFmt21c:
+ case kFmt35c:
+ case kFmt35ms:
+ case kFmt3rc:
+ case kFmt3rms:
+ case kFmt35mi:
+ case kFmt3rmi:
+ index = pDecInsn->vB;
+ width = 4;
+ break;
+ case kFmt31c:
+ case kFmt41c:
+ case kFmt5rc:
+ index = pDecInsn->vB;
+ width = 8;
+ break;
+ case kFmt22c:
+ case kFmt22cs:
+ index = pDecInsn->vC;
+ width = 4;
+ break;
+ case kFmt52c:
+ index = pDecInsn->vC;
+ width = 8;
+ break;
+ default:
+ index = 0;
+ width = 4;
+ break;
+ }
+
+ switch (pDecInsn->indexType) {
+ case kIndexUnknown:
+ /*
+ * This function shouldn't ever get called for this type, but do
+ * something sensible here, just to help with debugging.
+ */
+ outSize = snprintf(buf, bufSize, "<unknown-index>");
+ break;
+ case kIndexNone:
+ /*
+ * This function shouldn't ever get called for this type, but do
+ * something sensible here, just to help with debugging.
+ */
+ outSize = snprintf(buf, bufSize, "<no-index>");
+ break;
+ case kIndexVaries:
+ /*
+ * This one should never show up in a dexdump, so no need to try
+ * to get fancy here.
+ */
+ outSize = snprintf(buf, bufSize, "<index-varies> // thing@%0*x",
+ width, index);
+ break;
+ case kIndexClassRef:
+ outSize = snprintf(buf, bufSize, "%s // class@%0*x",
+ getClassDescriptor(pDexFile, index), width, index);
+ break;
+ case kIndexStringRef:
+ outSize = snprintf(buf, bufSize, "\"%s\" // string@%0*x",
+ dexStringById(pDexFile, index), width, index);
+ break;
+ case kIndexMethodRef:
+ {
+ FieldMethodInfo methInfo;
+ if (getMethodInfo(pDexFile, index, &methInfo)) {
+ outSize = snprintf(buf, bufSize, "%s.%s:%s // method@%0*x",
+ methInfo.classDescriptor, methInfo.name,
+ methInfo.signature, width, index);
+ } else {
+ outSize = snprintf(buf, bufSize, "<method?> // method@%0*x",
+ width, index);
+ }
+ }
+ break;
+ case kIndexFieldRef:
+ {
+ FieldMethodInfo fieldInfo;
+ if (getFieldInfo(pDexFile, index, &fieldInfo)) {
+ outSize = snprintf(buf, bufSize, "%s.%s:%s // field@%0*x",
+ fieldInfo.classDescriptor, fieldInfo.name,
+ fieldInfo.signature, width, index);
+ } else {
+ outSize = snprintf(buf, bufSize, "<field?> // field@%0*x",
+ width, index);
+ }
+ }
+ break;
+ case kIndexInlineMethod:
+ outSize = snprintf(buf, bufSize, "[%0*x] // inline #%0*x",
+ width, index, width, index);
+ break;
+ case kIndexVtableOffset:
+ outSize = snprintf(buf, bufSize, "[%0*x] // vtable #%0*x",
+ width, index, width, index);
+ break;
+ case kIndexFieldOffset:
+ outSize = snprintf(buf, bufSize, "[obj+%0*x]", width, index);
+ break;
+ default:
+ outSize = snprintf(buf, bufSize, "<?>");
+ break;
+ }
+
+ if (outSize >= (int) bufSize) {
+ /*
+ * The buffer wasn't big enough; allocate and retry. Note:
+ * snprintf() doesn't count the '\0' as part of its returned
+ * size, so we add explicit space for it here.
+ */
+ outSize++;
+ buf = malloc(outSize);
+ if (buf == NULL) {
+ return NULL;
+ }
+ return indexString(pDexFile, pDecInsn, buf, outSize);
+ } else {
+ return buf;
+ }
+}
+
+/*
* Dump a single instruction.
*/
void dumpInstruction(DexFile* pDexFile, const DexCode* pCode, int insnIdx,
int insnWidth, const DecodedInstruction* pDecInsn)
{
+ char indexBufChars[200];
+ char *indexBuf = indexBufChars;
const u2* insns = pCode->insns;
int i;
@@ -735,6 +877,11 @@ void dumpInstruction(DexFile* pDexFile, const DexCode* pCode, int insnIdx,
printf("|%04x: %s", insnIdx, dexGetOpcodeName(pDecInsn->opCode));
}
+ if (pDecInsn->indexType != kIndexNone) {
+ indexBuf = indexString(pDexFile, pDecInsn,
+ indexBufChars, sizeof(indexBufChars));
+ }
+
switch (dexGetInstrFormat(gInstrInfo.formats, pDecInsn->opCode)) {
case kFmt10x: // op
break;
@@ -787,27 +934,12 @@ void dumpInstruction(DexFile* pDexFile, const DexCode* pCode, int insnIdx,
}
break;
case kFmt21c: // op vAA, thing@BBBB
- if (pDecInsn->opCode == OP_CONST_STRING) {
- printf(" v%d, \"%s\" // string@%04x", pDecInsn->vA,
- dexStringById(pDexFile, pDecInsn->vB), pDecInsn->vB);
- } else if (pDecInsn->opCode == OP_CHECK_CAST ||
- pDecInsn->opCode == OP_NEW_INSTANCE ||
- pDecInsn->opCode == OP_CONST_CLASS)
- {
- printf(" v%d, %s // class@%04x", pDecInsn->vA,
- getClassDescriptor(pDexFile, pDecInsn->vB), pDecInsn->vB);
- } else /* OP_SGET* */ {
- FieldMethodInfo fieldInfo;
- if (getFieldInfo(pDexFile, pDecInsn->vB, &fieldInfo)) {
- printf(" v%d, %s.%s:%s // field@%04x", pDecInsn->vA,
- fieldInfo.classDescriptor, fieldInfo.name,
- fieldInfo.signature, pDecInsn->vB);
- } else {
- printf(" v%d, ??? // field@%04x", pDecInsn->vA, pDecInsn->vB);
- }
- }
+ case kFmt31c: // op vAA, thing@BBBBBBBB
+ case kFmt41c: // exop vAAAA, thing@BBBBBBBB
+ printf(" v%d, %s", pDecInsn->vA, indexBuf);
break;
case kFmt23x: // op vAA, vBB, vCC
+ case kFmt33x: // exop vAA, vBB, vCCCC
printf(" v%d, v%d, v%d", pDecInsn->vA, pDecInsn->vB, pDecInsn->vC);
break;
case kFmt22b: // op vAA, vBB, #+CC
@@ -824,32 +956,14 @@ void dumpInstruction(DexFile* pDexFile, const DexCode* pCode, int insnIdx,
}
break;
case kFmt22s: // op vA, vB, #+CCCC
+ case kFmt32s: // exop vAA, vBB, #+CCCC
printf(" v%d, v%d, #int %d // #%04x",
pDecInsn->vA, pDecInsn->vB, (s4)pDecInsn->vC, (u2)pDecInsn->vC);
break;
case kFmt22c: // op vA, vB, thing@CCCC
- if (pDecInsn->opCode == OP_INSTANCE_OF ||
- pDecInsn->opCode == OP_NEW_ARRAY)
- {
- printf(" v%d, v%d, %s // class@%04x",
- pDecInsn->vA, pDecInsn->vB,
- getClassDescriptor(pDexFile, pDecInsn->vC), pDecInsn->vC);
- } else {
- /* iget* and iput*, including dexopt-generated -volatile */
- FieldMethodInfo fieldInfo;
- if (getFieldInfo(pDexFile, pDecInsn->vC, &fieldInfo)) {
- printf(" v%d, v%d, %s.%s:%s // field@%04x", pDecInsn->vA,
- pDecInsn->vB, fieldInfo.classDescriptor, fieldInfo.name,
- fieldInfo.signature, pDecInsn->vC);
- } else {
- printf(" v%d, v%d, ??? // field@%04x", pDecInsn->vA,
- pDecInsn->vB, pDecInsn->vC);
- }
- }
- break;
case kFmt22cs: // [opt] op vA, vB, field offset CCCC
- printf(" v%d, v%d, [obj+%04x]",
- pDecInsn->vA, pDecInsn->vB, pDecInsn->vC);
+ case kFmt52c: // exop vAAAA, vBBBB, thing@CCCCCCCC
+ printf(" v%d, v%d, %s", pDecInsn->vA, pDecInsn->vB, indexBuf);
break;
case kFmt30t:
printf(" #%08x", pDecInsn->vA);
@@ -866,10 +980,6 @@ void dumpInstruction(DexFile* pDexFile, const DexCode* pCode, int insnIdx,
pDecInsn->vA, conv.f, pDecInsn->vB);
}
break;
- case kFmt31c: // op vAA, thing@BBBBBBBB
- printf(" v%d, \"%s\" // string@%08x", pDecInsn->vA,
- dexStringById(pDexFile, pDecInsn->vB), pDecInsn->vB);
- break;
case kFmt31t: // op vAA, offset +BBBBBBBB
printf(" v%d, %08x // +%08x",
pDecInsn->vA, insnIdx + pDecInsn->vB, pDecInsn->vB);
@@ -878,30 +988,8 @@ void dumpInstruction(DexFile* pDexFile, const DexCode* pCode, int insnIdx,
printf(" v%d, v%d", pDecInsn->vA, pDecInsn->vB);
break;
case kFmt35c: // op {vC, vD, vE, vF, vG}, thing@BBBB
- {
- fputs(" {", stdout);
- for (i = 0; i < (int) pDecInsn->vA; i++) {
- if (i == 0)
- printf("v%d", pDecInsn->arg[i]);
- else
- printf(", v%d", pDecInsn->arg[i]);
- }
- if (pDecInsn->opCode == OP_FILLED_NEW_ARRAY) {
- printf("}, %s // class@%04x",
- getClassDescriptor(pDexFile, pDecInsn->vB), pDecInsn->vB);
- } else {
- FieldMethodInfo methInfo;
- if (getMethodInfo(pDexFile, pDecInsn->vB, &methInfo)) {
- printf("}, %s.%s:%s // method@%04x",
- methInfo.classDescriptor, methInfo.name,
- methInfo.signature, pDecInsn->vB);
- } else {
- printf("}, ??? // method@%04x", pDecInsn->vB);
- }
- }
- }
- break;
case kFmt35ms: // [opt] invoke-virtual+super
+ case kFmt35mi: // [opt] inline invoke
{
fputs(" {", stdout);
for (i = 0; i < (int) pDecInsn->vA; i++) {
@@ -910,38 +998,13 @@ void dumpInstruction(DexFile* pDexFile, const DexCode* pCode, int insnIdx,
else
printf(", v%d", pDecInsn->arg[i]);
}
- printf("}, [%04x] // vtable #%04x", pDecInsn->vB, pDecInsn->vB);
- }
- break;
- case kFmt3rc: // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
- {
- /*
- * This doesn't match the "dx" output when some of the args are
- * 64-bit values -- dx only shows the first register.
- */
- fputs(" {", stdout);
- for (i = 0; i < (int) pDecInsn->vA; i++) {
- if (i == 0)
- printf("v%d", pDecInsn->vC + i);
- else
- printf(", v%d", pDecInsn->vC + i);
- }
- if (pDecInsn->opCode == OP_FILLED_NEW_ARRAY_RANGE) {
- printf("}, %s // class@%04x",
- getClassDescriptor(pDexFile, pDecInsn->vB), pDecInsn->vB);
- } else {
- FieldMethodInfo methInfo;
- if (getMethodInfo(pDexFile, pDecInsn->vB, &methInfo)) {
- printf("}, %s.%s:%s // method@%04x",
- methInfo.classDescriptor, methInfo.name,
- methInfo.signature, pDecInsn->vB);
- } else {
- printf("}, ??? // method@%04x", pDecInsn->vB);
- }
- }
+ printf("}, %s", indexBuf);
}
break;
+ case kFmt3rc: // op {vCCCC .. v(CCCC+AA-1)}, thing@BBBB
case kFmt3rms: // [opt] invoke-virtual+super/range
+ case kFmt3rmi: // [opt] execute-inline/range
+ case kFmt5rc: // exop {vCCCC .. v(CCCC+AAAA-1)}, meth@BBBBBBBB
{
/*
* This doesn't match the "dx" output when some of the args are
@@ -954,48 +1017,7 @@ void dumpInstruction(DexFile* pDexFile, const DexCode* pCode, int insnIdx,
else
printf(", v%d", pDecInsn->vC + i);
}
- printf("}, [%04x] // vtable #%04x", pDecInsn->vB, pDecInsn->vB);
- }
- break;
- case kFmt3rmi: // [opt] execute-inline/range
- {
- fputs(" {", stdout);
- for (i = 0; i < (int) pDecInsn->vA; i++) {
- if (i == 0)
- printf("v%d", pDecInsn->vC + i);
- else
- printf(", v%d", pDecInsn->vC + i);
- }
- printf("}, [%04x] // inline #%04x", pDecInsn->vB, pDecInsn->vB);
- }
- break;
- case kFmt35mi: // [opt] inline invoke
- {
-#if 0
- const InlineOperation* inlineOpsTable = dvmGetInlineOpsTable();
- u4 tableLen = dvmGetInlineOpsTableLength();
-#endif
-
- fputs(" {", stdout);
- for (i = 0; i < (int) pDecInsn->vA; i++) {
- if (i == 0)
- printf("v%d", pDecInsn->arg[i]);
- else
- printf(", v%d", pDecInsn->arg[i]);
- }
-#if 0
- if (pDecInsn->vB < tableLen) {
- printf("}, %s.%s:%s // inline #%04x",
- inlineOpsTable[pDecInsn->vB].classDescriptor,
- inlineOpsTable[pDecInsn->vB].methodName,
- inlineOpsTable[pDecInsn->vB].methodSignature,
- pDecInsn->vB);
- } else {
-#endif
- printf("}, [%04x] // inline #%04x", pDecInsn->vB, pDecInsn->vB);
-#if 0
- }
-#endif
+ printf("}, %s", indexBuf);
}
break;
case kFmt51l: // op vAA, #+BBBBBBBBBBBBBBBB
@@ -1017,9 +1039,11 @@ void dumpInstruction(DexFile* pDexFile, const DexCode* pCode, int insnIdx,
break;
}
-
putchar('\n');
+ if (indexBuf != indexBufChars) {
+ free(indexBuf);
+ }
}
/*