Combine checksum of all boot images.
Allows a change to be detected in more than just the first image.
Combines checksums of all boot images using xor. A better hash is left
as TODO.
Bug: 28054110
(cherry-picked from commit 4f351aae00f43dd4e3290976f249d3664cc47091)
Change-Id: Ia557e2460ca582082368ef93508c04ce32c3036a
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 0889098..370583e 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -68,6 +68,7 @@
#include "mirror/class_loader.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
+#include "oat_file_assistant.h"
#include "oat_writer.h"
#include "os.h"
#include "runtime.h"
@@ -1325,7 +1326,7 @@
TimingLogger::ScopedTiming t3("Loading image checksum", timings_);
std::vector<gc::space::ImageSpace*> image_spaces =
Runtime::Current()->GetHeap()->GetBootImageSpaces();
- image_file_location_oat_checksum_ = image_spaces[0]->GetImageHeader().GetOatChecksum();
+ image_file_location_oat_checksum_ = OatFileAssistant::CalculateCombinedImageChecksum();
image_file_location_oat_data_begin_ =
reinterpret_cast<uintptr_t>(image_spaces[0]->GetImageHeader().GetOatDataBegin());
image_patch_delta_ = image_spaces[0]->GetImageHeader().GetPatchDelta();
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 32e95e7..f0768f9 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -495,7 +495,7 @@
return true;
}
- if (file.GetOatHeader().GetImageFileLocationOatChecksum() != image_info->oat_checksum) {
+ if (file.GetOatHeader().GetImageFileLocationOatChecksum() != GetCombinedImageChecksum()) {
VLOG(oat) << "Oat image checksum does not match image checksum.";
return true;
}
@@ -931,8 +931,7 @@
cached_image_info_.patch_delta = image_header.GetPatchDelta();
} else {
std::unique_ptr<ImageHeader> image_header(
- gc::space::ImageSpace::ReadImageHeaderOrDie(
- cached_image_info_.location.c_str(), isa_));
+ gc::space::ImageSpace::ReadImageHeaderOrDie(cached_image_info_.location.c_str(), isa_));
cached_image_info_.oat_checksum = image_header->GetOatChecksum();
cached_image_info_.oat_data_begin = reinterpret_cast<uintptr_t>(
image_header->GetOatDataBegin());
@@ -940,10 +939,30 @@
}
}
image_info_load_succeeded_ = (!image_spaces.empty());
+
+ combined_image_checksum_ = CalculateCombinedImageChecksum();
}
return image_info_load_succeeded_ ? &cached_image_info_ : nullptr;
}
+// TODO: Use something better than xor.
+uint32_t OatFileAssistant::CalculateCombinedImageChecksum() {
+ uint32_t checksum = 0;
+ std::vector<gc::space::ImageSpace*> image_spaces =
+ Runtime::Current()->GetHeap()->GetBootImageSpaces();
+ for (gc::space::ImageSpace* image_space : image_spaces) {
+ checksum ^= image_space->GetImageHeader().GetOatChecksum();
+ }
+ return checksum;
+}
+
+uint32_t OatFileAssistant::GetCombinedImageChecksum() {
+ if (!image_info_load_attempted_) {
+ GetImageInfo();
+ }
+ return combined_image_checksum_;
+}
+
gc::space::ImageSpace* OatFileAssistant::OpenImageSpace(const OatFile* oat_file) {
DCHECK(oat_file != nullptr);
std::string art_file = ArtFileName(oat_file);
diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h
index 17f72fe..63b1573 100644
--- a/runtime/oat_file_assistant.h
+++ b/runtime/oat_file_assistant.h
@@ -279,6 +279,8 @@
static bool DexFilenameToOdexFilename(const std::string& location,
InstructionSet isa, std::string* odex_filename, std::string* error_msg);
+ static uint32_t CalculateCombinedImageChecksum();
+
private:
struct ImageInfo {
uint32_t oat_checksum = 0;
@@ -352,6 +354,8 @@
// The caller shouldn't clean up or free the returned pointer.
const ImageInfo* GetImageInfo();
+ uint32_t GetCombinedImageChecksum();
+
// To implement Lock(), we lock a dummy file where the oat file would go
// (adding ".flock" to the target file name) and retain the lock for the
// remaining lifetime of the OatFileAssistant object.
@@ -423,6 +427,7 @@
bool image_info_load_attempted_ = false;
bool image_info_load_succeeded_ = false;
ImageInfo cached_image_info_;
+ uint32_t combined_image_checksum_ = 0;
// For debugging only.
// If this flag is set, the oat or odex file has been released to the user
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index bddfa4f..f50d1cb 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -239,7 +239,8 @@
ASSERT_TRUE(!image_spaces.empty() && image_spaces[0] != nullptr);
const ImageHeader& image_header = image_spaces[0]->GetImageHeader();
const OatHeader& oat_header = odex_file->GetOatHeader();
- EXPECT_EQ(image_header.GetOatChecksum(), oat_header.GetImageFileLocationOatChecksum());
+ uint32_t combined_checksum = OatFileAssistant::CalculateCombinedImageChecksum();
+ EXPECT_EQ(combined_checksum, oat_header.GetImageFileLocationOatChecksum());
EXPECT_NE(reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin()),
oat_header.GetImageFileLocationOatDataBegin());
EXPECT_NE(image_header.GetPatchDelta(), oat_header.GetImagePatchDelta());