Reject boot images if there is a read barrier state mismatch.
This check is done for apps
(https://cs.android.com/android/platform/superproject/+/master:art/runtime/oat_file_assistant.cc;l=540;drc=b7a86cb474c180bcb93dfefb420bee00c0b70103).
It should be done for boot images as well.
Bug: 242553398
Test: Presubmit
Change-Id: I1fa5a4efe204611c8af58d006c7a04c002b6c184
(cherry picked from commit c396050efabcc0154bc883dcefeb5ab41d998bcd)
Merged-In: I1fa5a4efe204611c8af58d006c7a04c002b6c184
diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h
index b570d99..39ce4d7 100644
--- a/dex2oat/linker/image_test.h
+++ b/dex2oat/linker/image_test.h
@@ -50,6 +50,7 @@
#include "mirror/object-inl.h"
#include "oat.h"
#include "oat_writer.h"
+#include "read_barrier_config.h"
#include "scoped_thread_state_change-inl.h"
#include "signal_catcher.h"
#include "stream/buffered_output_stream.h"
@@ -229,6 +230,8 @@
key_value_store.Put(OatHeader::kBootClassPathKey,
android::base::Join(out_helper.dex_file_locations, ':'));
key_value_store.Put(OatHeader::kApexVersionsKey, Runtime::Current()->GetApexVersions());
+ key_value_store.Put(OatHeader::kConcurrentCopying,
+ gUseReadBarrier ? OatHeader::kTrueValue : OatHeader::kFalseValue);
std::vector<std::unique_ptr<ElfWriter>> elf_writers;
std::vector<std::unique_ptr<OatWriter>> oat_writers;
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 4deb089..5eee76b 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -49,6 +49,7 @@
#include "dex/art_dex_file_loader.h"
#include "dex/dex_file_loader.h"
#include "exec_utils.h"
+#include "fmt/format.h"
#include "gc/accounting/space_bitmap-inl.h"
#include "gc/task_processor.h"
#include "image-inl.h"
@@ -69,14 +70,20 @@
namespace gc {
namespace space {
-using android::base::Join;
-using android::base::StringAppendF;
-using android::base::StringPrintf;
+namespace {
+
+using ::android::base::Join;
+using ::android::base::StringAppendF;
+using ::android::base::StringPrintf;
+
+using ::fmt::literals::operator""_format; // NOLINT
// We do not allow the boot image and extensions to take more than 1GiB. They are
// supposed to be much smaller and allocating more that this would likely fail anyway.
static constexpr size_t kMaxTotalImageReservationSize = 1 * GB;
+} // namespace
+
Atomic<uint32_t> ImageSpace::bitmap_index_(0);
ImageSpace::ImageSpace(const std::string& image_filename,
@@ -3583,6 +3590,15 @@
return false;
}
+ // For a boot image, the key value store only exists in the first OAT file. Skip other OAT files.
+ if (oat_file.GetOatHeader().GetKeyValueStoreSize() != 0 &&
+ oat_file.GetOatHeader().IsConcurrentCopying() != gUseReadBarrier) {
+ *error_msg =
+ "ValidateOatFile found read barrier state mismatch (oat file: {}, runtime: {})"_format(
+ oat_file.GetOatHeader().IsConcurrentCopying(), gUseReadBarrier);
+ return false;
+ }
+
const ArtDexFileLoader dex_file_loader;
size_t dex_file_index = 0;
for (const OatDexFile* oat_dex_file : oat_file.GetOatDexFiles()) {