summaryrefslogtreecommitdiff
path: root/runtime/oat_file_assistant.cc
diff options
context:
space:
mode:
author David Srbecky <dsrbecky@google.com> 2023-06-15 15:48:20 +0100
committer Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2023-07-03 10:52:06 +0000
commitfdfa590b7b43ca70e497f1a8afe9a641b57ece56 (patch)
tree6054b4e9ae772c2f135fedde6be62864206ddcad /runtime/oat_file_assistant.cc
parent2f8499ef214f9eadb75b36eab43214842f4da64b (diff)
Reduce multidex checksum to single scalar value.
Change GetMultiDexChecksums to return a single value rather than a vector. The single checksum represents the whole multidex set, and will change if any dex file within the multidex set changes. Fundamentally, we need a value to represent a .zip/.jar archive, so that we can check whether our build artifacts are up to date. We previously used a vector of CRC32 values (one per dex file), however, one combined checksum per archive is also sufficient. This is necessary, since the future multidex format will have single zip entry, so we need to adjust the code to expect just one checksum per zip file. This separates the change to own CL. The two sides of the checksum comparison are trivially reduced: * Zip files are reduced by XORing the individual CRC values. * Likewise, checksums of already open DexFiles are XORed. As a consequence, ClassLoader path needs to be reduced to print only single checksum per jar file as well. Bug: 266950186 Test: ./art/test.py -b --host Change-Id: I848aee1e4836e87945a5172c7594e266739451e9
Diffstat (limited to 'runtime/oat_file_assistant.cc')
-rw-r--r--runtime/oat_file_assistant.cc82
1 files changed, 42 insertions, 40 deletions
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 9e16e49e40..cbbb31cd4f 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -453,11 +453,11 @@ bool OatFileAssistant::LoadDexFiles(const OatFile& oat_file,
std::optional<bool> OatFileAssistant::HasDexFiles(std::string* error_msg) {
ScopedTrace trace("HasDexFiles");
- const std::vector<std::uint32_t>* checksums = GetRequiredDexChecksums(error_msg);
- if (checksums == nullptr) {
+ std::optional<std::uint32_t> checksum;
+ if (!GetRequiredDexChecksum(&checksum, error_msg)) {
return std::nullopt;
}
- return !checksums->empty();
+ return checksum.has_value();
}
OatFileAssistant::OatStatus OatFileAssistant::OdexFileStatus() { return odex_.Status(); }
@@ -471,37 +471,35 @@ bool OatFileAssistant::DexChecksumUpToDate(const OatFile& file, std::string* err
return true;
}
ScopedTrace trace("DexChecksumUpToDate");
- const std::vector<uint32_t>* required_dex_checksums = GetRequiredDexChecksums(error_msg);
- if (required_dex_checksums == nullptr) {
+ std::optional<std::uint32_t> dex_checksum;
+ if (!GetRequiredDexChecksum(&dex_checksum, error_msg)) {
return false;
}
- if (required_dex_checksums->empty()) {
+ if (!dex_checksum.has_value()) {
LOG(WARNING) << "Required dex checksums not found. Assuming dex checksums are up to date.";
return true;
}
+ std::vector<const OatDexFile*> oat_dex_files;
uint32_t number_of_dex_files = file.GetOatHeader().GetDexFileCount();
- if (required_dex_checksums->size() != number_of_dex_files) {
- *error_msg = StringPrintf(
- "expected %zu dex files but found %u", required_dex_checksums->size(), number_of_dex_files);
- return false;
- }
-
for (uint32_t i = 0; i < number_of_dex_files; i++) {
std::string dex = DexFileLoader::GetMultiDexLocation(i, dex_location_.c_str());
- uint32_t expected_checksum = (*required_dex_checksums)[i];
const OatDexFile* oat_dex_file = file.GetOatDexFile(dex.c_str(), nullptr);
if (oat_dex_file == nullptr) {
*error_msg = StringPrintf("failed to find %s in %s", dex.c_str(), file.GetLocation().c_str());
return false;
}
- uint32_t actual_checksum = oat_dex_file->GetDexFileLocationChecksum();
- if (expected_checksum != actual_checksum) {
- VLOG(oat) << "Dex checksum does not match for dex: " << dex
- << ". Expected: " << expected_checksum << ", Actual: " << actual_checksum;
- return false;
- }
+ oat_dex_files.push_back(oat_dex_file);
}
+ uint32_t oat_checksum = DexFileLoader::GetMultiDexChecksum(oat_dex_files);
+
+ CHECK(dex_checksum.has_value());
+ if (dex_checksum != oat_checksum) {
+ VLOG(oat) << "Checksum does not match: " << std::hex << file.GetLocation() << " ("
+ << oat_checksum << ") vs " << dex_location_ << " (" << *dex_checksum << ")";
+ return false;
+ }
+
return true;
}
@@ -718,33 +716,36 @@ bool OatFileAssistant::DexLocationToOatFilename(const std::string& location,
return GetDalvikCacheFilename(location.c_str(), dalvik_cache.c_str(), oat_filename, error_msg);
}
-const std::vector<uint32_t>* OatFileAssistant::GetRequiredDexChecksums(std::string* error_msg) {
+bool OatFileAssistant::GetRequiredDexChecksum(std::optional<uint32_t>* checksum,
+ std::string* error) {
if (!required_dex_checksums_attempted_) {
required_dex_checksums_attempted_ = true;
- std::vector<uint32_t> checksums;
- std::vector<std::string> dex_locations_ignored;
- if (ArtDexFileLoader::GetMultiDexChecksums(dex_location_.c_str(),
- &checksums,
- &dex_locations_ignored,
- &cached_required_dex_checksums_error_,
- zip_fd_,
- &zip_file_only_contains_uncompressed_dex_)) {
- if (checksums.empty()) {
- // The only valid case here is for APKs without dex files.
- VLOG(oat) << "No dex file found in " << dex_location_;
- }
- cached_required_dex_checksums_ = std::move(checksums);
+ ArtDexFileLoader dex_loader(zip_fd_, dex_location_);
+ std::optional<uint32_t> checksum2;
+ std::string error2;
+ if (dex_loader.GetMultiDexChecksum(
+ &checksum2, &error2, &zip_file_only_contains_uncompressed_dex_)) {
+ cached_required_dex_checksums_ = checksum2;
+ cached_required_dex_checksums_error_ = std::nullopt;
+ } else {
+ cached_required_dex_checksums_ = std::nullopt;
+ cached_required_dex_checksums_error_ = error2;
}
}
- if (cached_required_dex_checksums_.has_value()) {
- return &cached_required_dex_checksums_.value();
- } else {
- *error_msg = cached_required_dex_checksums_error_;
- DCHECK(!error_msg->empty());
- return nullptr;
+ if (cached_required_dex_checksums_error_.has_value()) {
+ *error = cached_required_dex_checksums_error_.value();
+ DCHECK(!error->empty());
+ return false;
+ }
+
+ if (!cached_required_dex_checksums_.has_value()) {
+ // The only valid case here is for APKs without dex files.
+ VLOG(oat) << "No dex file found in " << dex_location_;
}
+ *checksum = cached_required_dex_checksums_;
+ return true;
}
bool OatFileAssistant::ValidateBootClassPathChecksums(OatFileAssistantContext* ofa_context,
@@ -1380,8 +1381,9 @@ void OatFileAssistant::GetOptimizationStatus(std::string* out_odex_location,
bool OatFileAssistant::ZipFileOnlyContainsUncompressedDex() {
// zip_file_only_contains_uncompressed_dex_ is only set during fetching the dex checksums.
+ std::optional<uint32_t> checksum;
std::string error_msg;
- if (GetRequiredDexChecksums(&error_msg) == nullptr) {
+ if (!GetRequiredDexChecksum(&checksum, &error_msg)) {
LOG(ERROR) << error_msg;
}
return zip_file_only_contains_uncompressed_dex_;