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