Fix missing receiver type information in invoke-custom

Bug:  36957105
Test: manual using the dex file generated by dx/tests/135-invoke-custom
Change-Id: I28db8c013a63cebce8a6202dc3241bb494153b80
diff --git a/dexdump/DexDump.cpp b/dexdump/DexDump.cpp
index 5cc4e8a..b1c8b00 100644
--- a/dexdump/DexDump.cpp
+++ b/dexdump/DexDump.cpp
@@ -1865,55 +1865,88 @@
             (const DexMethodHandleItem*)(pDexFile->baseAddr + item->offset);
     for (u4 i = 0; i < item->size; ++i) {
         const DexMethodHandleItem& mh = method_handles[i];
-        bool is_invoke = false;
         const char* type;
-        switch (mh.methodHandleType) {
-            case 0:
+        bool is_invoke;
+        bool is_static;
+        switch ((MethodHandleType) mh.methodHandleType) {
+            case MethodHandleType::STATIC_PUT:
                 type = "put-static";
+                is_invoke = false;
+                is_static = true;
                 break;
-            case 1:
+            case MethodHandleType::STATIC_GET:
                 type = "get-static";
+                is_invoke = false;
+                is_static = true;
                 break;
-            case 2:
+            case MethodHandleType::INSTANCE_PUT:
                 type = "put-instance";
+                is_invoke = false;
+                is_static = false;
                 break;
-            case 3:
+            case MethodHandleType::INSTANCE_GET:
                 type = "get-instance";
+                is_invoke = false;
+                is_static = false;
                 break;
-            case 4:
+            case MethodHandleType::INVOKE_STATIC:
                 type = "invoke-static";
                 is_invoke = true;
+                is_static = true;
                 break;
-            case 5:
+            case MethodHandleType::INVOKE_INSTANCE:
                 type = "invoke-instance";
                 is_invoke = true;
+                is_static = false;
                 break;
-            case 6:
+            case MethodHandleType::INVOKE_CONSTRUCTOR:
                 type = "invoke-constructor";
                 is_invoke = true;
+                is_static = false;
                 break;
+            case MethodHandleType::INVOKE_DIRECT:
+                type = "invoke-direct";
+                is_invoke = true;
+                is_static = false;
+                break;
+            case  MethodHandleType::INVOKE_INTERFACE:
+                type = "invoke-interface";
+                is_invoke = true;
+                is_static = false;
+                break;
+            default:
+                printf("Unknown method handle type 0x%02x, skipped.", mh.methodHandleType);
+                continue;
         }
 
         FieldMethodInfo info;
-        memset(&info, 0, sizeof(info));
         if (is_invoke) {
-            getMethodInfo(pDexFile, mh.fieldOrMethodIdx, &info);
+            if (!getMethodInfo(pDexFile, mh.fieldOrMethodIdx, &info)) {
+                printf("Unknown method handle target method@%04x, skipped.", mh.fieldOrMethodIdx);
+                continue;
+            }
         } else {
-            getFieldInfo(pDexFile, mh.fieldOrMethodIdx, &info);
+            if (!getFieldInfo(pDexFile, mh.fieldOrMethodIdx, &info)) {
+                printf("Unknown method handle target field@%04x, skipped.", mh.fieldOrMethodIdx);
+                continue;
+            }
         }
 
+        const char* instance = is_static ? "" : info.classDescriptor;
+
         if (gOptions.outputFormat == OUTPUT_XML) {
             printf("<method_handle index index=\"%u\"\n", i);
             printf(" type=\"%s\"\n", type);
             printf(" target_class=\"%s\"\n", info.classDescriptor);
             printf(" target_member=\"%s\"\n", info.name);
-            printf(" target_member_type=\"%s\"\n", info.signature);
+            printf(" target_member_type=\"%c%s%s\"\n",
+                   info.signature[0], instance, info.signature + 1);
             printf("</method_handle>\n");
         } else {
             printf("Method Handle #%u:\n", i);
             printf("  type        : %s\n", type);
             printf("  target      : %s %s\n", info.classDescriptor, info.name);
-            printf("  target_type : %s\n", info.signature);
+            printf("  target_type : %c%s%s\n", info.signature[0], instance, info.signature + 1);
         }
     }
 }
diff --git a/libdex/DexFile.h b/libdex/DexFile.h
index 74fce3c..c274e64 100644
--- a/libdex/DexFile.h
+++ b/libdex/DexFile.h
@@ -371,6 +371,21 @@
 };
 
 /*
+ * Enumeration of method handle type codes.
+ */
+enum MethodHandleType {
+    STATIC_PUT = 0x00,
+    STATIC_GET = 0x01,
+    INSTANCE_PUT = 0x02,
+    INSTANCE_GET = 0x03,
+    INVOKE_STATIC = 0x04,
+    INVOKE_INSTANCE = 0x05,
+    INVOKE_CONSTRUCTOR = 0x06,
+    INVOKE_DIRECT = 0x07,
+    INVOKE_INTERFACE = 0x08
+};
+
+/*
  * Direct-mapped "method_handle_item"
  */
 struct DexMethodHandleItem {
diff --git a/libdex/DexSwapVerify.cpp b/libdex/DexSwapVerify.cpp
index bd9140c..efb4fb7 100644
--- a/libdex/DexSwapVerify.cpp
+++ b/libdex/DexSwapVerify.cpp
@@ -1068,23 +1068,31 @@
         ALOGE("Verifying method handle but expecting none");
         return NULL;
     }
-    if (item->methodHandleType <= 3 &&
-        item->fieldOrMethodIdx >= state->pHeader->fieldIdsSize) {
-        // 0-3 are field accessors.
-        ALOGE("Method handle has invalid field id: %u\n", item->fieldOrMethodIdx);
-        return NULL;
-    }
-    if (item->methodHandleType >= 4 &&
-        item->methodHandleType <= 6 &&
-        item->fieldOrMethodIdx >= state->pHeader->methodIdsSize) {
-        // 4-6 are method invocations.
-        ALOGE("Method handle has invalid method id: %u\n", item->fieldOrMethodIdx);
-        return NULL;
-    }
-    if (item->methodHandleType >= 7) {
+    if (item->methodHandleType > (u2) MethodHandleType::INVOKE_INTERFACE) {
         ALOGE("Unknown method handle type: %u", item->methodHandleType);
         return NULL;
     }
+    switch ((MethodHandleType) item->methodHandleType) {
+        case MethodHandleType::STATIC_PUT:
+        case MethodHandleType::STATIC_GET:
+        case MethodHandleType::INSTANCE_PUT:
+        case MethodHandleType::INSTANCE_GET:
+            if (item->fieldOrMethodIdx >= state->pHeader->fieldIdsSize) {
+                ALOGE("Method handle has invalid field id: %u\n", item->fieldOrMethodIdx);
+                return NULL;
+            }
+            break;
+        case MethodHandleType::INVOKE_STATIC:
+        case MethodHandleType::INVOKE_INSTANCE:
+        case MethodHandleType::INVOKE_CONSTRUCTOR:
+        case MethodHandleType::INVOKE_DIRECT:
+        case MethodHandleType::INVOKE_INTERFACE:
+            if (item->fieldOrMethodIdx >= state->pHeader->methodIdsSize) {
+                ALOGE("Method handle has invalid method id: %u\n", item->fieldOrMethodIdx);
+                return NULL;
+            }
+            break;
+    }
     return (void*) (item + 1);
 }