diff options
author | 2023-06-15 15:48:20 +0100 | |
---|---|---|
committer | 2023-07-03 10:52:06 +0000 | |
commit | fdfa590b7b43ca70e497f1a8afe9a641b57ece56 (patch) | |
tree | 6054b4e9ae772c2f135fedde6be62864206ddcad /libdexfile/dex/dex_file_loader.h | |
parent | 2f8499ef214f9eadb75b36eab43214842f4da64b (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 'libdexfile/dex/dex_file_loader.h')
-rw-r--r-- | libdexfile/dex/dex_file_loader.h | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/libdexfile/dex/dex_file_loader.h b/libdexfile/dex/dex_file_loader.h index 532445acf9..14cbdadaad 100644 --- a/libdexfile/dex/dex_file_loader.h +++ b/libdexfile/dex/dex_file_loader.h @@ -32,7 +32,6 @@ namespace art { class MemMap; class OatDexFile; -class ScopedTrace; class ZipArchive; enum class DexFileLoaderErrorCode { @@ -72,6 +71,53 @@ 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 combined checksum of one or more dex files (one checksum for the whole multidex set). + // + // This uses the source path provided to DexFileLoader constructor. + // + // Returns false on error. Sets *checksum to nullopt for an empty set. + bool GetMultiDexChecksum(/*out*/ std::optional<uint32_t>* checksum, + /*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 already open dex files. + // + // It starts iteration at index 'i', which must be a primary dex file, + // and it sets 'i' to the next primary dex file or to end of the array. + template <typename DexFilePtrVector> // array|vector<unique_ptr|DexFile|OatDexFile*>. + static uint32_t GetMultiDexChecksum(const DexFilePtrVector& dex_files, + /*inout*/ size_t* i) { + CHECK_LT(*i, dex_files.size()) << "No dex files"; + std::optional<uint32_t> checksum; + for (; *i < dex_files.size(); ++(*i)) { + const char* location = dex_files[*i]->GetLocation().c_str(); + if (!checksum.has_value()) { // First dex file. + CHECK(!IsMultiDexLocation(location)) << location; // Expect primary dex. + } else if (!IsMultiDexLocation(location)) { // Later dex file. + break; // Found another primary dex file, terminate iteration. + } + checksum = checksum.value_or(kEmptyMultiDexChecksum) ^ dex_files[*i]->GetLocationChecksum(); + } + CHECK(checksum.has_value()); + return checksum.value(); + } + + // Calculate checksum of dex files in a vector, starting at index 0. + // It will CHECK that the whole vector is consumed (i.e. there is just one primary dex file). + template <typename DexFilePtrVector> + static uint32_t GetMultiDexChecksum(const DexFilePtrVector& dex_files) { + size_t i = 0; + uint32_t checksum = GetMultiDexChecksum(dex_files, &i); + CHECK_EQ(i, dex_files.size()); + return checksum; + } + + // Non-zero initial value for multi-dex to catch bugs if multi-dex checksum is compared + // directly to DexFile::GetLocationChecksum without going through GetMultiDexChecksum. + static constexpr uint32_t kEmptyMultiDexChecksum = 1; + // Returns the canonical form of the given dex location. // // There are different flavors of "dex locations" as follows: |