summaryrefslogtreecommitdiff
path: root/compiler/driver/compiler_driver.cc
diff options
context:
space:
mode:
author Calin Juravle <calin@google.com> 2019-01-25 01:04:54 -0800
committer Calin Juravle <calin@google.com> 2019-01-31 14:24:04 -0800
commit5ffefaa41de9b9e711f6e8bc7ed9ff9e9d844fe7 (patch)
tree359584429e9ef94c848551180d2ad73fa61d618a /compiler/driver/compiler_driver.cc
parentb8f88f33b5ad0a593e5c63beab45d05f4c791bf4 (diff)
Ensure the correctness of fast verify
We cannot guarantee that the resolution recorded in the vdex file is correct when the boot classes are redefined. For example we might be doing only sdk verification and not have the entire context available - as such, if an app redefines a class that is in the boot classpath but not the sdk we might record the wrong resolution. Another example is OTA time, when the boot classpath may change. The CL discards the vdex file when the app redefines classes from boot classpath. Test: test/testrunner/testrunner.py -t 719 Bug: 122968669 Change-Id: If0c56b1970d8ebe701d198ffccec52f586aea9e6
Diffstat (limited to 'compiler/driver/compiler_driver.cc')
-rw-r--r--compiler/driver/compiler_driver.cc47
1 files changed, 47 insertions, 0 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index e440eec735..d46cffb1e8 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -1765,6 +1765,42 @@ static void LoadAndUpdateStatus(const ClassAccessor& accessor,
}
}
+// 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,
@@ -1776,6 +1812,17 @@ bool CompilerDriver::FastVerify(jobject jclass_loader,
return false;
}
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(