Add arg for overwriting class loader class path
Added stored_context srgument to EncodeContextForOatFile that
overwrites the class path when non-null.
This is used by the --stored-class-loader-context argument. Fixed
the test.
Bug: 70934104
Bug: 67345922
Test: test-art-host-gtest
Change-Id: If877d8cfe9d34eeaa941e9f6df2e12539d9c4a6f
diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc
index 216ad8f..4afc44c 100644
--- a/runtime/class_loader_context.cc
+++ b/runtime/class_loader_context.cc
@@ -254,6 +254,7 @@
// 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 @@
}
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 @@
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 @@
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 @@
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) {
@@ -776,4 +799,3 @@
}
} // namespace art
-
diff --git a/runtime/class_loader_context.h b/runtime/class_loader_context.h
index 231acc4..1c83007 100644
--- a/runtime/class_loader_context.h
+++ b/runtime/class_loader_context.h
@@ -84,9 +84,12 @@
// (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
@@ -150,6 +153,8 @@
// 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;
@@ -202,7 +207,9 @@
// 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