summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author David Srbecky <dsrbecky@google.com> 2023-07-03 15:42:50 +0000
committer David Srbecky <dsrbecky@google.com> 2023-07-03 17:40:14 +0000
commit1bc114026d69fb112db5b671922e5c0c4df29e07 (patch)
tree352f60932a1bbf038a68519bf5c8d53e2da8f4c2
parent2522715378315a4e402a80c076f58689e1a02913 (diff)
Revert "Reduce multidex checksum to single scalar value."
This reverts commit fdfa590b7b43ca70e497f1a8afe9a641b57ece56. Reason for revert: b/289784075 Change-Id: Ib114ca32dac6d1aaced372334873bfa12f74d572
-rw-r--r--dex2oat/dex2oat_test.cc25
-rw-r--r--libartbase/base/common_art_test.cc9
-rw-r--r--libdexfile/dex/art_dex_file_loader.cc82
-rw-r--r--libdexfile/dex/art_dex_file_loader.h27
-rw-r--r--libdexfile/dex/art_dex_file_loader_test.cc65
-rw-r--r--libdexfile/dex/dex_file.cc2
-rw-r--r--libdexfile/dex/dex_file_loader.cc69
-rw-r--r--libdexfile/dex/dex_file_loader.h48
-rw-r--r--odrefresh/odrefresh.cc21
-rw-r--r--odrefresh/odrefresh_main.cc2
-rw-r--r--runtime/class_loader_context.cc53
-rw-r--r--runtime/class_loader_context_test.cc90
-rw-r--r--runtime/dex2oat_environment_test.h11
-rw-r--r--runtime/gc/space/image_space.cc96
-rw-r--r--runtime/oat.h4
-rw-r--r--runtime/oat_file.h6
-rw-r--r--runtime/oat_file_assistant.cc82
-rw-r--r--runtime/oat_file_assistant.h12
-rw-r--r--runtime/oat_file_assistant_context.cc34
-rw-r--r--runtime/runtime.cc9
20 files changed, 380 insertions, 367 deletions
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index 56d14a7143..be442075e4 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -19,7 +19,6 @@
#include <algorithm>
#include <iterator>
-#include <optional>
#include <regex>
#include <sstream>
#include <string>
@@ -1090,11 +1089,9 @@ TEST_F(Dex2oatClassLoaderContextTest, ContextWithTheSourceDexFiles) {
TEST_F(Dex2oatClassLoaderContextTest, ContextWithOtherDexFiles) {
std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Nested");
- uint32_t expected_checksum = DexFileLoader::GetMultiDexChecksum(dex_files);
-
std::string context = "PCL[" + dex_files[0]->GetLocation() + "]";
- std::string expected_classpath_key =
- "PCL[" + dex_files[0]->GetLocation() + "*" + std::to_string(expected_checksum) + "]";
+ std::string expected_classpath_key = "PCL[" + dex_files[0]->GetLocation() + "*" +
+ std::to_string(dex_files[0]->GetLocationChecksum()) + "]";
RunTest(context.c_str(), expected_classpath_key.c_str(), true);
}
@@ -2218,9 +2215,21 @@ TEST_F(Dex2oatClassLoaderContextTest, StoredClassLoaderContext) {
const std::string odex_location = out_dir + "/base.odex";
const std::string valid_context = "PCL[" + dex_files[0]->GetLocation() + "]";
const std::string stored_context = "PCL[/system/not_real_lib.jar]";
- uint32_t checksum = DexFileLoader::GetMultiDexChecksum(dex_files);
- std::string expected_stored_context =
- "PCL[/system/not_real_lib.jar*" + std::to_string(checksum) + "]";
+ std::string expected_stored_context = "PCL[";
+ size_t index = 1;
+ for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
+ const bool is_first = index == 1u;
+ if (!is_first) {
+ expected_stored_context += ":";
+ }
+ expected_stored_context += "/system/not_real_lib.jar";
+ if (!is_first) {
+ expected_stored_context += "!classes" + std::to_string(index) + ".dex";
+ }
+ expected_stored_context += "*" + std::to_string(dex_file->GetLocationChecksum());
+ ++index;
+ }
+ expected_stored_context += "]";
// The class path should not be valid and should fail being stored.
EXPECT_TRUE(GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
odex_location,
diff --git a/libartbase/base/common_art_test.cc b/libartbase/base/common_art_test.cc
index e83cc0d967..db0e1c157f 100644
--- a/libartbase/base/common_art_test.cc
+++ b/libartbase/base/common_art_test.cc
@@ -582,8 +582,13 @@ std::string CommonArtTestImpl::CreateClassPath(
std::string CommonArtTestImpl::CreateClassPathWithChecksums(
const std::vector<std::unique_ptr<const DexFile>>& dex_files) {
CHECK(!dex_files.empty());
- uint32_t checksum = DexFileLoader::GetMultiDexChecksum(dex_files);
- return dex_files[0]->GetLocation() + "*" + std::to_string(checksum);
+ std::string classpath = dex_files[0]->GetLocation() + "*" +
+ std::to_string(dex_files[0]->GetLocationChecksum());
+ for (size_t i = 1; i < dex_files.size(); i++) {
+ classpath += ":" + dex_files[i]->GetLocation() + "*" +
+ std::to_string(dex_files[i]->GetLocationChecksum());
+ }
+ return classpath;
}
CommonArtTestImpl::ForkAndExecResult CommonArtTestImpl::ForkAndExec(
diff --git a/libdexfile/dex/art_dex_file_loader.cc b/libdexfile/dex/art_dex_file_loader.cc
index 056d2fb261..ac52ca04e3 100644
--- a/libdexfile/dex/art_dex_file_loader.cc
+++ b/libdexfile/dex/art_dex_file_loader.cc
@@ -37,6 +37,88 @@
namespace art {
+using android::base::StringPrintf;
+
+bool ArtDexFileLoader::GetMultiDexChecksums(const char* filename,
+ std::vector<uint32_t>* checksums,
+ std::vector<std::string>* dex_locations,
+ std::string* error_msg,
+ int zip_fd,
+ bool* zip_file_only_contains_uncompressed_dex) {
+ CHECK(checksums != nullptr);
+ uint32_t magic;
+
+ File fd;
+ if (zip_fd != -1) {
+ if (ReadMagicAndReset(zip_fd, &magic, error_msg)) {
+ fd = File(DupCloexec(zip_fd), /* check_usage= */ false);
+ }
+ } else {
+ fd = OpenAndReadMagic(filename, &magic, error_msg);
+ }
+ if (fd.Fd() == -1) {
+ DCHECK(!error_msg->empty());
+ return false;
+ }
+ if (IsZipMagic(magic)) {
+ std::unique_ptr<ZipArchive> zip_archive(
+ ZipArchive::OpenFromFd(fd.Release(), filename, error_msg));
+ if (zip_archive.get() == nullptr) {
+ *error_msg = StringPrintf("Failed to open zip archive '%s' (error msg: %s)", filename,
+ error_msg->c_str());
+ return false;
+ }
+
+ if (zip_file_only_contains_uncompressed_dex != nullptr) {
+ // Start by assuming everything is uncompressed.
+ *zip_file_only_contains_uncompressed_dex = true;
+ }
+
+ uint32_t idx = 0;
+ std::string zip_entry_name = GetMultiDexClassesDexName(idx);
+ std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find(zip_entry_name.c_str(), error_msg));
+ if (zip_entry.get() == nullptr) {
+ // A zip file with no dex code should be accepted. It's likely a config split APK, which we
+ // are currently passing from higher levels.
+ VLOG(dex) << StringPrintf("Zip archive '%s' doesn't contain %s (error msg: %s)",
+ filename,
+ zip_entry_name.c_str(),
+ error_msg->c_str());
+ return true;
+ }
+
+ do {
+ if (zip_file_only_contains_uncompressed_dex != nullptr) {
+ if (!(zip_entry->IsUncompressed() && zip_entry->IsAlignedTo(alignof(DexFile::Header)))) {
+ *zip_file_only_contains_uncompressed_dex = false;
+ }
+ }
+ checksums->push_back(zip_entry->GetCrc32());
+ dex_locations->push_back(GetMultiDexLocation(idx, filename));
+ zip_entry_name = GetMultiDexClassesDexName(++idx);
+ zip_entry.reset(zip_archive->Find(zip_entry_name.c_str(), error_msg));
+ } while (zip_entry.get() != nullptr);
+ return true;
+ }
+ if (IsMagicValid(magic)) {
+ ArtDexFileLoader loader(fd.Release(), filename);
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ if (!loader.Open(/* verify= */ false,
+ /* verify_checksum= */ false,
+ error_msg,
+ &dex_files)) {
+ return false;
+ }
+ for (auto& dex_file : dex_files) {
+ checksums->push_back(dex_file->GetHeader().checksum_);
+ dex_locations->push_back(dex_file->GetLocation());
+ }
+ return true;
+ }
+ *error_msg = StringPrintf("Expected valid zip or dex file: '%s'", filename);
+ return false;
+}
+
std::unique_ptr<const DexFile> ArtDexFileLoader::Open(
const uint8_t* base,
size_t size,
diff --git a/libdexfile/dex/art_dex_file_loader.h b/libdexfile/dex/art_dex_file_loader.h
index 2fbc2cb794..9f2ae82e72 100644
--- a/libdexfile/dex/art_dex_file_loader.h
+++ b/libdexfile/dex/art_dex_file_loader.h
@@ -36,8 +36,31 @@ class ZipArchive;
// Class that is used to open dex files and deal with corresponding multidex and location logic.
class ArtDexFileLoader : public DexFileLoader {
public:
- using DexFileLoader::DexFileLoader; // Use constructors from base class.
- using DexFileLoader::Open; // Don't shadow overloads from base class.
+ using DexFileLoader::DexFileLoader;
+ virtual ~ArtDexFileLoader() { }
+
+ // Returns the checksums of a file for comparison with GetLocationChecksum().
+ // For .dex files, this is the single header checksum.
+ // For zip files, this is the zip entry CRC32 checksum for classes.dex and
+ // each additional multidex entry classes2.dex, classes3.dex, etc.
+ // If a valid zip_fd is provided the file content will be read directly from
+ // the descriptor and `filename` will be used as alias for error logging. If
+ // zip_fd is -1, the method will try to open the `filename` and read the
+ // content from it.
+ //
+ // The dex_locations vector will be populated with the corresponding multidex
+ // locations.
+ //
+ // Return true if the checksums could be found, false otherwise.
+ static bool GetMultiDexChecksums(const char* filename,
+ std::vector<uint32_t>* checksums,
+ std::vector<std::string>* dex_locations,
+ std::string* error_msg,
+ int zip_fd = -1,
+ bool* only_contains_uncompressed_dex = nullptr);
+
+ // Don't shadow overloads from base class.
+ using DexFileLoader::Open;
// Old signature preserved for app-compat.
std::unique_ptr<const DexFile> Open(const uint8_t* base,
diff --git a/libdexfile/dex/art_dex_file_loader_test.cc b/libdexfile/dex/art_dex_file_loader_test.cc
index 4663a02ff0..d8911ece78 100644
--- a/libdexfile/dex/art_dex_file_loader_test.cc
+++ b/libdexfile/dex/art_dex_file_loader_test.cc
@@ -19,8 +19,6 @@
#include <sys/mman.h>
#include <memory>
-#include <optional>
-#include <vector>
#include "base/common_art_test.h"
#include "base/mem_map.h"
@@ -31,8 +29,8 @@
#include "dex/class_accessor-inl.h"
#include "dex/code_item_accessors-inl.h"
#include "dex/descriptors_names.h"
-#include "dex/dex_file-inl.h"
#include "dex/dex_file.h"
+#include "dex/dex_file-inl.h"
#include "dex/dex_file_loader.h"
namespace art {
@@ -97,50 +95,65 @@ TEST_F(ArtDexFileLoaderTest, GetLocationChecksum) {
}
TEST_F(ArtDexFileLoaderTest, GetChecksum) {
- std::optional<uint32_t> checksum;
+ std::vector<uint32_t> checksums;
+ std::vector<std::string> dex_locations;
std::string error_msg;
- ArtDexFileLoader dex_loader(GetLibCoreDexFileNames()[0]);
- ASSERT_TRUE(dex_loader.GetMultiDexChecksum(&checksum, &error_msg)) << error_msg;
- ASSERT_TRUE(checksum.has_value());
-
- std::vector<const DexFile*> dex_files{java_lang_dex_file_};
- uint32_t expected_checksum = DexFileLoader::GetMultiDexChecksum(dex_files);
- EXPECT_EQ(expected_checksum, checksum.value());
+ EXPECT_TRUE(ArtDexFileLoader::GetMultiDexChecksums(
+ GetLibCoreDexFileNames()[0].c_str(), &checksums, &dex_locations, &error_msg))
+ << error_msg;
+ ASSERT_EQ(1U, checksums.size());
+ ASSERT_EQ(1U, dex_locations.size());
+ EXPECT_EQ(java_lang_dex_file_->GetLocationChecksum(), checksums[0]);
+ EXPECT_EQ(java_lang_dex_file_->GetLocation(), dex_locations[0]);
}
-TEST_F(ArtDexFileLoaderTest, GetMultiDexChecksum) {
+TEST_F(ArtDexFileLoaderTest, GetMultiDexChecksums) {
std::string error_msg;
- std::optional<uint32_t> checksum;
+ std::vector<uint32_t> checksums;
+ std::vector<std::string> dex_locations;
std::string multidex_file = GetTestDexFileName("MultiDex");
- ArtDexFileLoader dex_loader(multidex_file);
- EXPECT_TRUE(dex_loader.GetMultiDexChecksum(&checksum, &error_msg)) << error_msg;
+ EXPECT_TRUE(ArtDexFileLoader::GetMultiDexChecksums(
+ multidex_file.c_str(), &checksums, &dex_locations, &error_msg))
+ << error_msg;
std::vector<std::unique_ptr<const DexFile>> dexes = OpenTestDexFiles("MultiDex");
ASSERT_EQ(2U, dexes.size());
- ASSERT_TRUE(checksum.has_value());
+ ASSERT_EQ(2U, checksums.size());
+ ASSERT_EQ(2U, dex_locations.size());
- uint32_t expected_checksum = DexFileLoader::GetMultiDexChecksum(dexes);
EXPECT_EQ(dexes[0]->GetLocation(), DexFileLoader::GetMultiDexLocation(0, multidex_file.c_str()));
+ EXPECT_EQ(dexes[0]->GetLocation(), dex_locations[0]);
+ EXPECT_EQ(dexes[0]->GetLocationChecksum(), checksums[0]);
+
EXPECT_EQ(dexes[1]->GetLocation(), DexFileLoader::GetMultiDexLocation(1, multidex_file.c_str()));
- EXPECT_EQ(expected_checksum, checksum.value());
+ EXPECT_EQ(dexes[1]->GetLocation(), dex_locations[1]);
+ EXPECT_EQ(dexes[1]->GetLocationChecksum(), checksums[1]);
}
TEST_F(ArtDexFileLoaderTest, GetMultiDexChecksumsEmptyZip) {
std::string error_msg;
- std::optional<uint32_t> checksum;
+ std::vector<uint32_t> checksums;
+ std::vector<std::string> dex_locations;
std::string multidex_file = GetTestDexFileName("MainEmptyUncompressed");
- ArtDexFileLoader dex_loader(multidex_file);
- EXPECT_TRUE(dex_loader.GetMultiDexChecksum(&checksum, &error_msg)) << error_msg;
- EXPECT_FALSE(checksum.has_value());
+ EXPECT_TRUE(ArtDexFileLoader::GetMultiDexChecksums(
+ multidex_file.c_str(), &checksums, &dex_locations, &error_msg))
+ << error_msg;
+
+ EXPECT_EQ(dex_locations.size(), 0);
+ EXPECT_EQ(checksums.size(), 0);
}
TEST_F(ArtDexFileLoaderTest, GetMultiDexChecksumsDexFile) {
std::string error_msg;
- std::optional<uint32_t> checksum;
+ std::vector<uint32_t> checksums;
+ std::vector<std::string> dex_locations;
std::string multidex_file = GetTestDexFileName("VerifierDeps"); // This is a .dex file.
- DexFileLoader loader(multidex_file);
- EXPECT_TRUE(loader.GetMultiDexChecksum(&checksum, &error_msg)) << error_msg;
- EXPECT_TRUE(checksum.has_value());
+ EXPECT_TRUE(ArtDexFileLoader::GetMultiDexChecksums(
+ multidex_file.c_str(), &checksums, &dex_locations, &error_msg))
+ << error_msg;
+
+ EXPECT_EQ(dex_locations.size(), 1);
+ EXPECT_EQ(checksums.size(), 1);
}
TEST_F(ArtDexFileLoaderTest, ClassDefs) {
diff --git a/libdexfile/dex/dex_file.cc b/libdexfile/dex/dex_file.cc
index 8179559337..080e381fe0 100644
--- a/libdexfile/dex/dex_file.cc
+++ b/libdexfile/dex/dex_file.cc
@@ -23,12 +23,12 @@
#include <zlib.h>
#include <memory>
-#include <optional>
#include <ostream>
#include <sstream>
#include <type_traits>
#include "android-base/stringprintf.h"
+
#include "base/enums.h"
#include "base/hiddenapi_domain.h"
#include "base/leb128.h"
diff --git a/libdexfile/dex/dex_file_loader.cc b/libdexfile/dex/dex_file_loader.cc
index 9b54c15d9e..d375aac17b 100644
--- a/libdexfile/dex/dex_file_loader.cc
+++ b/libdexfile/dex/dex_file_loader.cc
@@ -148,72 +148,9 @@ std::string DexFileLoader::GetMultiDexClassesDexName(size_t index) {
}
std::string DexFileLoader::GetMultiDexLocation(size_t index, const char* dex_location) {
- if (index == 0) {
- return dex_location;
- }
- DCHECK(!IsMultiDexLocation(dex_location));
- 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.
-
- uint32_t magic;
- if (!InitAndReadMagic(&magic, error_msg)) {
- return false;
- }
-
- if (IsZipMagic(magic)) {
- std::unique_ptr<ZipArchive> zip_archive(
- file_.has_value() ?
- ZipArchive::OpenFromOwnedFd(file_->Fd(), location_.c_str(), error_msg) :
- ZipArchive::OpenFromMemory(
- root_container_->Begin(), root_container_->Size(), location_.c_str(), error_msg));
- if (zip_archive.get() == nullptr) {
- DCHECK(!error_msg->empty());
- return false;
- }
- if (only_contains_uncompressed_dex != nullptr) {
- *only_contains_uncompressed_dex = true;
- }
- for (size_t i = 0;; ++i) {
- std::string name = GetMultiDexClassesDexName(i);
- std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find(name.c_str(), error_msg));
- if (zip_entry == nullptr) {
- break;
- }
- if (only_contains_uncompressed_dex != nullptr) {
- if (!(zip_entry->IsUncompressed() && zip_entry->IsAlignedTo(alignof(DexFile::Header)))) {
- *only_contains_uncompressed_dex = false;
- }
- }
- *checksum = checksum->value_or(kEmptyMultiDexChecksum) ^ zip_entry->GetCrc32();
- }
- return true;
- }
- if (!MapRootContainer(error_msg)) {
- return false;
- }
- const uint8_t* begin = root_container_->Begin();
- const uint8_t* end = root_container_->End();
- 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);
- if (size < sizeof(*header) || !IsMagicValid(ptr)) {
- *error_msg = StringPrintf("Invalid dex header: '%s'", filename_.c_str());
- return false;
- }
- if (size < header->file_size_) {
- *error_msg = StringPrintf("Truncated dex file: '%s'", filename_.c_str());
- return false;
- }
- *checksum = checksum->value_or(kEmptyMultiDexChecksum) ^ header->checksum_;
- ptr += header->file_size_;
- }
- return true;
+ return (index == 0)
+ ? dex_location
+ : StringPrintf("%s%cclasses%zu.dex", dex_location, kMultiDexSeparator, index + 1);
}
std::string DexFileLoader::GetDexCanonicalLocation(const char* dex_location) {
diff --git a/libdexfile/dex/dex_file_loader.h b/libdexfile/dex/dex_file_loader.h
index 14cbdadaad..532445acf9 100644
--- a/libdexfile/dex/dex_file_loader.h
+++ b/libdexfile/dex/dex_file_loader.h
@@ -32,6 +32,7 @@ namespace art {
class MemMap;
class OatDexFile;
+class ScopedTrace;
class ZipArchive;
enum class DexFileLoaderErrorCode {
@@ -71,53 +72,6 @@ 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:
diff --git a/odrefresh/odrefresh.cc b/odrefresh/odrefresh.cc
index e925f856ef..7bc1a04441 100644
--- a/odrefresh/odrefresh.cc
+++ b/odrefresh/odrefresh.cc
@@ -316,18 +316,25 @@ std::vector<T> GenerateComponents(
return {};
}
- std::optional<uint32_t> checksum;
+ std::vector<uint32_t> checksums;
+ std::vector<std::string> dex_locations;
std::string error_msg;
- ArtDexFileLoader dex_loader(actual_path);
- if (!dex_loader.GetMultiDexChecksum(&checksum, &error_msg)) {
- LOG(ERROR) << "Failed to get multi-dex checksum: " << error_msg;
+ if (!ArtDexFileLoader::GetMultiDexChecksums(
+ actual_path.c_str(), &checksums, &dex_locations, &error_msg)) {
+ LOG(ERROR) << "Failed to get multi-dex checksums: " << error_msg;
return {};
}
- const std::string checksum_str =
- checksum.has_value() ? StringPrintf("%08x", checksum.value()) : std::string();
+ std::ostringstream oss;
+ for (size_t i = 0; i < checksums.size(); ++i) {
+ if (i != 0) {
+ oss << ';';
+ }
+ oss << StringPrintf("%08x", checksums[i]);
+ }
+ const std::string checksum = oss.str();
- Result<T> component = custom_generator(path, static_cast<uint64_t>(sb.st_size), checksum_str);
+ Result<T> component = custom_generator(path, static_cast<uint64_t>(sb.st_size), checksum);
if (!component.ok()) {
LOG(ERROR) << "Failed to generate component: " << component.error();
return {};
diff --git a/odrefresh/odrefresh_main.cc b/odrefresh/odrefresh_main.cc
index 07ea060eec..c0e5adeec9 100644
--- a/odrefresh/odrefresh_main.cc
+++ b/odrefresh/odrefresh_main.cc
@@ -27,7 +27,6 @@
#include "arch/instruction_set.h"
#include "base/file_utils.h"
#include "base/globals.h"
-#include "base/mem_map.h"
#include "base/stl_util.h"
#include "odr_common.h"
#include "odr_compilation_log.h"
@@ -269,7 +268,6 @@ int main(int argc, char** argv) {
if (!config.GetCompilationOsMode()) {
android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
}
- art::MemMap::Init(); // Needed by DexFileLoader.
argv += n;
argc -= n;
diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc
index 1b14449684..2f34f04f5b 100644
--- a/runtime/class_loader_context.cc
+++ b/runtime/class_loader_context.cc
@@ -17,7 +17,6 @@
#include "class_loader_context.h"
#include <algorithm>
-#include <optional>
#include "android-base/file.h"
#include "android-base/parseint.h"
@@ -474,12 +473,14 @@ bool ClassLoaderContext::OpenDexFiles(const std::string& classpath_dir,
}
std::string error_msg;
- ArtDexFileLoader dex_file_loader(fd, location);
- std::optional<uint32_t> dex_checksum;
if (only_read_checksums) {
bool zip_file_only_contains_uncompress_dex;
- if (!dex_file_loader.GetMultiDexChecksum(
- &dex_checksum, &error_msg, &zip_file_only_contains_uncompress_dex)) {
+ if (!ArtDexFileLoader::GetMultiDexChecksums(location.c_str(),
+ &dex_checksums,
+ &dex_locations,
+ &error_msg,
+ fd,
+ &zip_file_only_contains_uncompress_dex)) {
LOG(WARNING) << "Could not get dex checksums for location " << location << ", fd=" << fd;
dex_files_state_ = kDexFilesOpenFailed;
}
@@ -488,7 +489,8 @@ bool ClassLoaderContext::OpenDexFiles(const std::string& classpath_dir,
// contents. So pass true to verify_checksum.
// We don't need to do structural dex file verification, we only need to
// check the checksum, so pass false to verify.
- size_t i = info->opened_dex_files.size();
+ size_t opened_dex_files_index = info->opened_dex_files.size();
+ ArtDexFileLoader dex_file_loader(location.c_str(), fd, location);
if (!dex_file_loader.Open(/*verify=*/false,
/*verify_checksum=*/true,
&error_msg,
@@ -496,14 +498,13 @@ bool ClassLoaderContext::OpenDexFiles(const std::string& classpath_dir,
LOG(WARNING) << "Could not open dex files for location " << location << ", fd=" << fd;
dex_files_state_ = kDexFilesOpenFailed;
} else {
- dex_checksum = DexFileLoader::GetMultiDexChecksum(info->opened_dex_files, &i);
- DCHECK_EQ(i, info->opened_dex_files.size());
+ for (size_t k = opened_dex_files_index; k < info->opened_dex_files.size(); k++) {
+ std::unique_ptr<const DexFile>& dex = info->opened_dex_files[k];
+ dex_locations.push_back(dex->GetLocation());
+ dex_checksums.push_back(dex->GetLocationChecksum());
+ }
}
}
- if (dex_checksum.has_value()) {
- dex_locations.push_back(location);
- dex_checksums.push_back(dex_checksum.value());
- }
}
// We finished opening the dex files from the classpath.
@@ -517,8 +518,8 @@ bool ClassLoaderContext::OpenDexFiles(const std::string& classpath_dir,
// Note that this will also remove the paths that could not be opened.
info->original_classpath = std::move(info->classpath);
DCHECK(dex_locations.size() == dex_checksums.size());
- info->classpath = std::move(dex_locations);
- info->checksums = std::move(dex_checksums);
+ info->classpath = dex_locations;
+ info->checksums = dex_checksums;
AddToWorkList(info, work_list);
}
@@ -691,16 +692,16 @@ void ClassLoaderContext::EncodeContextInternal(const ClassLoaderInfo& info,
}
}
- for (size_t k = 0; k < info.opened_dex_files.size();) {
+ 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];
- uint32_t checksum = DexFileLoader::GetMultiDexChecksum(info.opened_dex_files, &k);
-
if (for_dex2oat) {
// dex2oat only needs the base location. It cannot accept multidex locations.
// So ensure we only add each file once.
bool new_insert =
seen_locations.insert(DexFileLoader::GetBaseLocation(dex_file->GetLocation())).second;
- CHECK(new_insert);
+ if (!new_insert) {
+ continue;
+ }
}
std::string location = dex_file->GetLocation();
@@ -715,7 +716,7 @@ void ClassLoaderContext::EncodeContextInternal(const ClassLoaderInfo& info,
// dex2oat does not need the checksums.
if (!for_dex2oat) {
- checksums.push_back(checksum);
+ checksums.push_back(dex_file->GetLocationChecksum());
}
}
EncodeClassPath(base_dir, locations, checksums, info.type, out);
@@ -1154,17 +1155,13 @@ bool ClassLoaderContext::CreateInfoFromClassLoader(
}
// Now that `info` is in the chain, populate dex files.
- for (size_t i = 0; i < dex_files_loaded.size();) {
- const DexFile* dex_file = dex_files_loaded[i];
- uint32_t checksum = DexFileLoader::GetMultiDexChecksum(dex_files_loaded, &i);
+ for (const DexFile* dex_file : dex_files_loaded) {
// Dex location of dex files loaded with InMemoryDexClassLoader is always bogus.
// Use a magic value for the classpath instead.
info->classpath.push_back((type == kInMemoryDexClassLoader) ?
kInMemoryDexClassLoaderDexLocationMagic :
dex_file->GetLocation());
- info->checksums.push_back(checksum);
- }
- for (auto* dex_file : dex_files_loaded) {
+ info->checksums.push_back(dex_file->GetLocationChecksum());
info->opened_dex_files.emplace_back(dex_file);
}
@@ -1480,10 +1477,8 @@ std::set<const DexFile*> ClassLoaderContext::CheckForDuplicateDexFiles(
// in the Android world) - and as such we decide not to warn on them.
ClassLoaderInfo* info = class_loader_chain_.get();
for (size_t k = 0; k < info->classpath.size(); k++) {
- for (size_t i = 0; i < dex_files_to_check.size();) {
- const DexFile* dex_file = dex_files_to_check[i];
- uint32_t checksum = DexFileLoader::GetMultiDexChecksum(dex_files_to_check, &i);
- if (info->checksums[k] == checksum &&
+ for (const DexFile* dex_file : dex_files_to_check) {
+ if (info->checksums[k] == dex_file->GetLocationChecksum() &&
AreDexNameMatching(info->classpath[k], dex_file->GetLocation())) {
result.insert(dex_file);
}
diff --git a/runtime/class_loader_context_test.cc b/runtime/class_loader_context_test.cc
index 98b8eed5d5..ce9780a74e 100644
--- a/runtime/class_loader_context_test.cc
+++ b/runtime/class_loader_context_test.cc
@@ -20,8 +20,6 @@
#include <filesystem>
#include <fstream>
-#include <optional>
-#include <vector>
#include "android-base/stringprintf.h"
#include "android-base/strings.h"
@@ -29,7 +27,6 @@
#include "art_method-alloc-inl.h"
#include "base/dchecked_vector.h"
#include "base/stl_util.h"
-#include "base/string_view_cpp20.h"
#include "class_linker.h"
#include "class_root-inl.h"
#include "common_runtime_test.h"
@@ -187,62 +184,41 @@ class ClassLoaderContextTest : public CommonRuntimeTest {
ClassLoaderContext::ContextDexFilesState::kDexFilesOpened);
}
ClassLoaderContext::ClassLoaderInfo& info = *context->GetParent(index);
-
- std::vector<const DexFile*> primary_dex_files;
- std::vector<std::optional<uint32_t>> primary_checksums;
- for (size_t i = 0; i < all_dex_files->size();) {
- primary_dex_files.push_back((*all_dex_files)[i].get());
- primary_checksums.push_back(DexFileLoader::GetMultiDexChecksum(*all_dex_files, &i));
- }
- ASSERT_EQ(primary_dex_files.size(), info.classpath.size());
- ASSERT_EQ(primary_dex_files.size(), info.checksums.size());
-
+ ASSERT_EQ(all_dex_files->size(), info.classpath.size());
+ ASSERT_EQ(all_dex_files->size(), info.checksums.size());
if (only_read_checksums) {
ASSERT_EQ(0u, info.opened_dex_files.size());
- for (size_t k = 0; k < primary_dex_files.size(); k++) {
- const std::string& opened_location = info.classpath[k];
- uint32_t opened_checksum = info.checksums[k];
-
- const DexFile* expected_dex_file = primary_dex_files[k];
- std::string expected_location = expected_dex_file->GetLocation();
-
- if (!IsAbsoluteLocation(opened_location)) {
- // If the opened location is relative (it was open from a relative path without a
- // classpath_dir) it might not match the expected location which is absolute in tests).
- // So we compare the endings (the checksum will validate it's actually the same file).
- ASSERT_TRUE(EndsWith(expected_location, opened_location))
- << expected_location << " " << opened_location;
- } else {
- ASSERT_EQ(expected_location, opened_location);
- }
- ASSERT_EQ(primary_checksums[k], opened_checksum);
- if (classpath_matches_dex_location) {
- ASSERT_EQ(info.classpath[k], opened_location);
- }
- }
} else {
ASSERT_EQ(all_dex_files->size(), info.opened_dex_files.size());
+ }
- for (size_t k = 0; k < all_dex_files->size(); k++) {
- const std::string& opened_location = info.opened_dex_files[k]->GetLocation();
- uint32_t opened_checksum = info.opened_dex_files[k]->GetLocationChecksum();
-
- std::unique_ptr<const DexFile>& expected_dex_file = (*all_dex_files)[k];
- std::string expected_location = expected_dex_file->GetLocation();
-
- if (!IsAbsoluteLocation(opened_location)) {
- // If the opened location is relative (it was open from a relative path without a
- // classpath_dir) it might not match the expected location which is absolute in tests).
- // So we compare the endings (the checksum will validate it's actually the same file).
- ASSERT_TRUE(EndsWith(expected_location, opened_location))
- << expected_location << " " << opened_location;
- } else {
- ASSERT_EQ(expected_location, opened_location);
- }
- ASSERT_EQ(expected_dex_file->GetLocationChecksum(), opened_checksum);
- if (classpath_matches_dex_location) {
- ASSERT_EQ(info.classpath[k], opened_location);
- }
+ for (size_t k = 0, cur_open_dex_index = 0;
+ k < all_dex_files->size();
+ k++, cur_open_dex_index++) {
+ const std::string& opened_location = only_read_checksums
+ ? info.classpath[cur_open_dex_index]
+ : info.opened_dex_files[cur_open_dex_index]->GetLocation();
+ uint32_t opened_checksum = only_read_checksums
+ ? info.checksums[cur_open_dex_index]
+ : info.opened_dex_files[cur_open_dex_index]->GetLocationChecksum();
+
+ std::unique_ptr<const DexFile>& expected_dex_file = (*all_dex_files)[k];
+ std::string expected_location = expected_dex_file->GetLocation();
+
+ if (!IsAbsoluteLocation(opened_location)) {
+ // If the opened location is relative (it was open from a relative path without a
+ // classpath_dir) it might not match the expected location which is absolute in tests).
+ // So we compare the endings (the checksum will validate it's actually the same file).
+ ASSERT_EQ(0, expected_location.compare(
+ expected_location.length() - opened_location.length(),
+ opened_location.length(),
+ opened_location));
+ } else {
+ ASSERT_EQ(expected_location, opened_location);
+ }
+ ASSERT_EQ(expected_dex_file->GetLocationChecksum(), opened_checksum);
+ if (classpath_matches_dex_location) {
+ ASSERT_EQ(info.classpath[k], opened_location);
}
}
}
@@ -1226,11 +1202,9 @@ TEST_F(ClassLoaderContextTest, EncodeInOatFileIMC) {
std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MyClass");
ASSERT_EQ(dex2.size(), 1u);
- uint32_t expected_checksum = DexFileLoader::GetMultiDexChecksum(dex2);
-
std::string encoding = context->EncodeContextForOatFile("");
- std::string expected_encoding = "IMC[<unknown>*" + std::to_string(expected_checksum) + "];PCL[" +
- CreateClassPathWithChecksums(dex1) + "]";
+ std::string expected_encoding = "IMC[<unknown>*" + std::to_string(dex2[0]->GetLocationChecksum())
+ + "];PCL[" + CreateClassPathWithChecksums(dex1) + "]";
ASSERT_EQ(expected_encoding, context->EncodeContextForOatFile(""));
}
diff --git a/runtime/dex2oat_environment_test.h b/runtime/dex2oat_environment_test.h
index 43e1bf816e..c7febcd4fb 100644
--- a/runtime/dex2oat_environment_test.h
+++ b/runtime/dex2oat_environment_test.h
@@ -18,7 +18,6 @@
#define ART_RUNTIME_DEX2OAT_ENVIRONMENT_TEST_H_
#include <fstream>
-#include <optional>
#include <string>
#include <vector>
@@ -99,7 +98,8 @@ class Dex2oatEnvironmentTest : public Dex2oatScratchDirs, public CommonRuntimeTe
Dex2oatScratchDirs::SetUp(android_data_);
// Verify the environment is as we expect
- std::optional<uint32_t> checksum;
+ std::vector<uint32_t> checksums;
+ std::vector<std::string> dex_locations;
std::string error_msg;
ASSERT_TRUE(OS::FileExists(GetSystemImageFile().c_str()))
<< "Expected pre-compiled boot image to be at: " << GetSystemImageFile();
@@ -107,8 +107,8 @@ class Dex2oatEnvironmentTest : public Dex2oatScratchDirs, public CommonRuntimeTe
<< "Expected dex file to be at: " << GetDexSrc1();
ASSERT_TRUE(OS::FileExists(GetResourceOnlySrc1().c_str()))
<< "Expected stripped dex file to be at: " << GetResourceOnlySrc1();
- ArtDexFileLoader dex_file_loader0(GetResourceOnlySrc1());
- ASSERT_TRUE(dex_file_loader0.GetMultiDexChecksum(&checksum, &error_msg))
+ ASSERT_TRUE(ArtDexFileLoader::GetMultiDexChecksums(
+ GetResourceOnlySrc1().c_str(), &checksums, &dex_locations, &error_msg))
<< "Expected stripped dex file to be stripped: " << GetResourceOnlySrc1();
ASSERT_TRUE(OS::FileExists(GetDexSrc2().c_str()))
<< "Expected dex file to be at: " << GetDexSrc2();
@@ -128,9 +128,6 @@ class Dex2oatEnvironmentTest : public Dex2oatScratchDirs, public CommonRuntimeTe
<< error_msg;
ASSERT_GT(multi2.size(), 1u);
- ASSERT_EQ(multi1[0]->GetHeader().checksum_, multi2[0]->GetHeader().checksum_);
- ASSERT_NE(multi1[1]->GetHeader().checksum_, multi2[1]->GetHeader().checksum_);
-
ASSERT_EQ(multi1[0]->GetLocationChecksum(), multi2[0]->GetLocationChecksum());
ASSERT_NE(multi1[1]->GetLocationChecksum(), multi2[1]->GetLocationChecksum());
}
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index ebd6681f5c..f4af50f07e 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -21,7 +21,6 @@
#include <unistd.h>
#include <memory>
-#include <optional>
#include <random>
#include <string>
#include <vector>
@@ -3449,44 +3448,66 @@ bool ImageSpace::ValidateOatFile(const OatFile& oat_file,
return false;
}
- size_t dex_file_index = 0; // Counts only primary dex files.
- const std::vector<const OatDexFile*>& oat_dex_files = oat_file.GetOatDexFiles();
- for (size_t i = 0; i < oat_dex_files.size();) {
+ size_t dex_file_index = 0;
+ for (const OatDexFile* oat_dex_file : oat_file.GetOatDexFiles()) {
+ // Skip multidex locations - These will be checked when we visit their
+ // corresponding primary non-multidex location.
+ if (DexFileLoader::IsMultiDexLocation(oat_dex_file->GetDexFileLocation().c_str())) {
+ continue;
+ }
+
DCHECK(dex_filenames.empty() || dex_file_index < dex_filenames.size());
- const std::string& dex_file_location = dex_filenames.empty() ?
- oat_dex_files[i]->GetDexFileLocation() :
- dex_filenames[dex_file_index];
+ const std::string& dex_file_location =
+ dex_filenames.empty() ? oat_dex_file->GetDexFileLocation() : dex_filenames[dex_file_index];
int dex_fd = dex_file_index < dex_fds.size() ? dex_fds[dex_file_index] : -1;
dex_file_index++;
- if (DexFileLoader::IsMultiDexLocation(oat_dex_files[i]->GetDexFileLocation().c_str())) {
- return false; // Expected primary dex file.
+ std::vector<uint32_t> checksums;
+ std::vector<std::string> dex_locations_ignored;
+ if (!ArtDexFileLoader::GetMultiDexChecksums(
+ dex_file_location.c_str(), &checksums, &dex_locations_ignored, error_msg, dex_fd)) {
+ *error_msg = StringPrintf("ValidateOatFile failed to get checksums of dex file '%s' "
+ "referenced by oat file %s: %s",
+ dex_file_location.c_str(),
+ oat_file.GetLocation().c_str(),
+ error_msg->c_str());
+ return false;
}
- uint32_t oat_checksum = DexFileLoader::GetMultiDexChecksum(oat_dex_files, &i);
-
- // Original checksum.
- std::optional<uint32_t> dex_checksum;
- ArtDexFileLoader dex_loader(dex_fd, dex_file_location);
- if (!dex_loader.GetMultiDexChecksum(&dex_checksum, error_msg)) {
- *error_msg = StringPrintf(
- "ValidateOatFile failed to get checksum of dex file '%s' "
- "referenced by oat file %s: %s",
- dex_file_location.c_str(),
- oat_file.GetLocation().c_str(),
- error_msg->c_str());
+ CHECK(!checksums.empty());
+ if (checksums[0] != oat_dex_file->GetDexFileLocationChecksum()) {
+ *error_msg = StringPrintf("ValidateOatFile found checksum mismatch between oat file "
+ "'%s' and dex file '%s' (0x%x != 0x%x)",
+ oat_file.GetLocation().c_str(),
+ dex_file_location.c_str(),
+ oat_dex_file->GetDexFileLocationChecksum(),
+ checksums[0]);
return false;
}
- CHECK(dex_checksum.has_value());
- if (oat_checksum != dex_checksum) {
- *error_msg = StringPrintf(
- "ValidateOatFile found checksum mismatch between oat file "
- "'%s' and dex file '%s' (0x%x != 0x%x)",
- oat_file.GetLocation().c_str(),
- dex_file_location.c_str(),
- oat_checksum,
- dex_checksum.value());
- return false;
+ // Verify checksums for any related multidex entries.
+ for (size_t i = 1; i < checksums.size(); i++) {
+ std::string multi_dex_location = DexFileLoader::GetMultiDexLocation(
+ i,
+ dex_file_location.c_str());
+ const OatDexFile* multi_dex = oat_file.GetOatDexFile(multi_dex_location.c_str(),
+ nullptr,
+ error_msg);
+ if (multi_dex == nullptr) {
+ *error_msg = StringPrintf("ValidateOatFile oat file '%s' is missing entry '%s'",
+ oat_file.GetLocation().c_str(),
+ multi_dex_location.c_str());
+ return false;
+ }
+
+ if (checksums[i] != multi_dex->GetDexFileLocationChecksum()) {
+ *error_msg = StringPrintf("ValidateOatFile found checksum mismatch between oat file "
+ "'%s' and dex file '%s' (0x%x != 0x%x)",
+ oat_file.GetLocation().c_str(),
+ multi_dex_location.c_str(),
+ multi_dex->GetDexFileLocationChecksum(),
+ checksums[i]);
+ return false;
+ }
}
}
return true;
@@ -3535,13 +3556,14 @@ std::string ImageSpace::GetBootClassPathChecksums(
ArrayRef<const DexFile* const>(boot_class_path).SubArray(bcp_pos);
DCHECK(boot_class_path_tail.empty() ||
!DexFileLoader::IsMultiDexLocation(boot_class_path_tail.front()->GetLocation().c_str()));
- for (size_t i = 0; i < boot_class_path_tail.size();) {
- uint32_t checksum = DexFileLoader::GetMultiDexChecksum(boot_class_path_tail, &i);
- if (!boot_image_checksum.empty()) {
- boot_image_checksum += ':';
+ for (const DexFile* dex_file : boot_class_path_tail) {
+ if (!DexFileLoader::IsMultiDexLocation(dex_file->GetLocation().c_str())) {
+ if (!boot_image_checksum.empty()) {
+ boot_image_checksum += ':';
+ }
+ boot_image_checksum += kDexFileChecksumPrefix;
}
- boot_image_checksum += kDexFileChecksumPrefix;
- StringAppendF(&boot_image_checksum, "/%08x", checksum);
+ StringAppendF(&boot_image_checksum, "/%08x", dex_file->GetLocationChecksum());
}
return boot_image_checksum;
}
diff --git a/runtime/oat.h b/runtime/oat.h
index d65f19a42b..e062baaee9 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -44,8 +44,8 @@ std::ostream& operator<<(std::ostream& stream, StubType stub_type);
class PACKED(4) OatHeader {
public:
static constexpr std::array<uint8_t, 4> kOatMagic { { 'o', 'a', 't', '\n' } };
- // Last oat version changed reason: Reduce multidex checksum to single scalar value.
- static constexpr std::array<uint8_t, 4> kOatVersion{{'2', '3', '1', '\0'}};
+ // Last oat version changed reason: ARM64: Enable implicit suspend checks; compiled code check.
+ static constexpr std::array<uint8_t, 4> kOatVersion { { '2', '3', '0', '\0' } };
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
static constexpr const char* kDebuggableKey = "debuggable";
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 4fdbb75a3a..68adb987c0 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -514,9 +514,6 @@ class OatDexFile final {
return dex_file_location_;
}
- // Returns original path of DexFile that was the source of this OatDexFile.
- const std::string& GetLocation() const { return dex_file_location_; }
-
// Returns the canonical location of DexFile that was the source of this OatDexFile.
const std::string& GetCanonicalDexFileLocation() const {
return canonical_dex_file_location_;
@@ -527,9 +524,6 @@ class OatDexFile final {
return dex_file_location_checksum_;
}
- // Returns checksum of original DexFile that was the source of this OatDexFile;
- uint32_t GetLocationChecksum() const { return dex_file_location_checksum_; }
-
// Returns the OatClass for the class specified by the given DexFile class_def_index.
OatFile::OatClass GetOatClass(uint16_t class_def_index) const;
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index cbbb31cd4f..9e16e49e40 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");
- std::optional<std::uint32_t> checksum;
- if (!GetRequiredDexChecksum(&checksum, error_msg)) {
+ const std::vector<std::uint32_t>* checksums = GetRequiredDexChecksums(error_msg);
+ if (checksums == nullptr) {
return std::nullopt;
}
- return checksum.has_value();
+ return !checksums->empty();
}
OatFileAssistant::OatStatus OatFileAssistant::OdexFileStatus() { return odex_.Status(); }
@@ -471,35 +471,37 @@ bool OatFileAssistant::DexChecksumUpToDate(const OatFile& file, std::string* err
return true;
}
ScopedTrace trace("DexChecksumUpToDate");
- std::optional<std::uint32_t> dex_checksum;
- if (!GetRequiredDexChecksum(&dex_checksum, error_msg)) {
+ const std::vector<uint32_t>* required_dex_checksums = GetRequiredDexChecksums(error_msg);
+ if (required_dex_checksums == nullptr) {
return false;
}
- if (!dex_checksum.has_value()) {
+ if (required_dex_checksums->empty()) {
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;
}
- 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;
+ 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;
+ }
}
-
return true;
}
@@ -716,36 +718,33 @@ bool OatFileAssistant::DexLocationToOatFilename(const std::string& location,
return GetDalvikCacheFilename(location.c_str(), dalvik_cache.c_str(), oat_filename, error_msg);
}
-bool OatFileAssistant::GetRequiredDexChecksum(std::optional<uint32_t>* checksum,
- std::string* error) {
+const std::vector<uint32_t>* OatFileAssistant::GetRequiredDexChecksums(std::string* error_msg) {
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_;
+ }
- 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;
+ cached_required_dex_checksums_ = std::move(checksums);
}
}
- 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_;
+ 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;
}
- *checksum = cached_required_dex_checksums_;
- return true;
}
bool OatFileAssistant::ValidateBootClassPathChecksums(OatFileAssistantContext* ofa_context,
@@ -1381,9 +1380,8 @@ 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 (!GetRequiredDexChecksum(&checksum, &error_msg)) {
+ if (GetRequiredDexChecksums(&error_msg) == nullptr) {
LOG(ERROR) << error_msg;
}
return zip_file_only_contains_uncompressed_dex_;
diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h
index 922dbf3e04..54287eb5f1 100644
--- a/runtime/oat_file_assistant.h
+++ b/runtime/oat_file_assistant.h
@@ -494,9 +494,11 @@ class OatFileAssistant {
// location.
OatStatus GivenOatFileStatus(const OatFile& file);
- // Gets the dex checksum required for an up-to-date oat file.
- // Returns cached result from GetMultiDexChecksum.
- bool GetRequiredDexChecksum(std::optional<uint32_t>* checksum, std::string* error);
+ // Gets the dex checksums required for an up-to-date oat file.
+ // Returns cached_required_dex_checksums if the required checksums were located. Returns an empty
+ // list if `dex_location_` refers to a zip and there is no dex file in it. Returns nullptr if an
+ // error occurred. The caller shouldn't clean up or free the returned pointer.
+ const std::vector<uint32_t>* GetRequiredDexChecksums(std::string* error_msg);
// Returns whether there is at least one boot image usable.
bool IsPrimaryBootImageUsable();
@@ -553,8 +555,8 @@ class OatFileAssistant {
// Cached value of the required dex checksums.
// This should be accessed only by the GetRequiredDexChecksums() method.
- std::optional<uint32_t> cached_required_dex_checksums_;
- std::optional<std::string> cached_required_dex_checksums_error_;
+ std::optional<std::vector<uint32_t>> cached_required_dex_checksums_;
+ std::string cached_required_dex_checksums_error_;
bool required_dex_checksums_attempted_ = false;
// The AOT-compiled file of an app when the APK of the app is in /data.
diff --git a/runtime/oat_file_assistant_context.cc b/runtime/oat_file_assistant_context.cc
index 0f9860f55d..c3fb73de4b 100644
--- a/runtime/oat_file_assistant_context.cc
+++ b/runtime/oat_file_assistant_context.cc
@@ -17,7 +17,6 @@
#include "oat_file_assistant_context.h"
#include <memory>
-#include <optional>
#include <string>
#include <vector>
@@ -77,13 +76,13 @@ OatFileAssistantContext::OatFileAssistantContext(Runtime* runtime)
// Fetch BCP checksums from the runtime.
size_t bcp_index = 0;
std::vector<std::string>* current_bcp_checksums = nullptr;
- const std::vector<const DexFile*>& bcp_dex_files = runtime->GetClassLinker()->GetBootClassPath();
- for (size_t i = 0; i < bcp_dex_files.size();) {
- uint32_t checksum = DexFileLoader::GetMultiDexChecksum(bcp_dex_files, &i);
- DCHECK_LT(bcp_index, runtime_options_->boot_class_path.size());
- current_bcp_checksums = &bcp_checksums_by_index_[bcp_index++];
+ for (const DexFile* dex_file : runtime->GetClassLinker()->GetBootClassPath()) {
+ if (!DexFileLoader::IsMultiDexLocation(dex_file->GetLocation().c_str())) {
+ DCHECK_LT(bcp_index, runtime_options_->boot_class_path.size());
+ current_bcp_checksums = &bcp_checksums_by_index_[bcp_index++];
+ }
DCHECK_NE(current_bcp_checksums, nullptr);
- current_bcp_checksums->push_back(StringPrintf("/%08x", checksum));
+ current_bcp_checksums->push_back(StringPrintf("/%08x", dex_file->GetLocationChecksum()));
}
DCHECK_EQ(bcp_index, runtime_options_->boot_class_path.size());
@@ -157,18 +156,23 @@ const std::vector<std::string>* OatFileAssistantContext::GetBcpChecksums(size_t
return &it->second;
}
- const std::vector<int>* fds = runtime_options_->boot_class_path_fds;
- ArtDexFileLoader dex_loader(fds != nullptr ? (*fds)[bcp_index] : -1,
- runtime_options_->boot_class_path[bcp_index]);
- std::optional<uint32_t> checksum;
- if (!dex_loader.GetMultiDexChecksum(&checksum, error_msg)) {
+ std::vector<uint32_t> checksums;
+ std::vector<std::string> dex_locations;
+ if (!ArtDexFileLoader::GetMultiDexChecksums(
+ runtime_options_->boot_class_path[bcp_index].c_str(),
+ &checksums,
+ &dex_locations,
+ error_msg,
+ runtime_options_->boot_class_path_fds != nullptr ?
+ (*runtime_options_->boot_class_path_fds)[bcp_index] :
+ -1)) {
return nullptr;
}
- DCHECK(checksum.has_value());
+ DCHECK(!checksums.empty());
std::vector<std::string>& bcp_checksums = bcp_checksums_by_index_[bcp_index];
- if (checksum.has_value()) {
- bcp_checksums.push_back(StringPrintf("/%08x", checksum.value()));
+ for (uint32_t checksum : checksums) {
+ bcp_checksums.push_back(StringPrintf("/%08x", checksum));
}
return &bcp_checksums;
}
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index f3bd4dd37e..36c8cde802 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -16,7 +16,6 @@
#include "runtime.h"
-#include <optional>
#include <utility>
#ifdef __linux__
@@ -2766,14 +2765,14 @@ void Runtime::RegisterAppInfo(const std::string& package_name,
bool has_code = false;
for (const std::string& path : code_paths) {
std::string error_msg;
- std::optional<uint32_t> checksum;
+ std::vector<uint32_t> checksums;
std::vector<std::string> dex_locations;
- DexFileLoader loader(path);
- if (!loader.GetMultiDexChecksum(&checksum, &error_msg)) {
+ if (!ArtDexFileLoader::GetMultiDexChecksums(
+ path.c_str(), &checksums, &dex_locations, &error_msg)) {
LOG(WARNING) << error_msg;
continue;
}
- if (checksum.has_value()) {
+ if (dex_locations.size() > 0) {
has_code = true;
break;
}