diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/class_linker.cc | 10 | ||||
-rw-r--r-- | runtime/gc/space/image_space.cc | 40 | ||||
-rw-r--r-- | runtime/gc/space/image_space.h | 10 | ||||
-rw-r--r-- | runtime/oat/oat.cc | 2 | ||||
-rw-r--r-- | runtime/oat/oat.h | 9 | ||||
-rw-r--r-- | runtime/oat/oat_file.cc | 9 | ||||
-rw-r--r-- | runtime/oat/oat_file.h | 6 | ||||
-rw-r--r-- | runtime/oat/oat_file_assistant.cc | 5 |
8 files changed, 64 insertions, 27 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 009d705caf..b14eaae51b 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -2240,8 +2240,16 @@ bool ClassLinker::AddImageSpace(gc::space::ImageSpace* space, return false; } + const char* oat_apex_versions = + oat_header->GetStoreValueByKeyUnsafe(OatHeader::kApexVersionsKey); + if (oat_apex_versions == nullptr) { + *error_msg = StringPrintf("Missing apex versions in special root in runtime image '%s'", + space->GetImageLocation().c_str()); + return false; + } + // Validate the apex versions. - if (!gc::space::ImageSpace::ValidateApexVersions(*oat_header, + if (!gc::space::ImageSpace::ValidateApexVersions(oat_apex_versions, runtime->GetApexVersions(), space->GetImageLocation(), error_msg)) { diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc index 97512bc79c..f557f3c8a9 100644 --- a/runtime/gc/space/image_space.cc +++ b/runtime/gc/space/image_space.cc @@ -26,6 +26,7 @@ #include <optional> #include <random> #include <string> +#include <string_view> #include <vector> #include "android-base/logging.h" @@ -3415,31 +3416,39 @@ void ImageSpace::Dump(std::ostream& os) const { << ",name=\"" << GetName() << "\"]"; } -bool ImageSpace::ValidateApexVersions(const OatHeader& oat_header, - const std::string& apex_versions, - const std::string& file_location, +bool ImageSpace::ValidateApexVersions(const OatFile& oat_file, + std::string_view runtime_apex_versions, std::string* error_msg) { // For a boot image, the key value store only exists in the first OAT file. Skip other OAT files. - if (oat_header.GetKeyValueStoreSize() == 0) { + if (oat_file.GetOatHeader().GetKeyValueStoreSize() == 0) { return true; } - const char* oat_apex_versions = oat_header.GetStoreValueByKey(OatHeader::kApexVersionsKey); - if (oat_apex_versions == nullptr) { + std::optional<std::string_view> oat_apex_versions = oat_file.GetApexVersions(); + if (!oat_apex_versions.has_value()) { *error_msg = StringPrintf("ValidateApexVersions failed to get APEX versions from oat file '%s'", - file_location.c_str()); + oat_file.GetLocation().c_str()); return false; } + + return ValidateApexVersions( + *oat_apex_versions, runtime_apex_versions, oat_file.GetLocation(), error_msg); +} + +bool ImageSpace::ValidateApexVersions(std::string_view oat_apex_versions, + std::string_view runtime_apex_versions, + const std::string& file_location, + std::string* error_msg) { // For a boot image, it can be generated from a subset of the bootclasspath. // For an app image, some dex files get compiled with a subset of the bootclasspath. // For such cases, the OAT APEX versions will be a prefix of the runtime APEX versions. - if (!apex_versions.starts_with(oat_apex_versions)) { - *error_msg = StringPrintf( - "ValidateApexVersions found APEX versions mismatch between oat file '%s' and the runtime " - "(Oat file: '%s', Runtime: '%s')", - file_location.c_str(), + if (!runtime_apex_versions.starts_with(oat_apex_versions)) { + *error_msg = ART_FORMAT( + "ValidateApexVersions found APEX versions mismatch between oat file '{}' and the runtime " + "(Oat file: '{}', Runtime: '{}')", + file_location, oat_apex_versions, - apex_versions.c_str()); + runtime_apex_versions); return false; } return true; @@ -3455,10 +3464,7 @@ bool ImageSpace::ValidateOatFile(const OatFile& oat_file, ArrayRef<const std::string> dex_filenames, ArrayRef<File> dex_files, const std::string& apex_versions) { - if (!ValidateApexVersions(oat_file.GetOatHeader(), - apex_versions, - oat_file.GetLocation(), - error_msg)) { + if (!ValidateApexVersions(oat_file, apex_versions, error_msg)) { return false; } diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h index 266b1d5925..4d0ce8181e 100644 --- a/runtime/gc/space/image_space.h +++ b/runtime/gc/space/image_space.h @@ -260,9 +260,13 @@ class ImageSpace : public MemMapSpace { const std::string& image_location, bool boot_image_extension = false); - // Returns true if the APEX versions in the OAT header match the given APEX versions. - static bool ValidateApexVersions(const OatHeader& oat_header, - const std::string& apex_versions, + // Returns true if the APEX versions of the OAT file match the given APEX versions. + static bool ValidateApexVersions(const OatFile& oat_file, + std::string_view runtime_apex_versions, + std::string* error_msg); + + static bool ValidateApexVersions(std::string_view oat_apex_versions, + std::string_view runtime_apex_versions, const std::string& file_location, std::string* error_msg); diff --git a/runtime/oat/oat.cc b/runtime/oat/oat.cc index 840825cea8..9882b0fa51 100644 --- a/runtime/oat/oat.cc +++ b/runtime/oat/oat.cc @@ -373,7 +373,7 @@ const uint8_t* OatHeader::GetKeyValueStore() const { return key_value_store_; } -const char* OatHeader::GetStoreValueByKey(const char* key) const { +const char* OatHeader::GetStoreValueByKeyUnsafe(const char* key) const { std::string_view key_view(key); uint32_t offset = 0; diff --git a/runtime/oat/oat.h b/runtime/oat/oat.h index 0061c90da9..2069b569e3 100644 --- a/runtime/oat/oat.h +++ b/runtime/oat/oat.h @@ -164,7 +164,14 @@ class EXPORT PACKED(4) OatHeader { uint32_t GetKeyValueStoreSize() const; const uint8_t* GetKeyValueStore() const; - const char* GetStoreValueByKey(const char* key) const; + const char* GetStoreValueByKeyUnsafe(const char* key) const; + + const char* GetStoreValueByKey(const char* key) const { + // Do not get apex versions from the oat header directly. Use `OatFile::GetApexVersions` + // instead. + DCHECK_NE(std::string_view(key), kApexVersionsKey); + return GetStoreValueByKeyUnsafe(key); + } // Returns the next key-value pair, at the given offset. On success, updates `offset`. // The expected use case is to start the iteration with an offset initialized to zero and diff --git a/runtime/oat/oat_file.cc b/runtime/oat/oat_file.cc index 1ecad4abf9..3f72401f43 100644 --- a/runtime/oat/oat_file.cc +++ b/runtime/oat/oat_file.cc @@ -2586,4 +2586,13 @@ bool OatFile::IsBackedByVdexOnly() const { return oat_dex_files_storage_.size() >= 1 && oat_dex_files_storage_[0]->IsBackedByVdexOnly(); } +std::optional<std::string_view> OatFile::GetApexVersions() const { + if (override_apex_versions_.has_value()) { + return override_apex_versions_; + } + const char* oat_apex_versions = + GetOatHeader().GetStoreValueByKeyUnsafe(OatHeader::kApexVersionsKey); + return oat_apex_versions != nullptr ? std::make_optional(oat_apex_versions) : std::nullopt; +} + } // namespace art diff --git a/runtime/oat/oat_file.h b/runtime/oat/oat_file.h index 9e66e1d4a7..53f1d173d1 100644 --- a/runtime/oat/oat_file.h +++ b/runtime/oat/oat_file.h @@ -19,6 +19,7 @@ #include <list> #include <memory> +#include <optional> #include <string> #include <string_view> #include <vector> @@ -426,6 +427,8 @@ class OatFile { // Returns the mapping info of `dex_file` if found in the BcpBssInfo, or nullptr otherwise. const BssMappingInfo* FindBcpMappingInfo(const DexFile* dex_file) const; + std::optional<std::string_view> GetApexVersions() const; + protected: OatFile(const std::string& filename, bool executable); @@ -518,6 +521,9 @@ class OatFile { // by the `dex_filenames` parameter, in case the OatFile does not embed the dex code. std::vector<std::unique_ptr<const DexFile>> external_dex_files_; + // If set, overrides the APEX versions in the header. + std::optional<std::string> override_apex_versions_ = std::nullopt; + friend class gc::collector::FakeOatFile; // For modifying begin_ and end_. friend class OatClass; friend class art::OatDexFile; diff --git a/runtime/oat/oat_file_assistant.cc b/runtime/oat/oat_file_assistant.cc index f5d6832cff..8df8459589 100644 --- a/runtime/oat/oat_file_assistant.cc +++ b/runtime/oat/oat_file_assistant.cc @@ -491,10 +491,7 @@ OatFileAssistant::OatStatus OatFileAssistant::GivenOatFileStatus(const OatFile& return kOatBootImageOutOfDate; } if (!gc::space::ImageSpace::ValidateApexVersions( - file.GetOatHeader(), - GetOatFileAssistantContext()->GetApexVersions(), - file.GetLocation(), - error_msg)) { + file, GetOatFileAssistantContext()->GetApexVersions(), error_msg)) { return kOatBootImageOutOfDate; } } |