ART: Allow method references across oat files for multi-image, 2nd attempt.

These were disabled because we didn't have sufficient
information about the multi-image layout when processing
link-time patches in OatWriter. This CL refactors the
ELF file creation so that the information is available.

Also clean up ImageWriter to use oat file indexes instead
of filenames and avoid reopening the oat file to retrieve
the checksum.

Change-Id: Icc7b528deca29da1e473c8f079521a36d6c4892f
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 541fb5a..9427eaf 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -65,6 +65,7 @@
 #include "interpreter/unstarted_runtime.h"
 #include "jit/offline_profiling_info.h"
 #include "leb128.h"
+#include "linker/multi_oat_relative_patcher.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/object-inl.h"
@@ -1408,7 +1409,7 @@
         if (opened_dex_files_map != nullptr) {
           opened_dex_files_maps_.push_back(std::move(opened_dex_files_map));
           for (std::unique_ptr<const DexFile>& dex_file : opened_dex_files) {
-            dex_file_oat_filename_map_.emplace(dex_file.get(), oat_filenames_[i]);
+            dex_file_oat_index_map_.emplace(dex_file.get(), i);
             opened_dex_files_.push_back(std::move(dex_file));
           }
         } else {
@@ -1557,13 +1558,12 @@
                                      IsBootImage(),
                                      image_classes_.release(),
                                      compiled_classes_.release(),
-                                     nullptr,
+                                     /* compiled_methods */ nullptr,
                                      thread_count_,
                                      dump_stats_,
                                      dump_passes_,
                                      compiler_phases_timings_.get(),
                                      swap_fd_,
-                                     &dex_file_oat_filename_map_,
                                      profile_compilation_info_.get()));
     driver_->SetDexFilesForOatFile(dex_files_);
     driver_->CompileAll(class_loader_, dex_files_, timings_);
@@ -1667,7 +1667,7 @@
                                           IsAppImage(),
                                           image_storage_mode_,
                                           oat_filenames_,
-                                          dex_file_oat_filename_map_));
+                                          dex_file_oat_index_map_));
 
       // We need to prepare method offsets in the image address space for direct method patching.
       TimingLogger::ScopedTiming t2("dex2oat Prepare image address space", timings_);
@@ -1677,21 +1677,39 @@
       }
     }
 
+    linker::MultiOatRelativePatcher patcher(instruction_set_, instruction_set_features_.get());
     {
       TimingLogger::ScopedTiming t2("dex2oat Write ELF", timings_);
       for (size_t i = 0, size = oat_files_.size(); i != size; ++i) {
+        std::unique_ptr<ElfWriter>& elf_writer = elf_writers_[i];
+        std::unique_ptr<OatWriter>& oat_writer = oat_writers_[i];
+
+        std::vector<const DexFile*>& dex_files = dex_files_per_oat_file_[i];
+        oat_writer->PrepareLayout(driver_.get(), image_writer_.get(), dex_files, &patcher);
+
+        size_t rodata_size = oat_writer->GetOatHeader().GetExecutableOffset();
+        size_t text_size = oat_writer->GetSize() - rodata_size;
+        elf_writer->SetLoadedSectionSizes(rodata_size, text_size, oat_writer->GetBssSize());
+
+        if (IsImage()) {
+          // Update oat layout.
+          DCHECK(image_writer_ != nullptr);
+          DCHECK_LT(i, oat_filenames_.size());
+          image_writer_->UpdateOatFileLayout(i,
+                                             elf_writer->GetLoadedSize(),
+                                             oat_writer->GetOatDataOffset(),
+                                             oat_writer->GetSize());
+        }
+      }
+
+      for (size_t i = 0, size = oat_files_.size(); i != size; ++i) {
         std::unique_ptr<File>& oat_file = oat_files_[i];
         std::unique_ptr<ElfWriter>& elf_writer = elf_writers_[i];
         std::unique_ptr<OatWriter>& oat_writer = oat_writers_[i];
 
-        std::vector<const DexFile*>& dex_files = dex_files_per_oat_file_[i];
-        oat_writer->PrepareLayout(driver_.get(), image_writer_.get(), dex_files);
-
         // We need to mirror the layout of the ELF file in the compressed debug-info.
-        // Therefore we need to propagate the sizes of at least those sections.
-        size_t rodata_size = oat_writer->GetOatHeader().GetExecutableOffset();
-        size_t text_size = oat_writer->GetSize() - rodata_size;
-        elf_writer->PrepareDebugInfo(rodata_size, text_size, oat_writer->GetMethodDebugInfo());
+        // Therefore PrepareDebugInfo() relies on the SetLoadedSectionSizes() call further above.
+        elf_writer->PrepareDebugInfo(oat_writer->GetMethodDebugInfo());
 
         OutputStream*& rodata = rodata_[i];
         DCHECK(rodata != nullptr);
@@ -1717,7 +1735,13 @@
           return false;
         }
 
-        elf_writer->SetBssSize(oat_writer->GetBssSize());
+        if (IsImage()) {
+          // Update oat header information.
+          DCHECK(image_writer_ != nullptr);
+          DCHECK_LT(i, oat_filenames_.size());
+          image_writer_->UpdateOatFileHeader(i, oat_writer->GetOatHeader());
+        }
+
         elf_writer->WriteDynamicSection();
         elf_writer->WriteDebugInfo(oat_writer->GetMethodDebugInfo());
         elf_writer->WritePatchLocations(oat_writer->GetAbsolutePatchLocations());
@@ -1731,19 +1755,10 @@
         if (oat_files_[i] != nullptr) {
           if (oat_files_[i]->Flush() != 0) {
             PLOG(ERROR) << "Failed to flush oat file: " << oat_filenames_[i];
-            oat_files_[i]->Erase();
             return false;
           }
         }
 
-        if (IsImage()) {
-          // Update oat estimates.
-          DCHECK(image_writer_ != nullptr);
-          DCHECK_LT(i, oat_filenames_.size());
-
-          image_writer_->UpdateOatFile(oat_file.get(), oat_filenames_[i]);
-        }
-
         VLOG(compiler) << "Oat file written successfully: " << oat_filenames_[i];
 
         oat_writer.reset();
@@ -2226,22 +2241,21 @@
     }
     if (!image_writer_->Write(app_image_fd_,
                               image_filenames_,
-                              oat_fd_,
-                              oat_filenames_,
-                              oat_location_)) {
+                              oat_filenames_)) {
       LOG(ERROR) << "Failure during image file creation";
       return false;
     }
 
     // We need the OatDataBegin entries.
-    std::map<const char*, uintptr_t> oat_data_begins;
-    for (const char* oat_filename : oat_filenames_) {
-      oat_data_begins.emplace(oat_filename, image_writer_->GetOatDataBegin(oat_filename));
+    dchecked_vector<uintptr_t> oat_data_begins;
+    for (size_t i = 0, size = oat_filenames_.size(); i != size; ++i) {
+      oat_data_begins.push_back(image_writer_->GetOatDataBegin(i));
     }
     // Destroy ImageWriter before doing FixupElf.
     image_writer_.reset();
 
-    for (const char* oat_filename : oat_filenames_) {
+    for (size_t i = 0, size = oat_filenames_.size(); i != size; ++i) {
+      const char* oat_filename = oat_filenames_[i];
       // Do not fix up the ELF file if we are --compile-pic or compiling the app image
       if (!compiler_options_->GetCompilePic() && IsBootImage()) {
         std::unique_ptr<File> oat_file(OS::OpenFileReadWrite(oat_filename));
@@ -2250,9 +2264,7 @@
           return false;
         }
 
-        uintptr_t oat_data_begin = oat_data_begins.find(oat_filename)->second;
-
-        if (!ElfWriter::Fixup(oat_file.get(), oat_data_begin)) {
+        if (!ElfWriter::Fixup(oat_file.get(), oat_data_begins[i])) {
           oat_file->Erase();
           LOG(ERROR) << "Failed to fixup ELF file " << oat_file->GetPath();
           return false;
@@ -2468,7 +2480,7 @@
   TimingLogger* timings_;
   std::unique_ptr<CumulativeLogger> compiler_phases_timings_;
   std::vector<std::vector<const DexFile*>> dex_files_per_oat_file_;
-  std::unordered_map<const DexFile*, const char*> dex_file_oat_filename_map_;
+  std::unordered_map<const DexFile*, size_t> dex_file_oat_index_map_;
 
   // Backing storage.
   std::vector<std::string> char_backing_storage_;