ART: Rerun the verifier for compile-time failures
To aid app failure diagnosis, by default re-run the verifier at
runtime to compute a better VerifyError message.
Rewrite the verifier driver code to pass the last actual low-level
verifier message.
Bug: 25432718
Change-Id: Ib8e6dd1ce8121045c0d38f54969100094c3dde6e
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 5dac95d..aae2d70 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2910,21 +2910,18 @@
const DexFile& dex_file = *klass->GetDexCache()->GetDexFile();
mirror::Class::Status oat_file_class_status(mirror::Class::kStatusNotReady);
bool preverified = VerifyClassUsingOatFile(dex_file, klass.Get(), oat_file_class_status);
- if (oat_file_class_status == mirror::Class::kStatusError) {
- VLOG(class_linker) << "Skipping runtime verification of erroneous class "
- << PrettyDescriptor(klass.Get()) << " in "
- << klass->GetDexCache()->GetLocation()->ToModifiedUtf8();
- ThrowVerifyError(klass.Get(), "Rejecting class %s because it failed compile-time verification",
- PrettyDescriptor(klass.Get()).c_str());
- mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self);
- return;
- }
+ // If the oat file says the class had an error, re-run the verifier. That way we will get a
+ // precise error message. To ensure a rerun, test:
+ // oat_file_class_status == mirror::Class::kStatusError => !preverified
+ DCHECK(!(oat_file_class_status == mirror::Class::kStatusError) || !preverified);
+
verifier::MethodVerifier::FailureKind verifier_failure = verifier::MethodVerifier::kNoFailure;
std::string error_msg;
if (!preverified) {
verifier_failure = verifier::MethodVerifier::VerifyClass(self,
klass.Get(),
Runtime::Current()->IsAotCompiler(),
+ Runtime::Current()->IsAotCompiler(),
&error_msg);
}
if (preverified || verifier_failure != verifier::MethodVerifier::kHardFailure) {
@@ -2962,9 +2959,9 @@
}
}
} else {
- LOG(WARNING) << "Verification failed on class " << PrettyDescriptor(klass.Get())
- << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8()
- << " because: " << error_msg;
+ VLOG(verifier) << "Verification failed on class " << PrettyDescriptor(klass.Get())
+ << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8()
+ << " because: " << error_msg;
self->AssertNoPendingException();
ThrowVerifyError(klass.Get(), "%s", error_msg.c_str());
mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self);