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);
}