diff options
Diffstat (limited to 'runtime')
| -rw-r--r-- | runtime/class_loader_context.cc | 58 | ||||
| -rw-r--r-- | runtime/class_loader_context.h | 17 | ||||
| -rw-r--r-- | runtime/debug_print.cc | 39 |
3 files changed, 84 insertions, 30 deletions
diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc index e646520f3d..4afc44cb91 100644 --- a/runtime/class_loader_context.cc +++ b/runtime/class_loader_context.cc @@ -254,6 +254,7 @@ bool ClassLoaderContext::OpenDexFiles(InstructionSet isa, const std::string& cla // This will allow the context to VerifyClassLoaderContextMatch which expects or multidex // location in the class paths. // Note that this will also remove the paths that could not be opened. + info.original_classpath = std::move(info.classpath); info.classpath.clear(); info.checksums.clear(); for (size_t k = opened_dex_files_index; k < info.opened_dex_files.size(); k++) { @@ -294,20 +295,26 @@ bool ClassLoaderContext::RemoveLocationsFromClassPaths( } std::string ClassLoaderContext::EncodeContextForDex2oat(const std::string& base_dir) const { - return EncodeContext(base_dir, /*for_dex2oat*/ true); + return EncodeContext(base_dir, /*for_dex2oat*/ true, /*stored_context*/ nullptr); } -std::string ClassLoaderContext::EncodeContextForOatFile(const std::string& base_dir) const { - return EncodeContext(base_dir, /*for_dex2oat*/ false); +std::string ClassLoaderContext::EncodeContextForOatFile(const std::string& base_dir, + ClassLoaderContext* stored_context) const { + return EncodeContext(base_dir, /*for_dex2oat*/ false, stored_context); } std::string ClassLoaderContext::EncodeContext(const std::string& base_dir, - bool for_dex2oat) const { + bool for_dex2oat, + ClassLoaderContext* stored_context) const { CheckDexFilesOpened("EncodeContextForOatFile"); if (special_shared_library_) { return OatFile::kSpecialSharedLibrary; } + if (stored_context != nullptr) { + DCHECK_EQ(class_loader_chain_.size(), stored_context->class_loader_chain_.size()); + } + std::ostringstream out; if (class_loader_chain_.empty()) { // We can get in this situation if the context was created with a class path containing the @@ -326,6 +333,15 @@ std::string ClassLoaderContext::EncodeContext(const std::string& base_dir, out << GetClassLoaderTypeName(info.type); out << kClassLoaderOpeningMark; std::set<std::string> seen_locations; + SafeMap<std::string, std::string> remap; + if (stored_context != nullptr) { + DCHECK_EQ(info.original_classpath.size(), + stored_context->class_loader_chain_[i].classpath.size()); + for (size_t k = 0; k < info.original_classpath.size(); ++k) { + // Note that we don't care if the same name appears twice. + remap.Put(info.original_classpath[k], stored_context->class_loader_chain_[i].classpath[k]); + } + } for (size_t k = 0; k < info.opened_dex_files.size(); k++) { const std::unique_ptr<const DexFile>& dex_file = info.opened_dex_files[k]; if (for_dex2oat) { @@ -337,7 +353,14 @@ std::string ClassLoaderContext::EncodeContext(const std::string& base_dir, continue; } } - const std::string& location = dex_file->GetLocation(); + std::string location = dex_file->GetLocation(); + // If there is a stored class loader remap, fix up the multidex strings. + if (!remap.empty()) { + std::string base_dex_location = DexFileLoader::GetBaseLocation(location); + auto it = remap.find(base_dex_location); + CHECK(it != remap.end()) << base_dex_location; + location = it->second + DexFileLoader::GetMultiDexSuffix(location); + } if (k > 0) { out << kClasspathSeparator; } @@ -345,7 +368,7 @@ std::string ClassLoaderContext::EncodeContext(const std::string& base_dir, if (!base_dir.empty() && location.substr(0, base_dir.length()) == base_dir) { out << location.substr(base_dir.length() + 1).c_str(); } else { - out << dex_file->GetLocation().c_str(); + out << location.c_str(); } // dex2oat does not need the checksums. if (!for_dex2oat) { @@ -649,12 +672,16 @@ static bool IsAbsoluteLocation(const std::string& location) { return !location.empty() && location[0] == '/'; } -bool ClassLoaderContext::VerifyClassLoaderContextMatch(const std::string& context_spec) const { - DCHECK(dex_files_open_attempted_); - DCHECK(dex_files_open_result_); +bool ClassLoaderContext::VerifyClassLoaderContextMatch(const std::string& context_spec, + bool verify_names, + bool verify_checksums) const { + if (verify_names || verify_checksums) { + DCHECK(dex_files_open_attempted_); + DCHECK(dex_files_open_result_); + } ClassLoaderContext expected_context; - if (!expected_context.Parse(context_spec, /*parse_checksums*/ true)) { + if (!expected_context.Parse(context_spec, verify_checksums)) { LOG(WARNING) << "Invalid class loader context: " << context_spec; return false; } @@ -693,8 +720,14 @@ bool ClassLoaderContext::VerifyClassLoaderContextMatch(const std::string& contex return false; } - DCHECK_EQ(info.classpath.size(), info.checksums.size()); - DCHECK_EQ(expected_info.classpath.size(), expected_info.checksums.size()); + if (verify_checksums) { + DCHECK_EQ(info.classpath.size(), info.checksums.size()); + DCHECK_EQ(expected_info.classpath.size(), expected_info.checksums.size()); + } + + if (!verify_names) { + continue; + } for (size_t k = 0; k < info.classpath.size(); k++) { // Compute the dex location that must be compared. @@ -766,4 +799,3 @@ jclass ClassLoaderContext::GetClassLoaderClass(ClassLoaderType type) { } } // namespace art - diff --git a/runtime/class_loader_context.h b/runtime/class_loader_context.h index 692a6cda5b..1c83007f41 100644 --- a/runtime/class_loader_context.h +++ b/runtime/class_loader_context.h @@ -84,9 +84,12 @@ class ClassLoaderContext { // (so that it can be read and verified at runtime against the actual class // loader hierarchy). // Should only be called if OpenDexFiles() returned true. + // If stored context is non-null, the stored names are overwritten by the class path from the + // stored context. // E.g. if the context is PCL[a.dex:b.dex] this will return // "PCL[a.dex*a_checksum*b.dex*a_checksum]". - std::string EncodeContextForOatFile(const std::string& base_dir) const; + std::string EncodeContextForOatFile(const std::string& base_dir, + ClassLoaderContext* stored_context = nullptr) const; // Encodes the context as a string suitable to be passed to dex2oat. // This is the same as EncodeContextForOatFile but without adding the checksums @@ -104,7 +107,11 @@ class ClassLoaderContext { // - the class loader from the same position have the same classpath // (the order and checksum of the dex files matches) // This should be called after OpenDexFiles(). - bool VerifyClassLoaderContextMatch(const std::string& context_spec) const; + // Names are only verified if verify_names is true. + // Checksums are only verified if verify_checksums is true. + bool VerifyClassLoaderContextMatch(const std::string& context_spec, + bool verify_names = true, + bool verify_checksums = true) const; // Creates the class loader context from the given string. // The format: ClassLoaderType1[ClasspathElem1:ClasspathElem2...];ClassLoaderType2[...]... @@ -146,6 +153,8 @@ class ClassLoaderContext { // The list of class path elements that this loader loads. // Note that this list may contain relative paths. std::vector<std::string> classpath; + // Original opened class path (ignoring multidex). + std::vector<std::string> original_classpath; // The list of class path elements checksums. // May be empty if the checksums are not given when the context is created. std::vector<uint32_t> checksums; @@ -198,7 +207,9 @@ class ClassLoaderContext { // location). Otherwise, for oat files, the encoding adds all the dex files (including multidex) // together with their checksums. // Should only be called if OpenDexFiles() returned true. - std::string EncodeContext(const std::string& base_dir, bool for_dex2oat) const; + std::string EncodeContext(const std::string& base_dir, + bool for_dex2oat, + ClassLoaderContext* stored_context) const; // Extracts the class loader type from the given spec. // Return ClassLoaderContext::kInvalidClassLoader if the class loader type is not diff --git a/runtime/debug_print.cc b/runtime/debug_print.cc index 60487670ac..7e075ce352 100644 --- a/runtime/debug_print.cc +++ b/runtime/debug_print.cc @@ -97,14 +97,27 @@ std::string DescribeLoaders(ObjPtr<mirror::ClassLoader> loader, const char* clas StackHandleScope<1> hs(soa.Self()); Handle<mirror::ClassLoader> handle(hs.NewHandle(loader)); const char* path_separator = ""; - VisitClassLoaderDexFiles(soa, - handle, - [&](const DexFile* dex_file) { - oss << path_separator << dex_file->GetLocation() - << "/" << static_cast<const void*>(dex_file); - path_separator = ":"; - return true; // Continue with the next DexFile. - }); + const DexFile* base_dex_file = nullptr; + VisitClassLoaderDexFiles( + soa, + handle, + [&](const DexFile* dex_file) { + oss << path_separator; + path_separator = ":"; + if (base_dex_file != nullptr && + dex_file->GetLocation().length() > base_dex_file->GetLocation().length() && + dex_file->GetLocation().compare(0u, + base_dex_file->GetLocation().length(), + base_dex_file->GetLocation()) == 0) { + // Replace the base location with "+" to shorten the output. + oss << "+" << dex_file->GetLocation().substr(base_dex_file->GetLocation().length()); + } else { + oss << dex_file->GetLocation(); + base_dex_file = dex_file; + } + oss << "/" << static_cast<const void*>(dex_file); + return true; // Continue with the next DexFile. + }); oss << ")"; } } @@ -132,13 +145,13 @@ void DumpB77342775DebugData(ObjPtr<mirror::Class> target_class, ObjPtr<mirror::C std::string source_descriptor_storage; const char* source_descriptor = src_class->GetDescriptor(&source_descriptor_storage); + LOG(ERROR) << "Maybe bug 77342775, looking for " << target_descriptor + << " with loader " << DescribeLoaders(target_class->GetClassLoader(), target_descriptor); if (target_class->IsInterface()) { ObjPtr<mirror::IfTable> iftable = src_class->GetIfTable(); CHECK(iftable != nullptr); size_t ifcount = iftable->Count(); - LOG(ERROR) << "Maybe bug 77342775, looking for " << target_descriptor - << " with loader " << DescribeLoaders(target_class->GetClassLoader(), target_descriptor) - << " in interface table for " << source_descriptor << " ifcount=" << ifcount + LOG(ERROR) << " in interface table for " << source_descriptor << " ifcount=" << ifcount << " with loader " << DescribeLoaders(src_class->GetClassLoader(), source_descriptor); for (size_t i = 0; i != ifcount; ++i) { ObjPtr<mirror::Class> iface = iftable->GetInterface(i); @@ -147,9 +160,7 @@ void DumpB77342775DebugData(ObjPtr<mirror::Class> target_class, ObjPtr<mirror::C matcher(iface); } } else { - LOG(ERROR) << "Maybe bug 77342775, looking for " << target_descriptor - << " with loader " << DescribeLoaders(target_class->GetClassLoader(), target_descriptor) - << " in superclass chain for " << source_descriptor + LOG(ERROR) << " in superclass chain for " << source_descriptor << " with loader " << DescribeLoaders(src_class->GetClassLoader(), source_descriptor); for (ObjPtr<mirror::Class> klass = src_class; klass != nullptr; |