Generalize vdex class redefinition check
The check introduced in CL If0c56b1970d8ebe701d198ffccec52f586aea9e6
skips fast verification if an apk's class is overshadowed by a class in
boot classpath because the vdex dependencies do not contain intra-apk
dependencies.
However, the change only checks for presence of a duplicate class in the
boot classloader, while a duplicate class could be in any of the parent
classloaders. Fix this and move the check into VerifierDeps to make it
a proper part of the verification process.
The CL also refactors VerifierDeps::ValidateDependencies to output
an error string for better logging.
Bug: 122968669
Test: test/testrunner/testrunner.py -t 719
Test: m test-art-gtest-verifier_deps_test
Change-Id: I0d06b82e31088c58d4493723a5435309740f1d0c
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index d46cffb..bfa039e 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -1765,42 +1765,6 @@
}
}
-// Returns true if any of the given dex files define a class from the boot classpath.
-static bool DexFilesRedefineBootClasses(
- const std::vector<const DexFile*>& dex_files,
- TimingLogger* timings) {
- TimingLogger::ScopedTiming t("Fast Verify: Boot Class Redefinition Check", timings);
-
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- Thread* self = Thread::Current();
- ScopedObjectAccess soa(self);
-
- bool foundRedefinition = false;
- for (const DexFile* dex_file : dex_files) {
- for (ClassAccessor accessor : dex_file->GetClasses()) {
- const char* descriptor = accessor.GetDescriptor();
- StackHandleScope<1> hs_class(self);
- Handle<mirror::Class> klass =
- hs_class.NewHandle(class_linker->FindSystemClass(self, descriptor));
- if (klass == nullptr) {
- self->ClearException();
- } else {
- LOG(WARNING) << "Redefinition of boot class " << descriptor
- << " App dex file: " << accessor.GetDexFile().GetLocation()
- << " Boot dex file: " << klass->GetDexFile().GetLocation();
- foundRedefinition = true;
- if (!VLOG_IS_ON(verifier)) {
- // If we are not in verbose mode, return early.
- // Otherwise continue and log all the collisions for easier debugging.
- return true;
- }
- }
- }
- }
-
- return foundRedefinition;
-}
-
bool CompilerDriver::FastVerify(jobject jclass_loader,
const std::vector<const DexFile*>& dex_files,
TimingLogger* timings,
@@ -1813,21 +1777,14 @@
}
TimingLogger::ScopedTiming t("Fast Verify", timings);
- // We cannot do fast verification if the app redefines classes from the boot classpath.
- // Vdex does not record resolution chains for boot classes and we might wrongfully
- // resolve a class to the app when it should have been resolved to the boot classpath
- // (e.g. if we verified against the SDK and the app redefines a boot class which is not
- // in the SDK.)
- if (DexFilesRedefineBootClasses(dex_files, timings)) {
- LOG(WARNING) << "Found redefinition of boot classes. Not doing fast verification.";
- return false;
- }
-
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<2> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
- if (!verifier_deps->ValidateDependencies(class_loader, soa.Self())) {
+ std::string error_msg;
+
+ if (!verifier_deps->ValidateDependencies(class_loader, soa.Self(), &error_msg)) {
+ LOG(WARNING) << "Fast verification failed: " << error_msg;
return false;
}