Better unresolved type support.
Also fix bug where miranda methods were changing their declaring class
and thereby breaking their return type indices.
Add support for dumping stacks on abort.
Change-Id: I3782864736b12d1f81ab9aea4909213d3344ba13
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index 6cb7104..85c4182 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -156,31 +156,30 @@
return true;
} else {
switch (GetType()) {
- case RegType::kRegTypeBoolean: return IsBooleanTypes();
- case RegType::kRegTypeByte: return IsByteTypes();
- case RegType::kRegTypeShort: return IsShortTypes();
- case RegType::kRegTypeChar: return IsCharTypes();
- case RegType::kRegTypeInteger: return IsIntegralTypes();
- case RegType::kRegTypeFloat: return IsFloatTypes();
- case RegType::kRegTypeLongLo: return IsLongTypes();
- case RegType::kRegTypeDoubleLo: return IsDoubleTypes();
+ case RegType::kRegTypeBoolean: return src.IsBooleanTypes();
+ case RegType::kRegTypeByte: return src.IsByteTypes();
+ case RegType::kRegTypeShort: return src.IsShortTypes();
+ case RegType::kRegTypeChar: return src.IsCharTypes();
+ case RegType::kRegTypeInteger: return src.IsIntegralTypes();
+ case RegType::kRegTypeFloat: return src.IsFloatTypes();
+ case RegType::kRegTypeLongLo: return src.IsLongTypes();
+ case RegType::kRegTypeDoubleLo: return src.IsDoubleTypes();
default:
if (!IsReferenceTypes()) {
LOG(FATAL) << "Unexpected register type in IsAssignableFrom: '" << src << "'";
}
if (src.IsZero()) {
- return true;
- } else if (IsUninitializedReference()) {
- return false; // Nonsensical to Join two uninitialized classes
- } else if (GetClass()->IsInterface()) {
+ return true; // all reference types can be assigned null
+ } else if (!src.IsReferenceTypes()) {
+ return false; // expect src to be a reference type
+ } else if (IsJavaLangObject()) {
+ return true; // all reference types can be assigned to Object
+ } else if (!IsUnresolvedTypes() && GetClass()->IsInterface()) {
return true; // We allow assignment to any interface, see comment in ClassJoin
- } else if (IsReference() && src.IsReference() &&
+ } else if (!IsUnresolvedTypes() && !src.IsUnresolvedTypes() &&
GetClass()->IsAssignableFrom(src.GetClass())) {
// We're assignable from the Class point-of-view
return true;
- } else if (src.IsUnresolvedReference() && IsReference() && GetClass()->IsObjectClass()) {
- // We're an object being assigned an unresolved reference, which is ok
- return true;
} else {
return false;
}
@@ -263,12 +262,14 @@
// float/long/double MERGE float/long/double_constant => float/long/double
return SelectNonConstant(*this, incoming_type);
} else if (IsReferenceTypes() && incoming_type.IsReferenceTypes()) {
- if (IsZero() | incoming_type.IsZero()) {
+ if (IsZero() || incoming_type.IsZero()) {
return SelectNonConstant(*this, incoming_type); // 0 MERGE ref => ref
- } else if (IsUnresolvedReference() || IsUninitializedReference() ||
- IsUninitializedThisReference()) {
- // Can only merge an uninitialized or unresolved type with itself or 0, we've already checked
- // these so => Conflict
+ } else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) {
+ return reg_types->JavaLangObject(); // Object MERGE ref => Object
+ } else if (IsUninitializedTypes() || incoming_type.IsUninitializedTypes() ||
+ IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) {
+ // Can only merge an unresolved or uninitialized type with itself, 0 or Object, we've already
+ // checked these so => Conflict
return reg_types->Conflict();
} else { // Two reference types, compute Join
Class* c1 = GetClass();
@@ -1865,18 +1866,14 @@
/* return_type is the *expected* return type, not register value */
DCHECK(!return_type.IsZero());
DCHECK(!return_type.IsUninitializedReference());
- // Verify that the reference in vAA is an instance of the type in "return_type". The Zero
- // type is allowed here. If the method is declared to return an interface, then any
- // initialized reference is acceptable.
- // Note GetClassFromRegister fails if the register holds an uninitialized reference, so
- // we do not allow them to be returned.
- Class* decl_class = return_type.GetClass();
- Class* res_class = work_line_->GetClassFromRegister(dec_insn.vA_);
- if (res_class != NULL && failure_ == VERIFY_ERROR_NONE) {
- if (!decl_class->IsInterface() && !decl_class->IsAssignableFrom(res_class)) {
- Fail(VERIFY_ERROR_GENERIC) << "returning " << PrettyClassAndClassLoader(res_class)
- << ", declared " << PrettyClassAndClassLoader(res_class);
- }
+ const RegType& reg_type = work_line_->GetRegisterType(dec_insn.vA_);
+ // Disallow returning uninitialized values and verify that the reference in vAA is an
+ // instance of the "return_type"
+ if (reg_type.IsUninitializedTypes()) {
+ Fail(VERIFY_ERROR_GENERIC) << "returning uninitialized object '" << reg_type << "'";
+ } else if (!return_type.IsAssignableFrom(reg_type)) {
+ Fail(VERIFY_ERROR_GENERIC) << "returning '" << reg_type
+ << "', but expected from declaration '" << return_type << "'";
}
}
}
@@ -2332,7 +2329,9 @@
dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
Method* called_method = VerifyInvocationArgs(dec_insn, METHOD_VIRTUAL, is_range, is_super);
if (failure_ == VERIFY_ERROR_NONE) {
- const RegType& return_type = reg_types_.FromClass(called_method->GetReturnType());
+ const RegType& return_type =
+ reg_types_.FromDescriptor(called_method->GetDeclaringClass()->GetClassLoader(),
+ called_method->GetReturnTypeDescriptor());
work_line_->SetResultRegisterType(return_type);
just_set_result = true;
}
@@ -2390,7 +2389,9 @@
if (failure_ != VERIFY_ERROR_NONE)
break;
}
- const RegType& return_type = reg_types_.FromClass(called_method->GetReturnType());
+ const RegType& return_type =
+ reg_types_.FromDescriptor(called_method->GetDeclaringClass()->GetClassLoader(),
+ called_method->GetReturnTypeDescriptor());
work_line_->SetResultRegisterType(return_type);
just_set_result = true;
}
@@ -2401,7 +2402,9 @@
bool is_range = (dec_insn.opcode_ == Instruction::INVOKE_STATIC_RANGE);
Method* called_method = VerifyInvocationArgs(dec_insn, METHOD_STATIC, is_range, false);
if (failure_ == VERIFY_ERROR_NONE) {
- const RegType& return_type = reg_types_.FromClass(called_method->GetReturnType());
+ const RegType& return_type =
+ reg_types_.FromDescriptor(called_method->GetDeclaringClass()->GetClassLoader(),
+ called_method->GetReturnTypeDescriptor());
work_line_->SetResultRegisterType(return_type);
just_set_result = true;
}
@@ -2445,7 +2448,9 @@
* We don't have an object instance, so we can't find the concrete method. However, all of
* the type information is in the abstract method, so we're good.
*/
- const RegType& return_type = reg_types_.FromClass(abs_method->GetReturnType());
+ const RegType& return_type =
+ reg_types_.FromDescriptor(abs_method->GetDeclaringClass()->GetClassLoader(),
+ abs_method->GetReturnTypeDescriptor());
work_line_->SetResultRegisterType(return_type);
just_set_result = true;
}
@@ -3057,11 +3062,10 @@
return NULL;
}
if (method_type != METHOD_INTERFACE && !actual_arg_type.IsZero()) {
- Class* actual_this_ref = actual_arg_type.GetClass();
- if (!res_method->GetDeclaringClass()->IsAssignableFrom(actual_this_ref)) {
- Fail(VERIFY_ERROR_GENERIC) << "'this' arg '"
- << PrettyDescriptor(actual_this_ref->GetDescriptor()) << "' not instance of '"
- << PrettyDescriptor(res_method->GetDeclaringClass()->GetDescriptor()) << "'";
+ const RegType& res_method_class = reg_types_.FromClass(res_method->GetDeclaringClass());
+ if (!res_method_class.IsAssignableFrom(actual_arg_type)) {
+ Fail(VERIFY_ERROR_GENERIC) << "'this' arg '" << actual_arg_type << "' not instance of '"
+ << res_method_class << "'";
return NULL;
}
}