Open only necessary files for BCP checksums test.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: aosp_taimen-userdebug boots.
Bug: 128479972
Change-Id: I13040acb5603d9207c2aaaa51ffd2fc7d3de1d82
diff --git a/runtime/dexopt_test.cc b/runtime/dexopt_test.cc
index 0624525..33f8c7f 100644
--- a/runtime/dexopt_test.cc
+++ b/runtime/dexopt_test.cc
@@ -120,7 +120,7 @@
EXPECT_EQ(filter, odex_file->GetCompilerFilter());
std::string boot_image_checksums = gc::space::ImageSpace::GetBootClassPathChecksums(
- Runtime::Current()->GetBootClassPath(),
+ ArrayRef<const std::string>(Runtime::Current()->GetBootClassPath()),
image_location,
kRuntimeISA,
gc::space::ImageSpaceLoadingOrder::kSystemFirst,
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 5ebd4b3..b10c9801 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -2181,7 +2181,7 @@
return true;
}
-std::string ImageSpace::GetBootClassPathChecksums(const std::vector<std::string>& boot_class_path,
+std::string ImageSpace::GetBootClassPathChecksums(ArrayRef<const std::string> boot_class_path,
const std::string& image_location,
InstructionSet image_isa,
ImageSpaceLoadingOrder order,
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index a3a9557..e27810d 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -135,7 +135,7 @@
// Returns the checksums for the boot image and extra boot class path dex files,
// based on the boot class path, image location and ISA (may differ from the ISA of an
// initialized Runtime). The boot image and dex files do not need to be loaded in memory.
- static std::string GetBootClassPathChecksums(const std::vector<std::string>& boot_class_path,
+ static std::string GetBootClassPathChecksums(ArrayRef<const std::string> boot_class_path,
const std::string& image_location,
InstructionSet image_isa,
ImageSpaceLoadingOrder order,
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 5529434..f122e57 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -28,6 +28,7 @@
#include "base/macros.h"
#include "base/os.h"
#include "base/stl_util.h"
+#include "base/string_view_cpp20.h"
#include "base/utils.h"
#include "class_linker.h"
#include "compiler_filter.h"
@@ -405,23 +406,7 @@
// Verify the image checksum
if (CompilerFilter::DependsOnImageChecksum(current_compiler_filter)) {
- const ImageInfo* image_info = GetImageInfo();
- if (image_info == nullptr) {
- VLOG(oat) << "No image for oat image checksum to match against.";
-
- if (HasOriginalDexFiles()) {
- return kOatBootImageOutOfDate;
- }
-
- // If there is no original dex file to fall back to, grudgingly accept
- // the oat file. This could technically lead to crashes, but there's no
- // way we could find a better oat file to use for this dex location,
- // and it's better than being stuck in a boot loop with no way out.
- // The problem will hopefully resolve itself the next time the runtime
- // starts up.
- LOG(WARNING) << "Dex location " << dex_location_ << " does not seem to include dex file. "
- << "Allow oat file use. This is potentially dangerous.";
- } else if (!image_info->ValidateBootClassPathChecksums(file)) {
+ if (!ValidateBootClassPathChecksums(file)) {
VLOG(oat) << "Oat image checksum does not match image checksum.";
return kOatBootImageOutOfDate;
}
@@ -562,51 +547,79 @@
return required_dex_checksums_found_ ? &cached_required_dex_checksums_ : nullptr;
}
-bool OatFileAssistant::ImageInfo::ValidateBootClassPathChecksums(const OatFile& oat_file) const {
+bool OatFileAssistant::ValidateBootClassPathChecksums(const OatFile& oat_file) {
+ // Get the BCP from the oat file.
+ const char* oat_boot_class_path =
+ oat_file.GetOatHeader().GetStoreValueByKey(OatHeader::kBootClassPathKey);
+ if (oat_boot_class_path == nullptr) {
+ return false;
+ }
+
+ // Check that the oat BCP is a prefix of current BCP locations and count components.
+ Runtime* runtime = Runtime::Current();
+ size_t component_count = 0u;
+ std::string_view remaining_bcp(oat_boot_class_path);
+ bool bcp_ok = false;
+ for (const std::string& location : runtime->GetBootClassPathLocations()) {
+ if (!StartsWith(remaining_bcp, location)) {
+ break;
+ }
+ remaining_bcp.remove_prefix(location.size());
+ ++component_count;
+ if (remaining_bcp.empty()) {
+ bcp_ok = true;
+ break;
+ }
+ if (!StartsWith(remaining_bcp, ":")) {
+ break;
+ }
+ remaining_bcp.remove_prefix(1u);
+ }
+ if (!bcp_ok) {
+ return false;
+ }
+
+ // Get the checksums.
const char* oat_boot_class_path_checksums =
oat_file.GetOatHeader().GetStoreValueByKey(OatHeader::kBootClassPathChecksumsKey);
if (oat_boot_class_path_checksums == nullptr) {
return false;
}
- // The checksums can be either the same or a prefix of the expected checksums,
- // ending before the ':' delimiter.
- size_t length = strlen(oat_boot_class_path_checksums);
- if (length > boot_class_path_checksums.length() ||
- (length < boot_class_path_checksums.length() && boot_class_path_checksums[length] != ':')) {
- return false;
- }
- return boot_class_path_checksums.compare(0u, length, oat_boot_class_path_checksums) == 0;
-}
-std::unique_ptr<OatFileAssistant::ImageInfo>
-OatFileAssistant::ImageInfo::GetRuntimeImageInfo(InstructionSet isa, std::string* error_msg) {
- CHECK(error_msg != nullptr);
-
- Runtime* runtime = Runtime::Current();
- std::unique_ptr<ImageInfo> info(new ImageInfo());
- info->location = runtime->GetImageLocation();
- info->boot_class_path_checksums = gc::space::ImageSpace::GetBootClassPathChecksums(
- runtime->GetBootClassPath(),
- info->location,
- isa,
- runtime->GetImageSpaceLoadingOrder(),
- error_msg);
- if (info->boot_class_path_checksums.empty()) {
- return nullptr;
- }
- return info;
-}
-
-const OatFileAssistant::ImageInfo* OatFileAssistant::GetImageInfo() {
- if (!image_info_load_attempted_) {
- image_info_load_attempted_ = true;
+ // Retrieve checksums for this portion of the BCP if we do not have them cached.
+ if (cached_boot_class_path_checksum_component_count_ != component_count) {
+ ArrayRef<const std::string> boot_class_path(runtime->GetBootClassPath());
std::string error_msg;
- cached_image_info_ = ImageInfo::GetRuntimeImageInfo(isa_, &error_msg);
- if (cached_image_info_ == nullptr) {
- LOG(WARNING) << "Unable to get runtime image info: " << error_msg;
+ std::string boot_class_path_checksums = gc::space::ImageSpace::GetBootClassPathChecksums(
+ boot_class_path.SubArray(/* pos= */ 0u, component_count),
+ runtime->GetImageLocation(),
+ isa_,
+ runtime->GetImageSpaceLoadingOrder(),
+ &error_msg);
+ if (boot_class_path_checksums.empty()) {
+ VLOG(oat) << "No image for oat image checksum to match against.";
+
+ if (HasOriginalDexFiles()) {
+ return false;
+ }
+
+ // If there is no original dex file to fall back to, grudgingly accept
+ // the oat file. This could technically lead to crashes, but there's no
+ // way we could find a better oat file to use for this dex location,
+ // and it's better than being stuck in a boot loop with no way out.
+ // The problem will hopefully resolve itself the next time the runtime
+ // starts up.
+ LOG(WARNING) << "Dex location " << dex_location_ << " does not seem to include dex file. "
+ << "Allow oat file use. This is potentially dangerous.";
+
+ return true;
}
+ cached_boot_class_path_checksum_component_count_ = component_count;
+ cached_boot_class_path_checksums_ = boot_class_path_checksums;
}
- return cached_image_info_.get();
+
+ // Compare the checksums.
+ return cached_boot_class_path_checksums_ == oat_boot_class_path_checksums;
}
OatFileAssistant::OatFileInfo& OatFileAssistant::GetBestInfo() {
diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h
index 85e5917..83ae3cb 100644
--- a/runtime/oat_file_assistant.h
+++ b/runtime/oat_file_assistant.h
@@ -246,16 +246,6 @@
std::string* error_msg);
private:
- struct ImageInfo {
- bool ValidateBootClassPathChecksums(const OatFile& oat_file) const;
-
- std::string location;
- std::string boot_class_path_checksums;
-
- static std::unique_ptr<ImageInfo> GetRuntimeImageInfo(InstructionSet isa,
- std::string* error_msg);
- };
-
class OatFileInfo {
public:
// Initially the info is for no file in particular. It will treat the
@@ -395,11 +385,8 @@
// dex_location_ dex file.
const std::vector<uint32_t>* GetRequiredDexChecksums();
- // Returns the loaded image info.
- // Loads the image info if needed. Returns null if the image info failed
- // to load.
- // The caller shouldn't clean up or free the returned pointer.
- const ImageInfo* GetImageInfo();
+ // Validates the boot class path checksum of an OatFile.
+ bool ValidateBootClassPathChecksums(const OatFile& oat_file);
// To implement Lock(), we lock a dummy file where the oat file would go
// (adding ".flock" to the target file name) and retain the lock for the
@@ -437,12 +424,8 @@
// File descriptor corresponding to apk, dex file, or zip.
int zip_fd_;
- // Cached value of the image info.
- // Use the GetImageInfo method rather than accessing these directly.
- // TODO: The image info should probably be moved out of the oat file
- // assistant to an image file manager.
- bool image_info_load_attempted_ = false;
- std::unique_ptr<ImageInfo> cached_image_info_;
+ size_t cached_boot_class_path_checksum_component_count_ = 0u;
+ std::string cached_boot_class_path_checksums_;
friend class OatFileAssistantTest;