Fix boot image size check.

Test: aosp_taimen-userdebug boots when built with
      export DEXPREOPT_USE_ART_IMAGE=true
      and logcat shows no messages about failing to open
      the app image services.art .
Bug: 150668267
Change-Id: I800ef2e09e3a61fe4c8418ba4d66f54dd605495e
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 9e3d201..147c6b4 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -975,6 +975,7 @@
     uint32_t checksum = 0u;
     size_t chunk_count = 0u;
     size_t space_pos = 0u;
+    uint64_t boot_image_size = 0u;
     for (size_t component_count = 0u; component_count != boot_image_component_count; ) {
       const ImageHeader& current_header = image_spaces[space_pos]->GetImageHeader();
       if (current_header.GetComponentCount() > boot_image_component_count - component_count) {
@@ -990,14 +991,22 @@
       checksum ^= current_header.GetImageChecksum();
       chunk_count += 1u;
       space_pos += current_header.GetImageSpaceCount();
+      boot_image_size += current_header.GetImageReservationSize();
     }
     if (image_header.GetBootImageChecksum() != checksum) {
-      *error_msg = StringPrintf("Boot image checksum mismatch (0x%x != 0x%x) in image %s",
+      *error_msg = StringPrintf("Boot image checksum mismatch (0x%08x != 0x%08x) in image %s",
                                 image_header.GetBootImageChecksum(),
                                 checksum,
                                 image_filename);
       return false;
     }
+    if (image_header.GetBootImageSize() != boot_image_size) {
+      *error_msg = StringPrintf("Boot image size (0x%08x != 0x%08" PRIx64 ") in image %s",
+                                image_header.GetBootImageSize(),
+                                boot_image_size,
+                                image_filename);
+      return false;
+    }
     // Oat checksums, if present, have already been validated, so we know that
     // they match the loaded image spaces. Therefore, we just verify that they
     // are consistent in the number of boot image chunks they list by looking
@@ -1263,19 +1272,7 @@
     // Set up sections.
     gc::Heap* const heap = Runtime::Current()->GetHeap();
     uint32_t boot_image_begin = heap->GetBootImagesStartAddress();
-    uint32_t boot_image_size = heap->GetBootImagesSize();
-    if (boot_image_size == 0u) {
-      *error_msg = "Can not relocate app image without boot image space";
-      return false;
-    }
-    const uint32_t image_header_boot_image_size = image_header.GetBootImageSize();
-    if (boot_image_size != image_header_boot_image_size) {
-      *error_msg = StringPrintf("Boot image size %" PRIu64 " does not match expected size %"
-                                    PRIu64,
-                                static_cast<uint64_t>(boot_image_size),
-                                static_cast<uint64_t>(image_header_boot_image_size));
-      return false;
-    }
+    const uint32_t boot_image_size = image_header.GetBootImageSize();
     const ImageSection& objects_section = image_header.GetObjectsSection();
     // Where the app image objects are mapped to.
     uint8_t* objects_location = target_base + objects_section.Offset();
@@ -1517,8 +1514,8 @@
     uint32_t reservation_size;
     uint32_t checksum;
     uint32_t boot_image_component_count;
-    uint32_t boot_image_space_count;
     uint32_t boot_image_checksum;
+    uint32_t boot_image_size;
 
     // The following file descriptors hold the memfd files for extensions compiled
     // in memory and described by the above fields. We want to use them to mmap()
@@ -1625,13 +1622,11 @@
 
   bool ValidateBootImageChecksum(const char* file_description,
                                  const ImageHeader& header,
-                                 /*out*/uint32_t* boot_image_space_count,
                                  /*out*/std::string* error_msg);
 
   bool ValidateHeader(const ImageHeader& header,
                       size_t bcp_index,
                       const char* file_description,
-                      /*out*/uint32_t* boot_image_space_count,
                       /*out*/std::string* error_msg);
 
   bool ReadHeader(const std::string& base_location,
@@ -1856,7 +1851,6 @@
 
 bool ImageSpace::BootImageLayout::ValidateBootImageChecksum(const char* file_description,
                                                             const ImageHeader& header,
-                                                            /*out*/uint32_t* boot_image_space_count,
                                                             /*out*/std::string* error_msg) {
   uint32_t boot_image_component_count = header.GetBootImageComponentCount();
   if (chunks_.empty() != (boot_image_component_count == 0u)) {
@@ -1868,7 +1862,7 @@
   }
   uint32_t component_count = 0u;
   uint32_t composite_checksum = 0u;
-  *boot_image_space_count = 0u;
+  uint64_t boot_image_size = 0u;
   for (const ImageChunk& chunk : chunks_) {
     if (component_count == boot_image_component_count) {
       break;  // Hit the component count.
@@ -1887,7 +1881,7 @@
     }
     component_count += chunk.component_count;
     composite_checksum ^= chunk.checksum;
-    *boot_image_space_count += chunk.image_space_count;
+    boot_image_size += chunk.reservation_size;
   }
   DCHECK_LE(component_count, boot_image_component_count);
   if (component_count != boot_image_component_count) {
@@ -1904,13 +1898,19 @@
                               composite_checksum);
     return false;
   }
+  if (boot_image_size != header.GetBootImageSize()) {
+    *error_msg = StringPrintf("Boot image size mismatch in %s: 0x%08x != 0x%08" PRIx64,
+                              file_description,
+                              header.GetBootImageSize(),
+                              boot_image_size);
+    return false;
+  }
   return true;
 }
 
 bool ImageSpace::BootImageLayout::ValidateHeader(const ImageHeader& header,
                                                  size_t bcp_index,
                                                  const char* file_description,
-                                                 /*out*/uint32_t* boot_image_space_count,
                                                  /*out*/std::string* error_msg) {
   size_t bcp_component_count = boot_class_path_.size();
   DCHECK_LT(bcp_index, bcp_component_count);
@@ -1934,7 +1934,7 @@
                               allowed_reservation_size);
     return false;
   }
-  if (!ValidateBootImageChecksum(file_description, header, boot_image_space_count, error_msg)) {
+  if (!ValidateBootImageChecksum(file_description, header, error_msg)) {
     return false;
   }
 
@@ -1954,8 +1954,7 @@
     return false;
   }
   const char* file_description = actual_filename.c_str();
-  uint32_t boot_image_space_count;
-  if (!ValidateHeader(header, bcp_index, file_description, &boot_image_space_count, error_msg)) {
+  if (!ValidateHeader(header, bcp_index, file_description, error_msg)) {
     return false;
   }
 
@@ -1971,8 +1970,8 @@
   chunk.reservation_size = header.GetImageReservationSize();
   chunk.checksum = header.GetImageChecksum();
   chunk.boot_image_component_count = header.GetBootImageComponentCount();
-  chunk.boot_image_space_count = boot_image_space_count;
   chunk.boot_image_checksum = header.GetBootImageChecksum();
+  chunk.boot_image_size = header.GetBootImageSize();
   chunks_.push_back(std::move(chunk));
   next_bcp_index_ = bcp_index + header.GetComponentCount();
   total_component_count_ += header.GetComponentCount();
@@ -2140,9 +2139,8 @@
     }
     art_fd.reset(image_file.Release());
   }
-  uint32_t boot_image_space_count;
   const char* file_description = "compiled image file";
-  if (!ValidateHeader(header, bcp_index, file_description, &boot_image_space_count, error_msg)) {
+  if (!ValidateHeader(header, bcp_index, file_description, error_msg)) {
     return false;
   }
 
@@ -2157,8 +2155,8 @@
   chunk.reservation_size = header.GetImageReservationSize();
   chunk.checksum = header.GetImageChecksum();
   chunk.boot_image_component_count = header.GetBootImageComponentCount();
-  chunk.boot_image_space_count = boot_image_space_count;
   chunk.boot_image_checksum = header.GetBootImageChecksum();
+  chunk.boot_image_size = header.GetBootImageSize();
   chunk.art_fd.reset(art_fd.release());
   chunk.vdex_fd.reset(vdex_fd.release());
   chunk.oat_fd.reset(oat_fd.release());
@@ -3147,12 +3145,14 @@
       if (i == 0 && (chunk.checksum != header.GetImageChecksum() ||
                      chunk.image_space_count != header.GetImageSpaceCount() ||
                      chunk.boot_image_component_count != header.GetBootImageComponentCount() ||
-                     chunk.boot_image_checksum != header.GetBootImageChecksum())) {
+                     chunk.boot_image_checksum != header.GetBootImageChecksum() ||
+                     chunk.boot_image_size != header.GetBootImageSize())) {
         *error_msg = StringPrintf("Image header modified since previously read from %s; "
                                       "checksum: 0x%08x -> 0x%08x,"
                                       "image_space_count: %u -> %u"
                                       "boot_image_component_count: %u -> %u, "
-                                      "boot_image_checksum: 0x%08x -> 0x%08x",
+                                      "boot_image_checksum: 0x%08x -> 0x%08x"
+                                      "boot_image_size: 0x%08x -> 0x%08x",
                                   space->GetImageFilename().c_str(),
                                   chunk.checksum,
                                   chunk.image_space_count,
@@ -3161,7 +3161,9 @@
                                   chunk.boot_image_component_count,
                                   header.GetBootImageComponentCount(),
                                   chunk.boot_image_checksum,
-                                  header.GetBootImageChecksum());
+                                  header.GetBootImageChecksum(),
+                                  chunk.boot_image_size,
+                                  header.GetBootImageSize());
         return false;
       }
     }