Add oat file dependency on boot.oat load location

Change-Id: I89742e361675bd4e5177e3af213bcc826ddd60de
diff --git a/src/class_linker.cc b/src/class_linker.cc
index b96db3e..a76c9c8 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -743,7 +743,11 @@
   }
   Runtime* runtime = Runtime::Current();
   const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
-  if (oat_file->GetOatHeader().GetImageFileLocationChecksum() != image_header.GetOatChecksum()) {
+  if (oat_file->GetOatHeader().GetImageFileLocationOatChecksum() != image_header.GetOatChecksum()) {
+    return NULL;
+  }
+  if (oat_file->GetOatHeader().GetImageFileLocationOatBegin()
+      != reinterpret_cast<uint32_t>(image_header.GetOatBegin())) {
     return NULL;
   }
   const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
@@ -814,8 +818,10 @@
                                          uint32_t dex_location_checksum) {
   Runtime* runtime = Runtime::Current();
   const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
-  uint32_t image_checksum = image_header.GetOatChecksum();
-  bool image_check = (oat_file->GetOatHeader().GetImageFileLocationChecksum() == image_checksum);
+  uint32_t image_oat_checksum = image_header.GetOatChecksum();
+  uint32_t image_oat_begin = reinterpret_cast<uint32_t>(image_header.GetOatBegin());
+  bool image_check = ((oat_file->GetOatHeader().GetImageFileLocationOatChecksum() == image_oat_checksum)
+                      && (oat_file->GetOatHeader().GetImageFileLocationOatBegin() == image_oat_begin));
 
   const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
   if (oat_dex_file == NULL) {
@@ -829,7 +835,7 @@
     }
     return false;
   }
-  bool dex_check = (dex_location_checksum == oat_dex_file->GetDexFileLocationChecksum());
+  bool dex_check = dex_location_checksum == oat_dex_file->GetDexFileLocationChecksum();
 
   if (image_check && dex_check) {
     return true;
@@ -839,14 +845,15 @@
     std::string image_file(image_header.GetImageRoot(
         ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8());
     LOG(WARNING) << ".oat file " << oat_file->GetLocation()
-                 << " checksum ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
-                 << ") mismatch with " << image_file
-                 << " (" << std::hex << image_checksum << ")";
+                 << " mismatch ( " << std::hex << oat_file->GetOatHeader().GetImageFileLocationOatChecksum()
+                 << ", " << oat_file->GetOatHeader().GetImageFileLocationOatBegin()
+                 << ") with " << image_file
+                 << " (" << image_oat_checksum << ", " << std::hex << image_oat_begin << ")";
   }
   if (!dex_check) {
     LOG(WARNING) << ".oat file " << oat_file->GetLocation()
-                 << " checksum ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
-                 << ") mismatch with " << dex_location
+                 << " mismatch ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
+                 << ") with " << dex_location
                  << " (" << std::hex << dex_location_checksum << ")";
   }
   return false;
@@ -958,7 +965,8 @@
   ImageSpace* space = heap->GetImageSpace();
   OatFile* oat_file = OpenOat(space);
   CHECK(oat_file != NULL) << "Failed to open oat file for image";
-  CHECK_EQ(oat_file->GetOatHeader().GetImageFileLocationChecksum(), 0U);
+  CHECK_EQ(oat_file->GetOatHeader().GetImageFileLocationOatChecksum(), 0U);
+  CHECK_EQ(oat_file->GetOatHeader().GetImageFileLocationOatBegin(), 0U);
   CHECK(oat_file->GetOatHeader().GetImageFileLocation().empty());
   Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches);
   ObjectArray<DexCache>* dex_caches = dex_caches_object->AsObjectArray<DexCache>();
diff --git a/src/class_linker.h b/src/class_linker.h
index 460fcd2..f1530f3 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -302,7 +302,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 
-  // Returns true if oat file contains the dex file with the given location and checksum
+  // Returns true if oat file contains the dex file with the given location and checksum.
   static bool VerifyOatFileChecksums(const OatFile* oat_file,
                                      const std::string& dex_location,
                                      uint32_t dex_location_checksum)
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index d20d7ab..20872e1 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -253,11 +253,13 @@
     Thread::Current()->TransitionFromSuspendedToRunnable();
 
     std::string image_file_location;
-    uint32_t image_file_location_checksum = 0;
+    uint32_t image_file_location_oat_checksum = 0;
+    uint32_t image_file_location_oat_begin = 0;
     Heap* heap = Runtime::Current()->GetHeap();
     if (heap->GetSpaces().size() > 1) {
       ImageSpace* image_space = heap->GetImageSpace();
-      image_file_location_checksum = image_space->GetImageHeader().GetOatChecksum();
+      image_file_location_oat_checksum = image_space->GetImageHeader().GetOatChecksum();
+      image_file_location_oat_begin = reinterpret_cast<uint32_t>(image_space->GetImageHeader().GetOatBegin());
       image_file_location = image_space->GetImageFilename();
       if (host_prefix != NULL && StartsWith(image_file_location, host_prefix->c_str())) {
         image_file_location = image_file_location.substr(host_prefix->size());
@@ -267,7 +269,8 @@
     if (!OatWriter::Create(oat_file,
                            class_loader,
                            dex_files,
-                           image_file_location_checksum,
+                           image_file_location_oat_checksum,
+                           image_file_location_oat_begin,
                            image_file_location,
                            *compiler.get())) {
       LOG(ERROR) << "Failed to create oat file " << oat_file->name();
diff --git a/src/dex_file.h b/src/dex_file.h
index f5e62c1..58a0b3f 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -347,7 +347,8 @@
 
   // Opens .dex file, backed by existing memory
   static const DexFile* Open(const uint8_t* base, size_t size,
-                             const std::string& location, uint32_t location_checksum) {
+                             const std::string& location,
+                             uint32_t location_checksum) {
     return OpenMemory(base, size, location, location_checksum, NULL);
   }
 
@@ -826,7 +827,8 @@
                                    MemMap* mem_map);
 
   DexFile(const byte* base, size_t size,
-          const std::string& location, uint32_t location_checksum,
+          const std::string& location,
+          uint32_t location_checksum,
           MemMap* mem_map)
       : begin_(base),
         size_(size),
diff --git a/src/image_test.cc b/src/image_test.cc
index 05ddc54..afccb4a 100644
--- a/src/image_test.cc
+++ b/src/image_test.cc
@@ -36,7 +36,7 @@
     ScopedObjectAccess soa(Thread::Current());
     std::vector<const DexFile*> dex_files;
     dex_files.push_back(java_lang_dex_file_);
-    bool success_oat = OatWriter::Create(tmp_oat.GetFile(), NULL, dex_files, 0, "", *compiler_.get());
+    bool success_oat = OatWriter::Create(tmp_oat.GetFile(), NULL, dex_files, 0, 0, "", *compiler_.get());
     ASSERT_TRUE(success_oat);
 
     // Force all system classes into memory
diff --git a/src/native/dalvik_system_DexFile.cc b/src/native/dalvik_system_DexFile.cc
index 3ef5e5c..a55d7f1 100644
--- a/src/native/dalvik_system_DexFile.cc
+++ b/src/native/dalvik_system_DexFile.cc
@@ -244,10 +244,18 @@
     if ((*cur)->IsImageSpace()) {
       // TODO: Ensure this works with multiple image spaces.
       const ImageHeader& image_header = (*cur)->AsImageSpace()->GetImageHeader();
-      if (oat_file->GetOatHeader().GetImageFileLocationChecksum() != image_header.GetOatChecksum()) {
+      if (oat_file->GetOatHeader().GetImageFileLocationOatChecksum() != image_header.GetOatChecksum()) {
         ScopedObjectAccess soa(env);
         LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location
-                  << " has out-of-date checksum compared to "
+                  << " has out-of-date oat checksum compared to "
+                  << image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8();
+        return JNI_TRUE;
+      }
+      if (oat_file->GetOatHeader().GetImageFileLocationOatBegin()
+          != reinterpret_cast<uint32_t>(image_header.GetOatBegin())) {
+        ScopedObjectAccess soa(env);
+        LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location
+                  << " has out-of-date oat begin compared to "
                   << image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8();
         return JNI_TRUE;
       }
diff --git a/src/oat.cc b/src/oat.cc
index 4df4543..6284f9a 100644
--- a/src/oat.cc
+++ b/src/oat.cc
@@ -21,7 +21,7 @@
 namespace art {
 
 const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' };
-const uint8_t OatHeader::kOatVersion[] = { '0', '0', '2', '\0' };
+const uint8_t OatHeader::kOatVersion[] = { '0', '0', '3', '\0' };
 
 OatHeader::OatHeader() {
   memset(this, 0, sizeof(*this));
@@ -29,7 +29,8 @@
 
 OatHeader::OatHeader(InstructionSet instruction_set,
                      const std::vector<const DexFile*>* dex_files,
-                     uint32_t image_file_location_checksum,
+                     uint32_t image_file_location_oat_checksum,
+                     uint32_t image_file_location_oat_begin,
                      const std::string& image_file_location) {
   memcpy(magic_, kOatMagic, sizeof(kOatMagic));
   memcpy(version_, kOatVersion, sizeof(kOatVersion));
@@ -42,8 +43,12 @@
   dex_file_count_ = dex_files->size();
   UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_));
 
-  image_file_location_checksum_ = image_file_location_checksum;
-  UpdateChecksum(&image_file_location_checksum_, sizeof(image_file_location_checksum_));
+  image_file_location_oat_checksum_ = image_file_location_oat_checksum;
+  UpdateChecksum(&image_file_location_oat_checksum_, sizeof(image_file_location_oat_checksum_));
+
+  CHECK(IsAligned<kPageSize>(image_file_location_oat_begin));
+  image_file_location_oat_begin_ = image_file_location_oat_begin;
+  UpdateChecksum(&image_file_location_oat_begin_, sizeof(image_file_location_oat_begin_));
 
   image_file_location_size_ = image_file_location.size();
   UpdateChecksum(&image_file_location_size_, sizeof(image_file_location_size_));
@@ -95,9 +100,14 @@
   return executable_offset_;
 }
 
-uint32_t OatHeader::GetImageFileLocationChecksum() const {
+uint32_t OatHeader::GetImageFileLocationOatChecksum() const {
   CHECK(IsValid());
-  return image_file_location_checksum_;
+  return image_file_location_oat_checksum_;
+}
+
+uint32_t OatHeader::GetImageFileLocationOatBegin() const {
+  CHECK(IsValid());
+  return image_file_location_oat_begin_;
 }
 
 uint32_t OatHeader::GetImageFileLocationSize() const {
diff --git a/src/oat.h b/src/oat.h
index cd3330b..96ed4c4 100644
--- a/src/oat.h
+++ b/src/oat.h
@@ -30,7 +30,8 @@
   OatHeader();
   OatHeader(InstructionSet instruction_set,
             const std::vector<const DexFile*>* dex_files,
-            uint32_t image_file_location_checksum,
+            uint32_t image_file_location_oat_checksum,
+            uint32_t image_file_location_oat_begin,
             const std::string& image_file_location);
 
   bool IsValid() const;
@@ -41,7 +42,8 @@
   uint32_t GetExecutableOffset() const;
   InstructionSet GetInstructionSet() const;
   void SetExecutableOffset(uint32_t executable_offset);
-  uint32_t GetImageFileLocationChecksum() const;
+  uint32_t GetImageFileLocationOatChecksum() const;
+  uint32_t GetImageFileLocationOatBegin() const;
   uint32_t GetImageFileLocationSize() const;
   const uint8_t* GetImageFileLocationData() const;
   std::string GetImageFileLocation() const;
@@ -58,7 +60,8 @@
   uint32_t dex_file_count_;
   uint32_t executable_offset_;
 
-  uint32_t image_file_location_checksum_;
+  uint32_t image_file_location_oat_checksum_;
+  uint32_t image_file_location_oat_begin_;
   uint32_t image_file_location_size_;
   uint8_t image_file_location_data_[0];  // note variable width data at end
 
diff --git a/src/oat_file.cc b/src/oat_file.cc
index 93ff7a6..58ba44c 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -230,7 +230,8 @@
 
 const DexFile* OatFile::OatDexFile::OpenDexFile() const {
   size_t length = reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_;
-  return DexFile::Open(dex_file_pointer_, length, dex_file_location_, dex_file_location_checksum_);
+  return DexFile::Open(dex_file_pointer_, length, dex_file_location_,
+                       dex_file_location_checksum_);
 }
 
 const OatFile::OatClass* OatFile::OatDexFile::GetOatClass(uint32_t class_def_index) const {
diff --git a/src/oat_test.cc b/src/oat_test.cc
index 788d1c7..3df831c 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -75,6 +75,7 @@
                                    class_loader,
                                    class_linker->GetBootClassPath(),
                                    42U,
+                                   4096U,
                                    "lue.art",
                                    *compiler_.get());
   ASSERT_TRUE(success);
@@ -89,7 +90,8 @@
   ASSERT_TRUE(oat_file.get() != NULL);
   const OatHeader& oat_header = oat_file->GetOatHeader();
   ASSERT_EQ(1U, oat_header.GetDexFileCount());
-  ASSERT_EQ(42U, oat_header.GetImageFileLocationChecksum());
+  ASSERT_EQ(42U, oat_header.GetImageFileLocationOatChecksum());
+  ASSERT_EQ(4096U, oat_header.GetImageFileLocationOatBegin());
   ASSERT_EQ("lue.art", oat_header.GetImageFileLocation());
 
   const DexFile* dex_file = java_lang_dex_file_;
@@ -124,7 +126,7 @@
 TEST_F(OatTest, OatHeaderSizeCheck) {
   // If this test is failing and you have to update these constants,
   // it is time to update OatHeader::kOatVersion
-  EXPECT_EQ(32U, sizeof(OatHeader));
+  EXPECT_EQ(36U, sizeof(OatHeader));
 #if !defined(ART_USE_LLVM_COMPILER)
   EXPECT_EQ(32U, sizeof(OatMethodOffsets));
 #else
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index 72ac6e6..e26e3cc 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -33,11 +33,13 @@
 bool OatWriter::Create(File* file,
                        jobject class_loader,
                        const std::vector<const DexFile*>& dex_files,
-                       uint32_t image_file_location_checksum,
+                       uint32_t image_file_location_oat_checksum,
+                       uint32_t image_file_location_oat_begin,
                        const std::string& image_file_location,
                        const Compiler& compiler) {
   OatWriter oat_writer(dex_files,
-                       image_file_location_checksum,
+                       image_file_location_oat_checksum,
+                       image_file_location_oat_begin,
                        image_file_location,
                        class_loader,
                        compiler);
@@ -45,13 +47,15 @@
 }
 
 OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files,
-                     uint32_t image_file_location_checksum,
+                     uint32_t image_file_location_oat_checksum,
+                     uint32_t image_file_location_oat_begin,
                      const std::string& image_file_location,
                      jobject class_loader,
                      const Compiler& compiler) {
   compiler_ = &compiler;
   class_loader_ = class_loader;
-  image_file_location_checksum_ = image_file_location_checksum;
+  image_file_location_oat_checksum_ = image_file_location_oat_checksum;
+  image_file_location_oat_begin_ = image_file_location_oat_begin;
   image_file_location_ = image_file_location;
   dex_files_ = &dex_files;
   oat_header_ = NULL;
@@ -77,7 +81,8 @@
   // create the OatHeader
   oat_header_ = new OatHeader(compiler_->GetInstructionSet(),
                               dex_files_,
-                              image_file_location_checksum_,
+                              image_file_location_oat_checksum_,
+                              image_file_location_oat_begin_,
                               image_file_location_);
   size_t offset = sizeof(*oat_header_);
   offset += image_file_location_.size();
diff --git a/src/oat_writer.h b/src/oat_writer.h
index fd8e2b2..09db96b 100644
--- a/src/oat_writer.h
+++ b/src/oat_writer.h
@@ -66,14 +66,16 @@
   static bool Create(File* file,
                      jobject class_loader,
                      const std::vector<const DexFile*>& dex_files,
-                     uint32_t image_file_location_checksum,
+                     uint32_t image_file_location_oat_checksum,
+                     uint32_t image_file_location_oat_begin,
                      const std::string& image_file_location,
                      const Compiler& compiler)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
  private:
   OatWriter(const std::vector<const DexFile*>& dex_files,
-            uint32_t image_file_location_checksum,
+            uint32_t image_file_location_oat_checksum,
+            uint32_t image_file_location_oat_begin,
             const std::string& image_file_location,
             jobject class_loader,
             const Compiler& compiler) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -156,8 +158,9 @@
   // note OatFile does not take ownership of the DexFiles
   const std::vector<const DexFile*>* dex_files_;
 
-  // dependency on the image
-  uint32_t image_file_location_checksum_;
+  // dependencies on the image.
+  uint32_t image_file_location_oat_checksum_;
+  uint32_t image_file_location_oat_begin_;
   std::string image_file_location_;
 
   // data to write
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 866c180..6c7e2ef 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -113,8 +113,11 @@
     os << "EXECUTABLE OFFSET:\n";
     os << StringPrintf("0x%08x\n\n", oat_header.GetExecutableOffset());
 
-    os << "IMAGE FILE LOCATION CHECKSUM:\n";
-    os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationChecksum());
+    os << "IMAGE FILE LOCATION OAT CHECKSUM:\n";
+    os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationOatChecksum());
+
+    os << "IMAGE FILE LOCATION OAT BEGIN:\n";
+    os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationOatBegin());
 
     os << "IMAGE FILE LOCATION:\n";
     const std::string image_file_location(oat_header.GetImageFileLocation());