Fixes for constant method handles
Add support for constant direct and interface method handles in the
DEX file.
Add error handling for field and method resolution failures in
ClassLinker::ResolveMethodHandle().
Bug: 36957105
Test: art/test/run-test --host 952-invoke-custom-kinds
Change-Id: I91a2a23ba3365310eccb8cadd193b62f57e5811c
diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc
index df0169f..65232bf 100644
--- a/dexdump/dexdump.cc
+++ b/dexdump/dexdump.cc
@@ -1582,31 +1582,53 @@
static void dumpMethodHandle(const DexFile* pDexFile, u4 idx) {
const DexFile::MethodHandleItem& mh = pDexFile->GetMethodHandle(idx);
+ const char* type = nullptr;
+ bool is_instance = false;
bool is_invoke = false;
- const char* type;
switch (static_cast<DexFile::MethodHandleType>(mh.method_handle_type_)) {
case DexFile::MethodHandleType::kStaticPut:
type = "put-static";
+ is_instance = false;
+ is_invoke = false;
break;
case DexFile::MethodHandleType::kStaticGet:
type = "get-static";
+ is_instance = false;
+ is_invoke = false;
break;
case DexFile::MethodHandleType::kInstancePut:
type = "put-instance";
+ is_instance = true;
+ is_invoke = false;
break;
case DexFile::MethodHandleType::kInstanceGet:
type = "get-instance";
+ is_instance = true;
+ is_invoke = false;
break;
case DexFile::MethodHandleType::kInvokeStatic:
type = "invoke-static";
+ is_instance = false;
is_invoke = true;
break;
case DexFile::MethodHandleType::kInvokeInstance:
type = "invoke-instance";
+ is_instance = true;
is_invoke = true;
break;
case DexFile::MethodHandleType::kInvokeConstructor:
type = "invoke-constructor";
+ is_instance = true;
+ is_invoke = true;
+ break;
+ case DexFile::MethodHandleType::kInvokeDirect:
+ type = "invoke-direct";
+ is_instance = true;
+ is_invoke = true;
+ break;
+ case DexFile::MethodHandleType::kInvokeInterface:
+ type = "invoke-interface";
+ is_instance = true;
is_invoke = true;
break;
}
@@ -1614,16 +1636,26 @@
const char* declaring_class;
const char* member;
std::string member_type;
- if (is_invoke) {
- const DexFile::MethodId& method_id = pDexFile->GetMethodId(mh.field_or_method_idx_);
- declaring_class = pDexFile->GetMethodDeclaringClassDescriptor(method_id);
- member = pDexFile->GetMethodName(method_id);
- member_type = pDexFile->GetMethodSignature(method_id).ToString();
+ if (type != nullptr) {
+ if (is_invoke) {
+ const DexFile::MethodId& method_id = pDexFile->GetMethodId(mh.field_or_method_idx_);
+ declaring_class = pDexFile->GetMethodDeclaringClassDescriptor(method_id);
+ member = pDexFile->GetMethodName(method_id);
+ member_type = pDexFile->GetMethodSignature(method_id).ToString();
+ } else {
+ const DexFile::FieldId& field_id = pDexFile->GetFieldId(mh.field_or_method_idx_);
+ declaring_class = pDexFile->GetFieldDeclaringClassDescriptor(field_id);
+ member = pDexFile->GetFieldName(field_id);
+ member_type = pDexFile->GetFieldTypeDescriptor(field_id);
+ }
+ if (is_instance) {
+ member_type = android::base::StringPrintf("(%s%s", declaring_class, member_type.c_str() + 1);
+ }
} else {
- const DexFile::FieldId& field_id = pDexFile->GetFieldId(mh.field_or_method_idx_);
- declaring_class = pDexFile->GetFieldDeclaringClassDescriptor(field_id);
- member = pDexFile->GetFieldName(field_id);
- member_type = pDexFile->GetFieldTypeDescriptor(field_id);
+ type = "?";
+ declaring_class = "?";
+ member = "?";
+ member_type = "?";
}
if (gOptions.outputFormat == OUTPUT_PLAIN) {