summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libdexfile/dex/dex_file_loader.cc31
-rw-r--r--libdexfile/dex/dex_file_loader.h10
-rw-r--r--profman/profman.cc81
3 files changed, 80 insertions, 42 deletions
diff --git a/libdexfile/dex/dex_file_loader.cc b/libdexfile/dex/dex_file_loader.cc
index d524dfceb1..e92a5ac813 100644
--- a/libdexfile/dex/dex_file_loader.cc
+++ b/libdexfile/dex/dex_file_loader.cc
@@ -161,12 +161,10 @@ std::string DexFileLoader::GetMultiDexLocation(size_t index, const char* dex_loc
return StringPrintf("%s%cclasses%zu.dex", dex_location, kMultiDexSeparator, index + 1);
}
-bool DexFileLoader::GetMultiDexChecksum(std::optional<uint32_t>* checksum,
- std::string* error_msg,
- bool* only_contains_uncompressed_dex) {
- CHECK(checksum != nullptr);
- checksum->reset(); // Return nullopt for an empty zip archive.
-
+bool DexFileLoader::GetMultiDexChecksums(
+ /*out*/ std::vector<std::pair<std::string, uint32_t>>* checksums,
+ /*out*/ std::string* error_msg,
+ /*out*/ bool* only_contains_uncompressed_dex) {
uint32_t magic;
if (!InitAndReadMagic(/*header_offset=*/0, &magic, error_msg)) {
return false;
@@ -196,7 +194,7 @@ bool DexFileLoader::GetMultiDexChecksum(std::optional<uint32_t>* checksum,
*only_contains_uncompressed_dex = false;
}
}
- *checksum = checksum->value_or(kEmptyMultiDexChecksum) ^ zip_entry->GetCrc32();
+ checksums->emplace_back(GetMultiDexLocation(i, location_.c_str()), zip_entry->GetCrc32());
}
return true;
}
@@ -205,6 +203,7 @@ bool DexFileLoader::GetMultiDexChecksum(std::optional<uint32_t>* checksum,
}
const uint8_t* begin = root_container_->Begin();
const uint8_t* end = root_container_->End();
+ size_t i = 0;
for (const uint8_t* ptr = begin; ptr < end;) {
const auto* header = reinterpret_cast<const DexFile::Header*>(ptr);
size_t size = dchecked_integral_cast<size_t>(end - ptr);
@@ -216,12 +215,28 @@ bool DexFileLoader::GetMultiDexChecksum(std::optional<uint32_t>* checksum,
*error_msg = StringPrintf("Truncated dex file: '%s'", filename_.c_str());
return false;
}
- *checksum = checksum->value_or(kEmptyMultiDexChecksum) ^ header->checksum_;
+ checksums->emplace_back(GetMultiDexLocation(i++, location_.c_str()), header->checksum_);
ptr += header->file_size_;
}
return true;
}
+bool DexFileLoader::GetMultiDexChecksum(std::optional<uint32_t>* checksum,
+ std::string* error_msg,
+ bool* only_contains_uncompressed_dex) {
+ CHECK(checksum != nullptr);
+ checksum->reset(); // Return nullopt for an empty zip archive.
+
+ std::vector<std::pair<std::string, uint32_t>> checksums;
+ if (!GetMultiDexChecksums(&checksums, error_msg, only_contains_uncompressed_dex)) {
+ return false;
+ }
+ for (const auto& [location, current_checksum] : checksums) {
+ *checksum = checksum->value_or(kEmptyMultiDexChecksum) ^ current_checksum;
+ }
+ return true;
+}
+
std::string DexFileLoader::GetDexCanonicalLocation(const char* dex_location) {
CHECK_NE(dex_location, static_cast<const char*>(nullptr));
std::string base_location = GetBaseLocation(dex_location);
diff --git a/libdexfile/dex/dex_file_loader.h b/libdexfile/dex/dex_file_loader.h
index 9b5f7d56cd..1c7348214f 100644
--- a/libdexfile/dex/dex_file_loader.h
+++ b/libdexfile/dex/dex_file_loader.h
@@ -23,6 +23,7 @@
#include <optional>
#include <string>
#include <string_view>
+#include <utility>
#include <vector>
#include "base/os.h"
@@ -72,6 +73,15 @@ class DexFileLoader {
// index == 0, and dex_location + multi-dex-separator + GetMultiDexClassesDexName(index) else.
static std::string GetMultiDexLocation(size_t index, const char* dex_location);
+ // Returns the multidex location and the checksum for each dex file in a zip or a dex container.
+ //
+ // This uses the source path provided to DexFileLoader constructor.
+ //
+ // Returns false on error.
+ bool GetMultiDexChecksums(/*out*/ std::vector<std::pair<std::string, uint32_t>>* checksums,
+ /*out*/ std::string* error_msg,
+ /*out*/ bool* only_contains_uncompressed_dex = nullptr);
+
// Returns combined checksum of one or more dex files (one checksum for the whole multidex set).
//
// This uses the source path provided to DexFileLoader constructor.
diff --git a/profman/profman.cc b/profman/profman.cc
index 2fcb2ef72b..19d480e233 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -562,13 +562,20 @@ class ProfMan final {
}
bool GetProfileFilterKeyFromApks(std::set<ProfileFilterKey>* profile_filter_keys) {
- auto process_fn = [profile_filter_keys](std::unique_ptr<const DexFile>&& dex_file) {
- // Store the profile key of the location instead of the location itself.
- // This will make the matching in the profile filter method much easier.
- profile_filter_keys->emplace(ProfileCompilationInfo::GetProfileDexFileBaseKey(
- dex_file->GetLocation()), dex_file->GetLocationChecksum());
- };
- return OpenApkFilesFromLocations(process_fn);
+ return ForEachApkFile([&](File file, const std::string& location) {
+ ArtDexFileLoader dex_file_loader(&file, location);
+ std::vector<std::pair<std::string, uint32_t>> checksums;
+ std::string error_msg;
+ if (!dex_file_loader.GetMultiDexChecksums(&checksums, &error_msg)) {
+ LOG(ERROR) << "Open failed for '" << location << "' " << error_msg;
+ return false;
+ }
+ for (const auto& [multi_dex_location, checksum] : checksums) {
+ profile_filter_keys->emplace(
+ ProfileCompilationInfo::GetProfileDexFileBaseKey(multi_dex_location), checksum);
+ }
+ return true;
+ });
}
bool OpenApkFilesFromLocations(std::vector<std::unique_ptr<const DexFile>>* dex_files) {
@@ -580,6 +587,32 @@ class ProfMan final {
bool OpenApkFilesFromLocations(
const std::function<void(std::unique_ptr<const DexFile>&&)>& process_fn) {
+ static constexpr bool kVerifyChecksum = true;
+ std::string error_msg;
+ std::vector<std::unique_ptr<const DexFile>> dex_files_for_location;
+ bool result = ForEachApkFile([&](File file, const std::string& location) {
+ ArtDexFileLoader dex_file_loader(&file, location);
+ if (!dex_file_loader.Open(/*verify=*/false,
+ kVerifyChecksum,
+ /*allow_no_dex_files=*/true,
+ &error_msg,
+ &dex_files_for_location)) {
+ LOG(ERROR) << "Open failed for '" << location << "' " << error_msg;
+ return false;
+ }
+ return true;
+ });
+ if (!result) {
+ return false;
+ }
+ for (std::unique_ptr<const DexFile>& dex_file : dex_files_for_location) {
+ process_fn(std::move(dex_file));
+ }
+ return true;
+ }
+
+ bool ForEachApkFile(
+ const std::function<bool(File file, const std::string& location)>& process_fn) {
bool use_apk_fd_list = !apks_fd_.empty();
if (use_apk_fd_list) {
// Get the APKs from the collection of FDs.
@@ -592,7 +625,7 @@ class ProfMan final {
}
} else {
if (dex_locations_.size() != apks_fd_.size()) {
- Usage("The number of apk-fds must match the number of dex-locations.");
+ Usage("The number of apk-fds must match the number of dex-locations.");
}
}
} else if (!apk_files_.empty()) {
@@ -600,50 +633,30 @@ class ProfMan final {
// If no dex locations are specified use the apk names as locations.
dex_locations_ = apk_files_;
} else if (dex_locations_.size() != apk_files_.size()) {
- Usage("The number of apk-fds must match the number of dex-locations.");
+ Usage("The number of apk-fds must match the number of dex-locations.");
}
} else {
// No APKs were specified.
CHECK(dex_locations_.empty());
return true;
}
- static constexpr bool kVerifyChecksum = true;
for (size_t i = 0; i < dex_locations_.size(); ++i) {
- std::string error_msg;
- std::vector<std::unique_ptr<const DexFile>> dex_files_for_location;
// We do not need to verify the apk for processing profiles.
if (use_apk_fd_list) {
- File file(apks_fd_[i], /*check_usage=*/false);
- ArtDexFileLoader dex_file_loader(&file, dex_locations_[i]);
- if (dex_file_loader.Open(/*verify=*/false,
- kVerifyChecksum,
- /*allow_no_dex_files=*/true,
- &error_msg,
- &dex_files_for_location)) {
- } else {
- LOG(ERROR) << "OpenZip failed for '" << dex_locations_[i] << "' " << error_msg;
- return false;
- }
+ File file(apks_fd_[i], /*check_usage=*/false);
+ if (!process_fn(std::move(file), dex_locations_[i])) {
+ return false;
+ }
} else {
File file(apk_files_[i], O_RDONLY, /*check_usage=*/false);
if (file.Fd() < 0) {
PLOG(ERROR) << "Unable to open '" << apk_files_[i] << "'";
return false;
}
- ArtDexFileLoader dex_file_loader(&file, dex_locations_[i]);
- if (dex_file_loader.Open(/*verify=*/false,
- kVerifyChecksum,
- /*allow_no_dex_files=*/true,
- &error_msg,
- &dex_files_for_location)) {
- } else {
- LOG(ERROR) << "Open failed for '" << dex_locations_[i] << "' " << error_msg;
+ if (!process_fn(std::move(file), dex_locations_[i])) {
return false;
}
}
- for (std::unique_ptr<const DexFile>& dex_file : dex_files_for_location) {
- process_fn(std::move(dex_file));
- }
}
return true;
}