Dex disassembly suppport for invoke-polymorphic.

Bug:  30550796
Test: art/test/dexdump/run-all-tests
Change-Id: I013ce2ebbcf9555e01170dc47fc38036c276b1b4
diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc
index 2042934..b241c8b 100644
--- a/dexdump/dexdump.cc
+++ b/dexdump/dexdump.cc
@@ -42,6 +42,7 @@
 #include <sstream>
 #include <vector>
 
+#include "base/stringprintf.h"
 #include "dex_file-inl.h"
 #include "dex_instruction-inl.h"
 #include "utils.h"
@@ -780,9 +781,11 @@
 static std::unique_ptr<char[]> indexString(const DexFile* pDexFile,
                                            const Instruction* pDecInsn,
                                            size_t bufSize) {
+  static const u4 kInvalidIndex = std::numeric_limits<u4>::max();
   std::unique_ptr<char[]> buf(new char[bufSize]);
   // Determine index and width of the string.
   u4 index = 0;
+  u4 secondary_index = kInvalidIndex;
   u4 width = 4;
   switch (Instruction::FormatOf(pDecInsn->Opcode())) {
     // SOME NOT SUPPORTED:
@@ -806,6 +809,12 @@
       index = pDecInsn->VRegC();
       width = 4;
       break;
+    case Instruction::k45cc:
+    case Instruction::k4rcc:
+      index = pDecInsn->VRegB();
+      secondary_index = pDecInsn->VRegH();
+      width = 4;
+      break;
     default:
       break;
   }  // switch
@@ -870,6 +879,26 @@
     case Instruction::kIndexFieldOffset:
       outSize = snprintf(buf.get(), bufSize, "[obj+%0*x]", width, index);
       break;
+    case Instruction::kIndexMethodAndProtoRef: {
+        std::string method("<method?>");
+        std::string proto("<proto?>");
+        if (index < pDexFile->GetHeader().method_ids_size_) {
+          const DexFile::MethodId& pMethodId = pDexFile->GetMethodId(index);
+          const char* name = pDexFile->StringDataByIdx(pMethodId.name_idx_);
+          const Signature signature = pDexFile->GetMethodSignature(pMethodId);
+          const char* backDescriptor = pDexFile->StringByTypeIdx(pMethodId.class_idx_);
+          method = StringPrintf("%s.%s:%s",
+                                backDescriptor, name, signature.ToString().c_str());
+        }
+        if (secondary_index < pDexFile->GetHeader().proto_ids_size_) {
+          const DexFile::ProtoId& protoId = pDexFile->GetProtoId(secondary_index);
+          const Signature signature = pDexFile->GetProtoSignature(protoId);
+          proto = signature.ToString();
+        }
+        outSize = snprintf(buf.get(), bufSize, "%s, %s // method@%0*x, proto@%0*x",
+                           method.c_str(), proto.c_str(), width, index, width, secondary_index);
+      }
+      break;
     // SOME NOT SUPPORTED:
     // case Instruction::kIndexVaries:
     // case Instruction::kIndexInlineMethod:
@@ -1043,7 +1072,8 @@
     case Instruction::k32x:        // op vAAAA, vBBBB
       fprintf(gOutFile, " v%d, v%d", pDecInsn->VRegA(), pDecInsn->VRegB());
       break;
-    case Instruction::k35c: {      // op {vC, vD, vE, vF, vG}, thing@BBBB
+    case Instruction::k35c:       // op {vC, vD, vE, vF, vG}, thing@BBBB
+    case Instruction::k45cc: {    // op {vC, vD, vE, vF, vG}, method@BBBB, proto@HHHH
     // NOT SUPPORTED:
     // case Instruction::k35ms:       // [opt] invoke-virtual+super
     // case Instruction::k35mi:       // [opt] inline invoke
@@ -1061,10 +1091,10 @@
       break;
     }
     case Instruction::k3rc:        // op {vCCCC .. v(CCCC+AA-1)}, thing@BBBB
+    case Instruction::k4rcc: {     // op {vCCCC .. v(CCCC+AA-1)}, method@BBBB, proto@HHHH
     // NOT SUPPORTED:
     // case Instruction::k3rms:       // [opt] invoke-virtual+super/range
     // case Instruction::k3rmi:       // [opt] execute-inline/range
-      {
         // This doesn't match the "dx" output when some of the args are
         // 64-bit values -- dx only shows the first register.
         fputs(" {", gOutFile);