diff --git a/dex2oat/Android.bp b/dex2oat/Android.bp
index f13f01c..bdb8ff1 100644
--- a/dex2oat/Android.bp
+++ b/dex2oat/Android.bp
@@ -14,6 +14,78 @@
 // limitations under the License.
 //
 
+art_cc_defaults {
+    name: "libart-dex2oat-defaults",
+    defaults: ["art_defaults"],
+    host_supported: true,
+    clang: true,
+    srcs: [
+        "linker/elf_writer.cc",
+        "linker/elf_writer_quick.cc",
+        "linker/image_writer.cc",
+        "linker/multi_oat_relative_patcher.cc",
+        "linker/oat_writer.cc",
+    ],
+    target: {
+        host: {
+            // For compiler driver TLS.
+            host_ldlibs: ["-lpthread"],
+        },
+        android: {
+            // For atrace.
+            shared_libs: ["libcutils"],
+        },
+    },
+    generated_sources: ["art_dex2oat_operator_srcs"],
+    shared_libs: [
+        "libart-compiler",
+        "libart-dexlayout",
+        "libbase",
+        "liblz4",
+        "liblzma",
+    ],
+    export_include_dirs: ["."],
+
+    // For SHA-1 checksumming of build ID
+    static: {
+        whole_static_libs: ["libcrypto"],
+    },
+    shared: {
+        shared_libs: ["libcrypto"],
+    },
+}
+
+gensrcs {
+    name: "art_dex2oat_operator_srcs",
+    cmd: "$(location generate-operator-out.py) art/dex2oat $(in) > $(out)",
+    tool_files: ["generate-operator-out.py"],
+    srcs: [
+        "linker/image_writer.h",
+    ],
+    output_extension: "operator_out.cc",
+}
+
+art_cc_static_library {
+    name: "libart-dex2oat",
+    defaults: ["libart-dex2oat-defaults"],
+    shared_libs: [
+        "libart-compiler",
+        "libart"
+    ],
+}
+
+art_cc_static_library {
+    name: "libartd-dex2oat",
+    defaults: [
+        "art_debug_defaults",
+        "libart-dex2oat-defaults",
+    ],
+    shared_libs: [
+        "libartd-compiler",
+        "libartd"
+    ],
+}
+
 cc_library_headers {
     name: "dex2oat_headers",
     host_supported: true,
@@ -45,11 +117,16 @@
         "dex2oat-defaults",
     ],
     shared_libs: [
-        "libart",
         "libart-compiler",
+        "libart-dexlayout",
+        "libart",
         "libbase",
+        "liblz4",
         "libsigchain",
     ],
+    static_libs: [
+        "libart-dex2oat",
+    ]
 }
 
 art_cc_binary {
@@ -59,11 +136,16 @@
         "dex2oat-defaults",
     ],
     shared_libs: [
-        "libartd",
         "libartd-compiler",
+        "libartd-dexlayout",
+        "libartd",
         "libbase",
+        "liblz4",
         "libsigchain",
     ],
+    static_libs: [
+        "libartd-dex2oat",
+    ]
 }
 
 art_cc_binary {
@@ -85,6 +167,7 @@
         "-z muldefs",
     ],
     static_libs: [
+        "libart-dex2oat",
         "libart-compiler",
         "libart-dexlayout",
         "libart",
@@ -115,6 +198,7 @@
         "-z muldefs",
     ],
     static_libs: [
+        "libartd-dex2oat",
         "libartd-compiler",
         "libartd-dexlayout",
         "libartd",
@@ -131,6 +215,21 @@
     srcs: [
         "dex2oat_test.cc",
         "dex2oat_image_test.cc",
+        "linker/elf_writer_test.cc",
+        "linker/image_test.cc",
+        "linker/image_write_read_test.cc",
+        "linker/multi_oat_relative_patcher_test.cc",
+        "linker/oat_writer_test.cc",
     ],
     header_libs: ["dex2oat_headers"],
+    shared_libs: [
+        "libartd-compiler",
+        "libartd-dexlayout",
+        "libbase",
+        "liblz4",
+        "libsigchain",
+    ],
+    static_libs: [
+        "libartd-dex2oat",
+    ]
 }
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index d8caf42..21d3895 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -61,19 +61,20 @@
 #include "driver/compiler_driver.h"
 #include "driver/compiler_options.h"
 #include "elf_file.h"
-#include "elf_writer.h"
-#include "elf_writer_quick.h"
 #include "gc/space/image_space.h"
 #include "gc/space/space-inl.h"
 #include "gc/verification.h"
-#include "image_writer.h"
 #include "interpreter/unstarted_runtime.h"
 #include "java_vm_ext.h"
 #include "jit/profile_compilation_info.h"
 #include "leb128.h"
 #include "linker/buffered_output_stream.h"
+#include "linker/elf_writer.h"
+#include "linker/elf_writer_quick.h"
 #include "linker/file_output_stream.h"
+#include "linker/image_writer.h"
 #include "linker/multi_oat_relative_patcher.h"
+#include "linker/oat_writer.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/object-inl.h"
@@ -81,7 +82,6 @@
 #include "nativehelper/ScopedLocalRef.h"
 #include "oat_file.h"
 #include "oat_file_assistant.h"
-#include "oat_writer.h"
 #include "os.h"
 #include "runtime.h"
 #include "runtime_options.h"
@@ -1455,8 +1455,9 @@
     // Note: we're only invalidating the magic data in the file, as dex2oat needs the rest of
     // the information to remain valid.
     if (update_input_vdex_) {
-      std::unique_ptr<BufferedOutputStream> vdex_out = std::make_unique<BufferedOutputStream>(
-          std::make_unique<FileOutputStream>(vdex_files_.back().get()));
+      std::unique_ptr<linker::BufferedOutputStream> vdex_out =
+          std::make_unique<linker::BufferedOutputStream>(
+              std::make_unique<linker::FileOutputStream>(vdex_files_.back().get()));
       if (!vdex_out->WriteFully(&VdexFile::Header::kVdexInvalidMagic,
                                 arraysize(VdexFile::Header::kVdexInvalidMagic))) {
         PLOG(ERROR) << "Failed to invalidate vdex header. File: " << vdex_out->GetLocation();
@@ -2026,14 +2027,14 @@
         VLOG(compiler) << "App image base=" << reinterpret_cast<void*>(image_base_);
       }
 
-      image_writer_.reset(new ImageWriter(*driver_,
-                                          image_base_,
-                                          compiler_options_->GetCompilePic(),
-                                          IsAppImage(),
-                                          image_storage_mode_,
-                                          oat_filenames_,
-                                          dex_file_oat_index_map_,
-                                          dirty_image_objects_.get()));
+      image_writer_.reset(new linker::ImageWriter(*driver_,
+                                                  image_base_,
+                                                  compiler_options_->GetCompilePic(),
+                                                  IsAppImage(),
+                                                  image_storage_mode_,
+                                                  oat_filenames_,
+                                                  dex_file_oat_index_map_,
+                                                  dirty_image_objects_.get()));
 
       // We need to prepare method offsets in the image address space for direct method patching.
       TimingLogger::ScopedTiming t2("dex2oat Prepare image address space", timings_);
@@ -2046,7 +2047,7 @@
     // Initialize the writers with the compiler driver, image writer, and their
     // dex files. The writers were created without those being there yet.
     for (size_t i = 0, size = oat_files_.size(); i != size; ++i) {
-      std::unique_ptr<OatWriter>& oat_writer = oat_writers_[i];
+      std::unique_ptr<linker::OatWriter>& oat_writer = oat_writers_[i];
       std::vector<const DexFile*>& dex_files = dex_files_per_oat_file_[i];
       oat_writer->Initialize(driver_.get(), image_writer_.get(), dex_files);
     }
@@ -2057,8 +2058,9 @@
       verifier::VerifierDeps* verifier_deps = callbacks_->GetVerifierDeps();
       for (size_t i = 0, size = oat_files_.size(); i != size; ++i) {
         File* vdex_file = vdex_files_[i].get();
-        std::unique_ptr<BufferedOutputStream> vdex_out =
-            std::make_unique<BufferedOutputStream>(std::make_unique<FileOutputStream>(vdex_file));
+        std::unique_ptr<linker::BufferedOutputStream> vdex_out =
+            std::make_unique<linker::BufferedOutputStream>(
+                std::make_unique<linker::FileOutputStream>(vdex_file));
 
         if (!oat_writers_[i]->WriteVerifierDeps(vdex_out.get(), verifier_deps)) {
           LOG(ERROR) << "Failed to write verifier dependencies into VDEX " << vdex_file->GetPath();
@@ -2082,8 +2084,8 @@
       TimingLogger::ScopedTiming t2("dex2oat Write ELF", timings_);
       linker::MultiOatRelativePatcher patcher(instruction_set_, instruction_set_features_.get());
       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::unique_ptr<linker::ElfWriter>& elf_writer = elf_writers_[i];
+        std::unique_ptr<linker::OatWriter>& oat_writer = oat_writers_[i];
 
         oat_writer->PrepareLayout(&patcher);
 
@@ -2116,14 +2118,14 @@
 
       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::unique_ptr<linker::ElfWriter>& elf_writer = elf_writers_[i];
+        std::unique_ptr<linker::OatWriter>& oat_writer = oat_writers_[i];
 
         // We need to mirror the layout of the ELF file in the compressed debug-info.
         // Therefore PrepareDebugInfo() relies on the SetLoadedSectionSizes() call further above.
         elf_writer->PrepareDebugInfo(oat_writer->GetMethodDebugInfo());
 
-        OutputStream*& rodata = rodata_[i];
+        linker::OutputStream*& rodata = rodata_[i];
         DCHECK(rodata != nullptr);
         if (!oat_writer->WriteRodata(rodata)) {
           LOG(ERROR) << "Failed to write .rodata section to the ELF file " << oat_file->GetPath();
@@ -2132,7 +2134,7 @@
         elf_writer->EndRoData(rodata);
         rodata = nullptr;
 
-        OutputStream* text = elf_writer->StartText();
+        linker::OutputStream* text = elf_writer->StartText();
         if (!oat_writer->WriteCode(text)) {
           LOG(ERROR) << "Failed to write .text section to the ELF file " << oat_file->GetPath();
           return false;
@@ -2510,13 +2512,13 @@
     elf_writers_.reserve(oat_files_.size());
     oat_writers_.reserve(oat_files_.size());
     for (const std::unique_ptr<File>& oat_file : oat_files_) {
-      elf_writers_.emplace_back(CreateElfWriterQuick(instruction_set_,
-                                                     instruction_set_features_.get(),
-                                                     compiler_options_.get(),
-                                                     oat_file.get()));
+      elf_writers_.emplace_back(linker::CreateElfWriterQuick(instruction_set_,
+                                                             instruction_set_features_.get(),
+                                                             compiler_options_.get(),
+                                                             oat_file.get()));
       elf_writers_.back()->Start();
       const bool do_dexlayout = DoDexLayoutOptimizations();
-      oat_writers_.emplace_back(new OatWriter(
+      oat_writers_.emplace_back(new linker::OatWriter(
           IsBootImage(), timings_, do_dexlayout ? profile_compilation_info_.get() : nullptr));
     }
   }
@@ -2679,7 +2681,7 @@
           return false;
         }
 
-        if (!ElfWriter::Fixup(oat_file.get(), oat_data_begins[i])) {
+        if (!linker::ElfWriter::Fixup(oat_file.get(), oat_data_begins[i])) {
           oat_file->Erase();
           LOG(ERROR) << "Failed to fixup ELF file " << oat_file->GetPath();
           return false;
@@ -2882,11 +2884,11 @@
   std::vector<const DexFile*> dex_files_;
   std::string no_inline_from_string_;
 
-  std::vector<std::unique_ptr<ElfWriter>> elf_writers_;
-  std::vector<std::unique_ptr<OatWriter>> oat_writers_;
-  std::vector<OutputStream*> rodata_;
-  std::vector<std::unique_ptr<OutputStream>> vdex_out_;
-  std::unique_ptr<ImageWriter> image_writer_;
+  std::vector<std::unique_ptr<linker::ElfWriter>> elf_writers_;
+  std::vector<std::unique_ptr<linker::OatWriter>> oat_writers_;
+  std::vector<linker::OutputStream*> rodata_;
+  std::vector<std::unique_ptr<linker::OutputStream>> vdex_out_;
+  std::unique_ptr<linker::ImageWriter> image_writer_;
   std::unique_ptr<CompilerDriver> driver_;
 
   std::vector<std::unique_ptr<MemMap>> opened_dex_files_maps_;
diff --git a/dex2oat/generate-operator-out.py b/dex2oat/generate-operator-out.py
new file mode 120000
index 0000000..cc291d2
--- /dev/null
+++ b/dex2oat/generate-operator-out.py
@@ -0,0 +1 @@
+../tools/generate-operator-out.py
\ No newline at end of file
diff --git a/dex2oat/linker/elf_writer.cc b/dex2oat/linker/elf_writer.cc
new file mode 100644
index 0000000..ca34864
--- /dev/null
+++ b/dex2oat/linker/elf_writer.cc
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "elf_writer.h"
+
+#include "base/unix_file/fd_file.h"
+#include "elf_file.h"
+
+namespace art {
+namespace linker {
+
+uintptr_t ElfWriter::GetOatDataAddress(ElfFile* elf_file) {
+  uintptr_t oatdata_address = elf_file->FindSymbolAddress(SHT_DYNSYM,
+                                                           "oatdata",
+                                                           false);
+  CHECK_NE(0U, oatdata_address);
+  return oatdata_address;
+}
+
+void ElfWriter::GetOatElfInformation(File* file,
+                                     size_t* oat_loaded_size,
+                                     size_t* oat_data_offset) {
+  std::string error_msg;
+  std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file,
+                                                  false,
+                                                  false,
+                                                  /*low_4gb*/false,
+                                                  &error_msg));
+  CHECK(elf_file.get() != nullptr) << error_msg;
+
+  bool success = elf_file->GetLoadedSize(oat_loaded_size, &error_msg);
+  CHECK(success) << error_msg;
+  CHECK_NE(0U, *oat_loaded_size);
+  *oat_data_offset = GetOatDataAddress(elf_file.get());
+  CHECK_NE(0U, *oat_data_offset);
+}
+
+bool ElfWriter::Fixup(File* file, uintptr_t oat_data_begin) {
+  std::string error_msg;
+  std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, /*low_4gb*/false, &error_msg));
+  CHECK(elf_file.get() != nullptr) << error_msg;
+
+  // Lookup "oatdata" symbol address.
+  uintptr_t oatdata_address = ElfWriter::GetOatDataAddress(elf_file.get());
+  uintptr_t base_address = oat_data_begin - oatdata_address;
+
+  return elf_file->Fixup(base_address);
+}
+
+}  // namespace linker
+}  // namespace art
diff --git a/dex2oat/linker/elf_writer.h b/dex2oat/linker/elf_writer.h
new file mode 100644
index 0000000..0eb36ed
--- /dev/null
+++ b/dex2oat/linker/elf_writer.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_DEX2OAT_LINKER_ELF_WRITER_H_
+#define ART_DEX2OAT_LINKER_ELF_WRITER_H_
+
+#include <stdint.h>
+#include <cstddef>
+#include <string>
+#include <vector>
+
+#include "base/array_ref.h"
+#include "base/macros.h"
+#include "base/mutex.h"
+#include "os.h"
+
+namespace art {
+
+class ElfFile;
+
+namespace debug {
+struct MethodDebugInfo;
+}  // namespace debug
+
+namespace linker {
+
+class OutputStream;
+
+class ElfWriter {
+ public:
+  // Looks up information about location of oat file in elf file container.
+  // Used for ImageWriter to perform memory layout.
+  static void GetOatElfInformation(File* file,
+                                   size_t* oat_loaded_size,
+                                   size_t* oat_data_offset);
+
+  // Returns runtime oat_data runtime address for an opened ElfFile.
+  static uintptr_t GetOatDataAddress(ElfFile* elf_file);
+
+  static bool Fixup(File* file, uintptr_t oat_data_begin);
+
+  virtual ~ElfWriter() {}
+
+  virtual void Start() = 0;
+  virtual void PrepareDynamicSection(size_t rodata_size,
+                                     size_t text_size,
+                                     size_t bss_size,
+                                     size_t bss_methods_offset,
+                                     size_t bss_roots_offset) = 0;
+  virtual void PrepareDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) = 0;
+  virtual OutputStream* StartRoData() = 0;
+  virtual void EndRoData(OutputStream* rodata) = 0;
+  virtual OutputStream* StartText() = 0;
+  virtual void EndText(OutputStream* text) = 0;
+  virtual void WriteDynamicSection() = 0;
+  virtual void WriteDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) = 0;
+  virtual bool End() = 0;
+
+  // Get the ELF writer's stream. This stream can be used for writing data directly
+  // to a section after the section has been finished. When that's done, the user
+  // should Seek() back to the position where the stream was before this operation.
+  virtual OutputStream* GetStream() = 0;
+
+  // Get the size that the loaded ELF file will occupy in memory.
+  virtual size_t GetLoadedSize() = 0;
+
+ protected:
+  ElfWriter() = default;
+};
+
+}  // namespace linker
+}  // namespace art
+
+#endif  // ART_DEX2OAT_LINKER_ELF_WRITER_H_
diff --git a/dex2oat/linker/elf_writer_quick.cc b/dex2oat/linker/elf_writer_quick.cc
new file mode 100644
index 0000000..93f5a1d
--- /dev/null
+++ b/dex2oat/linker/elf_writer_quick.cc
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "elf_writer_quick.h"
+
+#include <openssl/sha.h>
+#include <unordered_map>
+#include <unordered_set>
+
+#include "base/casts.h"
+#include "base/logging.h"
+#include "compiled_method.h"
+#include "debug/elf_debug_writer.h"
+#include "debug/method_debug_info.h"
+#include "driver/compiler_options.h"
+#include "elf.h"
+#include "elf_utils.h"
+#include "globals.h"
+#include "leb128.h"
+#include "linker/buffered_output_stream.h"
+#include "linker/elf_builder.h"
+#include "linker/file_output_stream.h"
+#include "thread-current-inl.h"
+#include "thread_pool.h"
+#include "utils.h"
+
+namespace art {
+namespace linker {
+
+// .eh_frame and .debug_frame are almost identical.
+// Except for some minor formatting differences, the main difference
+// is that .eh_frame is allocated within the running program because
+// it is used by C++ exception handling (which we do not use so we
+// can choose either).  C++ compilers generally tend to use .eh_frame
+// because if they need it sometimes, they might as well always use it.
+// Let's use .debug_frame because it is easier to strip or compress.
+constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_DEBUG_FRAME_FORMAT;
+
+class DebugInfoTask : public Task {
+ public:
+  DebugInfoTask(InstructionSet isa,
+                const InstructionSetFeatures* features,
+                size_t rodata_section_size,
+                size_t text_section_size,
+                const ArrayRef<const debug::MethodDebugInfo>& method_infos)
+      : isa_(isa),
+        instruction_set_features_(features),
+        rodata_section_size_(rodata_section_size),
+        text_section_size_(text_section_size),
+        method_infos_(method_infos) {
+  }
+
+  void Run(Thread*) {
+    result_ = debug::MakeMiniDebugInfo(isa_,
+                                       instruction_set_features_,
+                                       rodata_section_size_,
+                                       text_section_size_,
+                                       method_infos_);
+  }
+
+  std::vector<uint8_t>* GetResult() {
+    return &result_;
+  }
+
+ private:
+  InstructionSet isa_;
+  const InstructionSetFeatures* instruction_set_features_;
+  size_t rodata_section_size_;
+  size_t text_section_size_;
+  const ArrayRef<const debug::MethodDebugInfo> method_infos_;
+  std::vector<uint8_t> result_;
+};
+
+template <typename ElfTypes>
+class ElfWriterQuick FINAL : public ElfWriter {
+ public:
+  ElfWriterQuick(InstructionSet instruction_set,
+                 const InstructionSetFeatures* features,
+                 const CompilerOptions* compiler_options,
+                 File* elf_file);
+  ~ElfWriterQuick();
+
+  void Start() OVERRIDE;
+  void PrepareDynamicSection(size_t rodata_size,
+                             size_t text_size,
+                             size_t bss_size,
+                             size_t bss_methods_offset,
+                             size_t bss_roots_offset) OVERRIDE;
+  void PrepareDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) OVERRIDE;
+  OutputStream* StartRoData() OVERRIDE;
+  void EndRoData(OutputStream* rodata) OVERRIDE;
+  OutputStream* StartText() OVERRIDE;
+  void EndText(OutputStream* text) OVERRIDE;
+  void WriteDynamicSection() OVERRIDE;
+  void WriteDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) OVERRIDE;
+  bool End() OVERRIDE;
+
+  virtual OutputStream* GetStream() OVERRIDE;
+
+  size_t GetLoadedSize() OVERRIDE;
+
+  static void EncodeOatPatches(const std::vector<uintptr_t>& locations,
+                               std::vector<uint8_t>* buffer);
+
+ private:
+  const InstructionSetFeatures* instruction_set_features_;
+  const CompilerOptions* const compiler_options_;
+  File* const elf_file_;
+  size_t rodata_size_;
+  size_t text_size_;
+  size_t bss_size_;
+  std::unique_ptr<BufferedOutputStream> output_stream_;
+  std::unique_ptr<ElfBuilder<ElfTypes>> builder_;
+  std::unique_ptr<DebugInfoTask> debug_info_task_;
+  std::unique_ptr<ThreadPool> debug_info_thread_pool_;
+
+  void ComputeFileBuildId(uint8_t (*build_id)[ElfBuilder<ElfTypes>::kBuildIdLen]);
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick);
+};
+
+std::unique_ptr<ElfWriter> CreateElfWriterQuick(InstructionSet instruction_set,
+                                                const InstructionSetFeatures* features,
+                                                const CompilerOptions* compiler_options,
+                                                File* elf_file) {
+  if (Is64BitInstructionSet(instruction_set)) {
+    return std::make_unique<ElfWriterQuick<ElfTypes64>>(instruction_set,
+                                                        features,
+                                                        compiler_options,
+                                                        elf_file);
+  } else {
+    return std::make_unique<ElfWriterQuick<ElfTypes32>>(instruction_set,
+                                                        features,
+                                                        compiler_options,
+                                                        elf_file);
+  }
+}
+
+template <typename ElfTypes>
+ElfWriterQuick<ElfTypes>::ElfWriterQuick(InstructionSet instruction_set,
+                                         const InstructionSetFeatures* features,
+                                         const CompilerOptions* compiler_options,
+                                         File* elf_file)
+    : ElfWriter(),
+      instruction_set_features_(features),
+      compiler_options_(compiler_options),
+      elf_file_(elf_file),
+      rodata_size_(0u),
+      text_size_(0u),
+      bss_size_(0u),
+      output_stream_(
+          std::make_unique<BufferedOutputStream>(std::make_unique<FileOutputStream>(elf_file))),
+      builder_(new ElfBuilder<ElfTypes>(instruction_set, features, output_stream_.get())) {}
+
+template <typename ElfTypes>
+ElfWriterQuick<ElfTypes>::~ElfWriterQuick() {}
+
+template <typename ElfTypes>
+void ElfWriterQuick<ElfTypes>::Start() {
+  builder_->Start();
+  if (compiler_options_->GetGenerateBuildId()) {
+    builder_->WriteBuildIdSection();
+  }
+}
+
+template <typename ElfTypes>
+void ElfWriterQuick<ElfTypes>::PrepareDynamicSection(size_t rodata_size,
+                                                     size_t text_size,
+                                                     size_t bss_size,
+                                                     size_t bss_methods_offset,
+                                                     size_t bss_roots_offset) {
+  DCHECK_EQ(rodata_size_, 0u);
+  rodata_size_ = rodata_size;
+  DCHECK_EQ(text_size_, 0u);
+  text_size_ = text_size;
+  DCHECK_EQ(bss_size_, 0u);
+  bss_size_ = bss_size;
+  builder_->PrepareDynamicSection(elf_file_->GetPath(),
+                                  rodata_size_,
+                                  text_size_,
+                                  bss_size_,
+                                  bss_methods_offset,
+                                  bss_roots_offset);
+}
+
+template <typename ElfTypes>
+OutputStream* ElfWriterQuick<ElfTypes>::StartRoData() {
+  auto* rodata = builder_->GetRoData();
+  rodata->Start();
+  return rodata;
+}
+
+template <typename ElfTypes>
+void ElfWriterQuick<ElfTypes>::EndRoData(OutputStream* rodata) {
+  CHECK_EQ(builder_->GetRoData(), rodata);
+  builder_->GetRoData()->End();
+}
+
+template <typename ElfTypes>
+OutputStream* ElfWriterQuick<ElfTypes>::StartText() {
+  auto* text = builder_->GetText();
+  text->Start();
+  return text;
+}
+
+template <typename ElfTypes>
+void ElfWriterQuick<ElfTypes>::EndText(OutputStream* text) {
+  CHECK_EQ(builder_->GetText(), text);
+  builder_->GetText()->End();
+}
+
+template <typename ElfTypes>
+void ElfWriterQuick<ElfTypes>::WriteDynamicSection() {
+  if (bss_size_ != 0u) {
+    builder_->GetBss()->WriteNoBitsSection(bss_size_);
+  }
+  if (builder_->GetIsa() == kMips || builder_->GetIsa() == kMips64) {
+    builder_->WriteMIPSabiflagsSection();
+  }
+  builder_->WriteDynamicSection();
+}
+
+template <typename ElfTypes>
+void ElfWriterQuick<ElfTypes>::PrepareDebugInfo(
+    const ArrayRef<const debug::MethodDebugInfo>& method_infos) {
+  if (!method_infos.empty() && compiler_options_->GetGenerateMiniDebugInfo()) {
+    // Prepare the mini-debug-info in background while we do other I/O.
+    Thread* self = Thread::Current();
+    debug_info_task_ = std::unique_ptr<DebugInfoTask>(
+        new DebugInfoTask(builder_->GetIsa(),
+                          instruction_set_features_,
+                          rodata_size_,
+                          text_size_,
+                          method_infos));
+    debug_info_thread_pool_ = std::unique_ptr<ThreadPool>(
+        new ThreadPool("Mini-debug-info writer", 1));
+    debug_info_thread_pool_->AddTask(self, debug_info_task_.get());
+    debug_info_thread_pool_->StartWorkers(self);
+  }
+}
+
+template <typename ElfTypes>
+void ElfWriterQuick<ElfTypes>::WriteDebugInfo(
+    const ArrayRef<const debug::MethodDebugInfo>& method_infos) {
+  if (!method_infos.empty()) {
+    if (compiler_options_->GetGenerateDebugInfo()) {
+      // Generate all the debug information we can.
+      debug::WriteDebugInfo(builder_.get(), method_infos, kCFIFormat, true /* write_oat_patches */);
+    }
+    if (compiler_options_->GetGenerateMiniDebugInfo()) {
+      // Wait for the mini-debug-info generation to finish and write it to disk.
+      Thread* self = Thread::Current();
+      DCHECK(debug_info_thread_pool_ != nullptr);
+      debug_info_thread_pool_->Wait(self, true, false);
+      builder_->WriteSection(".gnu_debugdata", debug_info_task_->GetResult());
+    }
+  }
+}
+
+template <typename ElfTypes>
+bool ElfWriterQuick<ElfTypes>::End() {
+  builder_->End();
+  if (compiler_options_->GetGenerateBuildId()) {
+    uint8_t build_id[ElfBuilder<ElfTypes>::kBuildIdLen];
+    ComputeFileBuildId(&build_id);
+    builder_->WriteBuildId(build_id);
+  }
+  return builder_->Good();
+}
+
+template <typename ElfTypes>
+void ElfWriterQuick<ElfTypes>::ComputeFileBuildId(
+    uint8_t (*build_id)[ElfBuilder<ElfTypes>::kBuildIdLen]) {
+  constexpr int kBufSize = 8192;
+  std::vector<char> buffer(kBufSize);
+  int64_t offset = 0;
+  SHA_CTX ctx;
+  SHA1_Init(&ctx);
+  while (true) {
+    int64_t bytes_read = elf_file_->Read(buffer.data(), kBufSize, offset);
+    CHECK_GE(bytes_read, 0);
+    if (bytes_read == 0) {
+      // End of file.
+      break;
+    }
+    SHA1_Update(&ctx, buffer.data(), bytes_read);
+    offset += bytes_read;
+  }
+  SHA1_Final(*build_id, &ctx);
+}
+
+template <typename ElfTypes>
+OutputStream* ElfWriterQuick<ElfTypes>::GetStream() {
+  return builder_->GetStream();
+}
+
+template <typename ElfTypes>
+size_t ElfWriterQuick<ElfTypes>::GetLoadedSize() {
+  return builder_->GetLoadedSize();
+}
+
+// Explicit instantiations
+template class ElfWriterQuick<ElfTypes32>;
+template class ElfWriterQuick<ElfTypes64>;
+
+}  // namespace linker
+}  // namespace art
diff --git a/dex2oat/linker/elf_writer_quick.h b/dex2oat/linker/elf_writer_quick.h
new file mode 100644
index 0000000..e20957c
--- /dev/null
+++ b/dex2oat/linker/elf_writer_quick.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_DEX2OAT_LINKER_ELF_WRITER_QUICK_H_
+#define ART_DEX2OAT_LINKER_ELF_WRITER_QUICK_H_
+
+#include <memory>
+
+#include "arch/instruction_set.h"
+#include "elf_writer.h"
+#include "os.h"
+
+namespace art {
+
+class CompilerOptions;
+class InstructionSetFeatures;
+
+namespace linker {
+
+std::unique_ptr<ElfWriter> CreateElfWriterQuick(InstructionSet instruction_set,
+                                                const InstructionSetFeatures* features,
+                                                const CompilerOptions* compiler_options,
+                                                File* elf_file);
+
+}  // namespace linker
+}  // namespace art
+
+#endif  // ART_DEX2OAT_LINKER_ELF_WRITER_QUICK_H_
diff --git a/dex2oat/linker/elf_writer_test.cc b/dex2oat/linker/elf_writer_test.cc
new file mode 100644
index 0000000..9f8ed77
--- /dev/null
+++ b/dex2oat/linker/elf_writer_test.cc
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "elf_file.h"
+
+#include "base/unix_file/fd_file.h"
+#include "common_compiler_test.h"
+#include "elf_file.h"
+#include "elf_file_impl.h"
+#include "elf_writer_quick.h"
+#include "linker/elf_builder.h"
+#include "oat.h"
+#include "utils.h"
+
+namespace art {
+namespace linker {
+
+class ElfWriterTest : public CommonCompilerTest {
+ protected:
+  virtual void SetUp() {
+    ReserveImageSpace();
+    CommonCompilerTest::SetUp();
+  }
+};
+
+#define EXPECT_ELF_FILE_ADDRESS(ef, expected_value, symbol_name, build_map) \
+  do { \
+    void* addr = reinterpret_cast<void*>((ef)->FindSymbolAddress(SHT_DYNSYM, \
+                                                                 symbol_name, \
+                                                                 build_map)); \
+    EXPECT_NE(nullptr, addr); \
+    if ((expected_value) == nullptr) { \
+      (expected_value) = addr; \
+    }                        \
+    EXPECT_EQ(expected_value, addr); \
+    EXPECT_EQ(expected_value, (ef)->FindDynamicSymbolAddress(symbol_name)); \
+  } while (false)
+
+TEST_F(ElfWriterTest, dlsym) {
+  std::string elf_location = GetCoreOatLocation();
+  std::string elf_filename = GetSystemImageFilename(elf_location.c_str(), kRuntimeISA);
+  LOG(INFO) << "elf_filename=" << elf_filename;
+
+  UnreserveImageSpace();
+  void* dl_oatdata = nullptr;
+  void* dl_oatexec = nullptr;
+  void* dl_oatlastword = nullptr;
+
+  std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
+  ASSERT_TRUE(file.get() != nullptr) << elf_filename;
+  {
+    std::string error_msg;
+    std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(),
+                                              false,
+                                              false,
+                                              /*low_4gb*/false,
+                                              &error_msg));
+    CHECK(ef.get() != nullptr) << error_msg;
+    EXPECT_ELF_FILE_ADDRESS(ef, dl_oatdata, "oatdata", false);
+    EXPECT_ELF_FILE_ADDRESS(ef, dl_oatexec, "oatexec", false);
+    EXPECT_ELF_FILE_ADDRESS(ef, dl_oatlastword, "oatlastword", false);
+  }
+  {
+    std::string error_msg;
+    std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(),
+                                              false,
+                                              false,
+                                              /*low_4gb*/false,
+                                              &error_msg));
+    CHECK(ef.get() != nullptr) << error_msg;
+    EXPECT_ELF_FILE_ADDRESS(ef, dl_oatdata, "oatdata", true);
+    EXPECT_ELF_FILE_ADDRESS(ef, dl_oatexec, "oatexec", true);
+    EXPECT_ELF_FILE_ADDRESS(ef, dl_oatlastword, "oatlastword", true);
+  }
+  {
+    uint8_t* base = reinterpret_cast<uint8_t*>(ART_BASE_ADDRESS);
+    std::string error_msg;
+    std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(),
+                                              false,
+                                              true,
+                                              /*low_4gb*/false,
+                                              &error_msg,
+                                              base));
+    CHECK(ef.get() != nullptr) << error_msg;
+    CHECK(ef->Load(file.get(), false, /*low_4gb*/false, &error_msg)) << error_msg;
+    EXPECT_EQ(reinterpret_cast<uintptr_t>(dl_oatdata) + reinterpret_cast<uintptr_t>(base),
+        reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatdata")));
+    EXPECT_EQ(reinterpret_cast<uintptr_t>(dl_oatexec) + reinterpret_cast<uintptr_t>(base),
+        reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatexec")));
+    EXPECT_EQ(reinterpret_cast<uintptr_t>(dl_oatlastword) + reinterpret_cast<uintptr_t>(base),
+        reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatlastword")));
+  }
+}
+
+TEST_F(ElfWriterTest, CheckBuildIdPresent) {
+  std::string elf_location = GetCoreOatLocation();
+  std::string elf_filename = GetSystemImageFilename(elf_location.c_str(), kRuntimeISA);
+  LOG(INFO) << "elf_filename=" << elf_filename;
+
+  std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
+  ASSERT_TRUE(file.get() != nullptr);
+  {
+    std::string error_msg;
+    std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(),
+                                              false,
+                                              false,
+                                              /*low_4gb*/false,
+                                              &error_msg));
+    CHECK(ef.get() != nullptr) << error_msg;
+    EXPECT_TRUE(ef->HasSection(".note.gnu.build-id"));
+  }
+}
+
+TEST_F(ElfWriterTest, EncodeDecodeOatPatches) {
+  const std::vector<std::vector<uintptr_t>> test_data {
+      { 0, 4, 8, 15, 128, 200 },
+      { 8, 8 + 127 },
+      { 8, 8 + 128 },
+      { },
+  };
+  for (const auto& patch_locations : test_data) {
+    constexpr int32_t delta = 0x11235813;
+
+    // Encode patch locations.
+    std::vector<uint8_t> oat_patches;
+    ElfBuilder<ElfTypes32>::EncodeOatPatches(ArrayRef<const uintptr_t>(patch_locations),
+                                             &oat_patches);
+
+    // Create buffer to be patched.
+    std::vector<uint8_t> initial_data(256);
+    for (size_t i = 0; i < initial_data.size(); i++) {
+      initial_data[i] = i;
+    }
+
+    // Patch manually.
+    std::vector<uint8_t> expected = initial_data;
+    for (uintptr_t location : patch_locations) {
+      typedef __attribute__((__aligned__(1))) uint32_t UnalignedAddress;
+      *reinterpret_cast<UnalignedAddress*>(expected.data() + location) += delta;
+    }
+
+    // Decode and apply patch locations.
+    std::vector<uint8_t> actual = initial_data;
+    ElfFileImpl32::ApplyOatPatches(
+        oat_patches.data(), oat_patches.data() + oat_patches.size(), delta,
+        actual.data(), actual.data() + actual.size());
+
+    EXPECT_EQ(expected, actual);
+  }
+}
+
+}  // namespace linker
+}  // namespace art
diff --git a/dex2oat/linker/image_test.cc b/dex2oat/linker/image_test.cc
new file mode 100644
index 0000000..ab6e7a8
--- /dev/null
+++ b/dex2oat/linker/image_test.cc
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+#include <vector>
+
+#include "image_test.h"
+
+#include "image.h"
+#include "scoped_thread_state_change-inl.h"
+#include "thread.h"
+
+namespace art {
+namespace linker {
+
+TEST_F(ImageTest, TestImageLayout) {
+  std::vector<size_t> image_sizes;
+  std::vector<size_t> image_sizes_extra;
+  // Compile multi-image with ImageLayoutA being the last image.
+  {
+    CompilationHelper helper;
+    Compile(ImageHeader::kStorageModeUncompressed, helper, "ImageLayoutA", {"LMyClass;"});
+    image_sizes = helper.GetImageObjectSectionSizes();
+  }
+  TearDown();
+  runtime_.reset();
+  SetUp();
+  // Compile multi-image with ImageLayoutB being the last image.
+  {
+    CompilationHelper helper;
+    Compile(ImageHeader::kStorageModeUncompressed, helper, "ImageLayoutB", {"LMyClass;"});
+    image_sizes_extra = helper.GetImageObjectSectionSizes();
+  }
+  // Make sure that the new stuff in the clinit in ImageLayoutB is in the last image and not in the
+  // first two images.
+  ASSERT_EQ(image_sizes.size(), image_sizes.size());
+  // Sizes of the object sections should be the same for all but the last image.
+  for (size_t i = 0; i < image_sizes.size() - 1; ++i) {
+    EXPECT_EQ(image_sizes[i], image_sizes_extra[i]);
+  }
+  // Last image should be larger since it has a hash map and a string.
+  EXPECT_LT(image_sizes.back(), image_sizes_extra.back());
+}
+
+TEST_F(ImageTest, ImageHeaderIsValid) {
+    uint32_t image_begin = ART_BASE_ADDRESS;
+    uint32_t image_size_ = 16 * KB;
+    uint32_t image_roots = ART_BASE_ADDRESS + (1 * KB);
+    uint32_t oat_checksum = 0;
+    uint32_t oat_file_begin = ART_BASE_ADDRESS + (4 * KB);  // page aligned
+    uint32_t oat_data_begin = ART_BASE_ADDRESS + (8 * KB);  // page aligned
+    uint32_t oat_data_end = ART_BASE_ADDRESS + (9 * KB);
+    uint32_t oat_file_end = ART_BASE_ADDRESS + (10 * KB);
+    ImageSection sections[ImageHeader::kSectionCount];
+    ImageHeader image_header(image_begin,
+                             image_size_,
+                             sections,
+                             image_roots,
+                             oat_checksum,
+                             oat_file_begin,
+                             oat_data_begin,
+                             oat_data_end,
+                             oat_file_end,
+                             /*boot_image_begin*/0U,
+                             /*boot_image_size*/0U,
+                             /*boot_oat_begin*/0U,
+                             /*boot_oat_size_*/0U,
+                             sizeof(void*),
+                             /*compile_pic*/false,
+                             /*is_pic*/false,
+                             ImageHeader::kDefaultStorageMode,
+                             /*data_size*/0u);
+    ASSERT_TRUE(image_header.IsValid());
+    ASSERT_TRUE(!image_header.IsAppImage());
+
+    char* magic = const_cast<char*>(image_header.GetMagic());
+    strcpy(magic, "");  // bad magic
+    ASSERT_FALSE(image_header.IsValid());
+    strcpy(magic, "art\n000");  // bad version
+    ASSERT_FALSE(image_header.IsValid());
+}
+
+// Test that pointer to quick code is the same in
+// a default method of an interface and in a copied method
+// of a class which implements the interface. This should be true
+// only if the copied method and the origin method are located in the
+// same oat file.
+TEST_F(ImageTest, TestDefaultMethods) {
+  CompilationHelper helper;
+  Compile(ImageHeader::kStorageModeUncompressed,
+      helper,
+      "DefaultMethods",
+      {"LIface;", "LImpl;", "LIterableBase;"});
+
+  PointerSize pointer_size = class_linker_->GetImagePointerSize();
+  Thread* self = Thread::Current();
+  ScopedObjectAccess soa(self);
+
+  // Test the pointer to quick code is the same in origin method
+  // and in the copied method form the same oat file.
+  mirror::Class* iface_klass = class_linker_->LookupClass(
+      self, "LIface;", ObjPtr<mirror::ClassLoader>());
+  ASSERT_NE(nullptr, iface_klass);
+  ArtMethod* origin = iface_klass->FindInterfaceMethod("defaultMethod", "()V", pointer_size);
+  ASSERT_NE(nullptr, origin);
+  ASSERT_TRUE(origin->GetDeclaringClass() == iface_klass);
+  const void* code = origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
+  // The origin method should have a pointer to quick code
+  ASSERT_NE(nullptr, code);
+  ASSERT_FALSE(class_linker_->IsQuickToInterpreterBridge(code));
+  mirror::Class* impl_klass = class_linker_->LookupClass(
+      self, "LImpl;", ObjPtr<mirror::ClassLoader>());
+  ASSERT_NE(nullptr, impl_klass);
+  ArtMethod* copied = FindCopiedMethod(origin, impl_klass);
+  ASSERT_NE(nullptr, copied);
+  // the copied method should have pointer to the same quick code as the origin method
+  ASSERT_EQ(code, copied->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size));
+
+  // Test the origin method has pointer to quick code
+  // but the copied method has pointer to interpreter
+  // because these methods are in different oat files.
+  mirror::Class* iterable_klass = class_linker_->LookupClass(
+      self, "Ljava/lang/Iterable;", ObjPtr<mirror::ClassLoader>());
+  ASSERT_NE(nullptr, iterable_klass);
+  origin = iterable_klass->FindClassMethod(
+      "forEach", "(Ljava/util/function/Consumer;)V", pointer_size);
+  ASSERT_NE(nullptr, origin);
+  ASSERT_FALSE(origin->IsDirect());
+  ASSERT_TRUE(origin->GetDeclaringClass() == iterable_klass);
+  code = origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
+  // the origin method should have a pointer to quick code
+  ASSERT_NE(nullptr, code);
+  ASSERT_FALSE(class_linker_->IsQuickToInterpreterBridge(code));
+  mirror::Class* iterablebase_klass = class_linker_->LookupClass(
+      self, "LIterableBase;", ObjPtr<mirror::ClassLoader>());
+  ASSERT_NE(nullptr, iterablebase_klass);
+  copied = FindCopiedMethod(origin, iterablebase_klass);
+  ASSERT_NE(nullptr, copied);
+  code = copied->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
+  // the copied method should have a pointer to interpreter
+  ASSERT_TRUE(class_linker_->IsQuickToInterpreterBridge(code));
+}
+
+}  // namespace linker
+}  // namespace art
diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h
new file mode 100644
index 0000000..71f1fa6
--- /dev/null
+++ b/dex2oat/linker/image_test.h
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_DEX2OAT_LINKER_IMAGE_TEST_H_
+#define ART_DEX2OAT_LINKER_IMAGE_TEST_H_
+
+#include "image.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "android-base/stringprintf.h"
+
+#include "art_method-inl.h"
+#include "base/unix_file/fd_file.h"
+#include "class_linker-inl.h"
+#include "common_compiler_test.h"
+#include "compiler_callbacks.h"
+#include "debug/method_debug_info.h"
+#include "dex/quick_compiler_callbacks.h"
+#include "driver/compiler_options.h"
+#include "gc/space/image_space.h"
+#include "image_writer.h"
+#include "linker/buffered_output_stream.h"
+#include "linker/elf_writer.h"
+#include "linker/elf_writer_quick.h"
+#include "linker/file_output_stream.h"
+#include "linker/multi_oat_relative_patcher.h"
+#include "lock_word.h"
+#include "mirror/object-inl.h"
+#include "oat_writer.h"
+#include "scoped_thread_state_change-inl.h"
+#include "signal_catcher.h"
+#include "utils.h"
+
+namespace art {
+namespace linker {
+
+static const uintptr_t kRequestedImageBase = ART_BASE_ADDRESS;
+
+struct CompilationHelper {
+  std::vector<std::string> dex_file_locations;
+  std::vector<ScratchFile> image_locations;
+  std::vector<std::unique_ptr<const DexFile>> extra_dex_files;
+  std::vector<ScratchFile> image_files;
+  std::vector<ScratchFile> oat_files;
+  std::vector<ScratchFile> vdex_files;
+  std::string image_dir;
+
+  void Compile(CompilerDriver* driver,
+               ImageHeader::StorageMode storage_mode);
+
+  std::vector<size_t> GetImageObjectSectionSizes();
+
+  ~CompilationHelper();
+};
+
+class ImageTest : public CommonCompilerTest {
+ protected:
+  virtual void SetUp() {
+    ReserveImageSpace();
+    CommonCompilerTest::SetUp();
+  }
+
+  void TestWriteRead(ImageHeader::StorageMode storage_mode);
+
+  void Compile(ImageHeader::StorageMode storage_mode,
+               CompilationHelper& out_helper,
+               const std::string& extra_dex = "",
+               const std::initializer_list<std::string>& image_classes = {});
+
+  void SetUpRuntimeOptions(RuntimeOptions* options) OVERRIDE {
+    CommonCompilerTest::SetUpRuntimeOptions(options);
+    QuickCompilerCallbacks* new_callbacks =
+        new QuickCompilerCallbacks(CompilerCallbacks::CallbackMode::kCompileBootImage);
+    new_callbacks->SetVerificationResults(verification_results_.get());
+    callbacks_.reset(new_callbacks);
+    options->push_back(std::make_pair("compilercallbacks", callbacks_.get()));
+  }
+
+  std::unordered_set<std::string>* GetImageClasses() OVERRIDE {
+    return new std::unordered_set<std::string>(image_classes_);
+  }
+
+  ArtMethod* FindCopiedMethod(ArtMethod* origin, mirror::Class* klass)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    PointerSize pointer_size = class_linker_->GetImagePointerSize();
+    for (ArtMethod& m : klass->GetCopiedMethods(pointer_size)) {
+      if (strcmp(origin->GetName(), m.GetName()) == 0 &&
+          origin->GetSignature() == m.GetSignature()) {
+        return &m;
+      }
+    }
+    return nullptr;
+  }
+
+ private:
+  std::unordered_set<std::string> image_classes_;
+};
+
+inline CompilationHelper::~CompilationHelper() {
+  for (ScratchFile& image_file : image_files) {
+    image_file.Unlink();
+  }
+  for (ScratchFile& oat_file : oat_files) {
+    oat_file.Unlink();
+  }
+  for (ScratchFile& vdex_file : vdex_files) {
+    vdex_file.Unlink();
+  }
+  const int rmdir_result = rmdir(image_dir.c_str());
+  CHECK_EQ(0, rmdir_result);
+}
+
+inline std::vector<size_t> CompilationHelper::GetImageObjectSectionSizes() {
+  std::vector<size_t> ret;
+  for (ScratchFile& image_file : image_files) {
+    std::unique_ptr<File> file(OS::OpenFileForReading(image_file.GetFilename().c_str()));
+    CHECK(file.get() != nullptr);
+    ImageHeader image_header;
+    CHECK_EQ(file->ReadFully(&image_header, sizeof(image_header)), true);
+    CHECK(image_header.IsValid());
+    ret.push_back(image_header.GetObjectsSection().Size());
+  }
+  return ret;
+}
+
+inline void CompilationHelper::Compile(CompilerDriver* driver,
+                                       ImageHeader::StorageMode storage_mode) {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  std::vector<const DexFile*> class_path = class_linker->GetBootClassPath();
+
+  for (const std::unique_ptr<const DexFile>& dex_file : extra_dex_files) {
+    {
+      ScopedObjectAccess soa(Thread::Current());
+      // Inject in boot class path so that the compiler driver can see it.
+      class_linker->AppendToBootClassPath(soa.Self(), *dex_file.get());
+    }
+    class_path.push_back(dex_file.get());
+  }
+
+  // Enable write for dex2dex.
+  for (const DexFile* dex_file : class_path) {
+    dex_file_locations.push_back(dex_file->GetLocation());
+    if (dex_file->IsReadOnly()) {
+      dex_file->EnableWrite();
+    }
+  }
+  {
+    // Create a generic tmp file, to be the base of the .art and .oat temporary files.
+    ScratchFile location;
+    for (int i = 0; i < static_cast<int>(class_path.size()); ++i) {
+      std::string cur_location =
+          android::base::StringPrintf("%s-%d.art", location.GetFilename().c_str(), i);
+      image_locations.push_back(ScratchFile(cur_location));
+    }
+  }
+  std::vector<std::string> image_filenames;
+  for (ScratchFile& file : image_locations) {
+    std::string image_filename(GetSystemImageFilename(file.GetFilename().c_str(), kRuntimeISA));
+    image_filenames.push_back(image_filename);
+    size_t pos = image_filename.rfind('/');
+    CHECK_NE(pos, std::string::npos) << image_filename;
+    if (image_dir.empty()) {
+      image_dir = image_filename.substr(0, pos);
+      int mkdir_result = mkdir(image_dir.c_str(), 0700);
+      CHECK_EQ(0, mkdir_result) << image_dir;
+    }
+    image_files.push_back(ScratchFile(OS::CreateEmptyFile(image_filename.c_str())));
+  }
+
+  std::vector<std::string> oat_filenames;
+  std::vector<std::string> vdex_filenames;
+  for (const std::string& image_filename : image_filenames) {
+    std::string oat_filename = ReplaceFileExtension(image_filename, "oat");
+    oat_files.push_back(ScratchFile(OS::CreateEmptyFile(oat_filename.c_str())));
+    oat_filenames.push_back(oat_filename);
+    std::string vdex_filename = ReplaceFileExtension(image_filename, "vdex");
+    vdex_files.push_back(ScratchFile(OS::CreateEmptyFile(vdex_filename.c_str())));
+    vdex_filenames.push_back(vdex_filename);
+  }
+
+  std::unordered_map<const DexFile*, size_t> dex_file_to_oat_index_map;
+  std::vector<const char*> oat_filename_vector;
+  for (const std::string& file : oat_filenames) {
+    oat_filename_vector.push_back(file.c_str());
+  }
+  std::vector<const char*> image_filename_vector;
+  for (const std::string& file : image_filenames) {
+    image_filename_vector.push_back(file.c_str());
+  }
+  size_t image_idx = 0;
+  for (const DexFile* dex_file : class_path) {
+    dex_file_to_oat_index_map.emplace(dex_file, image_idx);
+    ++image_idx;
+  }
+  // TODO: compile_pic should be a test argument.
+  std::unique_ptr<ImageWriter> writer(new ImageWriter(*driver,
+                                                      kRequestedImageBase,
+                                                      /*compile_pic*/false,
+                                                      /*compile_app_image*/false,
+                                                      storage_mode,
+                                                      oat_filename_vector,
+                                                      dex_file_to_oat_index_map,
+                                                      /*dirty_image_objects*/nullptr));
+  {
+    {
+      jobject class_loader = nullptr;
+      TimingLogger timings("ImageTest::WriteRead", false, false);
+      TimingLogger::ScopedTiming t("CompileAll", &timings);
+      driver->SetDexFilesForOatFile(class_path);
+      driver->CompileAll(class_loader, class_path, &timings);
+
+      t.NewTiming("WriteElf");
+      SafeMap<std::string, std::string> key_value_store;
+      std::vector<const char*> dex_filename_vector;
+      for (size_t i = 0; i < class_path.size(); ++i) {
+        dex_filename_vector.push_back("");
+      }
+      key_value_store.Put(OatHeader::kBootClassPathKey,
+                          gc::space::ImageSpace::GetMultiImageBootClassPath(
+                              dex_filename_vector,
+                              oat_filename_vector,
+                              image_filename_vector));
+
+      std::vector<std::unique_ptr<ElfWriter>> elf_writers;
+      std::vector<std::unique_ptr<OatWriter>> oat_writers;
+      for (ScratchFile& oat_file : oat_files) {
+        elf_writers.emplace_back(CreateElfWriterQuick(driver->GetInstructionSet(),
+                                                      driver->GetInstructionSetFeatures(),
+                                                      &driver->GetCompilerOptions(),
+                                                      oat_file.GetFile()));
+        elf_writers.back()->Start();
+        oat_writers.emplace_back(new OatWriter(/*compiling_boot_image*/true,
+                                               &timings,
+                                               /*profile_compilation_info*/nullptr));
+      }
+
+      std::vector<OutputStream*> rodata;
+      std::vector<std::unique_ptr<MemMap>> opened_dex_files_map;
+      std::vector<std::unique_ptr<const DexFile>> opened_dex_files;
+      // Now that we have finalized key_value_store_, start writing the oat file.
+      for (size_t i = 0, size = oat_writers.size(); i != size; ++i) {
+        const DexFile* dex_file = class_path[i];
+        rodata.push_back(elf_writers[i]->StartRoData());
+        ArrayRef<const uint8_t> raw_dex_file(
+            reinterpret_cast<const uint8_t*>(&dex_file->GetHeader()),
+            dex_file->GetHeader().file_size_);
+        oat_writers[i]->AddRawDexFileSource(raw_dex_file,
+                                            dex_file->GetLocation().c_str(),
+                                            dex_file->GetLocationChecksum());
+
+        std::unique_ptr<MemMap> cur_opened_dex_files_map;
+        std::vector<std::unique_ptr<const DexFile>> cur_opened_dex_files;
+        bool dex_files_ok = oat_writers[i]->WriteAndOpenDexFiles(
+            kIsVdexEnabled ? vdex_files[i].GetFile() : oat_files[i].GetFile(),
+            rodata.back(),
+            driver->GetInstructionSet(),
+            driver->GetInstructionSetFeatures(),
+            &key_value_store,
+            /* verify */ false,           // Dex files may be dex-to-dex-ed, don't verify.
+            /* update_input_vdex */ false,
+            &cur_opened_dex_files_map,
+            &cur_opened_dex_files);
+        ASSERT_TRUE(dex_files_ok);
+
+        if (cur_opened_dex_files_map != nullptr) {
+          opened_dex_files_map.push_back(std::move(cur_opened_dex_files_map));
+          for (std::unique_ptr<const DexFile>& cur_dex_file : cur_opened_dex_files) {
+            // dex_file_oat_index_map_.emplace(dex_file.get(), i);
+            opened_dex_files.push_back(std::move(cur_dex_file));
+          }
+        } else {
+          ASSERT_TRUE(cur_opened_dex_files.empty());
+        }
+      }
+      bool image_space_ok = writer->PrepareImageAddressSpace();
+      ASSERT_TRUE(image_space_ok);
+
+      if (kIsVdexEnabled) {
+        for (size_t i = 0, size = vdex_files.size(); i != size; ++i) {
+          std::unique_ptr<BufferedOutputStream> vdex_out =
+              std::make_unique<BufferedOutputStream>(
+                  std::make_unique<FileOutputStream>(vdex_files[i].GetFile()));
+          oat_writers[i]->WriteVerifierDeps(vdex_out.get(), nullptr);
+          oat_writers[i]->WriteChecksumsAndVdexHeader(vdex_out.get());
+        }
+      }
+
+      for (size_t i = 0, size = oat_files.size(); i != size; ++i) {
+        linker::MultiOatRelativePatcher patcher(driver->GetInstructionSet(),
+                                                driver->GetInstructionSetFeatures());
+        OatWriter* const oat_writer = oat_writers[i].get();
+        ElfWriter* const elf_writer = elf_writers[i].get();
+        std::vector<const DexFile*> cur_dex_files(1u, class_path[i]);
+        oat_writer->Initialize(driver, writer.get(), cur_dex_files);
+        oat_writer->PrepareLayout(&patcher);
+        size_t rodata_size = oat_writer->GetOatHeader().GetExecutableOffset();
+        size_t text_size = oat_writer->GetOatSize() - rodata_size;
+        elf_writer->PrepareDynamicSection(rodata_size,
+                                          text_size,
+                                          oat_writer->GetBssSize(),
+                                          oat_writer->GetBssMethodsOffset(),
+                                          oat_writer->GetBssRootsOffset());
+
+        writer->UpdateOatFileLayout(i,
+                                    elf_writer->GetLoadedSize(),
+                                    oat_writer->GetOatDataOffset(),
+                                    oat_writer->GetOatSize());
+
+        bool rodata_ok = oat_writer->WriteRodata(rodata[i]);
+        ASSERT_TRUE(rodata_ok);
+        elf_writer->EndRoData(rodata[i]);
+
+        OutputStream* text = elf_writer->StartText();
+        bool text_ok = oat_writer->WriteCode(text);
+        ASSERT_TRUE(text_ok);
+        elf_writer->EndText(text);
+
+        bool header_ok = oat_writer->WriteHeader(elf_writer->GetStream(), 0u, 0u, 0u);
+        ASSERT_TRUE(header_ok);
+
+        writer->UpdateOatFileHeader(i, oat_writer->GetOatHeader());
+
+        elf_writer->WriteDynamicSection();
+        elf_writer->WriteDebugInfo(oat_writer->GetMethodDebugInfo());
+
+        bool success = elf_writer->End();
+        ASSERT_TRUE(success);
+      }
+    }
+
+    bool success_image = writer->Write(kInvalidFd,
+                                       image_filename_vector,
+                                       oat_filename_vector);
+    ASSERT_TRUE(success_image);
+
+    for (size_t i = 0, size = oat_filenames.size(); i != size; ++i) {
+      const char* oat_filename = oat_filenames[i].c_str();
+      std::unique_ptr<File> oat_file(OS::OpenFileReadWrite(oat_filename));
+      ASSERT_TRUE(oat_file != nullptr);
+      bool success_fixup = ElfWriter::Fixup(oat_file.get(),
+                                            writer->GetOatDataBegin(i));
+      ASSERT_TRUE(success_fixup);
+      ASSERT_EQ(oat_file->FlushCloseOrErase(), 0) << "Could not flush and close oat file "
+                                                  << oat_filename;
+    }
+  }
+}
+
+inline void ImageTest::Compile(ImageHeader::StorageMode storage_mode,
+                        CompilationHelper& helper,
+                        const std::string& extra_dex,
+                        const std::initializer_list<std::string>& image_classes) {
+  for (const std::string& image_class : image_classes) {
+    image_classes_.insert(image_class);
+  }
+  CreateCompilerDriver(Compiler::kOptimizing, kRuntimeISA, kIsTargetBuild ? 2U : 16U);
+  // Set inline filter values.
+  compiler_options_->SetInlineMaxCodeUnits(CompilerOptions::kDefaultInlineMaxCodeUnits);
+  image_classes_.clear();
+  if (!extra_dex.empty()) {
+    helper.extra_dex_files = OpenTestDexFiles(extra_dex.c_str());
+  }
+  helper.Compile(compiler_driver_.get(), storage_mode);
+  if (image_classes.begin() != image_classes.end()) {
+    // Make sure the class got initialized.
+    ScopedObjectAccess soa(Thread::Current());
+    ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
+    for (const std::string& image_class : image_classes) {
+      mirror::Class* klass = class_linker->FindSystemClass(Thread::Current(), image_class.c_str());
+      EXPECT_TRUE(klass != nullptr);
+      EXPECT_TRUE(klass->IsInitialized());
+    }
+  }
+}
+
+inline void ImageTest::TestWriteRead(ImageHeader::StorageMode storage_mode) {
+  CompilationHelper helper;
+  Compile(storage_mode, /*out*/ helper);
+  std::vector<uint64_t> image_file_sizes;
+  for (ScratchFile& image_file : helper.image_files) {
+    std::unique_ptr<File> file(OS::OpenFileForReading(image_file.GetFilename().c_str()));
+    ASSERT_TRUE(file.get() != nullptr);
+    ImageHeader image_header;
+    ASSERT_EQ(file->ReadFully(&image_header, sizeof(image_header)), true);
+    ASSERT_TRUE(image_header.IsValid());
+    const auto& bitmap_section = image_header.GetImageBitmapSection();
+    ASSERT_GE(bitmap_section.Offset(), sizeof(image_header));
+    ASSERT_NE(0U, bitmap_section.Size());
+
+    gc::Heap* heap = Runtime::Current()->GetHeap();
+    ASSERT_TRUE(heap->HaveContinuousSpaces());
+    gc::space::ContinuousSpace* space = heap->GetNonMovingSpace();
+    ASSERT_FALSE(space->IsImageSpace());
+    ASSERT_TRUE(space != nullptr);
+    ASSERT_TRUE(space->IsMallocSpace());
+    image_file_sizes.push_back(file->GetLength());
+  }
+
+  ASSERT_TRUE(compiler_driver_->GetImageClasses() != nullptr);
+  std::unordered_set<std::string> image_classes(*compiler_driver_->GetImageClasses());
+
+  // Need to delete the compiler since it has worker threads which are attached to runtime.
+  compiler_driver_.reset();
+
+  // Tear down old runtime before making a new one, clearing out misc state.
+
+  // Remove the reservation of the memory for use to load the image.
+  // Need to do this before we reset the runtime.
+  UnreserveImageSpace();
+
+  helper.extra_dex_files.clear();
+  runtime_.reset();
+  java_lang_dex_file_ = nullptr;
+
+  MemMap::Init();
+
+  RuntimeOptions options;
+  std::string image("-Ximage:");
+  image.append(helper.image_locations[0].GetFilename());
+  options.push_back(std::make_pair(image.c_str(), static_cast<void*>(nullptr)));
+  // By default the compiler this creates will not include patch information.
+  options.push_back(std::make_pair("-Xnorelocate", nullptr));
+
+  if (!Runtime::Create(options, false)) {
+    LOG(FATAL) << "Failed to create runtime";
+    return;
+  }
+  runtime_.reset(Runtime::Current());
+  // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
+  // give it away now and then switch to a more managable ScopedObjectAccess.
+  Thread::Current()->TransitionFromRunnableToSuspended(kNative);
+  ScopedObjectAccess soa(Thread::Current());
+  ASSERT_TRUE(runtime_.get() != nullptr);
+  class_linker_ = runtime_->GetClassLinker();
+
+  gc::Heap* heap = Runtime::Current()->GetHeap();
+  ASSERT_TRUE(heap->HasBootImageSpace());
+  ASSERT_TRUE(heap->GetNonMovingSpace()->IsMallocSpace());
+
+  // We loaded the runtime with an explicit image, so it must exist.
+  ASSERT_EQ(heap->GetBootImageSpaces().size(), image_file_sizes.size());
+  for (size_t i = 0; i < helper.dex_file_locations.size(); ++i) {
+    std::unique_ptr<const DexFile> dex(
+        LoadExpectSingleDexFile(helper.dex_file_locations[i].c_str()));
+    ASSERT_TRUE(dex != nullptr);
+    uint64_t image_file_size = image_file_sizes[i];
+    gc::space::ImageSpace* image_space = heap->GetBootImageSpaces()[i];
+    ASSERT_TRUE(image_space != nullptr);
+    if (storage_mode == ImageHeader::kStorageModeUncompressed) {
+      // Uncompressed, image should be smaller than file.
+      ASSERT_LE(image_space->GetImageHeader().GetImageSize(), image_file_size);
+    } else if (image_file_size > 16 * KB) {
+      // Compressed, file should be smaller than image. Not really valid for small images.
+      ASSERT_LE(image_file_size, image_space->GetImageHeader().GetImageSize());
+    }
+
+    image_space->VerifyImageAllocations();
+    uint8_t* image_begin = image_space->Begin();
+    uint8_t* image_end = image_space->End();
+    if (i == 0) {
+      // This check is only valid for image 0.
+      CHECK_EQ(kRequestedImageBase, reinterpret_cast<uintptr_t>(image_begin));
+    }
+    for (size_t j = 0; j < dex->NumClassDefs(); ++j) {
+      const DexFile::ClassDef& class_def = dex->GetClassDef(j);
+      const char* descriptor = dex->GetClassDescriptor(class_def);
+      mirror::Class* klass = class_linker_->FindSystemClass(soa.Self(), descriptor);
+      EXPECT_TRUE(klass != nullptr) << descriptor;
+      if (image_classes.find(descriptor) == image_classes.end()) {
+        EXPECT_TRUE(reinterpret_cast<uint8_t*>(klass) >= image_end ||
+                    reinterpret_cast<uint8_t*>(klass) < image_begin) << descriptor;
+      } else {
+        // Image classes should be located inside the image.
+        EXPECT_LT(image_begin, reinterpret_cast<uint8_t*>(klass)) << descriptor;
+        EXPECT_LT(reinterpret_cast<uint8_t*>(klass), image_end) << descriptor;
+      }
+      EXPECT_TRUE(Monitor::IsValidLockWord(klass->GetLockWord(false)));
+    }
+  }
+}
+
+}  // namespace linker
+}  // namespace art
+
+#endif  // ART_DEX2OAT_LINKER_IMAGE_TEST_H_
diff --git a/dex2oat/linker/image_write_read_test.cc b/dex2oat/linker/image_write_read_test.cc
new file mode 100644
index 0000000..30996b5
--- /dev/null
+++ b/dex2oat/linker/image_write_read_test.cc
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "image_test.h"
+
+namespace art {
+namespace linker {
+
+TEST_F(ImageTest, WriteReadUncompressed) {
+  TestWriteRead(ImageHeader::kStorageModeUncompressed);
+}
+
+TEST_F(ImageTest, WriteReadLZ4) {
+  TestWriteRead(ImageHeader::kStorageModeLZ4);
+}
+
+TEST_F(ImageTest, WriteReadLZ4HC) {
+  TestWriteRead(ImageHeader::kStorageModeLZ4HC);
+}
+
+}  // namespace linker
+}  // namespace art
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
new file mode 100644
index 0000000..ee568e8
--- /dev/null
+++ b/dex2oat/linker/image_writer.cc
@@ -0,0 +1,2839 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "image_writer.h"
+
+#include <lz4.h>
+#include <lz4hc.h>
+#include <sys/stat.h>
+
+#include <memory>
+#include <numeric>
+#include <unordered_set>
+#include <vector>
+
+#include "art_field-inl.h"
+#include "art_method-inl.h"
+#include "base/callee_save_type.h"
+#include "base/enums.h"
+#include "base/logging.h"
+#include "base/unix_file/fd_file.h"
+#include "class_linker-inl.h"
+#include "compiled_method.h"
+#include "dex_file-inl.h"
+#include "dex_file_types.h"
+#include "driver/compiler_driver.h"
+#include "elf_file.h"
+#include "elf_utils.h"
+#include "gc/accounting/card_table-inl.h"
+#include "gc/accounting/heap_bitmap.h"
+#include "gc/accounting/space_bitmap-inl.h"
+#include "gc/collector/concurrent_copying.h"
+#include "gc/heap-visit-objects-inl.h"
+#include "gc/heap.h"
+#include "gc/space/large_object_space.h"
+#include "gc/space/space-inl.h"
+#include "gc/verification.h"
+#include "globals.h"
+#include "handle_scope-inl.h"
+#include "image.h"
+#include "imt_conflict_table.h"
+#include "jni_internal.h"
+#include "linear_alloc.h"
+#include "lock_word.h"
+#include "mirror/array-inl.h"
+#include "mirror/class-inl.h"
+#include "mirror/class_ext.h"
+#include "mirror/class_loader.h"
+#include "mirror/dex_cache-inl.h"
+#include "mirror/dex_cache.h"
+#include "mirror/executable.h"
+#include "mirror/method.h"
+#include "mirror/object-inl.h"
+#include "mirror/object-refvisitor-inl.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/string-inl.h"
+#include "oat.h"
+#include "oat_file.h"
+#include "oat_file_manager.h"
+#include "runtime.h"
+#include "scoped_thread_state_change-inl.h"
+#include "utils/dex_cache_arrays_layout-inl.h"
+#include "well_known_classes.h"
+
+using ::art::mirror::Class;
+using ::art::mirror::DexCache;
+using ::art::mirror::Object;
+using ::art::mirror::ObjectArray;
+using ::art::mirror::String;
+
+namespace art {
+namespace linker {
+
+// Separate objects into multiple bins to optimize dirty memory use.
+static constexpr bool kBinObjects = true;
+
+// Return true if an object is already in an image space.
+bool ImageWriter::IsInBootImage(const void* obj) const {
+  gc::Heap* const heap = Runtime::Current()->GetHeap();
+  if (!compile_app_image_) {
+    DCHECK(heap->GetBootImageSpaces().empty());
+    return false;
+  }
+  for (gc::space::ImageSpace* boot_image_space : heap->GetBootImageSpaces()) {
+    const uint8_t* image_begin = boot_image_space->Begin();
+    // Real image end including ArtMethods and ArtField sections.
+    const uint8_t* image_end = image_begin + boot_image_space->GetImageHeader().GetImageSize();
+    if (image_begin <= obj && obj < image_end) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool ImageWriter::IsInBootOatFile(const void* ptr) const {
+  gc::Heap* const heap = Runtime::Current()->GetHeap();
+  if (!compile_app_image_) {
+    DCHECK(heap->GetBootImageSpaces().empty());
+    return false;
+  }
+  for (gc::space::ImageSpace* boot_image_space : heap->GetBootImageSpaces()) {
+    const ImageHeader& image_header = boot_image_space->GetImageHeader();
+    if (image_header.GetOatFileBegin() <= ptr && ptr < image_header.GetOatFileEnd()) {
+      return true;
+    }
+  }
+  return false;
+}
+
+static void ClearDexFileCookies() REQUIRES_SHARED(Locks::mutator_lock_) {
+  auto visitor = [](Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
+    DCHECK(obj != nullptr);
+    Class* klass = obj->GetClass();
+    if (klass == WellKnownClasses::ToClass(WellKnownClasses::dalvik_system_DexFile)) {
+      ArtField* field = jni::DecodeArtField(WellKnownClasses::dalvik_system_DexFile_cookie);
+      // Null out the cookie to enable determinism. b/34090128
+      field->SetObject</*kTransactionActive*/false>(obj, nullptr);
+    }
+  };
+  Runtime::Current()->GetHeap()->VisitObjects(visitor);
+}
+
+bool ImageWriter::PrepareImageAddressSpace() {
+  target_ptr_size_ = InstructionSetPointerSize(compiler_driver_.GetInstructionSet());
+  gc::Heap* const heap = Runtime::Current()->GetHeap();
+  {
+    ScopedObjectAccess soa(Thread::Current());
+    PruneNonImageClasses();  // Remove junk
+    if (compile_app_image_) {
+      // Clear dex file cookies for app images to enable app image determinism. This is required
+      // since the cookie field contains long pointers to DexFiles which are not deterministic.
+      // b/34090128
+      ClearDexFileCookies();
+    } else {
+      // Avoid for app image since this may increase RAM and image size.
+      ComputeLazyFieldsForImageClasses();  // Add useful information
+    }
+  }
+  heap->CollectGarbage(false);  // Remove garbage.
+
+  if (kIsDebugBuild) {
+    ScopedObjectAccess soa(Thread::Current());
+    CheckNonImageClassesRemoved();
+  }
+
+  {
+    ScopedObjectAccess soa(Thread::Current());
+    CalculateNewObjectOffsets();
+  }
+
+  // This needs to happen after CalculateNewObjectOffsets since it relies on intern_table_bytes_ and
+  // bin size sums being calculated.
+  if (!AllocMemory()) {
+    return false;
+  }
+
+  return true;
+}
+
+bool ImageWriter::Write(int image_fd,
+                        const std::vector<const char*>& image_filenames,
+                        const std::vector<const char*>& oat_filenames) {
+  // If image_fd or oat_fd are not kInvalidFd then we may have empty strings in image_filenames or
+  // oat_filenames.
+  CHECK(!image_filenames.empty());
+  if (image_fd != kInvalidFd) {
+    CHECK_EQ(image_filenames.size(), 1u);
+  }
+  CHECK(!oat_filenames.empty());
+  CHECK_EQ(image_filenames.size(), oat_filenames.size());
+
+  {
+    ScopedObjectAccess soa(Thread::Current());
+    for (size_t i = 0; i < oat_filenames.size(); ++i) {
+      CreateHeader(i);
+      CopyAndFixupNativeData(i);
+    }
+  }
+
+  {
+    // TODO: heap validation can't handle these fix up passes.
+    ScopedObjectAccess soa(Thread::Current());
+    Runtime::Current()->GetHeap()->DisableObjectValidation();
+    CopyAndFixupObjects();
+  }
+
+  for (size_t i = 0; i < image_filenames.size(); ++i) {
+    const char* image_filename = image_filenames[i];
+    ImageInfo& image_info = GetImageInfo(i);
+    std::unique_ptr<File> image_file;
+    if (image_fd != kInvalidFd) {
+      if (strlen(image_filename) == 0u) {
+        image_file.reset(new File(image_fd, unix_file::kCheckSafeUsage));
+        // Empty the file in case it already exists.
+        if (image_file != nullptr) {
+          TEMP_FAILURE_RETRY(image_file->SetLength(0));
+          TEMP_FAILURE_RETRY(image_file->Flush());
+        }
+      } else {
+        LOG(ERROR) << "image fd " << image_fd << " name " << image_filename;
+      }
+    } else {
+      image_file.reset(OS::CreateEmptyFile(image_filename));
+    }
+
+    if (image_file == nullptr) {
+      LOG(ERROR) << "Failed to open image file " << image_filename;
+      return false;
+    }
+
+    if (!compile_app_image_ && fchmod(image_file->Fd(), 0644) != 0) {
+      PLOG(ERROR) << "Failed to make image file world readable: " << image_filename;
+      image_file->Erase();
+      return EXIT_FAILURE;
+    }
+
+    std::unique_ptr<char[]> compressed_data;
+    // Image data size excludes the bitmap and the header.
+    ImageHeader* const image_header = reinterpret_cast<ImageHeader*>(image_info.image_->Begin());
+    const size_t image_data_size = image_header->GetImageSize() - sizeof(ImageHeader);
+    char* image_data = reinterpret_cast<char*>(image_info.image_->Begin()) + sizeof(ImageHeader);
+    size_t data_size;
+    const char* image_data_to_write;
+    const uint64_t compress_start_time = NanoTime();
+
+    CHECK_EQ(image_header->storage_mode_, image_storage_mode_);
+    switch (image_storage_mode_) {
+      case ImageHeader::kStorageModeLZ4HC:  // Fall-through.
+      case ImageHeader::kStorageModeLZ4: {
+        const size_t compressed_max_size = LZ4_compressBound(image_data_size);
+        compressed_data.reset(new char[compressed_max_size]);
+        data_size = LZ4_compress_default(
+            reinterpret_cast<char*>(image_info.image_->Begin()) + sizeof(ImageHeader),
+            &compressed_data[0],
+            image_data_size,
+            compressed_max_size);
+
+        break;
+      }
+      /*
+       * Disabled due to image_test64 flakyness. Both use same decompression. b/27560444
+      case ImageHeader::kStorageModeLZ4HC: {
+        // Bound is same as non HC.
+        const size_t compressed_max_size = LZ4_compressBound(image_data_size);
+        compressed_data.reset(new char[compressed_max_size]);
+        data_size = LZ4_compressHC(
+            reinterpret_cast<char*>(image_info.image_->Begin()) + sizeof(ImageHeader),
+            &compressed_data[0],
+            image_data_size);
+        break;
+      }
+      */
+      case ImageHeader::kStorageModeUncompressed: {
+        data_size = image_data_size;
+        image_data_to_write = image_data;
+        break;
+      }
+      default: {
+        LOG(FATAL) << "Unsupported";
+        UNREACHABLE();
+      }
+    }
+
+    if (compressed_data != nullptr) {
+      image_data_to_write = &compressed_data[0];
+      VLOG(compiler) << "Compressed from " << image_data_size << " to " << data_size << " in "
+                     << PrettyDuration(NanoTime() - compress_start_time);
+      if (kIsDebugBuild) {
+        std::unique_ptr<uint8_t[]> temp(new uint8_t[image_data_size]);
+        const size_t decompressed_size = LZ4_decompress_safe(
+            reinterpret_cast<char*>(&compressed_data[0]),
+            reinterpret_cast<char*>(&temp[0]),
+            data_size,
+            image_data_size);
+        CHECK_EQ(decompressed_size, image_data_size);
+        CHECK_EQ(memcmp(image_data, &temp[0], image_data_size), 0) << image_storage_mode_;
+      }
+    }
+
+    // Write out the image + fields + methods.
+    const bool is_compressed = compressed_data != nullptr;
+    if (!image_file->PwriteFully(image_data_to_write, data_size, sizeof(ImageHeader))) {
+      PLOG(ERROR) << "Failed to write image file data " << image_filename;
+      image_file->Erase();
+      return false;
+    }
+
+    // Write out the image bitmap at the page aligned start of the image end, also uncompressed for
+    // convenience.
+    const ImageSection& bitmap_section = image_header->GetImageBitmapSection();
+    // Align up since data size may be unaligned if the image is compressed.
+    size_t bitmap_position_in_file = RoundUp(sizeof(ImageHeader) + data_size, kPageSize);
+    if (!is_compressed) {
+      CHECK_EQ(bitmap_position_in_file, bitmap_section.Offset());
+    }
+    if (!image_file->PwriteFully(reinterpret_cast<char*>(image_info.image_bitmap_->Begin()),
+                                 bitmap_section.Size(),
+                                 bitmap_position_in_file)) {
+      PLOG(ERROR) << "Failed to write image file " << image_filename;
+      image_file->Erase();
+      return false;
+    }
+
+    int err = image_file->Flush();
+    if (err < 0) {
+      PLOG(ERROR) << "Failed to flush image file " << image_filename << " with result " << err;
+      image_file->Erase();
+      return false;
+    }
+
+    // Write header last in case the compiler gets killed in the middle of image writing.
+    // We do not want to have a corrupted image with a valid header.
+    // The header is uncompressed since it contains whether the image is compressed or not.
+    image_header->data_size_ = data_size;
+    if (!image_file->PwriteFully(reinterpret_cast<char*>(image_info.image_->Begin()),
+                                 sizeof(ImageHeader),
+                                 0)) {
+      PLOG(ERROR) << "Failed to write image file header " << image_filename;
+      image_file->Erase();
+      return false;
+    }
+
+    CHECK_EQ(bitmap_position_in_file + bitmap_section.Size(),
+             static_cast<size_t>(image_file->GetLength()));
+    if (image_file->FlushCloseOrErase() != 0) {
+      PLOG(ERROR) << "Failed to flush and close image file " << image_filename;
+      return false;
+    }
+  }
+  return true;
+}
+
+void ImageWriter::SetImageOffset(mirror::Object* object, size_t offset) {
+  DCHECK(object != nullptr);
+  DCHECK_NE(offset, 0U);
+
+  // The object is already deflated from when we set the bin slot. Just overwrite the lock word.
+  object->SetLockWord(LockWord::FromForwardingAddress(offset), false);
+  DCHECK_EQ(object->GetLockWord(false).ReadBarrierState(), 0u);
+  DCHECK(IsImageOffsetAssigned(object));
+}
+
+void ImageWriter::UpdateImageOffset(mirror::Object* obj, uintptr_t offset) {
+  DCHECK(IsImageOffsetAssigned(obj)) << obj << " " << offset;
+  obj->SetLockWord(LockWord::FromForwardingAddress(offset), false);
+  DCHECK_EQ(obj->GetLockWord(false).ReadBarrierState(), 0u);
+}
+
+void ImageWriter::AssignImageOffset(mirror::Object* object, ImageWriter::BinSlot bin_slot) {
+  DCHECK(object != nullptr);
+  DCHECK_NE(image_objects_offset_begin_, 0u);
+
+  size_t oat_index = GetOatIndex(object);
+  ImageInfo& image_info = GetImageInfo(oat_index);
+  size_t bin_slot_offset = image_info.bin_slot_offsets_[bin_slot.GetBin()];
+  size_t new_offset = bin_slot_offset + bin_slot.GetIndex();
+  DCHECK_ALIGNED(new_offset, kObjectAlignment);
+
+  SetImageOffset(object, new_offset);
+  DCHECK_LT(new_offset, image_info.image_end_);
+}
+
+bool ImageWriter::IsImageOffsetAssigned(mirror::Object* object) const {
+  // Will also return true if the bin slot was assigned since we are reusing the lock word.
+  DCHECK(object != nullptr);
+  return object->GetLockWord(false).GetState() == LockWord::kForwardingAddress;
+}
+
+size_t ImageWriter::GetImageOffset(mirror::Object* object) const {
+  DCHECK(object != nullptr);
+  DCHECK(IsImageOffsetAssigned(object));
+  LockWord lock_word = object->GetLockWord(false);
+  size_t offset = lock_word.ForwardingAddress();
+  size_t oat_index = GetOatIndex(object);
+  const ImageInfo& image_info = GetImageInfo(oat_index);
+  DCHECK_LT(offset, image_info.image_end_);
+  return offset;
+}
+
+void ImageWriter::SetImageBinSlot(mirror::Object* object, BinSlot bin_slot) {
+  DCHECK(object != nullptr);
+  DCHECK(!IsImageOffsetAssigned(object));
+  DCHECK(!IsImageBinSlotAssigned(object));
+
+  // Before we stomp over the lock word, save the hash code for later.
+  LockWord lw(object->GetLockWord(false));
+  switch (lw.GetState()) {
+    case LockWord::kFatLocked:
+      FALLTHROUGH_INTENDED;
+    case LockWord::kThinLocked: {
+      std::ostringstream oss;
+      bool thin = (lw.GetState() == LockWord::kThinLocked);
+      oss << (thin ? "Thin" : "Fat")
+          << " locked object " << object << "(" << object->PrettyTypeOf()
+          << ") found during object copy";
+      if (thin) {
+        oss << ". Lock owner:" << lw.ThinLockOwner();
+      }
+      LOG(FATAL) << oss.str();
+      break;
+    }
+    case LockWord::kUnlocked:
+      // No hash, don't need to save it.
+      break;
+    case LockWord::kHashCode:
+      DCHECK(saved_hashcode_map_.find(object) == saved_hashcode_map_.end());
+      saved_hashcode_map_.emplace(object, lw.GetHashCode());
+      break;
+    default:
+      LOG(FATAL) << "Unreachable.";
+      UNREACHABLE();
+  }
+  object->SetLockWord(LockWord::FromForwardingAddress(bin_slot.Uint32Value()), false);
+  DCHECK_EQ(object->GetLockWord(false).ReadBarrierState(), 0u);
+  DCHECK(IsImageBinSlotAssigned(object));
+}
+
+void ImageWriter::PrepareDexCacheArraySlots() {
+  // Prepare dex cache array starts based on the ordering specified in the CompilerDriver.
+  // Set the slot size early to avoid DCHECK() failures in IsImageBinSlotAssigned()
+  // when AssignImageBinSlot() assigns their indexes out or order.
+  for (const DexFile* dex_file : compiler_driver_.GetDexFilesForOatFile()) {
+    auto it = dex_file_oat_index_map_.find(dex_file);
+    DCHECK(it != dex_file_oat_index_map_.end()) << dex_file->GetLocation();
+    ImageInfo& image_info = GetImageInfo(it->second);
+    image_info.dex_cache_array_starts_.Put(dex_file, image_info.bin_slot_sizes_[kBinDexCacheArray]);
+    DexCacheArraysLayout layout(target_ptr_size_, dex_file);
+    image_info.bin_slot_sizes_[kBinDexCacheArray] += layout.Size();
+  }
+
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  Thread* const self = Thread::Current();
+  ReaderMutexLock mu(self, *Locks::dex_lock_);
+  for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
+    ObjPtr<mirror::DexCache> dex_cache =
+        ObjPtr<mirror::DexCache>::DownCast(self->DecodeJObject(data.weak_root));
+    if (dex_cache == nullptr || IsInBootImage(dex_cache.Ptr())) {
+      continue;
+    }
+    const DexFile* dex_file = dex_cache->GetDexFile();
+    CHECK(dex_file_oat_index_map_.find(dex_file) != dex_file_oat_index_map_.end())
+        << "Dex cache should have been pruned " << dex_file->GetLocation()
+        << "; possibly in class path";
+    DexCacheArraysLayout layout(target_ptr_size_, dex_file);
+    DCHECK(layout.Valid());
+    size_t oat_index = GetOatIndexForDexCache(dex_cache);
+    ImageInfo& image_info = GetImageInfo(oat_index);
+    uint32_t start = image_info.dex_cache_array_starts_.Get(dex_file);
+    DCHECK_EQ(dex_file->NumTypeIds() != 0u, dex_cache->GetResolvedTypes() != nullptr);
+    AddDexCacheArrayRelocation(dex_cache->GetResolvedTypes(),
+                               start + layout.TypesOffset(),
+                               dex_cache);
+    DCHECK_EQ(dex_file->NumMethodIds() != 0u, dex_cache->GetResolvedMethods() != nullptr);
+    AddDexCacheArrayRelocation(dex_cache->GetResolvedMethods(),
+                               start + layout.MethodsOffset(),
+                               dex_cache);
+    DCHECK_EQ(dex_file->NumFieldIds() != 0u, dex_cache->GetResolvedFields() != nullptr);
+    AddDexCacheArrayRelocation(dex_cache->GetResolvedFields(),
+                               start + layout.FieldsOffset(),
+                               dex_cache);
+    DCHECK_EQ(dex_file->NumStringIds() != 0u, dex_cache->GetStrings() != nullptr);
+    AddDexCacheArrayRelocation(dex_cache->GetStrings(), start + layout.StringsOffset(), dex_cache);
+
+    if (dex_cache->GetResolvedMethodTypes() != nullptr) {
+      AddDexCacheArrayRelocation(dex_cache->GetResolvedMethodTypes(),
+                                 start + layout.MethodTypesOffset(),
+                                 dex_cache);
+    }
+    if (dex_cache->GetResolvedCallSites() != nullptr) {
+      AddDexCacheArrayRelocation(dex_cache->GetResolvedCallSites(),
+                                 start + layout.CallSitesOffset(),
+                                 dex_cache);
+    }
+  }
+}
+
+void ImageWriter::AddDexCacheArrayRelocation(void* array,
+                                             size_t offset,
+                                             ObjPtr<mirror::DexCache> dex_cache) {
+  if (array != nullptr) {
+    DCHECK(!IsInBootImage(array));
+    size_t oat_index = GetOatIndexForDexCache(dex_cache);
+    native_object_relocations_.emplace(array,
+        NativeObjectRelocation { oat_index, offset, kNativeObjectRelocationTypeDexCacheArray });
+  }
+}
+
+void ImageWriter::AddMethodPointerArray(mirror::PointerArray* arr) {
+  DCHECK(arr != nullptr);
+  if (kIsDebugBuild) {
+    for (size_t i = 0, len = arr->GetLength(); i < len; i++) {
+      ArtMethod* method = arr->GetElementPtrSize<ArtMethod*>(i, target_ptr_size_);
+      if (method != nullptr && !method->IsRuntimeMethod()) {
+        mirror::Class* klass = method->GetDeclaringClass();
+        CHECK(klass == nullptr || KeepClass(klass))
+            << Class::PrettyClass(klass) << " should be a kept class";
+      }
+    }
+  }
+  // kBinArtMethodClean picked arbitrarily, just required to differentiate between ArtFields and
+  // ArtMethods.
+  pointer_arrays_.emplace(arr, kBinArtMethodClean);
+}
+
+void ImageWriter::AssignImageBinSlot(mirror::Object* object, size_t oat_index) {
+  DCHECK(object != nullptr);
+  size_t object_size = object->SizeOf();
+
+  // The magic happens here. We segregate objects into different bins based
+  // on how likely they are to get dirty at runtime.
+  //
+  // Likely-to-dirty objects get packed together into the same bin so that
+  // at runtime their page dirtiness ratio (how many dirty objects a page has) is
+  // maximized.
+  //
+  // This means more pages will stay either clean or shared dirty (with zygote) and
+  // the app will use less of its own (private) memory.
+  Bin bin = kBinRegular;
+  size_t current_offset = 0u;
+
+  if (kBinObjects) {
+    //
+    // Changing the bin of an object is purely a memory-use tuning.
+    // It has no change on runtime correctness.
+    //
+    // Memory analysis has determined that the following types of objects get dirtied
+    // the most:
+    //
+    // * Dex cache arrays are stored in a special bin. The arrays for each dex cache have
+    //   a fixed layout which helps improve generated code (using PC-relative addressing),
+    //   so we pre-calculate their offsets separately in PrepareDexCacheArraySlots().
+    //   Since these arrays are huge, most pages do not overlap other objects and it's not
+    //   really important where they are for the clean/dirty separation. Due to their
+    //   special PC-relative addressing, we arbitrarily keep them at the end.
+    // * Class'es which are verified [their clinit runs only at runtime]
+    //   - classes in general [because their static fields get overwritten]
+    //   - initialized classes with all-final statics are unlikely to be ever dirty,
+    //     so bin them separately
+    // * Art Methods that are:
+    //   - native [their native entry point is not looked up until runtime]
+    //   - have declaring classes that aren't initialized
+    //            [their interpreter/quick entry points are trampolines until the class
+    //             becomes initialized]
+    //
+    // We also assume the following objects get dirtied either never or extremely rarely:
+    //  * Strings (they are immutable)
+    //  * Art methods that aren't native and have initialized declared classes
+    //
+    // We assume that "regular" bin objects are highly unlikely to become dirtied,
+    // so packing them together will not result in a noticeably tighter dirty-to-clean ratio.
+    //
+    if (object->IsClass()) {
+      bin = kBinClassVerified;
+      mirror::Class* klass = object->AsClass();
+
+      // Add non-embedded vtable to the pointer array table if there is one.
+      auto* vtable = klass->GetVTable();
+      if (vtable != nullptr) {
+        AddMethodPointerArray(vtable);
+      }
+      auto* iftable = klass->GetIfTable();
+      if (iftable != nullptr) {
+        for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) {
+          if (iftable->GetMethodArrayCount(i) > 0) {
+            AddMethodPointerArray(iftable->GetMethodArray(i));
+          }
+        }
+      }
+
+      // Move known dirty objects into their own sections. This includes:
+      //   - classes with dirty static fields.
+      if (dirty_image_objects_ != nullptr &&
+          dirty_image_objects_->find(klass->PrettyDescriptor()) != dirty_image_objects_->end()) {
+        bin = kBinKnownDirty;
+      } else if (klass->GetStatus() == Class::kStatusInitialized) {
+        bin = kBinClassInitialized;
+
+        // If the class's static fields are all final, put it into a separate bin
+        // since it's very likely it will stay clean.
+        uint32_t num_static_fields = klass->NumStaticFields();
+        if (num_static_fields == 0) {
+          bin = kBinClassInitializedFinalStatics;
+        } else {
+          // Maybe all the statics are final?
+          bool all_final = true;
+          for (uint32_t i = 0; i < num_static_fields; ++i) {
+            ArtField* field = klass->GetStaticField(i);
+            if (!field->IsFinal()) {
+              all_final = false;
+              break;
+            }
+          }
+
+          if (all_final) {
+            bin = kBinClassInitializedFinalStatics;
+          }
+        }
+      }
+    } else if (object->GetClass<kVerifyNone>()->IsStringClass()) {
+      bin = kBinString;  // Strings are almost always immutable (except for object header).
+    } else if (object->GetClass<kVerifyNone>() ==
+        Runtime::Current()->GetClassLinker()->GetClassRoot(ClassLinker::kJavaLangObject)) {
+      // Instance of java lang object, probably a lock object. This means it will be dirty when we
+      // synchronize on it.
+      bin = kBinMiscDirty;
+    } else if (object->IsDexCache()) {
+      // Dex file field becomes dirty when the image is loaded.
+      bin = kBinMiscDirty;
+    }
+    // else bin = kBinRegular
+  }
+
+  // Assign the oat index too.
+  DCHECK(oat_index_map_.find(object) == oat_index_map_.end());
+  oat_index_map_.emplace(object, oat_index);
+
+  ImageInfo& image_info = GetImageInfo(oat_index);
+
+  size_t offset_delta = RoundUp(object_size, kObjectAlignment);  // 64-bit alignment
+  current_offset = image_info.bin_slot_sizes_[bin];  // How many bytes the current bin is at (aligned).
+  // Move the current bin size up to accommodate the object we just assigned a bin slot.
+  image_info.bin_slot_sizes_[bin] += offset_delta;
+
+  BinSlot new_bin_slot(bin, current_offset);
+  SetImageBinSlot(object, new_bin_slot);
+
+  ++image_info.bin_slot_count_[bin];
+
+  // Grow the image closer to the end by the object we just assigned.
+  image_info.image_end_ += offset_delta;
+}
+
+bool ImageWriter::WillMethodBeDirty(ArtMethod* m) const {
+  if (m->IsNative()) {
+    return true;
+  }
+  mirror::Class* declaring_class = m->GetDeclaringClass();
+  // Initialized is highly unlikely to dirty since there's no entry points to mutate.
+  return declaring_class == nullptr || declaring_class->GetStatus() != Class::kStatusInitialized;
+}
+
+bool ImageWriter::IsImageBinSlotAssigned(mirror::Object* object) const {
+  DCHECK(object != nullptr);
+
+  // We always stash the bin slot into a lockword, in the 'forwarding address' state.
+  // If it's in some other state, then we haven't yet assigned an image bin slot.
+  if (object->GetLockWord(false).GetState() != LockWord::kForwardingAddress) {
+    return false;
+  } else if (kIsDebugBuild) {
+    LockWord lock_word = object->GetLockWord(false);
+    size_t offset = lock_word.ForwardingAddress();
+    BinSlot bin_slot(offset);
+    size_t oat_index = GetOatIndex(object);
+    const ImageInfo& image_info = GetImageInfo(oat_index);
+    DCHECK_LT(bin_slot.GetIndex(), image_info.bin_slot_sizes_[bin_slot.GetBin()])
+        << "bin slot offset should not exceed the size of that bin";
+  }
+  return true;
+}
+
+ImageWriter::BinSlot ImageWriter::GetImageBinSlot(mirror::Object* object) const {
+  DCHECK(object != nullptr);
+  DCHECK(IsImageBinSlotAssigned(object));
+
+  LockWord lock_word = object->GetLockWord(false);
+  size_t offset = lock_word.ForwardingAddress();  // TODO: ForwardingAddress should be uint32_t
+  DCHECK_LE(offset, std::numeric_limits<uint32_t>::max());
+
+  BinSlot bin_slot(static_cast<uint32_t>(offset));
+  size_t oat_index = GetOatIndex(object);
+  const ImageInfo& image_info = GetImageInfo(oat_index);
+  DCHECK_LT(bin_slot.GetIndex(), image_info.bin_slot_sizes_[bin_slot.GetBin()]);
+
+  return bin_slot;
+}
+
+bool ImageWriter::AllocMemory() {
+  for (ImageInfo& image_info : image_infos_) {
+    ImageSection unused_sections[ImageHeader::kSectionCount];
+    const size_t length = RoundUp(
+        image_info.CreateImageSections(unused_sections, compile_app_image_), kPageSize);
+
+    std::string error_msg;
+    image_info.image_.reset(MemMap::MapAnonymous("image writer image",
+                                                 nullptr,
+                                                 length,
+                                                 PROT_READ | PROT_WRITE,
+                                                 false,
+                                                 false,
+                                                 &error_msg));
+    if (UNLIKELY(image_info.image_.get() == nullptr)) {
+      LOG(ERROR) << "Failed to allocate memory for image file generation: " << error_msg;
+      return false;
+    }
+
+    // Create the image bitmap, only needs to cover mirror object section which is up to image_end_.
+    CHECK_LE(image_info.image_end_, length);
+    image_info.image_bitmap_.reset(gc::accounting::ContinuousSpaceBitmap::Create(
+        "image bitmap", image_info.image_->Begin(), RoundUp(image_info.image_end_, kPageSize)));
+    if (image_info.image_bitmap_.get() == nullptr) {
+      LOG(ERROR) << "Failed to allocate memory for image bitmap";
+      return false;
+    }
+  }
+  return true;
+}
+
+class ImageWriter::ComputeLazyFieldsForClassesVisitor : public ClassVisitor {
+ public:
+  bool operator()(ObjPtr<Class> c) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
+    StackHandleScope<1> hs(Thread::Current());
+    mirror::Class::ComputeName(hs.NewHandle(c));
+    return true;
+  }
+};
+
+void ImageWriter::ComputeLazyFieldsForImageClasses() {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  ComputeLazyFieldsForClassesVisitor visitor;
+  class_linker->VisitClassesWithoutClassesLock(&visitor);
+}
+
+static bool IsBootClassLoaderClass(ObjPtr<mirror::Class> klass)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  return klass->GetClassLoader() == nullptr;
+}
+
+bool ImageWriter::IsBootClassLoaderNonImageClass(mirror::Class* klass) {
+  return IsBootClassLoaderClass(klass) && !IsInBootImage(klass);
+}
+
+// This visitor follows the references of an instance, recursively then prune this class
+// if a type of any field is pruned.
+class ImageWriter::PruneObjectReferenceVisitor {
+ public:
+  PruneObjectReferenceVisitor(ImageWriter* image_writer,
+                        bool* early_exit,
+                        std::unordered_set<mirror::Object*>* visited,
+                        bool* result)
+      : image_writer_(image_writer), early_exit_(early_exit), visited_(visited), result_(result) {}
+
+  ALWAYS_INLINE void VisitRootIfNonNull(
+      mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED) const
+      REQUIRES_SHARED(Locks::mutator_lock_) { }
+
+  ALWAYS_INLINE void VisitRoot(
+      mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED) const
+      REQUIRES_SHARED(Locks::mutator_lock_) { }
+
+  ALWAYS_INLINE void operator() (ObjPtr<mirror::Object> obj,
+                                 MemberOffset offset,
+                                 bool is_static ATTRIBUTE_UNUSED) const
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    mirror::Object* ref =
+        obj->GetFieldObject<mirror::Object, kVerifyNone, kWithoutReadBarrier>(offset);
+    if (ref == nullptr || visited_->find(ref) != visited_->end()) {
+      return;
+    }
+
+    ObjPtr<mirror::Class> klass = ref->IsClass() ? ref->AsClass() : ref->GetClass();
+    if (klass == mirror::Method::StaticClass() || klass == mirror::Constructor::StaticClass()) {
+      // Prune all classes using reflection because the content they held will not be fixup.
+      *result_ = true;
+    }
+
+    if (ref->IsClass()) {
+      *result_ = *result_ ||
+          image_writer_->PruneAppImageClassInternal(ref->AsClass(), early_exit_, visited_);
+    } else {
+      // Record the object visited in case of circular reference.
+      visited_->emplace(ref);
+      *result_ = *result_ ||
+          image_writer_->PruneAppImageClassInternal(klass, early_exit_, visited_);
+      ref->VisitReferences(*this, *this);
+      // Clean up before exit for next call of this function.
+      visited_->erase(ref);
+    }
+  }
+
+  ALWAYS_INLINE void operator() (ObjPtr<mirror::Class> klass ATTRIBUTE_UNUSED,
+                                 ObjPtr<mirror::Reference> ref) const
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    operator()(ref, mirror::Reference::ReferentOffset(), /* is_static */ false);
+  }
+
+  ALWAYS_INLINE bool GetResult() const {
+    return result_;
+  }
+
+ private:
+  ImageWriter* image_writer_;
+  bool* early_exit_;
+  std::unordered_set<mirror::Object*>* visited_;
+  bool* const result_;
+};
+
+
+bool ImageWriter::PruneAppImageClass(ObjPtr<mirror::Class> klass) {
+  bool early_exit = false;
+  std::unordered_set<mirror::Object*> visited;
+  return PruneAppImageClassInternal(klass, &early_exit, &visited);
+}
+
+bool ImageWriter::PruneAppImageClassInternal(
+    ObjPtr<mirror::Class> klass,
+    bool* early_exit,
+    std::unordered_set<mirror::Object*>* visited) {
+  DCHECK(early_exit != nullptr);
+  DCHECK(visited != nullptr);
+  DCHECK(compile_app_image_);
+  if (klass == nullptr || IsInBootImage(klass.Ptr())) {
+    return false;
+  }
+  auto found = prune_class_memo_.find(klass.Ptr());
+  if (found != prune_class_memo_.end()) {
+    // Already computed, return the found value.
+    return found->second;
+  }
+  // Circular dependencies, return false but do not store the result in the memoization table.
+  if (visited->find(klass.Ptr()) != visited->end()) {
+    *early_exit = true;
+    return false;
+  }
+  visited->emplace(klass.Ptr());
+  bool result = IsBootClassLoaderClass(klass);
+  std::string temp;
+  // Prune if not an image class, this handles any broken sets of image classes such as having a
+  // class in the set but not it's superclass.
+  result = result || !compiler_driver_.IsImageClass(klass->GetDescriptor(&temp));
+  bool my_early_exit = false;  // Only for ourselves, ignore caller.
+  // Remove classes that failed to verify since we don't want to have java.lang.VerifyError in the
+  // app image.
+  if (klass->IsErroneous()) {
+    result = true;
+  } else {
+    ObjPtr<mirror::ClassExt> ext(klass->GetExtData());
+    CHECK(ext.IsNull() || ext->GetVerifyError() == nullptr) << klass->PrettyClass();
+  }
+  if (!result) {
+    // Check interfaces since these wont be visited through VisitReferences.)
+    mirror::IfTable* if_table = klass->GetIfTable();
+    for (size_t i = 0, num_interfaces = klass->GetIfTableCount(); i < num_interfaces; ++i) {
+      result = result || PruneAppImageClassInternal(if_table->GetInterface(i),
+                                                    &my_early_exit,
+                                                    visited);
+    }
+  }
+  if (klass->IsObjectArrayClass()) {
+    result = result || PruneAppImageClassInternal(klass->GetComponentType(),
+                                                  &my_early_exit,
+                                                  visited);
+  }
+  // Check static fields and their classes.
+  if (klass->IsResolved() && klass->NumReferenceStaticFields() != 0) {
+    size_t num_static_fields = klass->NumReferenceStaticFields();
+    // Presumably GC can happen when we are cross compiling, it should not cause performance
+    // problems to do pointer size logic.
+    MemberOffset field_offset = klass->GetFirstReferenceStaticFieldOffset(
+        Runtime::Current()->GetClassLinker()->GetImagePointerSize());
+    for (size_t i = 0u; i < num_static_fields; ++i) {
+      mirror::Object* ref = klass->GetFieldObject<mirror::Object>(field_offset);
+      if (ref != nullptr) {
+        if (ref->IsClass()) {
+          result = result || PruneAppImageClassInternal(ref->AsClass(),
+                                                        &my_early_exit,
+                                                        visited);
+        } else {
+          mirror::Class* type = ref->GetClass();
+          result = result || PruneAppImageClassInternal(type,
+                                                        &my_early_exit,
+                                                        visited);
+          if (!result) {
+            // For non-class case, also go through all the types mentioned by it's fields'
+            // references recursively to decide whether to keep this class.
+            bool tmp = false;
+            PruneObjectReferenceVisitor visitor(this, &my_early_exit, visited, &tmp);
+            ref->VisitReferences(visitor, visitor);
+            result = result || tmp;
+          }
+        }
+      }
+      field_offset = MemberOffset(field_offset.Uint32Value() +
+                                  sizeof(mirror::HeapReference<mirror::Object>));
+    }
+  }
+  result = result || PruneAppImageClassInternal(klass->GetSuperClass(),
+                                                &my_early_exit,
+                                                visited);
+  // Remove the class if the dex file is not in the set of dex files. This happens for classes that
+  // are from uses-library if there is no profile. b/30688277
+  mirror::DexCache* dex_cache = klass->GetDexCache();
+  if (dex_cache != nullptr) {
+    result = result ||
+        dex_file_oat_index_map_.find(dex_cache->GetDexFile()) == dex_file_oat_index_map_.end();
+  }
+  // Erase the element we stored earlier since we are exiting the function.
+  auto it = visited->find(klass.Ptr());
+  DCHECK(it != visited->end());
+  visited->erase(it);
+  // Only store result if it is true or none of the calls early exited due to circular
+  // dependencies. If visited is empty then we are the root caller, in this case the cycle was in
+  // a child call and we can remember the result.
+  if (result == true || !my_early_exit || visited->empty()) {
+    prune_class_memo_[klass.Ptr()] = result;
+  }
+  *early_exit |= my_early_exit;
+  return result;
+}
+
+bool ImageWriter::KeepClass(ObjPtr<mirror::Class> klass) {
+  if (klass == nullptr) {
+    return false;
+  }
+  if (compile_app_image_ && Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(klass)) {
+    // Already in boot image, return true.
+    return true;
+  }
+  std::string temp;
+  if (!compiler_driver_.IsImageClass(klass->GetDescriptor(&temp))) {
+    return false;
+  }
+  if (compile_app_image_) {
+    // For app images, we need to prune boot loader classes that are not in the boot image since
+    // these may have already been loaded when the app image is loaded.
+    // Keep classes in the boot image space since we don't want to re-resolve these.
+    return !PruneAppImageClass(klass);
+  }
+  return true;
+}
+
+class ImageWriter::PruneClassesVisitor : public ClassVisitor {
+ public:
+  PruneClassesVisitor(ImageWriter* image_writer, ObjPtr<mirror::ClassLoader> class_loader)
+      : image_writer_(image_writer),
+        class_loader_(class_loader),
+        classes_to_prune_(),
+        defined_class_count_(0u) { }
+
+  bool operator()(ObjPtr<mirror::Class> klass) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
+    if (!image_writer_->KeepClass(klass.Ptr())) {
+      classes_to_prune_.insert(klass.Ptr());
+      if (klass->GetClassLoader() == class_loader_) {
+        ++defined_class_count_;
+      }
+    }
+    return true;
+  }
+
+  size_t Prune() REQUIRES_SHARED(Locks::mutator_lock_) {
+    ClassTable* class_table =
+        Runtime::Current()->GetClassLinker()->ClassTableForClassLoader(class_loader_);
+    for (mirror::Class* klass : classes_to_prune_) {
+      std::string storage;
+      const char* descriptor = klass->GetDescriptor(&storage);
+      bool result = class_table->Remove(descriptor);
+      DCHECK(result);
+      DCHECK(!class_table->Remove(descriptor)) << descriptor;
+    }
+    return defined_class_count_;
+  }
+
+ private:
+  ImageWriter* const image_writer_;
+  const ObjPtr<mirror::ClassLoader> class_loader_;
+  std::unordered_set<mirror::Class*> classes_to_prune_;
+  size_t defined_class_count_;
+};
+
+class ImageWriter::PruneClassLoaderClassesVisitor : public ClassLoaderVisitor {
+ public:
+  explicit PruneClassLoaderClassesVisitor(ImageWriter* image_writer)
+      : image_writer_(image_writer), removed_class_count_(0) {}
+
+  virtual void Visit(ObjPtr<mirror::ClassLoader> class_loader) OVERRIDE
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    PruneClassesVisitor classes_visitor(image_writer_, class_loader);
+    ClassTable* class_table =
+        Runtime::Current()->GetClassLinker()->ClassTableForClassLoader(class_loader);
+    class_table->Visit(classes_visitor);
+    removed_class_count_ += classes_visitor.Prune();
+
+    // Record app image class loader. The fake boot class loader should not get registered
+    // and we should end up with only one class loader for an app and none for boot image.
+    if (class_loader != nullptr && class_table != nullptr) {
+      DCHECK(class_loader_ == nullptr);
+      class_loader_ = class_loader;
+    }
+  }
+
+  size_t GetRemovedClassCount() const {
+    return removed_class_count_;
+  }
+
+  ObjPtr<mirror::ClassLoader> GetClassLoader() const REQUIRES_SHARED(Locks::mutator_lock_) {
+    return class_loader_;
+  }
+
+ private:
+  ImageWriter* const image_writer_;
+  size_t removed_class_count_;
+  ObjPtr<mirror::ClassLoader> class_loader_;
+};
+
+void ImageWriter::VisitClassLoaders(ClassLoaderVisitor* visitor) {
+  WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+  visitor->Visit(nullptr);  // Visit boot class loader.
+  Runtime::Current()->GetClassLinker()->VisitClassLoaders(visitor);
+}
+
+void ImageWriter::PruneAndPreloadDexCache(ObjPtr<mirror::DexCache> dex_cache,
+                                          ObjPtr<mirror::ClassLoader> class_loader) {
+  // To ensure deterministic contents of the hash-based arrays, each slot shall contain
+  // the candidate with the lowest index. As we're processing entries in increasing index
+  // order, this means trying to look up the entry for the current index if the slot is
+  // empty or if it contains a higher index.
+
+  Runtime* runtime = Runtime::Current();
+  ClassLinker* class_linker = runtime->GetClassLinker();
+  const DexFile& dex_file = *dex_cache->GetDexFile();
+  // Prune methods.
+  mirror::MethodDexCacheType* resolved_methods = dex_cache->GetResolvedMethods();
+  dex::TypeIndex last_class_idx;  // Initialized to invalid index.
+  ObjPtr<mirror::Class> last_class = nullptr;
+  for (size_t i = 0, num = dex_cache->GetDexFile()->NumMethodIds(); i != num; ++i) {
+    uint32_t slot_idx = dex_cache->MethodSlotIndex(i);
+    auto pair =
+        mirror::DexCache::GetNativePairPtrSize(resolved_methods, slot_idx, target_ptr_size_);
+    uint32_t stored_index = pair.index;
+    ArtMethod* method = pair.object;
+    if (method != nullptr && i > stored_index) {
+      continue;  // Already checked.
+    }
+    // Check if the referenced class is in the image. Note that we want to check the referenced
+    // class rather than the declaring class to preserve the semantics, i.e. using a MethodId
+    // results in resolving the referenced class and that can for example throw OOME.
+    const DexFile::MethodId& method_id = dex_file.GetMethodId(i);
+    if (method_id.class_idx_ != last_class_idx) {
+      last_class_idx = method_id.class_idx_;
+      last_class = class_linker->LookupResolvedType(
+          dex_file, last_class_idx, dex_cache, class_loader);
+      if (last_class != nullptr && !KeepClass(last_class)) {
+        last_class = nullptr;
+      }
+    }
+    if (method == nullptr || i < stored_index) {
+      if (last_class != nullptr) {
+        const char* name = dex_file.StringDataByIdx(method_id.name_idx_);
+        Signature signature = dex_file.GetMethodSignature(method_id);
+        if (last_class->IsInterface()) {
+          method = last_class->FindInterfaceMethod(name, signature, target_ptr_size_);
+        } else {
+          method = last_class->FindClassMethod(name, signature, target_ptr_size_);
+        }
+        if (method != nullptr) {
+          // If the referenced class is in the image, the defining class must also be there.
+          DCHECK(KeepClass(method->GetDeclaringClass()));
+          dex_cache->SetResolvedMethod(i, method, target_ptr_size_);
+        }
+      }
+    } else {
+      DCHECK_EQ(i, stored_index);
+      if (last_class == nullptr) {
+        dex_cache->ClearResolvedMethod(stored_index, target_ptr_size_);
+      }
+    }
+  }
+  // Prune fields and make the contents of the field array deterministic.
+  mirror::FieldDexCacheType* resolved_fields = dex_cache->GetResolvedFields();
+  last_class_idx = dex::TypeIndex();  // Initialized to invalid index.
+  last_class = nullptr;
+  for (size_t i = 0, end = dex_file.NumFieldIds(); i < end; ++i) {
+    uint32_t slot_idx = dex_cache->FieldSlotIndex(i);
+    auto pair = mirror::DexCache::GetNativePairPtrSize(resolved_fields, slot_idx, target_ptr_size_);
+    uint32_t stored_index = pair.index;
+    ArtField* field = pair.object;
+    if (field != nullptr && i > stored_index) {
+      continue;  // Already checked.
+    }
+    // Check if the referenced class is in the image. Note that we want to check the referenced
+    // class rather than the declaring class to preserve the semantics, i.e. using a FieldId
+    // results in resolving the referenced class and that can for example throw OOME.
+    const DexFile::FieldId& field_id = dex_file.GetFieldId(i);
+    if (field_id.class_idx_ != last_class_idx) {
+      last_class_idx = field_id.class_idx_;
+      last_class = class_linker->LookupResolvedType(
+          dex_file, last_class_idx, dex_cache, class_loader);
+      if (last_class != nullptr && !KeepClass(last_class)) {
+        last_class = nullptr;
+      }
+    }
+    if (field == nullptr || i < stored_index) {
+      if (last_class != nullptr) {
+        const char* name = dex_file.StringDataByIdx(field_id.name_idx_);
+        const char* type = dex_file.StringByTypeIdx(field_id.type_idx_);
+        field = mirror::Class::FindField(Thread::Current(), last_class, name, type);
+        if (field != nullptr) {
+          // If the referenced class is in the image, the defining class must also be there.
+          DCHECK(KeepClass(field->GetDeclaringClass()));
+          dex_cache->SetResolvedField(i, field, target_ptr_size_);
+        }
+      }
+    } else {
+      DCHECK_EQ(i, stored_index);
+      if (last_class == nullptr) {
+        dex_cache->ClearResolvedField(stored_index, target_ptr_size_);
+      }
+    }
+  }
+  // Prune types and make the contents of the type array deterministic.
+  // This is done after fields and methods as their lookup can touch the types array.
+  for (size_t i = 0, end = dex_cache->GetDexFile()->NumTypeIds(); i < end; ++i) {
+    dex::TypeIndex type_idx(i);
+    uint32_t slot_idx = dex_cache->TypeSlotIndex(type_idx);
+    mirror::TypeDexCachePair pair =
+        dex_cache->GetResolvedTypes()[slot_idx].load(std::memory_order_relaxed);
+    uint32_t stored_index = pair.index;
+    ObjPtr<mirror::Class> klass = pair.object.Read();
+    if (klass == nullptr || i < stored_index) {
+      klass = class_linker->LookupResolvedType(dex_file, type_idx, dex_cache, class_loader);
+      if (klass != nullptr) {
+        DCHECK_EQ(dex_cache->GetResolvedType(type_idx), klass);
+        stored_index = i;  // For correct clearing below if not keeping the `klass`.
+      }
+    } else if (i == stored_index && !KeepClass(klass)) {
+      dex_cache->ClearResolvedType(dex::TypeIndex(stored_index));
+    }
+  }
+  // Strings do not need pruning, but the contents of the string array must be deterministic.
+  for (size_t i = 0, end = dex_cache->GetDexFile()->NumStringIds(); i < end; ++i) {
+    dex::StringIndex string_idx(i);
+    uint32_t slot_idx = dex_cache->StringSlotIndex(string_idx);
+    mirror::StringDexCachePair pair =
+        dex_cache->GetStrings()[slot_idx].load(std::memory_order_relaxed);
+    uint32_t stored_index = pair.index;
+    ObjPtr<mirror::String> string = pair.object.Read();
+    if (string == nullptr || i < stored_index) {
+      string = class_linker->LookupString(dex_file, string_idx, dex_cache);
+      DCHECK(string == nullptr || dex_cache->GetResolvedString(string_idx) == string);
+    }
+  }
+}
+
+void ImageWriter::PruneNonImageClasses() {
+  Runtime* runtime = Runtime::Current();
+  ClassLinker* class_linker = runtime->GetClassLinker();
+  Thread* self = Thread::Current();
+  ScopedAssertNoThreadSuspension sa(__FUNCTION__);
+
+  // Prune uses-library dex caches. Only prune the uses-library dex caches since we want to make
+  // sure the other ones don't get unloaded before the OatWriter runs.
+  class_linker->VisitClassTables(
+      [&](ClassTable* table) REQUIRES_SHARED(Locks::mutator_lock_) {
+    table->RemoveStrongRoots(
+        [&](GcRoot<mirror::Object> root) REQUIRES_SHARED(Locks::mutator_lock_) {
+      ObjPtr<mirror::Object> obj = root.Read();
+      if (obj->IsDexCache()) {
+        // Return true if the dex file is not one of the ones in the map.
+        return dex_file_oat_index_map_.find(obj->AsDexCache()->GetDexFile()) ==
+            dex_file_oat_index_map_.end();
+      }
+      // Return false to avoid removing.
+      return false;
+    });
+  });
+
+  // Remove the undesired classes from the class roots.
+  ObjPtr<mirror::ClassLoader> class_loader;
+  {
+    PruneClassLoaderClassesVisitor class_loader_visitor(this);
+    VisitClassLoaders(&class_loader_visitor);
+    VLOG(compiler) << "Pruned " << class_loader_visitor.GetRemovedClassCount() << " classes";
+    class_loader = class_loader_visitor.GetClassLoader();
+    DCHECK_EQ(class_loader != nullptr, compile_app_image_);
+  }
+
+  // Clear references to removed classes from the DexCaches.
+  std::vector<ObjPtr<mirror::DexCache>> dex_caches;
+  {
+    ReaderMutexLock mu2(self, *Locks::dex_lock_);
+    dex_caches.reserve(class_linker->GetDexCachesData().size());
+    for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
+      if (self->IsJWeakCleared(data.weak_root)) {
+        continue;
+      }
+      dex_caches.push_back(self->DecodeJObject(data.weak_root)->AsDexCache());
+    }
+  }
+  for (ObjPtr<mirror::DexCache> dex_cache : dex_caches) {
+    PruneAndPreloadDexCache(dex_cache, class_loader);
+  }
+
+  // Drop the array class cache in the ClassLinker, as these are roots holding those classes live.
+  class_linker->DropFindArrayClassCache();
+
+  // Clear to save RAM.
+  prune_class_memo_.clear();
+}
+
+void ImageWriter::CheckNonImageClassesRemoved() {
+  if (compiler_driver_.GetImageClasses() != nullptr) {
+    auto visitor = [&](Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
+      if (obj->IsClass() && !IsInBootImage(obj)) {
+        Class* klass = obj->AsClass();
+        if (!KeepClass(klass)) {
+          DumpImageClasses();
+          std::string temp;
+          CHECK(KeepClass(klass))
+              << Runtime::Current()->GetHeap()->GetVerification()->FirstPathFromRootSet(klass);
+        }
+      }
+    };
+    gc::Heap* heap = Runtime::Current()->GetHeap();
+    heap->VisitObjects(visitor);
+  }
+}
+
+void ImageWriter::DumpImageClasses() {
+  auto image_classes = compiler_driver_.GetImageClasses();
+  CHECK(image_classes != nullptr);
+  for (const std::string& image_class : *image_classes) {
+    LOG(INFO) << " " << image_class;
+  }
+}
+
+mirror::String* ImageWriter::FindInternedString(mirror::String* string) {
+  Thread* const self = Thread::Current();
+  for (const ImageInfo& image_info : image_infos_) {
+    ObjPtr<mirror::String> const found = image_info.intern_table_->LookupStrong(self, string);
+    DCHECK(image_info.intern_table_->LookupWeak(self, string) == nullptr)
+        << string->ToModifiedUtf8();
+    if (found != nullptr) {
+      return found.Ptr();
+    }
+  }
+  if (compile_app_image_) {
+    Runtime* const runtime = Runtime::Current();
+    ObjPtr<mirror::String> found = runtime->GetInternTable()->LookupStrong(self, string);
+    // If we found it in the runtime intern table it could either be in the boot image or interned
+    // during app image compilation. If it was in the boot image return that, otherwise return null
+    // since it belongs to another image space.
+    if (found != nullptr && runtime->GetHeap()->ObjectIsInBootImageSpace(found.Ptr())) {
+      return found.Ptr();
+    }
+    DCHECK(runtime->GetInternTable()->LookupWeak(self, string) == nullptr)
+        << string->ToModifiedUtf8();
+  }
+  return nullptr;
+}
+
+
+ObjectArray<Object>* ImageWriter::CreateImageRoots(size_t oat_index) const {
+  Runtime* runtime = Runtime::Current();
+  ClassLinker* class_linker = runtime->GetClassLinker();
+  Thread* self = Thread::Current();
+  StackHandleScope<3> hs(self);
+  Handle<Class> object_array_class(hs.NewHandle(
+      class_linker->FindSystemClass(self, "[Ljava/lang/Object;")));
+
+  std::unordered_set<const DexFile*> image_dex_files;
+  for (auto& pair : dex_file_oat_index_map_) {
+    const DexFile* image_dex_file = pair.first;
+    size_t image_oat_index = pair.second;
+    if (oat_index == image_oat_index) {
+      image_dex_files.insert(image_dex_file);
+    }
+  }
+
+  // build an Object[] of all the DexCaches used in the source_space_.
+  // Since we can't hold the dex lock when allocating the dex_caches
+  // ObjectArray, we lock the dex lock twice, first to get the number
+  // of dex caches first and then lock it again to copy the dex
+  // caches. We check that the number of dex caches does not change.
+  size_t dex_cache_count = 0;
+  {
+    ReaderMutexLock mu(self, *Locks::dex_lock_);
+    // Count number of dex caches not in the boot image.
+    for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
+      ObjPtr<mirror::DexCache> dex_cache =
+          ObjPtr<mirror::DexCache>::DownCast(self->DecodeJObject(data.weak_root));
+      if (dex_cache == nullptr) {
+        continue;
+      }
+      const DexFile* dex_file = dex_cache->GetDexFile();
+      if (!IsInBootImage(dex_cache.Ptr())) {
+        dex_cache_count += image_dex_files.find(dex_file) != image_dex_files.end() ? 1u : 0u;
+      }
+    }
+  }
+  Handle<ObjectArray<Object>> dex_caches(
+      hs.NewHandle(ObjectArray<Object>::Alloc(self, object_array_class.Get(), dex_cache_count)));
+  CHECK(dex_caches != nullptr) << "Failed to allocate a dex cache array.";
+  {
+    ReaderMutexLock mu(self, *Locks::dex_lock_);
+    size_t non_image_dex_caches = 0;
+    // Re-count number of non image dex caches.
+    for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
+      ObjPtr<mirror::DexCache> dex_cache =
+          ObjPtr<mirror::DexCache>::DownCast(self->DecodeJObject(data.weak_root));
+      if (dex_cache == nullptr) {
+        continue;
+      }
+      const DexFile* dex_file = dex_cache->GetDexFile();
+      if (!IsInBootImage(dex_cache.Ptr())) {
+        non_image_dex_caches += image_dex_files.find(dex_file) != image_dex_files.end() ? 1u : 0u;
+      }
+    }
+    CHECK_EQ(dex_cache_count, non_image_dex_caches)
+        << "The number of non-image dex caches changed.";
+    size_t i = 0;
+    for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
+      ObjPtr<mirror::DexCache> dex_cache =
+          ObjPtr<mirror::DexCache>::DownCast(self->DecodeJObject(data.weak_root));
+      if (dex_cache == nullptr) {
+        continue;
+      }
+      const DexFile* dex_file = dex_cache->GetDexFile();
+      if (!IsInBootImage(dex_cache.Ptr()) &&
+          image_dex_files.find(dex_file) != image_dex_files.end()) {
+        dex_caches->Set<false>(i, dex_cache.Ptr());
+        ++i;
+      }
+    }
+  }
+
+  // build an Object[] of the roots needed to restore the runtime
+  int32_t image_roots_size = ImageHeader::NumberOfImageRoots(compile_app_image_);
+  auto image_roots(hs.NewHandle(
+      ObjectArray<Object>::Alloc(self, object_array_class.Get(), image_roots_size)));
+  image_roots->Set<false>(ImageHeader::kDexCaches, dex_caches.Get());
+  image_roots->Set<false>(ImageHeader::kClassRoots, class_linker->GetClassRoots());
+  // image_roots[ImageHeader::kClassLoader] will be set later for app image.
+  static_assert(ImageHeader::kClassLoader + 1u == ImageHeader::kImageRootsMax,
+                "Class loader should be the last image root.");
+  for (int32_t i = 0; i < ImageHeader::kImageRootsMax - 1; ++i) {
+    CHECK(image_roots->Get(i) != nullptr);
+  }
+  return image_roots.Get();
+}
+
+mirror::Object* ImageWriter::TryAssignBinSlot(WorkStack& work_stack,
+                                              mirror::Object* obj,
+                                              size_t oat_index) {
+  if (obj == nullptr || IsInBootImage(obj)) {
+    // Object is null or already in the image, there is no work to do.
+    return obj;
+  }
+  if (!IsImageBinSlotAssigned(obj)) {
+    // We want to intern all strings but also assign offsets for the source string. Since the
+    // pruning phase has already happened, if we intern a string to one in the image we still
+    // end up copying an unreachable string.
+    if (obj->IsString()) {
+      // Need to check if the string is already interned in another image info so that we don't have
+      // the intern tables of two different images contain the same string.
+      mirror::String* interned = FindInternedString(obj->AsString());
+      if (interned == nullptr) {
+        // Not in another image space, insert to our table.
+        interned =
+            GetImageInfo(oat_index).intern_table_->InternStrongImageString(obj->AsString()).Ptr();
+        DCHECK_EQ(interned, obj);
+      }
+    } else if (obj->IsDexCache()) {
+      oat_index = GetOatIndexForDexCache(obj->AsDexCache());
+    } else if (obj->IsClass()) {
+      // Visit and assign offsets for fields and field arrays.
+      mirror::Class* as_klass = obj->AsClass();
+      mirror::DexCache* dex_cache = as_klass->GetDexCache();
+      DCHECK(!as_klass->IsErroneous()) << as_klass->GetStatus();
+      if (compile_app_image_) {
+        // Extra sanity, no boot loader classes should be left!
+        CHECK(!IsBootClassLoaderClass(as_klass)) << as_klass->PrettyClass();
+      }
+      LengthPrefixedArray<ArtField>* fields[] = {
+          as_klass->GetSFieldsPtr(), as_klass->GetIFieldsPtr(),
+      };
+      // Overwrite the oat index value since the class' dex cache is more accurate of where it
+      // belongs.
+      oat_index = GetOatIndexForDexCache(dex_cache);
+      ImageInfo& image_info = GetImageInfo(oat_index);
+      if (!compile_app_image_) {
+        // Note: Avoid locking to prevent lock order violations from root visiting;
+        // image_info.class_table_ is only accessed from the image writer.
+        image_info.class_table_->InsertWithoutLocks(as_klass);
+      }
+      for (LengthPrefixedArray<ArtField>* cur_fields : fields) {
+        // Total array length including header.
+        if (cur_fields != nullptr) {
+          const size_t header_size = LengthPrefixedArray<ArtField>::ComputeSize(0);
+          // Forward the entire array at once.
+          auto it = native_object_relocations_.find(cur_fields);
+          CHECK(it == native_object_relocations_.end()) << "Field array " << cur_fields
+                                                  << " already forwarded";
+          size_t& offset = image_info.bin_slot_sizes_[kBinArtField];
+          DCHECK(!IsInBootImage(cur_fields));
+          native_object_relocations_.emplace(
+              cur_fields,
+              NativeObjectRelocation {
+                  oat_index, offset, kNativeObjectRelocationTypeArtFieldArray
+              });
+          offset += header_size;
+          // Forward individual fields so that we can quickly find where they belong.
+          for (size_t i = 0, count = cur_fields->size(); i < count; ++i) {
+            // Need to forward arrays separate of fields.
+            ArtField* field = &cur_fields->At(i);
+            auto it2 = native_object_relocations_.find(field);
+            CHECK(it2 == native_object_relocations_.end()) << "Field at index=" << i
+                << " already assigned " << field->PrettyField() << " static=" << field->IsStatic();
+            DCHECK(!IsInBootImage(field));
+            native_object_relocations_.emplace(
+                field,
+                NativeObjectRelocation { oat_index, offset, kNativeObjectRelocationTypeArtField });
+            offset += sizeof(ArtField);
+          }
+        }
+      }
+      // Visit and assign offsets for methods.
+      size_t num_methods = as_klass->NumMethods();
+      if (num_methods != 0) {
+        bool any_dirty = false;
+        for (auto& m : as_klass->GetMethods(target_ptr_size_)) {
+          if (WillMethodBeDirty(&m)) {
+            any_dirty = true;
+            break;
+          }
+        }
+        NativeObjectRelocationType type = any_dirty
+            ? kNativeObjectRelocationTypeArtMethodDirty
+            : kNativeObjectRelocationTypeArtMethodClean;
+        Bin bin_type = BinTypeForNativeRelocationType(type);
+        // Forward the entire array at once, but header first.
+        const size_t method_alignment = ArtMethod::Alignment(target_ptr_size_);
+        const size_t method_size = ArtMethod::Size(target_ptr_size_);
+        const size_t header_size = LengthPrefixedArray<ArtMethod>::ComputeSize(0,
+                                                                               method_size,
+                                                                               method_alignment);
+        LengthPrefixedArray<ArtMethod>* array = as_klass->GetMethodsPtr();
+        auto it = native_object_relocations_.find(array);
+        CHECK(it == native_object_relocations_.end())
+            << "Method array " << array << " already forwarded";
+        size_t& offset = image_info.bin_slot_sizes_[bin_type];
+        DCHECK(!IsInBootImage(array));
+        native_object_relocations_.emplace(array,
+            NativeObjectRelocation {
+                oat_index,
+                offset,
+                any_dirty ? kNativeObjectRelocationTypeArtMethodArrayDirty
+                          : kNativeObjectRelocationTypeArtMethodArrayClean });
+        offset += header_size;
+        for (auto& m : as_klass->GetMethods(target_ptr_size_)) {
+          AssignMethodOffset(&m, type, oat_index);
+        }
+        (any_dirty ? dirty_methods_ : clean_methods_) += num_methods;
+      }
+      // Assign offsets for all runtime methods in the IMT since these may hold conflict tables
+      // live.
+      if (as_klass->ShouldHaveImt()) {
+        ImTable* imt = as_klass->GetImt(target_ptr_size_);
+        if (TryAssignImTableOffset(imt, oat_index)) {
+          // Since imt's can be shared only do this the first time to not double count imt method
+          // fixups.
+          for (size_t i = 0; i < ImTable::kSize; ++i) {
+            ArtMethod* imt_method = imt->Get(i, target_ptr_size_);
+            DCHECK(imt_method != nullptr);
+            if (imt_method->IsRuntimeMethod() &&
+                !IsInBootImage(imt_method) &&
+                !NativeRelocationAssigned(imt_method)) {
+              AssignMethodOffset(imt_method, kNativeObjectRelocationTypeRuntimeMethod, oat_index);
+            }
+          }
+        }
+      }
+    } else if (obj->IsClassLoader()) {
+      // Register the class loader if it has a class table.
+      // The fake boot class loader should not get registered and we should end up with only one
+      // class loader.
+      mirror::ClassLoader* class_loader = obj->AsClassLoader();
+      if (class_loader->GetClassTable() != nullptr) {
+        DCHECK(compile_app_image_);
+        DCHECK(class_loaders_.empty());
+        class_loaders_.insert(class_loader);
+        ImageInfo& image_info = GetImageInfo(oat_index);
+        // Note: Avoid locking to prevent lock order violations from root visiting;
+        // image_info.class_table_ table is only accessed from the image writer
+        // and class_loader->GetClassTable() is iterated but not modified.
+        image_info.class_table_->CopyWithoutLocks(*class_loader->GetClassTable());
+      }
+    }
+    AssignImageBinSlot(obj, oat_index);
+    work_stack.emplace(obj, oat_index);
+  }
+  if (obj->IsString()) {
+    // Always return the interned string if there exists one.
+    mirror::String* interned = FindInternedString(obj->AsString());
+    if (interned != nullptr) {
+      return interned;
+    }
+  }
+  return obj;
+}
+
+bool ImageWriter::NativeRelocationAssigned(void* ptr) const {
+  return native_object_relocations_.find(ptr) != native_object_relocations_.end();
+}
+
+bool ImageWriter::TryAssignImTableOffset(ImTable* imt, size_t oat_index) {
+  // No offset, or already assigned.
+  if (imt == nullptr || IsInBootImage(imt) || NativeRelocationAssigned(imt)) {
+    return false;
+  }
+  // If the method is a conflict method we also want to assign the conflict table offset.
+  ImageInfo& image_info = GetImageInfo(oat_index);
+  const size_t size = ImTable::SizeInBytes(target_ptr_size_);
+  native_object_relocations_.emplace(
+      imt,
+      NativeObjectRelocation {
+          oat_index,
+          image_info.bin_slot_sizes_[kBinImTable],
+          kNativeObjectRelocationTypeIMTable});
+  image_info.bin_slot_sizes_[kBinImTable] += size;
+  return true;
+}
+
+void ImageWriter::TryAssignConflictTableOffset(ImtConflictTable* table, size_t oat_index) {
+  // No offset, or already assigned.
+  if (table == nullptr || NativeRelocationAssigned(table)) {
+    return;
+  }
+  CHECK(!IsInBootImage(table));
+  // If the method is a conflict method we also want to assign the conflict table offset.
+  ImageInfo& image_info = GetImageInfo(oat_index);
+  const size_t size = table->ComputeSize(target_ptr_size_);
+  native_object_relocations_.emplace(
+      table,
+      NativeObjectRelocation {
+          oat_index,
+          image_info.bin_slot_sizes_[kBinIMTConflictTable],
+          kNativeObjectRelocationTypeIMTConflictTable});
+  image_info.bin_slot_sizes_[kBinIMTConflictTable] += size;
+}
+
+void ImageWriter::AssignMethodOffset(ArtMethod* method,
+                                     NativeObjectRelocationType type,
+                                     size_t oat_index) {
+  DCHECK(!IsInBootImage(method));
+  CHECK(!NativeRelocationAssigned(method)) << "Method " << method << " already assigned "
+      << ArtMethod::PrettyMethod(method);
+  if (method->IsRuntimeMethod()) {
+    TryAssignConflictTableOffset(method->GetImtConflictTable(target_ptr_size_), oat_index);
+  }
+  ImageInfo& image_info = GetImageInfo(oat_index);
+  size_t& offset = image_info.bin_slot_sizes_[BinTypeForNativeRelocationType(type)];
+  native_object_relocations_.emplace(method, NativeObjectRelocation { oat_index, offset, type });
+  offset += ArtMethod::Size(target_ptr_size_);
+}
+
+void ImageWriter::UnbinObjectsIntoOffset(mirror::Object* obj) {
+  DCHECK(!IsInBootImage(obj));
+  CHECK(obj != nullptr);
+
+  // We know the bin slot, and the total bin sizes for all objects by now,
+  // so calculate the object's final image offset.
+
+  DCHECK(IsImageBinSlotAssigned(obj));
+  BinSlot bin_slot = GetImageBinSlot(obj);
+  // Change the lockword from a bin slot into an offset
+  AssignImageOffset(obj, bin_slot);
+}
+
+class ImageWriter::VisitReferencesVisitor {
+ public:
+  VisitReferencesVisitor(ImageWriter* image_writer, WorkStack* work_stack, size_t oat_index)
+      : image_writer_(image_writer), work_stack_(work_stack), oat_index_(oat_index) {}
+
+  // Fix up separately since we also need to fix up method entrypoints.
+  ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<mirror::Object>* root) const
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    if (!root->IsNull()) {
+      VisitRoot(root);
+    }
+  }
+
+  ALWAYS_INLINE void VisitRoot(mirror::CompressedReference<mirror::Object>* root) const
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    root->Assign(VisitReference(root->AsMirrorPtr()));
+  }
+
+  ALWAYS_INLINE void operator() (ObjPtr<mirror::Object> obj,
+                                 MemberOffset offset,
+                                 bool is_static ATTRIBUTE_UNUSED) const
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    mirror::Object* ref =
+        obj->GetFieldObject<mirror::Object, kVerifyNone, kWithoutReadBarrier>(offset);
+    obj->SetFieldObject</*kTransactionActive*/false>(offset, VisitReference(ref));
+  }
+
+  ALWAYS_INLINE void operator() (ObjPtr<mirror::Class> klass ATTRIBUTE_UNUSED,
+                                 ObjPtr<mirror::Reference> ref) const
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    operator()(ref, mirror::Reference::ReferentOffset(), /* is_static */ false);
+  }
+
+ private:
+  mirror::Object* VisitReference(mirror::Object* ref) const REQUIRES_SHARED(Locks::mutator_lock_) {
+    return image_writer_->TryAssignBinSlot(*work_stack_, ref, oat_index_);
+  }
+
+  ImageWriter* const image_writer_;
+  WorkStack* const work_stack_;
+  const size_t oat_index_;
+};
+
+class ImageWriter::GetRootsVisitor : public RootVisitor  {
+ public:
+  explicit GetRootsVisitor(std::vector<mirror::Object*>* roots) : roots_(roots) {}
+
+  void VisitRoots(mirror::Object*** roots,
+                  size_t count,
+                  const RootInfo& info ATTRIBUTE_UNUSED) OVERRIDE
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    for (size_t i = 0; i < count; ++i) {
+      roots_->push_back(*roots[i]);
+    }
+  }
+
+  void VisitRoots(mirror::CompressedReference<mirror::Object>** roots,
+                  size_t count,
+                  const RootInfo& info ATTRIBUTE_UNUSED) OVERRIDE
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    for (size_t i = 0; i < count; ++i) {
+      roots_->push_back(roots[i]->AsMirrorPtr());
+    }
+  }
+
+ private:
+  std::vector<mirror::Object*>* const roots_;
+};
+
+void ImageWriter::ProcessWorkStack(WorkStack* work_stack) {
+  while (!work_stack->empty()) {
+    std::pair<mirror::Object*, size_t> pair(work_stack->top());
+    work_stack->pop();
+    VisitReferencesVisitor visitor(this, work_stack, /*oat_index*/ pair.second);
+    // Walk references and assign bin slots for them.
+    pair.first->VisitReferences</*kVisitNativeRoots*/true, kVerifyNone, kWithoutReadBarrier>(
+        visitor,
+        visitor);
+  }
+}
+
+void ImageWriter::CalculateNewObjectOffsets() {
+  Thread* const self = Thread::Current();
+  VariableSizedHandleScope handles(self);
+  std::vector<Handle<ObjectArray<Object>>> image_roots;
+  for (size_t i = 0, size = oat_filenames_.size(); i != size; ++i) {
+    image_roots.push_back(handles.NewHandle(CreateImageRoots(i)));
+  }
+
+  Runtime* const runtime = Runtime::Current();
+  gc::Heap* const heap = runtime->GetHeap();
+
+  // Leave space for the header, but do not write it yet, we need to
+  // know where image_roots is going to end up
+  image_objects_offset_begin_ = RoundUp(sizeof(ImageHeader), kObjectAlignment);  // 64-bit-alignment
+
+  const size_t method_alignment = ArtMethod::Alignment(target_ptr_size_);
+  // Write the image runtime methods.
+  image_methods_[ImageHeader::kResolutionMethod] = runtime->GetResolutionMethod();
+  image_methods_[ImageHeader::kImtConflictMethod] = runtime->GetImtConflictMethod();
+  image_methods_[ImageHeader::kImtUnimplementedMethod] = runtime->GetImtUnimplementedMethod();
+  image_methods_[ImageHeader::kSaveAllCalleeSavesMethod] =
+      runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveAllCalleeSaves);
+  image_methods_[ImageHeader::kSaveRefsOnlyMethod] =
+      runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsOnly);
+  image_methods_[ImageHeader::kSaveRefsAndArgsMethod] =
+      runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsAndArgs);
+  image_methods_[ImageHeader::kSaveEverythingMethod] =
+      runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverything);
+  image_methods_[ImageHeader::kSaveEverythingMethodForClinit] =
+      runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverythingForClinit);
+  image_methods_[ImageHeader::kSaveEverythingMethodForSuspendCheck] =
+      runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverythingForSuspendCheck);
+  // Visit image methods first to have the main runtime methods in the first image.
+  for (auto* m : image_methods_) {
+    CHECK(m != nullptr);
+    CHECK(m->IsRuntimeMethod());
+    DCHECK_EQ(compile_app_image_, IsInBootImage(m)) << "Trampolines should be in boot image";
+    if (!IsInBootImage(m)) {
+      AssignMethodOffset(m, kNativeObjectRelocationTypeRuntimeMethod, GetDefaultOatIndex());
+    }
+  }
+
+  // Deflate monitors before we visit roots since deflating acquires the monitor lock. Acquiring
+  // this lock while holding other locks may cause lock order violations.
+  {
+    auto deflate_monitor = [](mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
+      Monitor::Deflate(Thread::Current(), obj);
+    };
+    heap->VisitObjects(deflate_monitor);
+  }
+
+  // Work list of <object, oat_index> for objects. Everything on the stack must already be
+  // assigned a bin slot.
+  WorkStack work_stack;
+
+  // Special case interned strings to put them in the image they are likely to be resolved from.
+  for (const DexFile* dex_file : compiler_driver_.GetDexFilesForOatFile()) {
+    auto it = dex_file_oat_index_map_.find(dex_file);
+    DCHECK(it != dex_file_oat_index_map_.end()) << dex_file->GetLocation();
+    const size_t oat_index = it->second;
+    InternTable* const intern_table = runtime->GetInternTable();
+    for (size_t i = 0, count = dex_file->NumStringIds(); i < count; ++i) {
+      uint32_t utf16_length;
+      const char* utf8_data = dex_file->StringDataAndUtf16LengthByIdx(dex::StringIndex(i),
+                                                                      &utf16_length);
+      mirror::String* string = intern_table->LookupStrong(self, utf16_length, utf8_data).Ptr();
+      TryAssignBinSlot(work_stack, string, oat_index);
+    }
+  }
+
+  // Get the GC roots and then visit them separately to avoid lock violations since the root visitor
+  // visits roots while holding various locks.
+  {
+    std::vector<mirror::Object*> roots;
+    GetRootsVisitor root_visitor(&roots);
+    runtime->VisitRoots(&root_visitor);
+    for (mirror::Object* obj : roots) {
+      TryAssignBinSlot(work_stack, obj, GetDefaultOatIndex());
+    }
+  }
+  ProcessWorkStack(&work_stack);
+
+  // For app images, there may be objects that are only held live by the by the boot image. One
+  // example is finalizer references. Forward these objects so that EnsureBinSlotAssignedCallback
+  // does not fail any checks. TODO: We should probably avoid copying these objects.
+  if (compile_app_image_) {
+    for (gc::space::ImageSpace* space : heap->GetBootImageSpaces()) {
+      DCHECK(space->IsImageSpace());
+      gc::accounting::ContinuousSpaceBitmap* live_bitmap = space->GetLiveBitmap();
+      live_bitmap->VisitMarkedRange(reinterpret_cast<uintptr_t>(space->Begin()),
+                                    reinterpret_cast<uintptr_t>(space->Limit()),
+                                    [this, &work_stack](mirror::Object* obj)
+          REQUIRES_SHARED(Locks::mutator_lock_) {
+        VisitReferencesVisitor visitor(this, &work_stack, GetDefaultOatIndex());
+        // Visit all references and try to assign bin slots for them (calls TryAssignBinSlot).
+        obj->VisitReferences</*kVisitNativeRoots*/true, kVerifyNone, kWithoutReadBarrier>(
+            visitor,
+            visitor);
+      });
+    }
+    // Process the work stack in case anything was added by TryAssignBinSlot.
+    ProcessWorkStack(&work_stack);
+
+    // Store the class loader in the class roots.
+    CHECK_EQ(class_loaders_.size(), 1u);
+    CHECK_EQ(image_roots.size(), 1u);
+    CHECK(*class_loaders_.begin() != nullptr);
+    image_roots[0]->Set<false>(ImageHeader::kClassLoader, *class_loaders_.begin());
+  }
+
+  // Verify that all objects have assigned image bin slots.
+  {
+    auto ensure_bin_slots_assigned = [&](mirror::Object* obj)
+        REQUIRES_SHARED(Locks::mutator_lock_) {
+      if (!Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(obj)) {
+        CHECK(IsImageBinSlotAssigned(obj)) << mirror::Object::PrettyTypeOf(obj) << " " << obj;
+      }
+    };
+    heap->VisitObjects(ensure_bin_slots_assigned);
+  }
+
+  // Calculate size of the dex cache arrays slot and prepare offsets.
+  PrepareDexCacheArraySlots();
+
+  // Calculate the sizes of the intern tables, class tables, and fixup tables.
+  for (ImageInfo& image_info : image_infos_) {
+    // Calculate how big the intern table will be after being serialized.
+    InternTable* const intern_table = image_info.intern_table_.get();
+    CHECK_EQ(intern_table->WeakSize(), 0u) << " should have strong interned all the strings";
+    if (intern_table->StrongSize() != 0u) {
+      image_info.intern_table_bytes_ = intern_table->WriteToMemory(nullptr);
+    }
+
+    // Calculate the size of the class table.
+    ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_);
+    DCHECK_EQ(image_info.class_table_->NumReferencedZygoteClasses(), 0u);
+    if (image_info.class_table_->NumReferencedNonZygoteClasses() != 0u) {
+      image_info.class_table_bytes_ += image_info.class_table_->WriteToMemory(nullptr);
+    }
+  }
+
+  // Calculate bin slot offsets.
+  for (ImageInfo& image_info : image_infos_) {
+    size_t bin_offset = image_objects_offset_begin_;
+    for (size_t i = 0; i != kBinSize; ++i) {
+      switch (i) {
+        case kBinArtMethodClean:
+        case kBinArtMethodDirty: {
+          bin_offset = RoundUp(bin_offset, method_alignment);
+          break;
+        }
+        case kBinDexCacheArray:
+          bin_offset = RoundUp(bin_offset, DexCacheArraysLayout::Alignment(target_ptr_size_));
+          break;
+        case kBinImTable:
+        case kBinIMTConflictTable: {
+          bin_offset = RoundUp(bin_offset, static_cast<size_t>(target_ptr_size_));
+          break;
+        }
+        default: {
+          // Normal alignment.
+        }
+      }
+      image_info.bin_slot_offsets_[i] = bin_offset;
+      bin_offset += image_info.bin_slot_sizes_[i];
+    }
+    // NOTE: There may be additional padding between the bin slots and the intern table.
+    DCHECK_EQ(image_info.image_end_,
+              GetBinSizeSum(image_info, kBinMirrorCount) + image_objects_offset_begin_);
+  }
+
+  // Calculate image offsets.
+  size_t image_offset = 0;
+  for (ImageInfo& image_info : image_infos_) {
+    image_info.image_begin_ = global_image_begin_ + image_offset;
+    image_info.image_offset_ = image_offset;
+    ImageSection unused_sections[ImageHeader::kSectionCount];
+    image_info.image_size_ =
+        RoundUp(image_info.CreateImageSections(unused_sections, compile_app_image_), kPageSize);
+    // There should be no gaps until the next image.
+    image_offset += image_info.image_size_;
+  }
+
+  // Transform each object's bin slot into an offset which will be used to do the final copy.
+  {
+    auto unbin_objects_into_offset = [&](mirror::Object* obj)
+        REQUIRES_SHARED(Locks::mutator_lock_) {
+      if (!IsInBootImage(obj)) {
+        UnbinObjectsIntoOffset(obj);
+      }
+    };
+    heap->VisitObjects(unbin_objects_into_offset);
+  }
+
+  size_t i = 0;
+  for (ImageInfo& image_info : image_infos_) {
+    image_info.image_roots_address_ = PointerToLowMemUInt32(GetImageAddress(image_roots[i].Get()));
+    i++;
+  }
+
+  // Update the native relocations by adding their bin sums.
+  for (auto& pair : native_object_relocations_) {
+    NativeObjectRelocation& relocation = pair.second;
+    Bin bin_type = BinTypeForNativeRelocationType(relocation.type);
+    ImageInfo& image_info = GetImageInfo(relocation.oat_index);
+    relocation.offset += image_info.bin_slot_offsets_[bin_type];
+  }
+}
+
+size_t ImageWriter::ImageInfo::CreateImageSections(ImageSection* out_sections,
+                                                   bool app_image) const {
+  DCHECK(out_sections != nullptr);
+
+  // Do not round up any sections here that are represented by the bins since it will break
+  // offsets.
+
+  // Objects section
+  ImageSection* objects_section = &out_sections[ImageHeader::kSectionObjects];
+  *objects_section = ImageSection(0u, image_end_);
+
+  // Add field section.
+  ImageSection* field_section = &out_sections[ImageHeader::kSectionArtFields];
+  *field_section = ImageSection(bin_slot_offsets_[kBinArtField], bin_slot_sizes_[kBinArtField]);
+  CHECK_EQ(bin_slot_offsets_[kBinArtField], field_section->Offset());
+
+  // Add method section.
+  ImageSection* methods_section = &out_sections[ImageHeader::kSectionArtMethods];
+  *methods_section = ImageSection(
+      bin_slot_offsets_[kBinArtMethodClean],
+      bin_slot_sizes_[kBinArtMethodClean] + bin_slot_sizes_[kBinArtMethodDirty]);
+
+  // IMT section.
+  ImageSection* imt_section = &out_sections[ImageHeader::kSectionImTables];
+  *imt_section = ImageSection(bin_slot_offsets_[kBinImTable], bin_slot_sizes_[kBinImTable]);
+
+  // Conflict tables section.
+  ImageSection* imt_conflict_tables_section = &out_sections[ImageHeader::kSectionIMTConflictTables];
+  *imt_conflict_tables_section = ImageSection(bin_slot_offsets_[kBinIMTConflictTable],
+                                              bin_slot_sizes_[kBinIMTConflictTable]);
+
+  // Runtime methods section.
+  ImageSection* runtime_methods_section = &out_sections[ImageHeader::kSectionRuntimeMethods];
+  *runtime_methods_section = ImageSection(bin_slot_offsets_[kBinRuntimeMethod],
+                                          bin_slot_sizes_[kBinRuntimeMethod]);
+
+  // Add dex cache arrays section.
+  ImageSection* dex_cache_arrays_section = &out_sections[ImageHeader::kSectionDexCacheArrays];
+  *dex_cache_arrays_section = ImageSection(bin_slot_offsets_[kBinDexCacheArray],
+                                           bin_slot_sizes_[kBinDexCacheArray]);
+  // For boot image, round up to the page boundary to separate the interned strings and
+  // class table from the modifiable data. We shall mprotect() these pages read-only when
+  // we load the boot image. This is more than sufficient for the string table alignment,
+  // namely sizeof(uint64_t). See HashSet::WriteToMemory.
+  static_assert(IsAligned<sizeof(uint64_t)>(kPageSize), "String table alignment check.");
+  size_t cur_pos =
+      RoundUp(dex_cache_arrays_section->End(), app_image ? sizeof(uint64_t) : kPageSize);
+  // Calculate the size of the interned strings.
+  ImageSection* interned_strings_section = &out_sections[ImageHeader::kSectionInternedStrings];
+  *interned_strings_section = ImageSection(cur_pos, intern_table_bytes_);
+  cur_pos = interned_strings_section->End();
+  // Round up to the alignment the class table expects. See HashSet::WriteToMemory.
+  cur_pos = RoundUp(cur_pos, sizeof(uint64_t));
+  // Calculate the size of the class table section.
+  ImageSection* class_table_section = &out_sections[ImageHeader::kSectionClassTable];
+  *class_table_section = ImageSection(cur_pos, class_table_bytes_);
+  cur_pos = class_table_section->End();
+  // Image end goes right before the start of the image bitmap.
+  return cur_pos;
+}
+
+void ImageWriter::CreateHeader(size_t oat_index) {
+  ImageInfo& image_info = GetImageInfo(oat_index);
+  const uint8_t* oat_file_begin = image_info.oat_file_begin_;
+  const uint8_t* oat_file_end = oat_file_begin + image_info.oat_loaded_size_;
+  const uint8_t* oat_data_end = image_info.oat_data_begin_ + image_info.oat_size_;
+
+  // Create the image sections.
+  ImageSection sections[ImageHeader::kSectionCount];
+  const size_t image_end = image_info.CreateImageSections(sections, compile_app_image_);
+
+  // Finally bitmap section.
+  const size_t bitmap_bytes = image_info.image_bitmap_->Size();
+  auto* bitmap_section = &sections[ImageHeader::kSectionImageBitmap];
+  *bitmap_section = ImageSection(RoundUp(image_end, kPageSize), RoundUp(bitmap_bytes, kPageSize));
+  if (VLOG_IS_ON(compiler)) {
+    LOG(INFO) << "Creating header for " << oat_filenames_[oat_index];
+    size_t idx = 0;
+    for (const ImageSection& section : sections) {
+      LOG(INFO) << static_cast<ImageHeader::ImageSections>(idx) << " " << section;
+      ++idx;
+    }
+    LOG(INFO) << "Methods: clean=" << clean_methods_ << " dirty=" << dirty_methods_;
+    LOG(INFO) << "Image roots address=" << std::hex << image_info.image_roots_address_ << std::dec;
+    LOG(INFO) << "Image begin=" << std::hex << reinterpret_cast<uintptr_t>(global_image_begin_)
+              << " Image offset=" << image_info.image_offset_ << std::dec;
+    LOG(INFO) << "Oat file begin=" << std::hex << reinterpret_cast<uintptr_t>(oat_file_begin)
+              << " Oat data begin=" << reinterpret_cast<uintptr_t>(image_info.oat_data_begin_)
+              << " Oat data end=" << reinterpret_cast<uintptr_t>(oat_data_end)
+              << " Oat file end=" << reinterpret_cast<uintptr_t>(oat_file_end);
+  }
+  // Store boot image info for app image so that we can relocate.
+  uint32_t boot_image_begin = 0;
+  uint32_t boot_image_end = 0;
+  uint32_t boot_oat_begin = 0;
+  uint32_t boot_oat_end = 0;
+  gc::Heap* const heap = Runtime::Current()->GetHeap();
+  heap->GetBootImagesSize(&boot_image_begin, &boot_image_end, &boot_oat_begin, &boot_oat_end);
+
+  // Create the header, leave 0 for data size since we will fill this in as we are writing the
+  // image.
+  new (image_info.image_->Begin()) ImageHeader(PointerToLowMemUInt32(image_info.image_begin_),
+                                               image_end,
+                                               sections,
+                                               image_info.image_roots_address_,
+                                               image_info.oat_checksum_,
+                                               PointerToLowMemUInt32(oat_file_begin),
+                                               PointerToLowMemUInt32(image_info.oat_data_begin_),
+                                               PointerToLowMemUInt32(oat_data_end),
+                                               PointerToLowMemUInt32(oat_file_end),
+                                               boot_image_begin,
+                                               boot_image_end - boot_image_begin,
+                                               boot_oat_begin,
+                                               boot_oat_end - boot_oat_begin,
+                                               static_cast<uint32_t>(target_ptr_size_),
+                                               compile_pic_,
+                                               /*is_pic*/compile_app_image_,
+                                               image_storage_mode_,
+                                               /*data_size*/0u);
+}
+
+ArtMethod* ImageWriter::GetImageMethodAddress(ArtMethod* method) {
+  auto it = native_object_relocations_.find(method);
+  CHECK(it != native_object_relocations_.end()) << ArtMethod::PrettyMethod(method) << " @ "
+                                                << method;
+  size_t oat_index = GetOatIndex(method->GetDexCache());
+  ImageInfo& image_info = GetImageInfo(oat_index);
+  CHECK_GE(it->second.offset, image_info.image_end_) << "ArtMethods should be after Objects";
+  return reinterpret_cast<ArtMethod*>(image_info.image_begin_ + it->second.offset);
+}
+
+class ImageWriter::FixupRootVisitor : public RootVisitor {
+ public:
+  explicit FixupRootVisitor(ImageWriter* image_writer) : image_writer_(image_writer) {
+  }
+
+  void VisitRoots(mirror::Object*** roots ATTRIBUTE_UNUSED,
+                  size_t count ATTRIBUTE_UNUSED,
+                  const RootInfo& info ATTRIBUTE_UNUSED)
+      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
+    LOG(FATAL) << "Unsupported";
+  }
+
+  void VisitRoots(mirror::CompressedReference<mirror::Object>** roots, size_t count,
+                  const RootInfo& info ATTRIBUTE_UNUSED)
+      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
+    for (size_t i = 0; i < count; ++i) {
+      image_writer_->CopyReference(roots[i], roots[i]->AsMirrorPtr());
+    }
+  }
+
+ private:
+  ImageWriter* const image_writer_;
+};
+
+void ImageWriter::CopyAndFixupImTable(ImTable* orig, ImTable* copy) {
+  for (size_t i = 0; i < ImTable::kSize; ++i) {
+    ArtMethod* method = orig->Get(i, target_ptr_size_);
+    void** address = reinterpret_cast<void**>(copy->AddressOfElement(i, target_ptr_size_));
+    CopyAndFixupPointer(address, method);
+    DCHECK_EQ(copy->Get(i, target_ptr_size_), NativeLocationInImage(method));
+  }
+}
+
+void ImageWriter::CopyAndFixupImtConflictTable(ImtConflictTable* orig, ImtConflictTable* copy) {
+  const size_t count = orig->NumEntries(target_ptr_size_);
+  for (size_t i = 0; i < count; ++i) {
+    ArtMethod* interface_method = orig->GetInterfaceMethod(i, target_ptr_size_);
+    ArtMethod* implementation_method = orig->GetImplementationMethod(i, target_ptr_size_);
+    CopyAndFixupPointer(copy->AddressOfInterfaceMethod(i, target_ptr_size_), interface_method);
+    CopyAndFixupPointer(copy->AddressOfImplementationMethod(i, target_ptr_size_),
+                        implementation_method);
+    DCHECK_EQ(copy->GetInterfaceMethod(i, target_ptr_size_),
+              NativeLocationInImage(interface_method));
+    DCHECK_EQ(copy->GetImplementationMethod(i, target_ptr_size_),
+              NativeLocationInImage(implementation_method));
+  }
+}
+
+void ImageWriter::CopyAndFixupNativeData(size_t oat_index) {
+  const ImageInfo& image_info = GetImageInfo(oat_index);
+  // Copy ArtFields and methods to their locations and update the array for convenience.
+  for (auto& pair : native_object_relocations_) {
+    NativeObjectRelocation& relocation = pair.second;
+    // Only work with fields and methods that are in the current oat file.
+    if (relocation.oat_index != oat_index) {
+      continue;
+    }
+    auto* dest = image_info.image_->Begin() + relocation.offset;
+    DCHECK_GE(dest, image_info.image_->Begin() + image_info.image_end_);
+    DCHECK(!IsInBootImage(pair.first));
+    switch (relocation.type) {
+      case kNativeObjectRelocationTypeArtField: {
+        memcpy(dest, pair.first, sizeof(ArtField));
+        CopyReference(
+            reinterpret_cast<ArtField*>(dest)->GetDeclaringClassAddressWithoutBarrier(),
+            reinterpret_cast<ArtField*>(pair.first)->GetDeclaringClass().Ptr());
+        break;
+      }
+      case kNativeObjectRelocationTypeRuntimeMethod:
+      case kNativeObjectRelocationTypeArtMethodClean:
+      case kNativeObjectRelocationTypeArtMethodDirty: {
+        CopyAndFixupMethod(reinterpret_cast<ArtMethod*>(pair.first),
+                           reinterpret_cast<ArtMethod*>(dest),
+                           image_info);
+        break;
+      }
+      // For arrays, copy just the header since the elements will get copied by their corresponding
+      // relocations.
+      case kNativeObjectRelocationTypeArtFieldArray: {
+        memcpy(dest, pair.first, LengthPrefixedArray<ArtField>::ComputeSize(0));
+        break;
+      }
+      case kNativeObjectRelocationTypeArtMethodArrayClean:
+      case kNativeObjectRelocationTypeArtMethodArrayDirty: {
+        size_t size = ArtMethod::Size(target_ptr_size_);
+        size_t alignment = ArtMethod::Alignment(target_ptr_size_);
+        memcpy(dest, pair.first, LengthPrefixedArray<ArtMethod>::ComputeSize(0, size, alignment));
+        // Clear padding to avoid non-deterministic data in the image (and placate valgrind).
+        reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(dest)->ClearPadding(size, alignment);
+        break;
+      }
+      case kNativeObjectRelocationTypeDexCacheArray:
+        // Nothing to copy here, everything is done in FixupDexCache().
+        break;
+      case kNativeObjectRelocationTypeIMTable: {
+        ImTable* orig_imt = reinterpret_cast<ImTable*>(pair.first);
+        ImTable* dest_imt = reinterpret_cast<ImTable*>(dest);
+        CopyAndFixupImTable(orig_imt, dest_imt);
+        break;
+      }
+      case kNativeObjectRelocationTypeIMTConflictTable: {
+        auto* orig_table = reinterpret_cast<ImtConflictTable*>(pair.first);
+        CopyAndFixupImtConflictTable(
+            orig_table,
+            new(dest)ImtConflictTable(orig_table->NumEntries(target_ptr_size_), target_ptr_size_));
+        break;
+      }
+    }
+  }
+  // Fixup the image method roots.
+  auto* image_header = reinterpret_cast<ImageHeader*>(image_info.image_->Begin());
+  for (size_t i = 0; i < ImageHeader::kImageMethodsCount; ++i) {
+    ArtMethod* method = image_methods_[i];
+    CHECK(method != nullptr);
+    if (!IsInBootImage(method)) {
+      method = NativeLocationInImage(method);
+    }
+    image_header->SetImageMethod(static_cast<ImageHeader::ImageMethod>(i), method);
+  }
+  FixupRootVisitor root_visitor(this);
+
+  // Write the intern table into the image.
+  if (image_info.intern_table_bytes_ > 0) {
+    const ImageSection& intern_table_section = image_header->GetInternedStringsSection();
+    InternTable* const intern_table = image_info.intern_table_.get();
+    uint8_t* const intern_table_memory_ptr =
+        image_info.image_->Begin() + intern_table_section.Offset();
+    const size_t intern_table_bytes = intern_table->WriteToMemory(intern_table_memory_ptr);
+    CHECK_EQ(intern_table_bytes, image_info.intern_table_bytes_);
+    // Fixup the pointers in the newly written intern table to contain image addresses.
+    InternTable temp_intern_table;
+    // Note that we require that ReadFromMemory does not make an internal copy of the elements so that
+    // the VisitRoots() will update the memory directly rather than the copies.
+    // This also relies on visit roots not doing any verification which could fail after we update
+    // the roots to be the image addresses.
+    temp_intern_table.AddTableFromMemory(intern_table_memory_ptr);
+    CHECK_EQ(temp_intern_table.Size(), intern_table->Size());
+    temp_intern_table.VisitRoots(&root_visitor, kVisitRootFlagAllRoots);
+  }
+  // Write the class table(s) into the image. class_table_bytes_ may be 0 if there are multiple
+  // class loaders. Writing multiple class tables into the image is currently unsupported.
+  if (image_info.class_table_bytes_ > 0u) {
+    const ImageSection& class_table_section = image_header->GetClassTableSection();
+    uint8_t* const class_table_memory_ptr =
+        image_info.image_->Begin() + class_table_section.Offset();
+    ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+
+    ClassTable* table = image_info.class_table_.get();
+    CHECK(table != nullptr);
+    const size_t class_table_bytes = table->WriteToMemory(class_table_memory_ptr);
+    CHECK_EQ(class_table_bytes, image_info.class_table_bytes_);
+    // Fixup the pointers in the newly written class table to contain image addresses. See
+    // above comment for intern tables.
+    ClassTable temp_class_table;
+    temp_class_table.ReadFromMemory(class_table_memory_ptr);
+    CHECK_EQ(temp_class_table.NumReferencedZygoteClasses(),
+             table->NumReferencedNonZygoteClasses() + table->NumReferencedZygoteClasses());
+    UnbufferedRootVisitor visitor(&root_visitor, RootInfo(kRootUnknown));
+    temp_class_table.VisitRoots(visitor);
+  }
+}
+
+void ImageWriter::CopyAndFixupObjects() {
+  auto visitor = [&](Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
+    DCHECK(obj != nullptr);
+    CopyAndFixupObject(obj);
+  };
+  Runtime::Current()->GetHeap()->VisitObjects(visitor);
+  // Fix up the object previously had hash codes.
+  for (const auto& hash_pair : saved_hashcode_map_) {
+    Object* obj = hash_pair.first;
+    DCHECK_EQ(obj->GetLockWord<kVerifyNone>(false).ReadBarrierState(), 0U);
+    obj->SetLockWord<kVerifyNone>(LockWord::FromHashCode(hash_pair.second, 0U), false);
+  }
+  saved_hashcode_map_.clear();
+}
+
+void ImageWriter::FixupPointerArray(mirror::Object* dst,
+                                    mirror::PointerArray* arr,
+                                    mirror::Class* klass,
+                                    Bin array_type) {
+  CHECK(klass->IsArrayClass());
+  CHECK(arr->IsIntArray() || arr->IsLongArray()) << klass->PrettyClass() << " " << arr;
+  // Fixup int and long pointers for the ArtMethod or ArtField arrays.
+  const size_t num_elements = arr->GetLength();
+  dst->SetClass(GetImageAddress(arr->GetClass()));
+  auto* dest_array = down_cast<mirror::PointerArray*>(dst);
+  for (size_t i = 0, count = num_elements; i < count; ++i) {
+    void* elem = arr->GetElementPtrSize<void*>(i, target_ptr_size_);
+    if (kIsDebugBuild && elem != nullptr && !IsInBootImage(elem)) {
+      auto it = native_object_relocations_.find(elem);
+      if (UNLIKELY(it == native_object_relocations_.end())) {
+        if (it->second.IsArtMethodRelocation()) {
+          auto* method = reinterpret_cast<ArtMethod*>(elem);
+          LOG(FATAL) << "No relocation entry for ArtMethod " << method->PrettyMethod() << " @ "
+                     << method << " idx=" << i << "/" << num_elements << " with declaring class "
+                     << Class::PrettyClass(method->GetDeclaringClass());
+        } else {
+          CHECK_EQ(array_type, kBinArtField);
+          auto* field = reinterpret_cast<ArtField*>(elem);
+          LOG(FATAL) << "No relocation entry for ArtField " << field->PrettyField() << " @ "
+              << field << " idx=" << i << "/" << num_elements << " with declaring class "
+              << Class::PrettyClass(field->GetDeclaringClass());
+        }
+        UNREACHABLE();
+      }
+    }
+    CopyAndFixupPointer(dest_array->ElementAddress(i, target_ptr_size_), elem);
+  }
+}
+
+void ImageWriter::CopyAndFixupObject(Object* obj) {
+  if (IsInBootImage(obj)) {
+    return;
+  }
+  size_t offset = GetImageOffset(obj);
+  size_t oat_index = GetOatIndex(obj);
+  ImageInfo& image_info = GetImageInfo(oat_index);
+  auto* dst = reinterpret_cast<Object*>(image_info.image_->Begin() + offset);
+  DCHECK_LT(offset, image_info.image_end_);
+  const auto* src = reinterpret_cast<const uint8_t*>(obj);
+
+  image_info.image_bitmap_->Set(dst);  // Mark the obj as live.
+
+  const size_t n = obj->SizeOf();
+  DCHECK_LE(offset + n, image_info.image_->Size());
+  memcpy(dst, src, n);
+
+  // Write in a hash code of objects which have inflated monitors or a hash code in their monitor
+  // word.
+  const auto it = saved_hashcode_map_.find(obj);
+  dst->SetLockWord(it != saved_hashcode_map_.end() ?
+      LockWord::FromHashCode(it->second, 0u) : LockWord::Default(), false);
+  if (kUseBakerReadBarrier && gc::collector::ConcurrentCopying::kGrayDirtyImmuneObjects) {
+    // Treat all of the objects in the image as marked to avoid unnecessary dirty pages. This is
+    // safe since we mark all of the objects that may reference non immune objects as gray.
+    CHECK(dst->AtomicSetMarkBit(0, 1));
+  }
+  FixupObject(obj, dst);
+}
+
+// Rewrite all the references in the copied object to point to their image address equivalent
+class ImageWriter::FixupVisitor {
+ public:
+  FixupVisitor(ImageWriter* image_writer, Object* copy) : image_writer_(image_writer), copy_(copy) {
+  }
+
+  // Ignore class roots since we don't have a way to map them to the destination. These are handled
+  // with other logic.
+  void VisitRootIfNonNull(mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED)
+      const {}
+  void VisitRoot(mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED) const {}
+
+
+  void operator()(ObjPtr<Object> obj, MemberOffset offset, bool is_static ATTRIBUTE_UNUSED) const
+      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) {
+    ObjPtr<Object> ref = obj->GetFieldObject<Object, kVerifyNone>(offset);
+    // Copy the reference and record the fixup if necessary.
+    image_writer_->CopyReference(
+        copy_->GetFieldObjectReferenceAddr<kVerifyNone>(offset),
+        ref.Ptr());
+  }
+
+  // java.lang.ref.Reference visitor.
+  void operator()(ObjPtr<mirror::Class> klass ATTRIBUTE_UNUSED,
+                  ObjPtr<mirror::Reference> ref) const
+      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) {
+    operator()(ref, mirror::Reference::ReferentOffset(), /* is_static */ false);
+  }
+
+ protected:
+  ImageWriter* const image_writer_;
+  mirror::Object* const copy_;
+};
+
+class ImageWriter::FixupClassVisitor FINAL : public FixupVisitor {
+ public:
+  FixupClassVisitor(ImageWriter* image_writer, Object* copy) : FixupVisitor(image_writer, copy) {
+  }
+
+  void operator()(ObjPtr<Object> obj, MemberOffset offset, bool is_static ATTRIBUTE_UNUSED) const
+      REQUIRES(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
+    DCHECK(obj->IsClass());
+    FixupVisitor::operator()(obj, offset, /*is_static*/false);
+  }
+
+  void operator()(ObjPtr<mirror::Class> klass ATTRIBUTE_UNUSED,
+                  ObjPtr<mirror::Reference> ref ATTRIBUTE_UNUSED) const
+      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) {
+    LOG(FATAL) << "Reference not expected here.";
+  }
+};
+
+uintptr_t ImageWriter::NativeOffsetInImage(void* obj) {
+  DCHECK(obj != nullptr);
+  DCHECK(!IsInBootImage(obj));
+  auto it = native_object_relocations_.find(obj);
+  CHECK(it != native_object_relocations_.end()) << obj << " spaces "
+      << Runtime::Current()->GetHeap()->DumpSpaces();
+  const NativeObjectRelocation& relocation = it->second;
+  return relocation.offset;
+}
+
+template <typename T>
+std::string PrettyPrint(T* ptr) REQUIRES_SHARED(Locks::mutator_lock_) {
+  std::ostringstream oss;
+  oss << ptr;
+  return oss.str();
+}
+
+template <>
+std::string PrettyPrint(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
+  return ArtMethod::PrettyMethod(method);
+}
+
+template <typename T>
+T* ImageWriter::NativeLocationInImage(T* obj) {
+  if (obj == nullptr || IsInBootImage(obj)) {
+    return obj;
+  } else {
+    auto it = native_object_relocations_.find(obj);
+    CHECK(it != native_object_relocations_.end()) << obj << " " << PrettyPrint(obj)
+        << " spaces " << Runtime::Current()->GetHeap()->DumpSpaces();
+    const NativeObjectRelocation& relocation = it->second;
+    ImageInfo& image_info = GetImageInfo(relocation.oat_index);
+    return reinterpret_cast<T*>(image_info.image_begin_ + relocation.offset);
+  }
+}
+
+template <typename T>
+T* ImageWriter::NativeCopyLocation(T* obj, mirror::DexCache* dex_cache) {
+  if (obj == nullptr || IsInBootImage(obj)) {
+    return obj;
+  } else {
+    size_t oat_index = GetOatIndexForDexCache(dex_cache);
+    ImageInfo& image_info = GetImageInfo(oat_index);
+    return reinterpret_cast<T*>(image_info.image_->Begin() + NativeOffsetInImage(obj));
+  }
+}
+
+class ImageWriter::NativeLocationVisitor {
+ public:
+  explicit NativeLocationVisitor(ImageWriter* image_writer) : image_writer_(image_writer) {}
+
+  template <typename T>
+  T* operator()(T* ptr, void** dest_addr = nullptr) const REQUIRES_SHARED(Locks::mutator_lock_) {
+    if (dest_addr != nullptr) {
+      image_writer_->CopyAndFixupPointer(dest_addr, ptr);
+    }
+    return image_writer_->NativeLocationInImage(ptr);
+  }
+
+ private:
+  ImageWriter* const image_writer_;
+};
+
+void ImageWriter::FixupClass(mirror::Class* orig, mirror::Class* copy) {
+  orig->FixupNativePointers(copy, target_ptr_size_, NativeLocationVisitor(this));
+  FixupClassVisitor visitor(this, copy);
+  ObjPtr<mirror::Object>(orig)->VisitReferences(visitor, visitor);
+
+  // Remove the clinitThreadId. This is required for image determinism.
+  copy->SetClinitThreadId(static_cast<pid_t>(0));
+}
+
+void ImageWriter::FixupObject(Object* orig, Object* copy) {
+  DCHECK(orig != nullptr);
+  DCHECK(copy != nullptr);
+  if (kUseBakerReadBarrier) {
+    orig->AssertReadBarrierState();
+  }
+  auto* klass = orig->GetClass();
+  if (klass->IsIntArrayClass() || klass->IsLongArrayClass()) {
+    // Is this a native pointer array?
+    auto it = pointer_arrays_.find(down_cast<mirror::PointerArray*>(orig));
+    if (it != pointer_arrays_.end()) {
+      // Should only need to fixup every pointer array exactly once.
+      FixupPointerArray(copy, down_cast<mirror::PointerArray*>(orig), klass, it->second);
+      pointer_arrays_.erase(it);
+      return;
+    }
+  }
+  if (orig->IsClass()) {
+    FixupClass(orig->AsClass<kVerifyNone>(), down_cast<mirror::Class*>(copy));
+  } else {
+    if (klass == mirror::Method::StaticClass() || klass == mirror::Constructor::StaticClass()) {
+      // Need to go update the ArtMethod.
+      auto* dest = down_cast<mirror::Executable*>(copy);
+      auto* src = down_cast<mirror::Executable*>(orig);
+      ArtMethod* src_method = src->GetArtMethod();
+      dest->SetArtMethod(GetImageMethodAddress(src_method));
+    } else if (!klass->IsArrayClass()) {
+      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+      if (klass == class_linker->GetClassRoot(ClassLinker::kJavaLangDexCache)) {
+        FixupDexCache(down_cast<mirror::DexCache*>(orig), down_cast<mirror::DexCache*>(copy));
+      } else if (klass->IsClassLoaderClass()) {
+        mirror::ClassLoader* copy_loader = down_cast<mirror::ClassLoader*>(copy);
+        // If src is a ClassLoader, set the class table to null so that it gets recreated by the
+        // ClassLoader.
+        copy_loader->SetClassTable(nullptr);
+        // Also set allocator to null to be safe. The allocator is created when we create the class
+        // table. We also never expect to unload things in the image since they are held live as
+        // roots.
+        copy_loader->SetAllocator(nullptr);
+      }
+    }
+    FixupVisitor visitor(this, copy);
+    orig->VisitReferences(visitor, visitor);
+  }
+}
+
+class ImageWriter::ImageAddressVisitorForDexCacheArray {
+ public:
+  explicit ImageAddressVisitorForDexCacheArray(ImageWriter* image_writer)
+      : image_writer_(image_writer) {}
+
+  template <typename T>
+  T* operator()(T* ptr) const REQUIRES_SHARED(Locks::mutator_lock_) {
+    return image_writer_->GetImageAddress(ptr);
+  }
+
+ private:
+  ImageWriter* const image_writer_;
+};
+
+void ImageWriter::FixupDexCache(mirror::DexCache* orig_dex_cache,
+                                mirror::DexCache* copy_dex_cache) {
+  ImageAddressVisitorForDexCacheArray fixup_visitor(this);
+  // Though the DexCache array fields are usually treated as native pointers, we set the full
+  // 64-bit values here, clearing the top 32 bits for 32-bit targets. The zero-extension is
+  // done by casting to the unsigned type uintptr_t before casting to int64_t, i.e.
+  //     static_cast<int64_t>(reinterpret_cast<uintptr_t>(image_begin_ + offset))).
+  mirror::StringDexCacheType* orig_strings = orig_dex_cache->GetStrings();
+  if (orig_strings != nullptr) {
+    copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::StringsOffset(),
+                                               NativeLocationInImage(orig_strings),
+                                               PointerSize::k64);
+    orig_dex_cache->FixupStrings(NativeCopyLocation(orig_strings, orig_dex_cache), fixup_visitor);
+  }
+  mirror::TypeDexCacheType* orig_types = orig_dex_cache->GetResolvedTypes();
+  if (orig_types != nullptr) {
+    copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedTypesOffset(),
+                                               NativeLocationInImage(orig_types),
+                                               PointerSize::k64);
+    orig_dex_cache->FixupResolvedTypes(NativeCopyLocation(orig_types, orig_dex_cache),
+                                       fixup_visitor);
+  }
+  mirror::MethodDexCacheType* orig_methods = orig_dex_cache->GetResolvedMethods();
+  if (orig_methods != nullptr) {
+    copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedMethodsOffset(),
+                                               NativeLocationInImage(orig_methods),
+                                               PointerSize::k64);
+    mirror::MethodDexCacheType* copy_methods = NativeCopyLocation(orig_methods, orig_dex_cache);
+    for (size_t i = 0, num = orig_dex_cache->NumResolvedMethods(); i != num; ++i) {
+      mirror::MethodDexCachePair orig_pair =
+          mirror::DexCache::GetNativePairPtrSize(orig_methods, i, target_ptr_size_);
+      // NativeLocationInImage also handles runtime methods since these have relocation info.
+      mirror::MethodDexCachePair copy_pair(NativeLocationInImage(orig_pair.object),
+                                           orig_pair.index);
+      mirror::DexCache::SetNativePairPtrSize(copy_methods, i, copy_pair, target_ptr_size_);
+    }
+  }
+  mirror::FieldDexCacheType* orig_fields = orig_dex_cache->GetResolvedFields();
+  if (orig_fields != nullptr) {
+    copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedFieldsOffset(),
+                                               NativeLocationInImage(orig_fields),
+                                               PointerSize::k64);
+    mirror::FieldDexCacheType* copy_fields = NativeCopyLocation(orig_fields, orig_dex_cache);
+    for (size_t i = 0, num = orig_dex_cache->NumResolvedFields(); i != num; ++i) {
+      mirror::FieldDexCachePair orig =
+          mirror::DexCache::GetNativePairPtrSize(orig_fields, i, target_ptr_size_);
+      mirror::FieldDexCachePair copy = orig;
+      copy.object = NativeLocationInImage(orig.object);
+      mirror::DexCache::SetNativePairPtrSize(copy_fields, i, copy, target_ptr_size_);
+    }
+  }
+  mirror::MethodTypeDexCacheType* orig_method_types = orig_dex_cache->GetResolvedMethodTypes();
+  if (orig_method_types != nullptr) {
+    copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedMethodTypesOffset(),
+                                               NativeLocationInImage(orig_method_types),
+                                               PointerSize::k64);
+    orig_dex_cache->FixupResolvedMethodTypes(NativeCopyLocation(orig_method_types, orig_dex_cache),
+                                             fixup_visitor);
+  }
+  GcRoot<mirror::CallSite>* orig_call_sites = orig_dex_cache->GetResolvedCallSites();
+  if (orig_call_sites != nullptr) {
+    copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedCallSitesOffset(),
+                                               NativeLocationInImage(orig_call_sites),
+                                               PointerSize::k64);
+    orig_dex_cache->FixupResolvedCallSites(NativeCopyLocation(orig_call_sites, orig_dex_cache),
+                                           fixup_visitor);
+  }
+
+  // Remove the DexFile pointers. They will be fixed up when the runtime loads the oat file. Leaving
+  // compiler pointers in here will make the output non-deterministic.
+  copy_dex_cache->SetDexFile(nullptr);
+}
+
+const uint8_t* ImageWriter::GetOatAddress(OatAddress type) const {
+  DCHECK_LT(type, kOatAddressCount);
+  // If we are compiling an app image, we need to use the stubs of the boot image.
+  if (compile_app_image_) {
+    // Use the current image pointers.
+    const std::vector<gc::space::ImageSpace*>& image_spaces =
+        Runtime::Current()->GetHeap()->GetBootImageSpaces();
+    DCHECK(!image_spaces.empty());
+    const OatFile* oat_file = image_spaces[0]->GetOatFile();
+    CHECK(oat_file != nullptr);
+    const OatHeader& header = oat_file->GetOatHeader();
+    switch (type) {
+      // TODO: We could maybe clean this up if we stored them in an array in the oat header.
+      case kOatAddressQuickGenericJNITrampoline:
+        return static_cast<const uint8_t*>(header.GetQuickGenericJniTrampoline());
+      case kOatAddressInterpreterToInterpreterBridge:
+        return static_cast<const uint8_t*>(header.GetInterpreterToInterpreterBridge());
+      case kOatAddressInterpreterToCompiledCodeBridge:
+        return static_cast<const uint8_t*>(header.GetInterpreterToCompiledCodeBridge());
+      case kOatAddressJNIDlsymLookup:
+        return static_cast<const uint8_t*>(header.GetJniDlsymLookup());
+      case kOatAddressQuickIMTConflictTrampoline:
+        return static_cast<const uint8_t*>(header.GetQuickImtConflictTrampoline());
+      case kOatAddressQuickResolutionTrampoline:
+        return static_cast<const uint8_t*>(header.GetQuickResolutionTrampoline());
+      case kOatAddressQuickToInterpreterBridge:
+        return static_cast<const uint8_t*>(header.GetQuickToInterpreterBridge());
+      default:
+        UNREACHABLE();
+    }
+  }
+  const ImageInfo& primary_image_info = GetImageInfo(0);
+  return GetOatAddressForOffset(primary_image_info.oat_address_offsets_[type], primary_image_info);
+}
+
+const uint8_t* ImageWriter::GetQuickCode(ArtMethod* method,
+                                         const ImageInfo& image_info,
+                                         bool* quick_is_interpreted) {
+  DCHECK(!method->IsResolutionMethod()) << method->PrettyMethod();
+  DCHECK_NE(method, Runtime::Current()->GetImtConflictMethod()) << method->PrettyMethod();
+  DCHECK(!method->IsImtUnimplementedMethod()) << method->PrettyMethod();
+  DCHECK(method->IsInvokable()) << method->PrettyMethod();
+  DCHECK(!IsInBootImage(method)) << method->PrettyMethod();
+
+  // Use original code if it exists. Otherwise, set the code pointer to the resolution
+  // trampoline.
+
+  // Quick entrypoint:
+  const void* quick_oat_entry_point =
+      method->GetEntryPointFromQuickCompiledCodePtrSize(target_ptr_size_);
+  const uint8_t* quick_code;
+
+  if (UNLIKELY(IsInBootImage(method->GetDeclaringClass()))) {
+    DCHECK(method->IsCopied());
+    // If the code is not in the oat file corresponding to this image (e.g. default methods)
+    quick_code = reinterpret_cast<const uint8_t*>(quick_oat_entry_point);
+  } else {
+    uint32_t quick_oat_code_offset = PointerToLowMemUInt32(quick_oat_entry_point);
+    quick_code = GetOatAddressForOffset(quick_oat_code_offset, image_info);
+  }
+
+  *quick_is_interpreted = false;
+  if (quick_code != nullptr && (!method->IsStatic() || method->IsConstructor() ||
+      method->GetDeclaringClass()->IsInitialized())) {
+    // We have code for a non-static or initialized method, just use the code.
+  } else if (quick_code == nullptr && method->IsNative() &&
+      (!method->IsStatic() || method->GetDeclaringClass()->IsInitialized())) {
+    // Non-static or initialized native method missing compiled code, use generic JNI version.
+    quick_code = GetOatAddress(kOatAddressQuickGenericJNITrampoline);
+  } else if (quick_code == nullptr && !method->IsNative()) {
+    // We don't have code at all for a non-native method, use the interpreter.
+    quick_code = GetOatAddress(kOatAddressQuickToInterpreterBridge);
+    *quick_is_interpreted = true;
+  } else {
+    CHECK(!method->GetDeclaringClass()->IsInitialized());
+    // We have code for a static method, but need to go through the resolution stub for class
+    // initialization.
+    quick_code = GetOatAddress(kOatAddressQuickResolutionTrampoline);
+  }
+  if (!IsInBootOatFile(quick_code)) {
+    // DCHECK_GE(quick_code, oat_data_begin_);
+  }
+  return quick_code;
+}
+
+void ImageWriter::CopyAndFixupMethod(ArtMethod* orig,
+                                     ArtMethod* copy,
+                                     const ImageInfo& image_info) {
+  if (orig->IsAbstract()) {
+    // Ignore the single-implementation info for abstract method.
+    // Do this on orig instead of copy, otherwise there is a crash due to methods
+    // are copied before classes.
+    // TODO: handle fixup of single-implementation method for abstract method.
+    orig->SetHasSingleImplementation(false);
+    orig->SetSingleImplementation(
+        nullptr, Runtime::Current()->GetClassLinker()->GetImagePointerSize());
+  }
+
+  memcpy(copy, orig, ArtMethod::Size(target_ptr_size_));
+
+  CopyReference(copy->GetDeclaringClassAddressWithoutBarrier(), orig->GetDeclaringClassUnchecked());
+
+  // OatWriter replaces the code_ with an offset value. Here we re-adjust to a pointer relative to
+  // oat_begin_
+
+  // The resolution method has a special trampoline to call.
+  Runtime* runtime = Runtime::Current();
+  if (orig->IsRuntimeMethod()) {
+    ImtConflictTable* orig_table = orig->GetImtConflictTable(target_ptr_size_);
+    if (orig_table != nullptr) {
+      // Special IMT conflict method, normal IMT conflict method or unimplemented IMT method.
+      copy->SetEntryPointFromQuickCompiledCodePtrSize(
+          GetOatAddress(kOatAddressQuickIMTConflictTrampoline), target_ptr_size_);
+      copy->SetImtConflictTable(NativeLocationInImage(orig_table), target_ptr_size_);
+    } else if (UNLIKELY(orig == runtime->GetResolutionMethod())) {
+      copy->SetEntryPointFromQuickCompiledCodePtrSize(
+          GetOatAddress(kOatAddressQuickResolutionTrampoline), target_ptr_size_);
+    } else {
+      bool found_one = false;
+      for (size_t i = 0; i < static_cast<size_t>(CalleeSaveType::kLastCalleeSaveType); ++i) {
+        auto idx = static_cast<CalleeSaveType>(i);
+        if (runtime->HasCalleeSaveMethod(idx) && runtime->GetCalleeSaveMethod(idx) == orig) {
+          found_one = true;
+          break;
+        }
+      }
+      CHECK(found_one) << "Expected to find callee save method but got " << orig->PrettyMethod();
+      CHECK(copy->IsRuntimeMethod());
+    }
+  } else {
+    // We assume all methods have code. If they don't currently then we set them to the use the
+    // resolution trampoline. Abstract methods never have code and so we need to make sure their
+    // use results in an AbstractMethodError. We use the interpreter to achieve this.
+    if (UNLIKELY(!orig->IsInvokable())) {
+      copy->SetEntryPointFromQuickCompiledCodePtrSize(
+          GetOatAddress(kOatAddressQuickToInterpreterBridge), target_ptr_size_);
+    } else {
+      bool quick_is_interpreted;
+      const uint8_t* quick_code = GetQuickCode(orig, image_info, &quick_is_interpreted);
+      copy->SetEntryPointFromQuickCompiledCodePtrSize(quick_code, target_ptr_size_);
+
+      // JNI entrypoint:
+      if (orig->IsNative()) {
+        // The native method's pointer is set to a stub to lookup via dlsym.
+        // Note this is not the code_ pointer, that is handled above.
+        copy->SetEntryPointFromJniPtrSize(
+            GetOatAddress(kOatAddressJNIDlsymLookup), target_ptr_size_);
+      }
+    }
+  }
+}
+
+size_t ImageWriter::GetBinSizeSum(ImageWriter::ImageInfo& image_info, ImageWriter::Bin up_to) const {
+  DCHECK_LE(up_to, kBinSize);
+  return std::accumulate(&image_info.bin_slot_sizes_[0],
+                         &image_info.bin_slot_sizes_[up_to],
+                         /*init*/0);
+}
+
+ImageWriter::BinSlot::BinSlot(uint32_t lockword) : lockword_(lockword) {
+  // These values may need to get updated if more bins are added to the enum Bin
+  static_assert(kBinBits == 3, "wrong number of bin bits");
+  static_assert(kBinShift == 27, "wrong number of shift");
+  static_assert(sizeof(BinSlot) == sizeof(LockWord), "BinSlot/LockWord must have equal sizes");
+
+  DCHECK_LT(GetBin(), kBinSize);
+  DCHECK_ALIGNED(GetIndex(), kObjectAlignment);
+}
+
+ImageWriter::BinSlot::BinSlot(Bin bin, uint32_t index)
+    : BinSlot(index | (static_cast<uint32_t>(bin) << kBinShift)) {
+  DCHECK_EQ(index, GetIndex());
+}
+
+ImageWriter::Bin ImageWriter::BinSlot::GetBin() const {
+  return static_cast<Bin>((lockword_ & kBinMask) >> kBinShift);
+}
+
+uint32_t ImageWriter::BinSlot::GetIndex() const {
+  return lockword_ & ~kBinMask;
+}
+
+ImageWriter::Bin ImageWriter::BinTypeForNativeRelocationType(NativeObjectRelocationType type) {
+  switch (type) {
+    case kNativeObjectRelocationTypeArtField:
+    case kNativeObjectRelocationTypeArtFieldArray:
+      return kBinArtField;
+    case kNativeObjectRelocationTypeArtMethodClean:
+    case kNativeObjectRelocationTypeArtMethodArrayClean:
+      return kBinArtMethodClean;
+    case kNativeObjectRelocationTypeArtMethodDirty:
+    case kNativeObjectRelocationTypeArtMethodArrayDirty:
+      return kBinArtMethodDirty;
+    case kNativeObjectRelocationTypeDexCacheArray:
+      return kBinDexCacheArray;
+    case kNativeObjectRelocationTypeRuntimeMethod:
+      return kBinRuntimeMethod;
+    case kNativeObjectRelocationTypeIMTable:
+      return kBinImTable;
+    case kNativeObjectRelocationTypeIMTConflictTable:
+      return kBinIMTConflictTable;
+  }
+  UNREACHABLE();
+}
+
+size_t ImageWriter::GetOatIndex(mirror::Object* obj) const {
+  if (!IsMultiImage()) {
+    return GetDefaultOatIndex();
+  }
+  auto it = oat_index_map_.find(obj);
+  DCHECK(it != oat_index_map_.end()) << obj;
+  return it->second;
+}
+
+size_t ImageWriter::GetOatIndexForDexFile(const DexFile* dex_file) const {
+  if (!IsMultiImage()) {
+    return GetDefaultOatIndex();
+  }
+  auto it = dex_file_oat_index_map_.find(dex_file);
+  DCHECK(it != dex_file_oat_index_map_.end()) << dex_file->GetLocation();
+  return it->second;
+}
+
+size_t ImageWriter::GetOatIndexForDexCache(ObjPtr<mirror::DexCache> dex_cache) const {
+  return (dex_cache == nullptr)
+      ? GetDefaultOatIndex()
+      : GetOatIndexForDexFile(dex_cache->GetDexFile());
+}
+
+void ImageWriter::UpdateOatFileLayout(size_t oat_index,
+                                      size_t oat_loaded_size,
+                                      size_t oat_data_offset,
+                                      size_t oat_data_size) {
+  const uint8_t* images_end = image_infos_.back().image_begin_ + image_infos_.back().image_size_;
+  for (const ImageInfo& info : image_infos_) {
+    DCHECK_LE(info.image_begin_ + info.image_size_, images_end);
+  }
+  DCHECK(images_end != nullptr);  // Image space must be ready.
+
+  ImageInfo& cur_image_info = GetImageInfo(oat_index);
+  cur_image_info.oat_file_begin_ = images_end + cur_image_info.oat_offset_;
+  cur_image_info.oat_loaded_size_ = oat_loaded_size;
+  cur_image_info.oat_data_begin_ = cur_image_info.oat_file_begin_ + oat_data_offset;
+  cur_image_info.oat_size_ = oat_data_size;
+
+  if (compile_app_image_) {
+    CHECK_EQ(oat_filenames_.size(), 1u) << "App image should have no next image.";
+    return;
+  }
+
+  // Update the oat_offset of the next image info.
+  if (oat_index + 1u != oat_filenames_.size()) {
+    // There is a following one.
+    ImageInfo& next_image_info = GetImageInfo(oat_index + 1u);
+    next_image_info.oat_offset_ = cur_image_info.oat_offset_ + oat_loaded_size;
+  }
+}
+
+void ImageWriter::UpdateOatFileHeader(size_t oat_index, const OatHeader& oat_header) {
+  ImageInfo& cur_image_info = GetImageInfo(oat_index);
+  cur_image_info.oat_checksum_ = oat_header.GetChecksum();
+
+  if (oat_index == GetDefaultOatIndex()) {
+    // Primary oat file, read the trampolines.
+    cur_image_info.oat_address_offsets_[kOatAddressInterpreterToInterpreterBridge] =
+        oat_header.GetInterpreterToInterpreterBridgeOffset();
+    cur_image_info.oat_address_offsets_[kOatAddressInterpreterToCompiledCodeBridge] =
+        oat_header.GetInterpreterToCompiledCodeBridgeOffset();
+    cur_image_info.oat_address_offsets_[kOatAddressJNIDlsymLookup] =
+        oat_header.GetJniDlsymLookupOffset();
+    cur_image_info.oat_address_offsets_[kOatAddressQuickGenericJNITrampoline] =
+        oat_header.GetQuickGenericJniTrampolineOffset();
+    cur_image_info.oat_address_offsets_[kOatAddressQuickIMTConflictTrampoline] =
+        oat_header.GetQuickImtConflictTrampolineOffset();
+    cur_image_info.oat_address_offsets_[kOatAddressQuickResolutionTrampoline] =
+        oat_header.GetQuickResolutionTrampolineOffset();
+    cur_image_info.oat_address_offsets_[kOatAddressQuickToInterpreterBridge] =
+        oat_header.GetQuickToInterpreterBridgeOffset();
+  }
+}
+
+ImageWriter::ImageWriter(
+    const CompilerDriver& compiler_driver,
+    uintptr_t image_begin,
+    bool compile_pic,
+    bool compile_app_image,
+    ImageHeader::StorageMode image_storage_mode,
+    const std::vector<const char*>& oat_filenames,
+    const std::unordered_map<const DexFile*, size_t>& dex_file_oat_index_map,
+    const std::unordered_set<std::string>* dirty_image_objects)
+    : compiler_driver_(compiler_driver),
+      global_image_begin_(reinterpret_cast<uint8_t*>(image_begin)),
+      image_objects_offset_begin_(0),
+      compile_pic_(compile_pic),
+      compile_app_image_(compile_app_image),
+      target_ptr_size_(InstructionSetPointerSize(compiler_driver_.GetInstructionSet())),
+      image_infos_(oat_filenames.size()),
+      dirty_methods_(0u),
+      clean_methods_(0u),
+      image_storage_mode_(image_storage_mode),
+      oat_filenames_(oat_filenames),
+      dex_file_oat_index_map_(dex_file_oat_index_map),
+      dirty_image_objects_(dirty_image_objects) {
+  CHECK_NE(image_begin, 0U);
+  std::fill_n(image_methods_, arraysize(image_methods_), nullptr);
+  CHECK_EQ(compile_app_image, !Runtime::Current()->GetHeap()->GetBootImageSpaces().empty())
+      << "Compiling a boot image should occur iff there are no boot image spaces loaded";
+}
+
+ImageWriter::ImageInfo::ImageInfo()
+    : intern_table_(new InternTable),
+      class_table_(new ClassTable) {}
+
+void ImageWriter::CopyReference(mirror::HeapReference<mirror::Object>* dest,
+                                ObjPtr<mirror::Object> src) {
+  dest->Assign(GetImageAddress(src.Ptr()));
+}
+
+void ImageWriter::CopyReference(mirror::CompressedReference<mirror::Object>* dest,
+                                ObjPtr<mirror::Object> src) {
+  dest->Assign(GetImageAddress(src.Ptr()));
+}
+
+void ImageWriter::CopyAndFixupPointer(void** target, void* value) {
+  void* new_value = value;
+  if (value != nullptr && !IsInBootImage(value)) {
+    auto it = native_object_relocations_.find(value);
+    CHECK(it != native_object_relocations_.end()) << value;
+    const NativeObjectRelocation& relocation = it->second;
+    ImageInfo& image_info = GetImageInfo(relocation.oat_index);
+    new_value = reinterpret_cast<void*>(image_info.image_begin_ + relocation.offset);
+  }
+  if (target_ptr_size_ == PointerSize::k32) {
+    *reinterpret_cast<uint32_t*>(target) = PointerToLowMemUInt32(new_value);
+  } else {
+    *reinterpret_cast<uint64_t*>(target) = reinterpret_cast<uintptr_t>(new_value);
+  }
+}
+
+}  // namespace linker
+}  // namespace art
diff --git a/dex2oat/linker/image_writer.h b/dex2oat/linker/image_writer.h
new file mode 100644
index 0000000..bdea000
--- /dev/null
+++ b/dex2oat/linker/image_writer.h
@@ -0,0 +1,628 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_DEX2OAT_LINKER_IMAGE_WRITER_H_
+#define ART_DEX2OAT_LINKER_IMAGE_WRITER_H_
+
+#include <stdint.h>
+#include "base/memory_tool.h"
+
+#include <cstddef>
+#include <memory>
+#include <ostream>
+#include <set>
+#include <stack>
+#include <string>
+
+#include "art_method.h"
+#include "base/bit_utils.h"
+#include "base/dchecked_vector.h"
+#include "base/enums.h"
+#include "base/length_prefixed_array.h"
+#include "base/macros.h"
+#include "class_table.h"
+#include "driver/compiler_driver.h"
+#include "image.h"
+#include "intern_table.h"
+#include "lock_word.h"
+#include "mem_map.h"
+#include "mirror/dex_cache.h"
+#include "oat_file.h"
+#include "obj_ptr.h"
+#include "os.h"
+#include "safe_map.h"
+#include "utils.h"
+
+namespace art {
+namespace gc {
+namespace accounting {
+template <size_t kAlignment> class SpaceBitmap;
+typedef SpaceBitmap<kObjectAlignment> ContinuousSpaceBitmap;
+}  // namespace accounting
+namespace space {
+class ImageSpace;
+}  // namespace space
+}  // namespace gc
+
+namespace mirror {
+class ClassLoader;
+}  // namespace mirror
+
+class ClassLoaderVisitor;
+class ImtConflictTable;
+
+static constexpr int kInvalidFd = -1;
+
+namespace linker {
+
+// Write a Space built during compilation for use during execution.
+class ImageWriter FINAL {
+ public:
+  ImageWriter(const CompilerDriver& compiler_driver,
+              uintptr_t image_begin,
+              bool compile_pic,
+              bool compile_app_image,
+              ImageHeader::StorageMode image_storage_mode,
+              const std::vector<const char*>& oat_filenames,
+              const std::unordered_map<const DexFile*, size_t>& dex_file_oat_index_map,
+              const std::unordered_set<std::string>* dirty_image_objects);
+
+  bool PrepareImageAddressSpace();
+
+  bool IsImageAddressSpaceReady() const {
+    DCHECK(!image_infos_.empty());
+    for (const ImageInfo& image_info : image_infos_) {
+      if (image_info.image_roots_address_ == 0u) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  ObjPtr<mirror::ClassLoader> GetClassLoader() {
+    CHECK_EQ(class_loaders_.size(), compile_app_image_ ? 1u : 0u);
+    return compile_app_image_ ? *class_loaders_.begin() : nullptr;
+  }
+
+  template <typename T>
+  T* GetImageAddress(T* object) const REQUIRES_SHARED(Locks::mutator_lock_) {
+    if (object == nullptr || IsInBootImage(object)) {
+      return object;
+    } else {
+      size_t oat_index = GetOatIndex(object);
+      const ImageInfo& image_info = GetImageInfo(oat_index);
+      return reinterpret_cast<T*>(image_info.image_begin_ + GetImageOffset(object));
+    }
+  }
+
+  ArtMethod* GetImageMethodAddress(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
+
+  size_t GetOatFileOffset(size_t oat_index) const {
+    return GetImageInfo(oat_index).oat_offset_;
+  }
+
+  const uint8_t* GetOatFileBegin(size_t oat_index) const {
+    return GetImageInfo(oat_index).oat_file_begin_;
+  }
+
+  // If image_fd is not kInvalidFd, then we use that for the image file. Otherwise we open
+  // the names in image_filenames.
+  // If oat_fd is not kInvalidFd, then we use that for the oat file. Otherwise we open
+  // the names in oat_filenames.
+  bool Write(int image_fd,
+             const std::vector<const char*>& image_filenames,
+             const std::vector<const char*>& oat_filenames)
+      REQUIRES(!Locks::mutator_lock_);
+
+  uintptr_t GetOatDataBegin(size_t oat_index) {
+    return reinterpret_cast<uintptr_t>(GetImageInfo(oat_index).oat_data_begin_);
+  }
+
+  // Get the index of the oat file containing the dex file.
+  //
+  // This "oat_index" is used to retrieve information about the the memory layout
+  // of the oat file and its associated image file, needed for link-time patching
+  // of references to the image or across oat files.
+  size_t GetOatIndexForDexFile(const DexFile* dex_file) const;
+
+  // Get the index of the oat file containing the dex file served by the dex cache.
+  size_t GetOatIndexForDexCache(ObjPtr<mirror::DexCache> dex_cache) const
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Update the oat layout for the given oat file.
+  // This will make the oat_offset for the next oat file valid.
+  void UpdateOatFileLayout(size_t oat_index,
+                           size_t oat_loaded_size,
+                           size_t oat_data_offset,
+                           size_t oat_data_size);
+  // Update information about the oat header, i.e. checksum and trampoline offsets.
+  void UpdateOatFileHeader(size_t oat_index, const OatHeader& oat_header);
+
+ private:
+  using WorkStack = std::stack<std::pair<mirror::Object*, size_t>>;
+
+  bool AllocMemory();
+
+  // Mark the objects defined in this space in the given live bitmap.
+  void RecordImageAllocations() REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Classify different kinds of bins that objects end up getting packed into during image writing.
+  // Ordered from dirtiest to cleanest (until ArtMethods).
+  enum Bin {
+    kBinKnownDirty,               // Known dirty objects from --dirty-image-objects list
+    kBinMiscDirty,                // Dex caches, object locks, etc...
+    kBinClassVerified,            // Class verified, but initializers haven't been run
+    // Unknown mix of clean/dirty:
+    kBinRegular,
+    kBinClassInitialized,         // Class initializers have been run
+    // All classes get their own bins since their fields often dirty
+    kBinClassInitializedFinalStatics,  // Class initializers have been run, no non-final statics
+    // Likely-clean:
+    kBinString,                        // [String] Almost always immutable (except for obj header).
+    // Add more bins here if we add more segregation code.
+    // Non mirror fields must be below.
+    // ArtFields should be always clean.
+    kBinArtField,
+    // If the class is initialized, then the ArtMethods are probably clean.
+    kBinArtMethodClean,
+    // ArtMethods may be dirty if the class has native methods or a declaring class that isn't
+    // initialized.
+    kBinArtMethodDirty,
+    // IMT (clean)
+    kBinImTable,
+    // Conflict tables (clean).
+    kBinIMTConflictTable,
+    // Runtime methods (always clean, do not have a length prefix array).
+    kBinRuntimeMethod,
+    // Dex cache arrays have a special slot for PC-relative addressing. Since they are
+    // huge, and as such their dirtiness is not important for the clean/dirty separation,
+    // we arbitrarily keep them at the end of the native data.
+    kBinDexCacheArray,            // Arrays belonging to dex cache.
+    kBinSize,
+    // Number of bins which are for mirror objects.
+    kBinMirrorCount = kBinArtField,
+  };
+  friend std::ostream& operator<<(std::ostream& stream, const Bin& bin);
+
+  enum NativeObjectRelocationType {
+    kNativeObjectRelocationTypeArtField,
+    kNativeObjectRelocationTypeArtFieldArray,
+    kNativeObjectRelocationTypeArtMethodClean,
+    kNativeObjectRelocationTypeArtMethodArrayClean,
+    kNativeObjectRelocationTypeArtMethodDirty,
+    kNativeObjectRelocationTypeArtMethodArrayDirty,
+    kNativeObjectRelocationTypeRuntimeMethod,
+    kNativeObjectRelocationTypeIMTable,
+    kNativeObjectRelocationTypeIMTConflictTable,
+    kNativeObjectRelocationTypeDexCacheArray,
+  };
+  friend std::ostream& operator<<(std::ostream& stream, const NativeObjectRelocationType& type);
+
+  enum OatAddress {
+    kOatAddressInterpreterToInterpreterBridge,
+    kOatAddressInterpreterToCompiledCodeBridge,
+    kOatAddressJNIDlsymLookup,
+    kOatAddressQuickGenericJNITrampoline,
+    kOatAddressQuickIMTConflictTrampoline,
+    kOatAddressQuickResolutionTrampoline,
+    kOatAddressQuickToInterpreterBridge,
+    // Number of elements in the enum.
+    kOatAddressCount,
+  };
+  friend std::ostream& operator<<(std::ostream& stream, const OatAddress& oat_address);
+
+  static constexpr size_t kBinBits = MinimumBitsToStore<uint32_t>(kBinMirrorCount - 1);
+  // uint32 = typeof(lockword_)
+  // Subtract read barrier bits since we want these to remain 0, or else it may result in DCHECK
+  // failures due to invalid read barrier bits during object field reads.
+  static const size_t kBinShift = BitSizeOf<uint32_t>() - kBinBits - LockWord::kGCStateSize;
+  // 111000.....0
+  static const size_t kBinMask = ((static_cast<size_t>(1) << kBinBits) - 1) << kBinShift;
+
+  // We use the lock word to store the bin # and bin index of the object in the image.
+  //
+  // The struct size must be exactly sizeof(LockWord), currently 32-bits, since this will end up
+  // stored in the lock word bit-for-bit when object forwarding addresses are being calculated.
+  struct BinSlot {
+    explicit BinSlot(uint32_t lockword);
+    BinSlot(Bin bin, uint32_t index);
+
+    // The bin an object belongs to, i.e. regular, class/verified, class/initialized, etc.
+    Bin GetBin() const;
+    // The offset in bytes from the beginning of the bin. Aligned to object size.
+    uint32_t GetIndex() const;
+    // Pack into a single uint32_t, for storing into a lock word.
+    uint32_t Uint32Value() const { return lockword_; }
+    // Comparison operator for map support
+    bool operator<(const BinSlot& other) const  { return lockword_ < other.lockword_; }
+
+  private:
+    // Must be the same size as LockWord, any larger and we would truncate the data.
+    const uint32_t lockword_;
+  };
+
+  struct ImageInfo {
+    ImageInfo();
+    ImageInfo(ImageInfo&&) = default;
+
+    // Create the image sections into the out sections variable, returns the size of the image
+    // excluding the bitmap.
+    size_t CreateImageSections(ImageSection* out_sections, bool app_image) const;
+
+    std::unique_ptr<MemMap> image_;  // Memory mapped for generating the image.
+
+    // Target begin of this image. Notes: It is not valid to write here, this is the address
+    // of the target image, not necessarily where image_ is mapped. The address is only valid
+    // after layouting (otherwise null).
+    uint8_t* image_begin_ = nullptr;
+
+    // Offset to the free space in image_, initially size of image header.
+    size_t image_end_ = RoundUp(sizeof(ImageHeader), kObjectAlignment);
+    uint32_t image_roots_address_ = 0;  // The image roots address in the image.
+    size_t image_offset_ = 0;  // Offset of this image from the start of the first image.
+
+    // Image size is the *address space* covered by this image. As the live bitmap is aligned
+    // to the page size, the live bitmap will cover more address space than necessary. But live
+    // bitmaps may not overlap, so an image has a "shadow," which is accounted for in the size.
+    // The next image may only start at image_begin_ + image_size_ (which is guaranteed to be
+    // page-aligned).
+    size_t image_size_ = 0;
+
+    // Oat data.
+    // Offset of the oat file for this image from start of oat files. This is
+    // valid when the previous oat file has been written.
+    size_t oat_offset_ = 0;
+    // Layout of the loaded ELF file containing the oat file, valid after UpdateOatFileLayout().
+    const uint8_t* oat_file_begin_ = nullptr;
+    size_t oat_loaded_size_ = 0;
+    const uint8_t* oat_data_begin_ = nullptr;
+    size_t oat_size_ = 0;  // Size of the corresponding oat data.
+    // The oat header checksum, valid after UpdateOatFileHeader().
+    uint32_t oat_checksum_ = 0u;
+
+    // Image bitmap which lets us know where the objects inside of the image reside.
+    std::unique_ptr<gc::accounting::ContinuousSpaceBitmap> image_bitmap_;
+
+    // The start offsets of the dex cache arrays.
+    SafeMap<const DexFile*, size_t> dex_cache_array_starts_;
+
+    // Offset from oat_data_begin_ to the stubs.
+    uint32_t oat_address_offsets_[kOatAddressCount] = {};
+
+    // Bin slot tracking for dirty object packing.
+    size_t bin_slot_sizes_[kBinSize] = {};  // Number of bytes in a bin.
+    size_t bin_slot_offsets_[kBinSize] = {};  // Number of bytes in previous bins.
+    size_t bin_slot_count_[kBinSize] = {};  // Number of objects in a bin.
+
+    // Cached size of the intern table for when we allocate memory.
+    size_t intern_table_bytes_ = 0;
+
+    // Number of image class table bytes.
+    size_t class_table_bytes_ = 0;
+
+    // Number of object fixup bytes.
+    size_t object_fixup_bytes_ = 0;
+
+    // Number of pointer fixup bytes.
+    size_t pointer_fixup_bytes_ = 0;
+
+    // Intern table associated with this image for serialization.
+    std::unique_ptr<InternTable> intern_table_;
+
+    // Class table associated with this image for serialization.
+    std::unique_ptr<ClassTable> class_table_;
+  };
+
+  // We use the lock word to store the offset of the object in the image.
+  void AssignImageOffset(mirror::Object* object, BinSlot bin_slot)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  void SetImageOffset(mirror::Object* object, size_t offset)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  bool IsImageOffsetAssigned(mirror::Object* object) const
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  size_t GetImageOffset(mirror::Object* object) const REQUIRES_SHARED(Locks::mutator_lock_);
+  void UpdateImageOffset(mirror::Object* obj, uintptr_t offset)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
+  void PrepareDexCacheArraySlots() REQUIRES_SHARED(Locks::mutator_lock_);
+  void AssignImageBinSlot(mirror::Object* object, size_t oat_index)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  mirror::Object* TryAssignBinSlot(WorkStack& work_stack, mirror::Object* obj, size_t oat_index)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  void SetImageBinSlot(mirror::Object* object, BinSlot bin_slot)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  bool IsImageBinSlotAssigned(mirror::Object* object) const
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  BinSlot GetImageBinSlot(mirror::Object* object) const REQUIRES_SHARED(Locks::mutator_lock_);
+
+  void AddDexCacheArrayRelocation(void* array, size_t offset, ObjPtr<mirror::DexCache> dex_cache)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  void AddMethodPointerArray(mirror::PointerArray* arr) REQUIRES_SHARED(Locks::mutator_lock_);
+
+  static void* GetImageAddressCallback(void* writer, mirror::Object* obj)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    return reinterpret_cast<ImageWriter*>(writer)->GetImageAddress(obj);
+  }
+
+  mirror::Object* GetLocalAddress(mirror::Object* object) const
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    size_t offset = GetImageOffset(object);
+    size_t oat_index = GetOatIndex(object);
+    const ImageInfo& image_info = GetImageInfo(oat_index);
+    uint8_t* dst = image_info.image_->Begin() + offset;
+    return reinterpret_cast<mirror::Object*>(dst);
+  }
+
+  // Returns the address in the boot image if we are compiling the app image.
+  const uint8_t* GetOatAddress(OatAddress type) const;
+
+  const uint8_t* GetOatAddressForOffset(uint32_t offset, const ImageInfo& image_info) const {
+    // With Quick, code is within the OatFile, as there are all in one
+    // .o ELF object. But interpret it as signed.
+    DCHECK_LE(static_cast<int32_t>(offset), static_cast<int32_t>(image_info.oat_size_));
+    DCHECK(image_info.oat_data_begin_ != nullptr);
+    return offset == 0u ? nullptr : image_info.oat_data_begin_ + static_cast<int32_t>(offset);
+  }
+
+  // Returns true if the class was in the original requested image classes list.
+  bool KeepClass(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Debug aid that list of requested image classes.
+  void DumpImageClasses();
+
+  // Preinitializes some otherwise lazy fields (such as Class name) to avoid runtime image dirtying.
+  void ComputeLazyFieldsForImageClasses()
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Visit all class loaders.
+  void VisitClassLoaders(ClassLoaderVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Remove unwanted classes from various roots.
+  void PruneNonImageClasses() REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Remove unwanted classes from the DexCache roots and preload deterministic DexCache contents.
+  void PruneAndPreloadDexCache(ObjPtr<mirror::DexCache> dex_cache,
+                               ObjPtr<mirror::ClassLoader> class_loader)
+      REQUIRES_SHARED(Locks::mutator_lock_)
+      REQUIRES(!Locks::classlinker_classes_lock_);
+
+  // Verify unwanted classes removed.
+  void CheckNonImageClassesRemoved() REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Lays out where the image objects will be at runtime.
+  void CalculateNewObjectOffsets()
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  void ProcessWorkStack(WorkStack* work_stack)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  void CreateHeader(size_t oat_index)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  mirror::ObjectArray<mirror::Object>* CreateImageRoots(size_t oat_index) const
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  void CalculateObjectBinSlots(mirror::Object* obj)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  void UnbinObjectsIntoOffset(mirror::Object* obj)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Creates the contiguous image in memory and adjusts pointers.
+  void CopyAndFixupNativeData(size_t oat_index) REQUIRES_SHARED(Locks::mutator_lock_);
+  void CopyAndFixupObjects() REQUIRES_SHARED(Locks::mutator_lock_);
+  void CopyAndFixupObject(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_);
+  void CopyAndFixupMethod(ArtMethod* orig, ArtMethod* copy, const ImageInfo& image_info)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  void CopyAndFixupImTable(ImTable* orig, ImTable* copy) REQUIRES_SHARED(Locks::mutator_lock_);
+  void CopyAndFixupImtConflictTable(ImtConflictTable* orig, ImtConflictTable* copy)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  void FixupClass(mirror::Class* orig, mirror::Class* copy)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  void FixupObject(mirror::Object* orig, mirror::Object* copy)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  void FixupDexCache(mirror::DexCache* orig_dex_cache, mirror::DexCache* copy_dex_cache)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  void FixupPointerArray(mirror::Object* dst,
+                         mirror::PointerArray* arr,
+                         mirror::Class* klass,
+                         Bin array_type)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Get quick code for non-resolution/imt_conflict/abstract method.
+  const uint8_t* GetQuickCode(ArtMethod* method,
+                              const ImageInfo& image_info,
+                              bool* quick_is_interpreted)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Calculate the sum total of the bin slot sizes in [0, up_to). Defaults to all bins.
+  size_t GetBinSizeSum(ImageInfo& image_info, Bin up_to = kBinSize) const;
+
+  // Return true if a method is likely to be dirtied at runtime.
+  bool WillMethodBeDirty(ArtMethod* m) const REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Assign the offset for an ArtMethod.
+  void AssignMethodOffset(ArtMethod* method,
+                          NativeObjectRelocationType type,
+                          size_t oat_index)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Return true if imt was newly inserted.
+  bool TryAssignImTableOffset(ImTable* imt, size_t oat_index) REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Assign the offset for an IMT conflict table. Does nothing if the table already has a native
+  // relocation.
+  void TryAssignConflictTableOffset(ImtConflictTable* table, size_t oat_index)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Return true if klass is loaded by the boot class loader but not in the boot image.
+  bool IsBootClassLoaderNonImageClass(mirror::Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Return true if klass depends on a boot class loader non image class. We want to prune these
+  // classes since we do not want any boot class loader classes in the image. This means that
+  // we also cannot have any classes which refer to these boot class loader non image classes.
+  // PruneAppImageClass also prunes if klass depends on a non-image class according to the compiler
+  // driver.
+  bool PruneAppImageClass(ObjPtr<mirror::Class> klass)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // early_exit is true if we had a cyclic dependency anywhere down the chain.
+  bool PruneAppImageClassInternal(ObjPtr<mirror::Class> klass,
+                                  bool* early_exit,
+                                  std::unordered_set<mirror::Object*>* visited)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
+  bool IsMultiImage() const {
+    return image_infos_.size() > 1;
+  }
+
+  static Bin BinTypeForNativeRelocationType(NativeObjectRelocationType type);
+
+  uintptr_t NativeOffsetInImage(void* obj) REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Location of where the object will be when the image is loaded at runtime.
+  template <typename T>
+  T* NativeLocationInImage(T* obj) REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Location of where the temporary copy of the object currently is.
+  template <typename T>
+  T* NativeCopyLocation(T* obj, mirror::DexCache* dex_cache) REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Return true of obj is inside of the boot image space. This may only return true if we are
+  // compiling an app image.
+  bool IsInBootImage(const void* obj) const;
+
+  // Return true if ptr is within the boot oat file.
+  bool IsInBootOatFile(const void* ptr) const;
+
+  // Get the index of the oat file associated with the object.
+  size_t GetOatIndex(mirror::Object* object) const REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // The oat index for shared data in multi-image and all data in single-image compilation.
+  size_t GetDefaultOatIndex() const {
+    return 0u;
+  }
+
+  ImageInfo& GetImageInfo(size_t oat_index) {
+    return image_infos_[oat_index];
+  }
+
+  const ImageInfo& GetImageInfo(size_t oat_index) const {
+    return image_infos_[oat_index];
+  }
+
+  // Find an already strong interned string in the other images or in the boot image. Used to
+  // remove duplicates in the multi image and app image case.
+  mirror::String* FindInternedString(mirror::String* string) REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Return true if there already exists a native allocation for an object.
+  bool NativeRelocationAssigned(void* ptr) const;
+
+  void CopyReference(mirror::HeapReference<mirror::Object>* dest, ObjPtr<mirror::Object> src)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
+  void CopyReference(mirror::CompressedReference<mirror::Object>* dest, ObjPtr<mirror::Object> src)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
+  void CopyAndFixupPointer(void** target, void* value);
+
+  const CompilerDriver& compiler_driver_;
+
+  // Beginning target image address for the first image.
+  uint8_t* global_image_begin_;
+
+  // Offset from image_begin_ to where the first object is in image_.
+  size_t image_objects_offset_begin_;
+
+  // Pointer arrays that need to be updated. Since these are only some int and long arrays, we need
+  // to keep track. These include vtable arrays, iftable arrays, and dex caches.
+  std::unordered_map<mirror::PointerArray*, Bin> pointer_arrays_;
+
+  // Saved hash codes. We use these to restore lockwords which were temporarily used to have
+  // forwarding addresses as well as copying over hash codes.
+  std::unordered_map<mirror::Object*, uint32_t> saved_hashcode_map_;
+
+  // Oat index map for objects.
+  std::unordered_map<mirror::Object*, uint32_t> oat_index_map_;
+
+  // Boolean flags.
+  const bool compile_pic_;
+  const bool compile_app_image_;
+
+  // Size of pointers on the target architecture.
+  PointerSize target_ptr_size_;
+
+  // Image data indexed by the oat file index.
+  dchecked_vector<ImageInfo> image_infos_;
+
+  // ArtField, ArtMethod relocating map. These are allocated as array of structs but we want to
+  // have one entry per art field for convenience. ArtFields are placed right after the end of the
+  // image objects (aka sum of bin_slot_sizes_). ArtMethods are placed right after the ArtFields.
+  struct NativeObjectRelocation {
+    size_t oat_index;
+    uintptr_t offset;
+    NativeObjectRelocationType type;
+
+    bool IsArtMethodRelocation() const {
+      return type == kNativeObjectRelocationTypeArtMethodClean ||
+          type == kNativeObjectRelocationTypeArtMethodDirty ||
+          type == kNativeObjectRelocationTypeRuntimeMethod;
+    }
+  };
+  std::unordered_map<void*, NativeObjectRelocation> native_object_relocations_;
+
+  // Runtime ArtMethods which aren't reachable from any Class but need to be copied into the image.
+  ArtMethod* image_methods_[ImageHeader::kImageMethodsCount];
+
+  // Counters for measurements, used for logging only.
+  uint64_t dirty_methods_;
+  uint64_t clean_methods_;
+
+  // Prune class memoization table to speed up ContainsBootClassLoaderNonImageClass.
+  std::unordered_map<mirror::Class*, bool> prune_class_memo_;
+
+  // Class loaders with a class table to write out. There should only be one class loader because
+  // dex2oat loads the dex files to be compiled into a single class loader. For the boot image,
+  // null is a valid entry.
+  std::unordered_set<mirror::ClassLoader*> class_loaders_;
+
+  // Which mode the image is stored as, see image.h
+  const ImageHeader::StorageMode image_storage_mode_;
+
+  // The file names of oat files.
+  const std::vector<const char*>& oat_filenames_;
+
+  // Map of dex files to the indexes of oat files that they were compiled into.
+  const std::unordered_map<const DexFile*, size_t>& dex_file_oat_index_map_;
+
+  // Set of objects known to be dirty in the image. Can be nullptr if there are none.
+  const std::unordered_set<std::string>* dirty_image_objects_;
+
+  class ComputeLazyFieldsForClassesVisitor;
+  class FixupClassVisitor;
+  class FixupRootVisitor;
+  class FixupVisitor;
+  class GetRootsVisitor;
+  class ImageAddressVisitorForDexCacheArray;
+  class NativeLocationVisitor;
+  class PruneClassesVisitor;
+  class PruneClassLoaderClassesVisitor;
+  class RegisterBootClassPathClassesVisitor;
+  class VisitReferencesVisitor;
+  class PruneObjectReferenceVisitor;
+
+  DISALLOW_COPY_AND_ASSIGN(ImageWriter);
+};
+
+}  // namespace linker
+}  // namespace art
+
+#endif  // ART_DEX2OAT_LINKER_IMAGE_WRITER_H_
diff --git a/dex2oat/linker/multi_oat_relative_patcher.cc b/dex2oat/linker/multi_oat_relative_patcher.cc
new file mode 100644
index 0000000..178a78f
--- /dev/null
+++ b/dex2oat/linker/multi_oat_relative_patcher.cc
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "multi_oat_relative_patcher.h"
+
+#include "base/bit_utils.h"
+#include "base/logging.h"
+#include "globals.h"
+
+namespace art {
+namespace linker {
+
+MultiOatRelativePatcher::MultiOatRelativePatcher(InstructionSet instruction_set,
+                                                 const InstructionSetFeatures* features)
+    : method_offset_map_(),
+      relative_patcher_(RelativePatcher::Create(instruction_set, features, &method_offset_map_)),
+      adjustment_(0u),
+      instruction_set_(instruction_set),
+      start_size_code_alignment_(0u),
+      start_size_relative_call_thunks_(0u),
+      start_size_misc_thunks_(0u) {
+}
+
+void MultiOatRelativePatcher::StartOatFile(uint32_t adjustment) {
+  DCHECK_ALIGNED(adjustment, kPageSize);
+  adjustment_ = adjustment;
+
+  start_size_code_alignment_ = relative_patcher_->CodeAlignmentSize();
+  start_size_relative_call_thunks_ = relative_patcher_->RelativeCallThunksSize();
+  start_size_misc_thunks_ = relative_patcher_->MiscThunksSize();
+}
+
+uint32_t MultiOatRelativePatcher::CodeAlignmentSize() const {
+  DCHECK_GE(relative_patcher_->CodeAlignmentSize(), start_size_code_alignment_);
+  return relative_patcher_->CodeAlignmentSize() - start_size_code_alignment_;
+}
+
+uint32_t MultiOatRelativePatcher::RelativeCallThunksSize() const {
+  DCHECK_GE(relative_patcher_->RelativeCallThunksSize(), start_size_relative_call_thunks_);
+  return relative_patcher_->RelativeCallThunksSize() - start_size_relative_call_thunks_;
+}
+
+uint32_t MultiOatRelativePatcher::MiscThunksSize() const {
+  DCHECK_GE(relative_patcher_->MiscThunksSize(), start_size_misc_thunks_);
+  return relative_patcher_->MiscThunksSize() - start_size_misc_thunks_;
+}
+
+std::pair<bool, uint32_t> MultiOatRelativePatcher::MethodOffsetMap::FindMethodOffset(
+    MethodReference ref) {
+  auto it = map.find(ref);
+  if (it == map.end()) {
+    return std::pair<bool, uint32_t>(false, 0u);
+  } else {
+    return std::pair<bool, uint32_t>(true, it->second);
+  }
+}
+}  // namespace linker
+}  // namespace art
diff --git a/dex2oat/linker/multi_oat_relative_patcher.h b/dex2oat/linker/multi_oat_relative_patcher.h
new file mode 100644
index 0000000..6683366
--- /dev/null
+++ b/dex2oat/linker/multi_oat_relative_patcher.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_DEX2OAT_LINKER_MULTI_OAT_RELATIVE_PATCHER_H_
+#define ART_DEX2OAT_LINKER_MULTI_OAT_RELATIVE_PATCHER_H_
+
+#include "arch/instruction_set.h"
+#include "debug/method_debug_info.h"
+#include "method_reference.h"
+#include "linker/relative_patcher.h"
+#include "safe_map.h"
+
+namespace art {
+
+class CompiledMethod;
+class LinkerPatch;
+class InstructionSetFeatures;
+
+namespace linker {
+
+// MultiOatRelativePatcher is a helper class for handling patching across
+// any number of oat files. It provides storage for method code offsets
+// and wraps RelativePatcher calls, adjusting relative offsets according
+// to the value set by SetAdjustment().
+class MultiOatRelativePatcher FINAL {
+ public:
+  using const_iterator = SafeMap<MethodReference, uint32_t>::const_iterator;
+
+  MultiOatRelativePatcher(InstructionSet instruction_set, const InstructionSetFeatures* features);
+
+  // Mark the start of a new oat file (for statistics retrieval) and set the
+  // adjustment for a new oat file to apply to all relative offsets that are
+  // passed to the MultiOatRelativePatcher.
+  //
+  // The adjustment should be the global offset of the base from which relative
+  // offsets are calculated, such as the start of .rodata for the current oat file.
+  // It must must never point directly to a method's code to avoid relative offsets
+  // with value 0 because this value is used as a missing offset indication in
+  // GetOffset() and an error indication in WriteThunks(). Additionally, it must be
+  // page-aligned, so that it does not skew alignment calculations, say arm64 ADRP.
+  void StartOatFile(uint32_t adjustment);
+
+  // Get relative offset. Returns 0 when the offset has not been set yet.
+  uint32_t GetOffset(MethodReference method_ref) {
+    auto it = method_offset_map_.map.find(method_ref);
+    return (it != method_offset_map_.map.end()) ? it->second - adjustment_ : 0u;
+  }
+
+  // Set the offset.
+  void SetOffset(MethodReference method_ref, uint32_t offset) {
+    method_offset_map_.map.Put(method_ref, offset + adjustment_);
+  }
+
+  // Wrapper around RelativePatcher::ReserveSpace(), doing offset adjustment.
+  uint32_t ReserveSpace(uint32_t offset,
+                        const CompiledMethod* compiled_method,
+                        MethodReference method_ref) {
+    offset += adjustment_;
+    offset = relative_patcher_->ReserveSpace(offset, compiled_method, method_ref);
+    offset -= adjustment_;
+    return offset;
+  }
+
+  // Wrapper around RelativePatcher::ReserveSpaceEnd(), doing offset adjustment.
+  uint32_t ReserveSpaceEnd(uint32_t offset) {
+    offset += adjustment_;
+    offset = relative_patcher_->ReserveSpaceEnd(offset);
+    offset -= adjustment_;
+    return offset;
+  }
+
+  // Wrapper around RelativePatcher::WriteThunks(), doing offset adjustment.
+  uint32_t WriteThunks(OutputStream* out, uint32_t offset) {
+    offset += adjustment_;
+    offset = relative_patcher_->WriteThunks(out, offset);
+    if (offset != 0u) {  // 0u indicates write error.
+      offset -= adjustment_;
+    }
+    return offset;
+  }
+
+  // Wrapper around RelativePatcher::PatchCall(), doing offset adjustment.
+  void PatchCall(std::vector<uint8_t>* code,
+                 uint32_t literal_offset,
+                 uint32_t patch_offset,
+                 uint32_t target_offset) {
+    patch_offset += adjustment_;
+    target_offset += adjustment_;
+    relative_patcher_->PatchCall(code, literal_offset, patch_offset, target_offset);
+  }
+
+  // Wrapper around RelativePatcher::PatchPcRelativeReference(), doing offset adjustment.
+  void PatchPcRelativeReference(std::vector<uint8_t>* code,
+                                const LinkerPatch& patch,
+                                uint32_t patch_offset,
+                                uint32_t target_offset) {
+    patch_offset += adjustment_;
+    target_offset += adjustment_;
+    relative_patcher_->PatchPcRelativeReference(code, patch, patch_offset, target_offset);
+  }
+
+  void PatchBakerReadBarrierBranch(std::vector<uint8_t>* code,
+                                   const LinkerPatch& patch,
+                                   uint32_t patch_offset) {
+    patch_offset += adjustment_;
+    relative_patcher_->PatchBakerReadBarrierBranch(code, patch, patch_offset);
+  }
+
+  std::vector<debug::MethodDebugInfo> GenerateThunkDebugInfo(size_t executable_offset) {
+    executable_offset += adjustment_;
+    return relative_patcher_->GenerateThunkDebugInfo(executable_offset);
+  }
+
+  // Wrappers around RelativePatcher for statistics retrieval.
+  uint32_t CodeAlignmentSize() const;
+  uint32_t RelativeCallThunksSize() const;
+  uint32_t MiscThunksSize() const;
+
+ private:
+  // Map method reference to assigned offset.
+  // Wrap the map in a class implementing RelativePatcherTargetProvider.
+  class MethodOffsetMap : public RelativePatcherTargetProvider {
+   public:
+    std::pair<bool, uint32_t> FindMethodOffset(MethodReference ref) OVERRIDE;
+    SafeMap<MethodReference, uint32_t> map;
+  };
+
+  MethodOffsetMap method_offset_map_;
+  std::unique_ptr<RelativePatcher> relative_patcher_;
+  uint32_t adjustment_;
+  InstructionSet instruction_set_;
+
+  uint32_t start_size_code_alignment_;
+  uint32_t start_size_relative_call_thunks_;
+  uint32_t start_size_misc_thunks_;
+
+  friend class MultiOatRelativePatcherTest;
+
+  DISALLOW_COPY_AND_ASSIGN(MultiOatRelativePatcher);
+};
+
+}  // namespace linker
+}  // namespace art
+
+#endif  // ART_DEX2OAT_LINKER_MULTI_OAT_RELATIVE_PATCHER_H_
diff --git a/dex2oat/linker/multi_oat_relative_patcher_test.cc b/dex2oat/linker/multi_oat_relative_patcher_test.cc
new file mode 100644
index 0000000..1b2d43e
--- /dev/null
+++ b/dex2oat/linker/multi_oat_relative_patcher_test.cc
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "multi_oat_relative_patcher.h"
+
+#include "compiled_method.h"
+#include "debug/method_debug_info.h"
+#include "gtest/gtest.h"
+#include "linker/vector_output_stream.h"
+
+namespace art {
+namespace linker {
+
+static const MethodReference kNullMethodRef = MethodReference(nullptr, 0u);
+
+class MultiOatRelativePatcherTest : public testing::Test {
+ protected:
+  class MockPatcher : public RelativePatcher {
+   public:
+    MockPatcher() { }
+
+    uint32_t ReserveSpace(uint32_t offset,
+                          const CompiledMethod* compiled_method ATTRIBUTE_UNUSED,
+                          MethodReference method_ref) OVERRIDE {
+      last_reserve_offset_ = offset;
+      last_reserve_method_ = method_ref;
+      offset += next_reserve_adjustment_;
+      next_reserve_adjustment_ = 0u;
+      return offset;
+    }
+
+    uint32_t ReserveSpaceEnd(uint32_t offset) OVERRIDE {
+      last_reserve_offset_ = offset;
+      last_reserve_method_ = kNullMethodRef;
+      offset += next_reserve_adjustment_;
+      next_reserve_adjustment_ = 0u;
+      return offset;
+    }
+
+    uint32_t WriteThunks(OutputStream* out, uint32_t offset) OVERRIDE {
+      last_write_offset_ = offset;
+      if (next_write_alignment_ != 0u) {
+        offset += next_write_alignment_;
+        bool success = WriteCodeAlignment(out, next_write_alignment_);
+        CHECK(success);
+        next_write_alignment_ = 0u;
+      }
+      if (next_write_call_thunk_ != 0u) {
+        offset += next_write_call_thunk_;
+        std::vector<uint8_t> thunk(next_write_call_thunk_, 'c');
+        bool success = WriteThunk(out, ArrayRef<const uint8_t>(thunk));
+        CHECK(success);
+        next_write_call_thunk_ = 0u;
+      }
+      if (next_write_misc_thunk_ != 0u) {
+        offset += next_write_misc_thunk_;
+        std::vector<uint8_t> thunk(next_write_misc_thunk_, 'm');
+        bool success = WriteMiscThunk(out, ArrayRef<const uint8_t>(thunk));
+        CHECK(success);
+        next_write_misc_thunk_ = 0u;
+      }
+      return offset;
+    }
+
+    void PatchCall(std::vector<uint8_t>* code ATTRIBUTE_UNUSED,
+                   uint32_t literal_offset,
+                   uint32_t patch_offset,
+                   uint32_t target_offset) OVERRIDE {
+      last_literal_offset_ = literal_offset;
+      last_patch_offset_ = patch_offset;
+      last_target_offset_ = target_offset;
+    }
+
+    void PatchPcRelativeReference(std::vector<uint8_t>* code ATTRIBUTE_UNUSED,
+                                  const LinkerPatch& patch,
+                                  uint32_t patch_offset,
+                                  uint32_t target_offset) OVERRIDE {
+      last_literal_offset_ = patch.LiteralOffset();
+      last_patch_offset_ = patch_offset;
+      last_target_offset_ = target_offset;
+    }
+
+    void PatchBakerReadBarrierBranch(std::vector<uint8_t>* code ATTRIBUTE_UNUSED,
+                                     const LinkerPatch& patch ATTRIBUTE_UNUSED,
+                                     uint32_t patch_offset ATTRIBUTE_UNUSED) {
+      LOG(FATAL) << "UNIMPLEMENTED";
+    }
+
+    std::vector<debug::MethodDebugInfo> GenerateThunkDebugInfo(
+        uint32_t executable_offset ATTRIBUTE_UNUSED) {
+      LOG(FATAL) << "UNIMPLEMENTED";
+      UNREACHABLE();
+    }
+
+    uint32_t last_reserve_offset_ = 0u;
+    MethodReference last_reserve_method_ = kNullMethodRef;
+    uint32_t next_reserve_adjustment_ = 0u;
+
+    uint32_t last_write_offset_ = 0u;
+    uint32_t next_write_alignment_ = 0u;
+    uint32_t next_write_call_thunk_ = 0u;
+    uint32_t next_write_misc_thunk_ = 0u;
+
+    uint32_t last_literal_offset_ = 0u;
+    uint32_t last_patch_offset_ = 0u;
+    uint32_t last_target_offset_ = 0u;
+  };
+
+  MultiOatRelativePatcherTest()
+      : instruction_set_features_(InstructionSetFeatures::FromCppDefines()),
+        patcher_(kRuntimeISA, instruction_set_features_.get()) {
+    std::unique_ptr<MockPatcher> mock(new MockPatcher());
+    mock_ = mock.get();
+    patcher_.relative_patcher_ = std::move(mock);
+  }
+
+  std::unique_ptr<const InstructionSetFeatures> instruction_set_features_;
+  MultiOatRelativePatcher patcher_;
+  MockPatcher* mock_;
+};
+
+TEST_F(MultiOatRelativePatcherTest, Offsets) {
+  const DexFile* dex_file = reinterpret_cast<const DexFile*>(1);
+  MethodReference ref1(dex_file, 1u);
+  MethodReference ref2(dex_file, 2u);
+  EXPECT_EQ(0u, patcher_.GetOffset(ref1));
+  EXPECT_EQ(0u, patcher_.GetOffset(ref2));
+
+  uint32_t adjustment1 = 0x1000;
+  patcher_.StartOatFile(adjustment1);
+  EXPECT_EQ(0u, patcher_.GetOffset(ref1));
+  EXPECT_EQ(0u, patcher_.GetOffset(ref2));
+
+  uint32_t off1 = 0x1234;
+  patcher_.SetOffset(ref1, off1);
+  EXPECT_EQ(off1, patcher_.GetOffset(ref1));
+  EXPECT_EQ(0u, patcher_.GetOffset(ref2));
+
+  uint32_t adjustment2 = 0x30000;
+  patcher_.StartOatFile(adjustment2);
+  EXPECT_EQ(off1 + adjustment1 - adjustment2, patcher_.GetOffset(ref1));
+  EXPECT_EQ(0u, patcher_.GetOffset(ref2));
+
+  uint32_t off2 = 0x4321;
+  patcher_.SetOffset(ref2, off2);
+  EXPECT_EQ(off1 + adjustment1 - adjustment2, patcher_.GetOffset(ref1));
+  EXPECT_EQ(off2, patcher_.GetOffset(ref2));
+
+  uint32_t adjustment3 = 0x78000;
+  patcher_.StartOatFile(adjustment3);
+  EXPECT_EQ(off1 + adjustment1 - adjustment3, patcher_.GetOffset(ref1));
+  EXPECT_EQ(off2 + adjustment2 - adjustment3, patcher_.GetOffset(ref2));
+}
+
+TEST_F(MultiOatRelativePatcherTest, OffsetsInReserve) {
+  const DexFile* dex_file = reinterpret_cast<const DexFile*>(1);
+  MethodReference ref1(dex_file, 1u);
+  MethodReference ref2(dex_file, 2u);
+  MethodReference ref3(dex_file, 3u);
+  const CompiledMethod* method = reinterpret_cast<const CompiledMethod*>(-1);
+
+  uint32_t adjustment1 = 0x1000;
+  patcher_.StartOatFile(adjustment1);
+
+  uint32_t method1_offset = 0x100;
+  uint32_t method1_offset_check = patcher_.ReserveSpace(method1_offset, method, ref1);
+  ASSERT_EQ(adjustment1 + method1_offset, mock_->last_reserve_offset_);
+  ASSERT_TRUE(ref1 == mock_->last_reserve_method_);
+  ASSERT_EQ(method1_offset, method1_offset_check);
+
+  uint32_t method2_offset = 0x1230;
+  uint32_t method2_reserve_adjustment = 0x10;
+  mock_->next_reserve_adjustment_ = method2_reserve_adjustment;
+  uint32_t method2_offset_adjusted = patcher_.ReserveSpace(method2_offset, method, ref2);
+  ASSERT_EQ(adjustment1 + method2_offset, mock_->last_reserve_offset_);
+  ASSERT_TRUE(ref2 == mock_->last_reserve_method_);
+  ASSERT_EQ(method2_offset + method2_reserve_adjustment, method2_offset_adjusted);
+
+  uint32_t end1_offset = 0x4320;
+  uint32_t end1_offset_check = patcher_.ReserveSpaceEnd(end1_offset);
+  ASSERT_EQ(adjustment1 + end1_offset, mock_->last_reserve_offset_);
+  ASSERT_TRUE(kNullMethodRef == mock_->last_reserve_method_);
+  ASSERT_EQ(end1_offset, end1_offset_check);
+
+  uint32_t adjustment2 = 0xd000;
+  patcher_.StartOatFile(adjustment2);
+
+  uint32_t method3_offset = 0xf00;
+  uint32_t method3_offset_check = patcher_.ReserveSpace(method3_offset, method, ref3);
+  ASSERT_EQ(adjustment2 + method3_offset, mock_->last_reserve_offset_);
+  ASSERT_TRUE(ref3 == mock_->last_reserve_method_);
+  ASSERT_EQ(method3_offset, method3_offset_check);
+
+  uint32_t end2_offset = 0x2400;
+  uint32_t end2_reserve_adjustment = 0x20;
+  mock_->next_reserve_adjustment_ = end2_reserve_adjustment;
+  uint32_t end2_offset_adjusted = patcher_.ReserveSpaceEnd(end2_offset);
+  ASSERT_EQ(adjustment2 + end2_offset, mock_->last_reserve_offset_);
+  ASSERT_TRUE(kNullMethodRef == mock_->last_reserve_method_);
+  ASSERT_EQ(end2_offset + end2_reserve_adjustment, end2_offset_adjusted);
+}
+
+TEST_F(MultiOatRelativePatcherTest, Write) {
+  std::vector<uint8_t> output;
+  VectorOutputStream vos("output", &output);
+
+  uint32_t adjustment1 = 0x1000;
+  patcher_.StartOatFile(adjustment1);
+
+  uint32_t method1_offset = 0x100;
+  uint32_t method1_offset_check = patcher_.WriteThunks(&vos, method1_offset);
+  ASSERT_EQ(adjustment1 + method1_offset, mock_->last_write_offset_);
+  ASSERT_EQ(method1_offset, method1_offset_check);
+  vos.WriteFully("1", 1);  // Mark method1.
+
+  uint32_t method2_offset = 0x1230;
+  uint32_t method2_alignment_size = 1;
+  uint32_t method2_call_thunk_size = 2;
+  mock_->next_write_alignment_ = method2_alignment_size;
+  mock_->next_write_call_thunk_ = method2_call_thunk_size;
+  uint32_t method2_offset_adjusted = patcher_.WriteThunks(&vos, method2_offset);
+  ASSERT_EQ(adjustment1 + method2_offset, mock_->last_write_offset_);
+  ASSERT_EQ(method2_offset + method2_alignment_size + method2_call_thunk_size,
+            method2_offset_adjusted);
+  vos.WriteFully("2", 1);  // Mark method2.
+
+  EXPECT_EQ(method2_alignment_size, patcher_.CodeAlignmentSize());
+  EXPECT_EQ(method2_call_thunk_size, patcher_.RelativeCallThunksSize());
+
+  uint32_t adjustment2 = 0xd000;
+  patcher_.StartOatFile(adjustment2);
+
+  uint32_t method3_offset = 0xf00;
+  uint32_t method3_alignment_size = 2;
+  uint32_t method3_misc_thunk_size = 1;
+  mock_->next_write_alignment_ = method3_alignment_size;
+  mock_->next_write_misc_thunk_ = method3_misc_thunk_size;
+  uint32_t method3_offset_adjusted = patcher_.WriteThunks(&vos, method3_offset);
+  ASSERT_EQ(adjustment2 + method3_offset, mock_->last_write_offset_);
+  ASSERT_EQ(method3_offset + method3_alignment_size + method3_misc_thunk_size,
+            method3_offset_adjusted);
+  vos.WriteFully("3", 1);  // Mark method3.
+
+  EXPECT_EQ(method3_alignment_size, patcher_.CodeAlignmentSize());
+  EXPECT_EQ(method3_misc_thunk_size, patcher_.MiscThunksSize());
+
+  uint8_t expected_output[] = {
+      '1',
+      0, 'c', 'c', '2',
+      0, 0, 'm', '3',
+  };
+  ASSERT_EQ(arraysize(expected_output), output.size());
+  for (size_t i = 0; i != arraysize(expected_output); ++i) {
+    ASSERT_EQ(expected_output[i], output[i]) << i;
+  }
+}
+
+TEST_F(MultiOatRelativePatcherTest, Patch) {
+  std::vector<uint8_t> code(16);
+
+  uint32_t adjustment1 = 0x1000;
+  patcher_.StartOatFile(adjustment1);
+
+  uint32_t method1_literal_offset = 4u;
+  uint32_t method1_patch_offset = 0x1234u;
+  uint32_t method1_target_offset = 0x8888u;
+  patcher_.PatchCall(&code, method1_literal_offset, method1_patch_offset, method1_target_offset);
+  DCHECK_EQ(method1_literal_offset, mock_->last_literal_offset_);
+  DCHECK_EQ(method1_patch_offset + adjustment1, mock_->last_patch_offset_);
+  DCHECK_EQ(method1_target_offset + adjustment1, mock_->last_target_offset_);
+
+  uint32_t method2_literal_offset = 12u;
+  uint32_t method2_patch_offset = 0x7654u;
+  uint32_t method2_target_offset = 0xccccu;
+  LinkerPatch method2_patch =
+      LinkerPatch::StringBssEntryPatch(method2_literal_offset, nullptr, 0u, 1u);
+  patcher_.PatchPcRelativeReference(
+      &code, method2_patch, method2_patch_offset, method2_target_offset);
+  DCHECK_EQ(method2_literal_offset, mock_->last_literal_offset_);
+  DCHECK_EQ(method2_patch_offset + adjustment1, mock_->last_patch_offset_);
+  DCHECK_EQ(method2_target_offset + adjustment1, mock_->last_target_offset_);
+
+  uint32_t adjustment2 = 0xd000;
+  patcher_.StartOatFile(adjustment2);
+
+  uint32_t method3_literal_offset = 8u;
+  uint32_t method3_patch_offset = 0x108u;
+  uint32_t method3_target_offset = 0x200u;
+  patcher_.PatchCall(&code, method3_literal_offset, method3_patch_offset, method3_target_offset);
+  DCHECK_EQ(method3_literal_offset, mock_->last_literal_offset_);
+  DCHECK_EQ(method3_patch_offset + adjustment2, mock_->last_patch_offset_);
+  DCHECK_EQ(method3_target_offset + adjustment2, mock_->last_target_offset_);
+}
+
+}  // namespace linker
+}  // namespace art
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
new file mode 100644
index 0000000..51c2a03
--- /dev/null
+++ b/dex2oat/linker/oat_writer.cc
@@ -0,0 +1,3634 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "oat_writer.h"
+
+#include <unistd.h>
+#include <zlib.h>
+
+#include "arch/arm64/instruction_set_features_arm64.h"
+#include "art_method-inl.h"
+#include "base/allocator.h"
+#include "base/bit_vector-inl.h"
+#include "base/enums.h"
+#include "base/file_magic.h"
+#include "base/stl_util.h"
+#include "base/unix_file/fd_file.h"
+#include "class_linker.h"
+#include "class_table-inl.h"
+#include "compiled_method.h"
+#include "debug/method_debug_info.h"
+#include "dex/verification_results.h"
+#include "dex_file-inl.h"
+#include "dex_file_types.h"
+#include "dexlayout.h"
+#include "driver/compiler_driver-inl.h"
+#include "driver/compiler_options.h"
+#include "gc/space/image_space.h"
+#include "gc/space/space.h"
+#include "handle_scope-inl.h"
+#include "image_writer.h"
+#include "linker/buffered_output_stream.h"
+#include "linker/file_output_stream.h"
+#include "linker/method_bss_mapping_encoder.h"
+#include "linker/multi_oat_relative_patcher.h"
+#include "linker/output_stream.h"
+#include "mirror/array.h"
+#include "mirror/class_loader.h"
+#include "mirror/dex_cache-inl.h"
+#include "mirror/object-inl.h"
+#include "oat_quick_method_header.h"
+#include "os.h"
+#include "safe_map.h"
+#include "scoped_thread_state_change-inl.h"
+#include "type_lookup_table.h"
+#include "utils/dex_cache_arrays_layout-inl.h"
+#include "vdex_file.h"
+#include "verifier/verifier_deps.h"
+#include "zip_archive.h"
+
+namespace art {
+namespace linker {
+
+namespace {  // anonymous namespace
+
+// If we write dex layout info in the oat file.
+static constexpr bool kWriteDexLayoutInfo = true;
+
+typedef DexFile::Header __attribute__((aligned(1))) UnalignedDexFileHeader;
+
+const UnalignedDexFileHeader* AsUnalignedDexFileHeader(const uint8_t* raw_data) {
+    return reinterpret_cast<const UnalignedDexFileHeader*>(raw_data);
+}
+
+class ChecksumUpdatingOutputStream : public OutputStream {
+ public:
+  ChecksumUpdatingOutputStream(OutputStream* out, OatHeader* oat_header)
+      : OutputStream(out->GetLocation()), out_(out), oat_header_(oat_header) { }
+
+  bool WriteFully(const void* buffer, size_t byte_count) OVERRIDE {
+    oat_header_->UpdateChecksum(buffer, byte_count);
+    return out_->WriteFully(buffer, byte_count);
+  }
+
+  off_t Seek(off_t offset, Whence whence) OVERRIDE {
+    return out_->Seek(offset, whence);
+  }
+
+  bool Flush() OVERRIDE {
+    return out_->Flush();
+  }
+
+ private:
+  OutputStream* const out_;
+  OatHeader* const oat_header_;
+};
+
+inline uint32_t CodeAlignmentSize(uint32_t header_offset, const CompiledMethod& compiled_method) {
+  // We want to align the code rather than the preheader.
+  uint32_t unaligned_code_offset = header_offset + sizeof(OatQuickMethodHeader);
+  uint32_t aligned_code_offset =  compiled_method.AlignCode(unaligned_code_offset);
+  return aligned_code_offset - unaligned_code_offset;
+}
+
+}  // anonymous namespace
+
+// Defines the location of the raw dex file to write.
+class OatWriter::DexFileSource {
+ public:
+  enum Type {
+    kNone,
+    kZipEntry,
+    kRawFile,
+    kRawData,
+  };
+
+  explicit DexFileSource(ZipEntry* zip_entry)
+      : type_(kZipEntry), source_(zip_entry) {
+    DCHECK(source_ != nullptr);
+  }
+
+  explicit DexFileSource(File* raw_file)
+      : type_(kRawFile), source_(raw_file) {
+    DCHECK(source_ != nullptr);
+  }
+
+  explicit DexFileSource(const uint8_t* dex_file)
+      : type_(kRawData), source_(dex_file) {
+    DCHECK(source_ != nullptr);
+  }
+
+  Type GetType() const { return type_; }
+  bool IsZipEntry() const { return type_ == kZipEntry; }
+  bool IsRawFile() const { return type_ == kRawFile; }
+  bool IsRawData() const { return type_ == kRawData; }
+
+  ZipEntry* GetZipEntry() const {
+    DCHECK(IsZipEntry());
+    DCHECK(source_ != nullptr);
+    return static_cast<ZipEntry*>(const_cast<void*>(source_));
+  }
+
+  File* GetRawFile() const {
+    DCHECK(IsRawFile());
+    DCHECK(source_ != nullptr);
+    return static_cast<File*>(const_cast<void*>(source_));
+  }
+
+  const uint8_t* GetRawData() const {
+    DCHECK(IsRawData());
+    DCHECK(source_ != nullptr);
+    return static_cast<const uint8_t*>(source_);
+  }
+
+  void Clear() {
+    type_ = kNone;
+    source_ = nullptr;
+  }
+
+ private:
+  Type type_;
+  const void* source_;
+};
+
+// OatClassHeader is the header only part of the oat class that is required even when compilation
+// is not enabled.
+class OatWriter::OatClassHeader {
+ public:
+  OatClassHeader(uint32_t offset,
+                 uint32_t num_non_null_compiled_methods,
+                 uint32_t num_methods,
+                 mirror::Class::Status status)
+      : status_(status),
+        offset_(offset) {
+    // We just arbitrarily say that 0 methods means kOatClassNoneCompiled and that we won't use
+    // kOatClassAllCompiled unless there is at least one compiled method. This means in an
+    // interpreter only system, we can assert that all classes are kOatClassNoneCompiled.
+    if (num_non_null_compiled_methods == 0) {
+      type_ = kOatClassNoneCompiled;
+    } else if (num_non_null_compiled_methods == num_methods) {
+      type_ = kOatClassAllCompiled;
+    } else {
+      type_ = kOatClassSomeCompiled;
+    }
+  }
+
+  bool Write(OatWriter* oat_writer, OutputStream* out, const size_t file_offset) const;
+
+  static size_t SizeOf() {
+    return sizeof(status_) + sizeof(type_);
+  }
+
+  // Data to write.
+  static_assert(mirror::Class::Status::kStatusMax < (1 << 16), "class status won't fit in 16bits");
+  int16_t status_;
+
+  static_assert(OatClassType::kOatClassMax < (1 << 16), "oat_class type won't fit in 16bits");
+  uint16_t type_;
+
+  // Offset of start of OatClass from beginning of OatHeader. It is
+  // used to validate file position when writing.
+  uint32_t offset_;
+};
+
+// The actual oat class body contains the information about compiled methods. It is only required
+// for compiler filters that have any compilation.
+class OatWriter::OatClass {
+ public:
+  OatClass(const dchecked_vector<CompiledMethod*>& compiled_methods,
+           uint32_t compiled_methods_with_code,
+           uint16_t oat_class_type);
+  OatClass(OatClass&& src) = default;
+  size_t SizeOf() const;
+  bool Write(OatWriter* oat_writer, OutputStream* out) const;
+
+  CompiledMethod* GetCompiledMethod(size_t class_def_method_index) const {
+    return compiled_methods_[class_def_method_index];
+  }
+
+  // CompiledMethods for each class_def_method_index, or null if no method is available.
+  dchecked_vector<CompiledMethod*> compiled_methods_;
+
+  // Offset from OatClass::offset_ to the OatMethodOffsets for the
+  // class_def_method_index. If 0, it means the corresponding
+  // CompiledMethod entry in OatClass::compiled_methods_ should be
+  // null and that the OatClass::type_ should be kOatClassBitmap.
+  dchecked_vector<uint32_t> oat_method_offsets_offsets_from_oat_class_;
+
+  // Data to write.
+  uint32_t method_bitmap_size_;
+
+  // bit vector indexed by ClassDef method index. When
+  // OatClassType::type_ is kOatClassBitmap, a set bit indicates the
+  // method has an OatMethodOffsets in methods_offsets_, otherwise
+  // the entry was ommited to save space. If OatClassType::type_ is
+  // not is kOatClassBitmap, the bitmap will be null.
+  std::unique_ptr<BitVector> method_bitmap_;
+
+  // OatMethodOffsets and OatMethodHeaders for each CompiledMethod
+  // present in the OatClass. Note that some may be missing if
+  // OatClass::compiled_methods_ contains null values (and
+  // oat_method_offsets_offsets_from_oat_class_ should contain 0
+  // values in this case).
+  dchecked_vector<OatMethodOffsets> method_offsets_;
+  dchecked_vector<OatQuickMethodHeader> method_headers_;
+
+ private:
+  size_t GetMethodOffsetsRawSize() const {
+    return method_offsets_.size() * sizeof(method_offsets_[0]);
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(OatClass);
+};
+
+class OatWriter::OatDexFile {
+ public:
+  OatDexFile(const char* dex_file_location,
+             DexFileSource source,
+             CreateTypeLookupTable create_type_lookup_table);
+  OatDexFile(OatDexFile&& src) = default;
+
+  const char* GetLocation() const {
+    return dex_file_location_data_;
+  }
+
+  size_t SizeOf() const;
+  bool Write(OatWriter* oat_writer, OutputStream* out) const;
+  bool WriteClassOffsets(OatWriter* oat_writer, OutputStream* out);
+
+  size_t GetClassOffsetsRawSize() const {
+    return class_offsets_.size() * sizeof(class_offsets_[0]);
+  }
+
+  // The source of the dex file.
+  DexFileSource source_;
+
+  // Whether to create the type lookup table.
+  CreateTypeLookupTable create_type_lookup_table_;
+
+  // Dex file size. Initialized when writing the dex file.
+  size_t dex_file_size_;
+
+  // Offset of start of OatDexFile from beginning of OatHeader. It is
+  // used to validate file position when writing.
+  size_t offset_;
+
+  // Data to write.
+  uint32_t dex_file_location_size_;
+  const char* dex_file_location_data_;
+  uint32_t dex_file_location_checksum_;
+  uint32_t dex_file_offset_;
+  uint32_t class_offsets_offset_;
+  uint32_t lookup_table_offset_;
+  uint32_t method_bss_mapping_offset_;
+  uint32_t dex_sections_layout_offset_;
+
+  // Data to write to a separate section.
+  dchecked_vector<uint32_t> class_offsets_;
+
+  // Dex section layout info to serialize.
+  DexLayoutSections dex_sections_layout_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(OatDexFile);
+};
+
+#define DCHECK_OFFSET() \
+  DCHECK_EQ(static_cast<off_t>(file_offset + relative_offset), out->Seek(0, kSeekCurrent)) \
+    << "file_offset=" << file_offset << " relative_offset=" << relative_offset
+
+#define DCHECK_OFFSET_() \
+  DCHECK_EQ(static_cast<off_t>(file_offset + offset_), out->Seek(0, kSeekCurrent)) \
+    << "file_offset=" << file_offset << " offset_=" << offset_
+
+OatWriter::OatWriter(bool compiling_boot_image, TimingLogger* timings, ProfileCompilationInfo* info)
+  : write_state_(WriteState::kAddingDexFileSources),
+    timings_(timings),
+    raw_dex_files_(),
+    zip_archives_(),
+    zipped_dex_files_(),
+    zipped_dex_file_locations_(),
+    compiler_driver_(nullptr),
+    image_writer_(nullptr),
+    compiling_boot_image_(compiling_boot_image),
+    dex_files_(nullptr),
+    vdex_size_(0u),
+    vdex_dex_files_offset_(0u),
+    vdex_verifier_deps_offset_(0u),
+    vdex_quickening_info_offset_(0u),
+    oat_size_(0u),
+    bss_start_(0u),
+    bss_size_(0u),
+    bss_methods_offset_(0u),
+    bss_roots_offset_(0u),
+    bss_method_entry_references_(),
+    bss_method_entries_(),
+    bss_type_entries_(),
+    bss_string_entries_(),
+    map_boot_image_tables_to_bss_(false),
+    oat_data_offset_(0u),
+    oat_header_(nullptr),
+    size_vdex_header_(0),
+    size_vdex_checksums_(0),
+    size_dex_file_alignment_(0),
+    size_executable_offset_alignment_(0),
+    size_oat_header_(0),
+    size_oat_header_key_value_store_(0),
+    size_dex_file_(0),
+    size_verifier_deps_(0),
+    size_verifier_deps_alignment_(0),
+    size_quickening_info_(0),
+    size_quickening_info_alignment_(0),
+    size_interpreter_to_interpreter_bridge_(0),
+    size_interpreter_to_compiled_code_bridge_(0),
+    size_jni_dlsym_lookup_(0),
+    size_quick_generic_jni_trampoline_(0),
+    size_quick_imt_conflict_trampoline_(0),
+    size_quick_resolution_trampoline_(0),
+    size_quick_to_interpreter_bridge_(0),
+    size_trampoline_alignment_(0),
+    size_method_header_(0),
+    size_code_(0),
+    size_code_alignment_(0),
+    size_relative_call_thunks_(0),
+    size_misc_thunks_(0),
+    size_vmap_table_(0),
+    size_method_info_(0),
+    size_oat_dex_file_location_size_(0),
+    size_oat_dex_file_location_data_(0),
+    size_oat_dex_file_location_checksum_(0),
+    size_oat_dex_file_offset_(0),
+    size_oat_dex_file_class_offsets_offset_(0),
+    size_oat_dex_file_lookup_table_offset_(0),
+    size_oat_dex_file_dex_layout_sections_offset_(0),
+    size_oat_dex_file_dex_layout_sections_(0),
+    size_oat_dex_file_dex_layout_sections_alignment_(0),
+    size_oat_dex_file_method_bss_mapping_offset_(0),
+    size_oat_lookup_table_alignment_(0),
+    size_oat_lookup_table_(0),
+    size_oat_class_offsets_alignment_(0),
+    size_oat_class_offsets_(0),
+    size_oat_class_type_(0),
+    size_oat_class_status_(0),
+    size_oat_class_method_bitmaps_(0),
+    size_oat_class_method_offsets_(0),
+    size_method_bss_mappings_(0u),
+    relative_patcher_(nullptr),
+    absolute_patch_locations_(),
+    profile_compilation_info_(info) {
+}
+
+bool OatWriter::AddDexFileSource(const char* filename,
+                                 const char* location,
+                                 CreateTypeLookupTable create_type_lookup_table) {
+  DCHECK(write_state_ == WriteState::kAddingDexFileSources);
+  uint32_t magic;
+  std::string error_msg;
+  File fd = OpenAndReadMagic(filename, &magic, &error_msg);
+  if (fd.Fd() == -1) {
+    PLOG(ERROR) << "Failed to read magic number from dex file: '" << filename << "'";
+    return false;
+  } else if (IsDexMagic(magic)) {
+    // The file is open for reading, not writing, so it's OK to let the File destructor
+    // close it without checking for explicit Close(), so pass checkUsage = false.
+    raw_dex_files_.emplace_back(new File(fd.Release(), location, /* checkUsage */ false));
+    oat_dex_files_.emplace_back(location,
+                                DexFileSource(raw_dex_files_.back().get()),
+                                create_type_lookup_table);
+  } else if (IsZipMagic(magic)) {
+    if (!AddZippedDexFilesSource(std::move(fd), location, create_type_lookup_table)) {
+      return false;
+    }
+  } else {
+    LOG(ERROR) << "Expected valid zip or dex file: '" << filename << "'";
+    return false;
+  }
+  return true;
+}
+
+// Add dex file source(s) from a zip file specified by a file handle.
+bool OatWriter::AddZippedDexFilesSource(File&& zip_fd,
+                                        const char* location,
+                                        CreateTypeLookupTable create_type_lookup_table) {
+  DCHECK(write_state_ == WriteState::kAddingDexFileSources);
+  std::string error_msg;
+  zip_archives_.emplace_back(ZipArchive::OpenFromFd(zip_fd.Release(), location, &error_msg));
+  ZipArchive* zip_archive = zip_archives_.back().get();
+  if (zip_archive == nullptr) {
+    LOG(ERROR) << "Failed to open zip from file descriptor for '" << location << "': "
+        << error_msg;
+    return false;
+  }
+  for (size_t i = 0; ; ++i) {
+    std::string entry_name = DexFile::GetMultiDexClassesDexName(i);
+    std::unique_ptr<ZipEntry> entry(zip_archive->Find(entry_name.c_str(), &error_msg));
+    if (entry == nullptr) {
+      break;
+    }
+    zipped_dex_files_.push_back(std::move(entry));
+    zipped_dex_file_locations_.push_back(DexFile::GetMultiDexLocation(i, location));
+    const char* full_location = zipped_dex_file_locations_.back().c_str();
+    oat_dex_files_.emplace_back(full_location,
+                                DexFileSource(zipped_dex_files_.back().get()),
+                                create_type_lookup_table);
+  }
+  if (zipped_dex_file_locations_.empty()) {
+    LOG(ERROR) << "No dex files in zip file '" << location << "': " << error_msg;
+    return false;
+  }
+  return true;
+}
+
+// Add dex file source(s) from a vdex file specified by a file handle.
+bool OatWriter::AddVdexDexFilesSource(const VdexFile& vdex_file,
+                                      const char* location,
+                                      CreateTypeLookupTable create_type_lookup_table) {
+  DCHECK(write_state_ == WriteState::kAddingDexFileSources);
+  const uint8_t* current_dex_data = nullptr;
+  for (size_t i = 0; i < vdex_file.GetHeader().GetNumberOfDexFiles(); ++i) {
+    current_dex_data = vdex_file.GetNextDexFileData(current_dex_data);
+    if (current_dex_data == nullptr) {
+      LOG(ERROR) << "Unexpected number of dex files in vdex " << location;
+      return false;
+    }
+    if (!DexFile::IsMagicValid(current_dex_data)) {
+      LOG(ERROR) << "Invalid magic in vdex file created from " << location;
+      return false;
+    }
+    // We used `zipped_dex_file_locations_` to keep the strings in memory.
+    zipped_dex_file_locations_.push_back(DexFile::GetMultiDexLocation(i, location));
+    const char* full_location = zipped_dex_file_locations_.back().c_str();
+    oat_dex_files_.emplace_back(full_location,
+                                DexFileSource(current_dex_data),
+                                create_type_lookup_table);
+    oat_dex_files_.back().dex_file_location_checksum_ = vdex_file.GetLocationChecksum(i);
+  }
+
+  if (vdex_file.GetNextDexFileData(current_dex_data) != nullptr) {
+    LOG(ERROR) << "Unexpected number of dex files in vdex " << location;
+    return false;
+  }
+
+  if (oat_dex_files_.empty()) {
+    LOG(ERROR) << "No dex files in vdex file created from " << location;
+    return false;
+  }
+  return true;
+}
+
+// Add dex file source from raw memory.
+bool OatWriter::AddRawDexFileSource(const ArrayRef<const uint8_t>& data,
+                                    const char* location,
+                                    uint32_t location_checksum,
+                                    CreateTypeLookupTable create_type_lookup_table) {
+  DCHECK(write_state_ == WriteState::kAddingDexFileSources);
+  if (data.size() < sizeof(DexFile::Header)) {
+    LOG(ERROR) << "Provided data is shorter than dex file header. size: "
+               << data.size() << " File: " << location;
+    return false;
+  }
+  if (!ValidateDexFileHeader(data.data(), location)) {
+    return false;
+  }
+  const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(data.data());
+  if (data.size() < header->file_size_) {
+    LOG(ERROR) << "Truncated dex file data. Data size: " << data.size()
+               << " file size from header: " << header->file_size_ << " File: " << location;
+    return false;
+  }
+
+  oat_dex_files_.emplace_back(location, DexFileSource(data.data()), create_type_lookup_table);
+  oat_dex_files_.back().dex_file_location_checksum_ = location_checksum;
+  return true;
+}
+
+dchecked_vector<std::string> OatWriter::GetSourceLocations() const {
+  dchecked_vector<std::string> locations;
+  locations.reserve(oat_dex_files_.size());
+  for (const OatDexFile& oat_dex_file : oat_dex_files_) {
+    locations.push_back(oat_dex_file.GetLocation());
+  }
+  return locations;
+}
+
+bool OatWriter::MayHaveCompiledMethods() const {
+  return CompilerFilter::IsAnyCompilationEnabled(
+      GetCompilerDriver()->GetCompilerOptions().GetCompilerFilter());
+}
+
+bool OatWriter::WriteAndOpenDexFiles(
+    File* vdex_file,
+    OutputStream* oat_rodata,
+    InstructionSet instruction_set,
+    const InstructionSetFeatures* instruction_set_features,
+    SafeMap<std::string, std::string>* key_value_store,
+    bool verify,
+    bool update_input_vdex,
+    /*out*/ std::unique_ptr<MemMap>* opened_dex_files_map,
+    /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files) {
+  CHECK(write_state_ == WriteState::kAddingDexFileSources);
+
+  // Record the ELF rodata section offset, i.e. the beginning of the OAT data.
+  if (!RecordOatDataOffset(oat_rodata)) {
+     return false;
+  }
+
+  std::unique_ptr<MemMap> dex_files_map;
+  std::vector<std::unique_ptr<const DexFile>> dex_files;
+
+  // Initialize VDEX and OAT headers.
+  if (kIsVdexEnabled) {
+    // Reserve space for Vdex header and checksums.
+    vdex_size_ = sizeof(VdexFile::Header) + oat_dex_files_.size() * sizeof(VdexFile::VdexChecksum);
+  }
+  oat_size_ = InitOatHeader(instruction_set,
+                            instruction_set_features,
+                            dchecked_integral_cast<uint32_t>(oat_dex_files_.size()),
+                            key_value_store);
+
+  ChecksumUpdatingOutputStream checksum_updating_rodata(oat_rodata, oat_header_.get());
+
+  if (kIsVdexEnabled) {
+    std::unique_ptr<BufferedOutputStream> vdex_out =
+        std::make_unique<BufferedOutputStream>(std::make_unique<FileOutputStream>(vdex_file));
+    // Write DEX files into VDEX, mmap and open them.
+    if (!WriteDexFiles(vdex_out.get(), vdex_file, update_input_vdex) ||
+        !OpenDexFiles(vdex_file, verify, &dex_files_map, &dex_files)) {
+      return false;
+    }
+  } else {
+    DCHECK(!update_input_vdex);
+    // Write DEX files into OAT, mmap and open them.
+    if (!WriteDexFiles(oat_rodata, vdex_file, update_input_vdex) ||
+        !OpenDexFiles(vdex_file, verify, &dex_files_map, &dex_files)) {
+      return false;
+    }
+
+    // Do a bulk checksum update for Dex[]. Doing it piece by piece would be
+    // difficult because we're not using the OutputStream directly.
+    if (!oat_dex_files_.empty()) {
+      size_t size = oat_size_ - oat_dex_files_[0].dex_file_offset_;
+      oat_header_->UpdateChecksum(dex_files_map->Begin(), size);
+    }
+  }
+
+  // Write type lookup tables into the oat file.
+  if (!WriteTypeLookupTables(&checksum_updating_rodata, dex_files)) {
+    return false;
+  }
+
+  // Write dex layout sections into the oat file.
+  if (!WriteDexLayoutSections(&checksum_updating_rodata, dex_files)) {
+    return false;
+  }
+
+  *opened_dex_files_map = std::move(dex_files_map);
+  *opened_dex_files = std::move(dex_files);
+  write_state_ = WriteState::kPrepareLayout;
+  return true;
+}
+
+void OatWriter::PrepareLayout(MultiOatRelativePatcher* relative_patcher) {
+  CHECK(write_state_ == WriteState::kPrepareLayout);
+
+  relative_patcher_ = relative_patcher;
+  SetMultiOatRelativePatcherAdjustment();
+
+  if (compiling_boot_image_) {
+    CHECK(image_writer_ != nullptr);
+  }
+  InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
+  CHECK_EQ(instruction_set, oat_header_->GetInstructionSet());
+
+  {
+    TimingLogger::ScopedTiming split("InitBssLayout", timings_);
+    InitBssLayout(instruction_set);
+  }
+
+  uint32_t offset = oat_size_;
+  {
+    TimingLogger::ScopedTiming split("InitClassOffsets", timings_);
+    offset = InitClassOffsets(offset);
+  }
+  {
+    TimingLogger::ScopedTiming split("InitOatClasses", timings_);
+    offset = InitOatClasses(offset);
+  }
+  {
+    TimingLogger::ScopedTiming split("InitMethodBssMappings", timings_);
+    offset = InitMethodBssMappings(offset);
+  }
+  {
+    TimingLogger::ScopedTiming split("InitOatMaps", timings_);
+    offset = InitOatMaps(offset);
+  }
+  {
+    TimingLogger::ScopedTiming split("InitOatDexFiles", timings_);
+    oat_header_->SetOatDexFilesOffset(offset);
+    offset = InitOatDexFiles(offset);
+  }
+  {
+    TimingLogger::ScopedTiming split("InitOatCode", timings_);
+    offset = InitOatCode(offset);
+  }
+  {
+    TimingLogger::ScopedTiming split("InitOatCodeDexFiles", timings_);
+    offset = InitOatCodeDexFiles(offset);
+  }
+  oat_size_ = offset;
+  bss_start_ = (bss_size_ != 0u) ? RoundUp(oat_size_, kPageSize) : 0u;
+
+  CHECK_EQ(dex_files_->size(), oat_dex_files_.size());
+  if (compiling_boot_image_) {
+    CHECK_EQ(image_writer_ != nullptr,
+             oat_header_->GetStoreValueByKey(OatHeader::kImageLocationKey) == nullptr);
+  }
+
+  write_state_ = WriteState::kWriteRoData;
+}
+
+OatWriter::~OatWriter() {
+}
+
+class OatWriter::DexMethodVisitor {
+ public:
+  DexMethodVisitor(OatWriter* writer, size_t offset)
+      : writer_(writer),
+        offset_(offset),
+        dex_file_(nullptr),
+        class_def_index_(dex::kDexNoIndex) {}
+
+  virtual bool StartClass(const DexFile* dex_file, size_t class_def_index) {
+    DCHECK(dex_file_ == nullptr);
+    DCHECK_EQ(class_def_index_, dex::kDexNoIndex);
+    dex_file_ = dex_file;
+    class_def_index_ = class_def_index;
+    return true;
+  }
+
+  virtual bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) = 0;
+
+  virtual bool EndClass() {
+    if (kIsDebugBuild) {
+      dex_file_ = nullptr;
+      class_def_index_ = dex::kDexNoIndex;
+    }
+    return true;
+  }
+
+  size_t GetOffset() const {
+    return offset_;
+  }
+
+ protected:
+  virtual ~DexMethodVisitor() { }
+
+  OatWriter* const writer_;
+
+  // The offset is usually advanced for each visited method by the derived class.
+  size_t offset_;
+
+  // The dex file and class def index are set in StartClass().
+  const DexFile* dex_file_;
+  size_t class_def_index_;
+};
+
+class OatWriter::OatDexMethodVisitor : public DexMethodVisitor {
+ public:
+  OatDexMethodVisitor(OatWriter* writer, size_t offset)
+      : DexMethodVisitor(writer, offset),
+        oat_class_index_(0u),
+        method_offsets_index_(0u) {}
+
+  bool StartClass(const DexFile* dex_file, size_t class_def_index) OVERRIDE {
+    DexMethodVisitor::StartClass(dex_file, class_def_index);
+    if (kIsDebugBuild && writer_->MayHaveCompiledMethods()) {
+      // There are no oat classes if there aren't any compiled methods.
+      CHECK_LT(oat_class_index_, writer_->oat_classes_.size());
+    }
+    method_offsets_index_ = 0u;
+    return true;
+  }
+
+  bool EndClass() OVERRIDE {
+    ++oat_class_index_;
+    return DexMethodVisitor::EndClass();
+  }
+
+ protected:
+  size_t oat_class_index_;
+  size_t method_offsets_index_;
+};
+
+static bool HasCompiledCode(const CompiledMethod* method) {
+  // The dextodexcompiler puts the quickening info table into the CompiledMethod
+  // for simplicity. For such methods, we will emit an OatQuickMethodHeader
+  // only when vdex is disabled.
+  return method != nullptr && (!method->GetQuickCode().empty() || !kIsVdexEnabled);
+}
+
+static bool HasQuickeningInfo(const CompiledMethod* method) {
+  return method != nullptr && method->GetQuickCode().empty() && !method->GetVmapTable().empty();
+}
+
+class OatWriter::InitBssLayoutMethodVisitor : public DexMethodVisitor {
+ public:
+  explicit InitBssLayoutMethodVisitor(OatWriter* writer)
+      : DexMethodVisitor(writer, /* offset */ 0u) {}
+
+  bool VisitMethod(size_t class_def_method_index ATTRIBUTE_UNUSED,
+                   const ClassDataItemIterator& it) OVERRIDE {
+    // Look for patches with .bss references and prepare maps with placeholders for their offsets.
+    CompiledMethod* compiled_method = writer_->compiler_driver_->GetCompiledMethod(
+        MethodReference(dex_file_, it.GetMemberIndex()));
+    if (HasCompiledCode(compiled_method)) {
+      for (const LinkerPatch& patch : compiled_method->GetPatches()) {
+        if (patch.GetType() == LinkerPatch::Type::kMethodBssEntry) {
+          MethodReference target_method = patch.TargetMethod();
+          auto refs_it = writer_->bss_method_entry_references_.find(target_method.dex_file);
+          if (refs_it == writer_->bss_method_entry_references_.end()) {
+            refs_it = writer_->bss_method_entry_references_.Put(
+                target_method.dex_file,
+                BitVector(target_method.dex_file->NumMethodIds(),
+                          /* expandable */ false,
+                          Allocator::GetMallocAllocator()));
+            refs_it->second.ClearAllBits();
+          }
+          refs_it->second.SetBit(target_method.index);
+          writer_->bss_method_entries_.Overwrite(target_method, /* placeholder */ 0u);
+        } else if (patch.GetType() == LinkerPatch::Type::kTypeBssEntry) {
+          TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex());
+          writer_->bss_type_entries_.Overwrite(ref, /* placeholder */ 0u);
+        } else if (patch.GetType() == LinkerPatch::Type::kStringBssEntry) {
+          StringReference ref(patch.TargetStringDexFile(), patch.TargetStringIndex());
+          writer_->bss_string_entries_.Overwrite(ref, /* placeholder */ 0u);
+        } else if (patch.GetType() == LinkerPatch::Type::kStringInternTable ||
+                   patch.GetType() == LinkerPatch::Type::kTypeClassTable) {
+          writer_->map_boot_image_tables_to_bss_ = true;
+        }
+      }
+    } else {
+      DCHECK(compiled_method == nullptr || compiled_method->GetPatches().empty());
+    }
+    return true;
+  }
+};
+
+class OatWriter::InitOatClassesMethodVisitor : public DexMethodVisitor {
+ public:
+  InitOatClassesMethodVisitor(OatWriter* writer, size_t offset)
+      : DexMethodVisitor(writer, offset),
+        compiled_methods_(),
+        compiled_methods_with_code_(0u) {
+    size_t num_classes = 0u;
+    for (const OatDexFile& oat_dex_file : writer_->oat_dex_files_) {
+      num_classes += oat_dex_file.class_offsets_.size();
+    }
+    // If we aren't compiling only reserve headers.
+    writer_->oat_class_headers_.reserve(num_classes);
+    if (writer->MayHaveCompiledMethods()) {
+      writer->oat_classes_.reserve(num_classes);
+    }
+    compiled_methods_.reserve(256u);
+    // If there are any classes, the class offsets allocation aligns the offset.
+    DCHECK(num_classes == 0u || IsAligned<4u>(offset));
+  }
+
+  bool StartClass(const DexFile* dex_file, size_t class_def_index) OVERRIDE {
+    DexMethodVisitor::StartClass(dex_file, class_def_index);
+    compiled_methods_.clear();
+    compiled_methods_with_code_ = 0u;
+    return true;
+  }
+
+  bool VisitMethod(size_t class_def_method_index ATTRIBUTE_UNUSED,
+                   const ClassDataItemIterator& it) OVERRIDE {
+    // Fill in the compiled_methods_ array for methods that have a
+    // CompiledMethod. We track the number of non-null entries in
+    // compiled_methods_with_code_ since we only want to allocate
+    // OatMethodOffsets for the compiled methods.
+    uint32_t method_idx = it.GetMemberIndex();
+    CompiledMethod* compiled_method =
+        writer_->compiler_driver_->GetCompiledMethod(MethodReference(dex_file_, method_idx));
+    compiled_methods_.push_back(compiled_method);
+    if (HasCompiledCode(compiled_method)) {
+      ++compiled_methods_with_code_;
+    }
+    return true;
+  }
+
+  bool EndClass() OVERRIDE {
+    ClassReference class_ref(dex_file_, class_def_index_);
+    mirror::Class::Status status;
+    bool found = writer_->compiler_driver_->GetCompiledClass(class_ref, &status);
+    if (!found) {
+      VerificationResults* results = writer_->compiler_driver_->GetVerificationResults();
+      if (results != nullptr && results->IsClassRejected(class_ref)) {
+        // The oat class status is used only for verification of resolved classes,
+        // so use kStatusErrorResolved whether the class was resolved or unresolved
+        // during compile-time verification.
+        status = mirror::Class::kStatusErrorResolved;
+      } else {
+        status = mirror::Class::kStatusNotReady;
+      }
+    }
+
+    writer_->oat_class_headers_.emplace_back(offset_,
+                                             compiled_methods_with_code_,
+                                             compiled_methods_.size(),
+                                             status);
+    OatClassHeader& header = writer_->oat_class_headers_.back();
+    offset_ += header.SizeOf();
+    if (writer_->MayHaveCompiledMethods()) {
+      writer_->oat_classes_.emplace_back(compiled_methods_,
+                                         compiled_methods_with_code_,
+                                         header.type_);
+      offset_ += writer_->oat_classes_.back().SizeOf();
+    }
+    return DexMethodVisitor::EndClass();
+  }
+
+ private:
+  dchecked_vector<CompiledMethod*> compiled_methods_;
+  size_t compiled_methods_with_code_;
+};
+
+class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor {
+ public:
+  InitCodeMethodVisitor(OatWriter* writer, size_t offset)
+      : InitCodeMethodVisitor(writer, offset, writer->GetCompilerDriver()->GetCompilerOptions()) {}
+
+  bool EndClass() OVERRIDE {
+    OatDexMethodVisitor::EndClass();
+    if (oat_class_index_ == writer_->oat_classes_.size()) {
+      offset_ = relative_patcher_->ReserveSpaceEnd(offset_);
+      if (generate_debug_info_) {
+        std::vector<debug::MethodDebugInfo> thunk_infos =
+            relative_patcher_->GenerateThunkDebugInfo(executable_offset_);
+        writer_->method_info_.insert(writer_->method_info_.end(),
+                                     std::make_move_iterator(thunk_infos.begin()),
+                                     std::make_move_iterator(thunk_infos.end()));
+      }
+    }
+    return true;
+  }
+
+  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
+    CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
+
+    if (HasCompiledCode(compiled_method)) {
+      // Derived from CompiledMethod.
+      uint32_t quick_code_offset = 0;
+
+      ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode();
+      uint32_t code_size = quick_code.size() * sizeof(uint8_t);
+      uint32_t thumb_offset = compiled_method->CodeDelta();
+
+      // Deduplicate code arrays if we are not producing debuggable code.
+      bool deduped = true;
+      MethodReference method_ref(dex_file_, it.GetMemberIndex());
+      if (debuggable_) {
+        quick_code_offset = relative_patcher_->GetOffset(method_ref);
+        if (quick_code_offset != 0u) {
+          // Duplicate methods, we want the same code for both of them so that the oat writer puts
+          // the same code in both ArtMethods so that we do not get different oat code at runtime.
+        } else {
+          quick_code_offset = NewQuickCodeOffset(compiled_method, it, thumb_offset);
+          deduped = false;
+        }
+      } else {
+        quick_code_offset = dedupe_map_.GetOrCreate(
+            compiled_method,
+            [this, &deduped, compiled_method, &it, thumb_offset]() {
+              deduped = false;
+              return NewQuickCodeOffset(compiled_method, it, thumb_offset);
+            });
+      }
+
+      if (code_size != 0) {
+        if (relative_patcher_->GetOffset(method_ref) != 0u) {
+          // TODO: Should this be a hard failure?
+          LOG(WARNING) << "Multiple definitions of "
+              << method_ref.PrettyMethod()
+              << " offsets " << relative_patcher_->GetOffset(method_ref)
+              << " " << quick_code_offset;
+        } else {
+          relative_patcher_->SetOffset(method_ref, quick_code_offset);
+        }
+      }
+
+      // Update quick method header.
+      DCHECK_LT(method_offsets_index_, oat_class->method_headers_.size());
+      OatQuickMethodHeader* method_header = &oat_class->method_headers_[method_offsets_index_];
+      uint32_t vmap_table_offset = method_header->GetVmapTableOffset();
+      uint32_t method_info_offset = method_header->GetMethodInfoOffset();
+      // The code offset was 0 when the mapping/vmap table offset was set, so it's set
+      // to 0-offset and we need to adjust it by code_offset.
+      uint32_t code_offset = quick_code_offset - thumb_offset;
+      if (!compiled_method->GetQuickCode().empty()) {
+        // If the code is compiled, we write the offset of the stack map relative
+        // to the code,
+        if (vmap_table_offset != 0u) {
+          vmap_table_offset += code_offset;
+          DCHECK_LT(vmap_table_offset, code_offset);
+        }
+        if (method_info_offset != 0u) {
+          method_info_offset += code_offset;
+          DCHECK_LT(method_info_offset, code_offset);
+        }
+      } else {
+        CHECK(!kIsVdexEnabled);
+        // We write the offset of the quickening info relative to the code.
+        vmap_table_offset += code_offset;
+        DCHECK_LT(vmap_table_offset, code_offset);
+      }
+      uint32_t frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
+      uint32_t core_spill_mask = compiled_method->GetCoreSpillMask();
+      uint32_t fp_spill_mask = compiled_method->GetFpSpillMask();
+      *method_header = OatQuickMethodHeader(vmap_table_offset,
+                                            method_info_offset,
+                                            frame_size_in_bytes,
+                                            core_spill_mask,
+                                            fp_spill_mask,
+                                            code_size);
+
+      if (!deduped) {
+        // Update offsets. (Checksum is updated when writing.)
+        offset_ += sizeof(*method_header);  // Method header is prepended before code.
+        offset_ += code_size;
+        // Record absolute patch locations.
+        if (!compiled_method->GetPatches().empty()) {
+          uintptr_t base_loc = offset_ - code_size - writer_->oat_header_->GetExecutableOffset();
+          for (const LinkerPatch& patch : compiled_method->GetPatches()) {
+            if (!patch.IsPcRelative()) {
+              writer_->absolute_patch_locations_.push_back(base_loc + patch.LiteralOffset());
+            }
+          }
+        }
+      }
+
+      // Exclude quickened dex methods (code_size == 0) since they have no native code.
+      if (generate_debug_info_ && code_size != 0) {
+        bool has_code_info = method_header->IsOptimized();
+        // Record debug information for this function if we are doing that.
+        debug::MethodDebugInfo info = {};
+        DCHECK(info.trampoline_name.empty());
+        info.dex_file = dex_file_;
+        info.class_def_index = class_def_index_;
+        info.dex_method_index = it.GetMemberIndex();
+        info.access_flags = it.GetMethodAccessFlags();
+        info.code_item = it.GetMethodCodeItem();
+        info.isa = compiled_method->GetInstructionSet();
+        info.deduped = deduped;
+        info.is_native_debuggable = native_debuggable_;
+        info.is_optimized = method_header->IsOptimized();
+        info.is_code_address_text_relative = true;
+        info.code_address = code_offset - executable_offset_;
+        info.code_size = code_size;
+        info.frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
+        info.code_info = has_code_info ? compiled_method->GetVmapTable().data() : nullptr;
+        info.cfi = compiled_method->GetCFIInfo();
+        writer_->method_info_.push_back(info);
+      }
+
+      DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
+      OatMethodOffsets* offsets = &oat_class->method_offsets_[method_offsets_index_];
+      offsets->code_offset_ = quick_code_offset;
+      ++method_offsets_index_;
+    }
+
+    return true;
+  }
+
+ private:
+  InitCodeMethodVisitor(OatWriter* writer, size_t offset, const CompilerOptions& compiler_options)
+      : OatDexMethodVisitor(writer, offset),
+        relative_patcher_(writer->relative_patcher_),
+        executable_offset_(writer->oat_header_->GetExecutableOffset()),
+        debuggable_(compiler_options.GetDebuggable()),
+        native_debuggable_(compiler_options.GetNativeDebuggable()),
+        generate_debug_info_(compiler_options.GenerateAnyDebugInfo()) {
+    writer->absolute_patch_locations_.reserve(
+        writer->GetCompilerDriver()->GetNonRelativeLinkerPatchCount());
+  }
+
+  struct CodeOffsetsKeyComparator {
+    bool operator()(const CompiledMethod* lhs, const CompiledMethod* rhs) const {
+      // Code is deduplicated by CompilerDriver, compare only data pointers.
+      if (lhs->GetQuickCode().data() != rhs->GetQuickCode().data()) {
+        return lhs->GetQuickCode().data() < rhs->GetQuickCode().data();
+      }
+      // If the code is the same, all other fields are likely to be the same as well.
+      if (UNLIKELY(lhs->GetVmapTable().data() != rhs->GetVmapTable().data())) {
+        return lhs->GetVmapTable().data() < rhs->GetVmapTable().data();
+      }
+      if (UNLIKELY(lhs->GetMethodInfo().data() != rhs->GetMethodInfo().data())) {
+        return lhs->GetMethodInfo().data() < rhs->GetMethodInfo().data();
+      }
+      if (UNLIKELY(lhs->GetPatches().data() != rhs->GetPatches().data())) {
+        return lhs->GetPatches().data() < rhs->GetPatches().data();
+      }
+      return false;
+    }
+  };
+
+  uint32_t NewQuickCodeOffset(CompiledMethod* compiled_method,
+                              const ClassDataItemIterator& it,
+                              uint32_t thumb_offset) {
+    offset_ = relative_patcher_->ReserveSpace(
+        offset_, compiled_method, MethodReference(dex_file_, it.GetMemberIndex()));
+    offset_ += CodeAlignmentSize(offset_, *compiled_method);
+    DCHECK_ALIGNED_PARAM(offset_ + sizeof(OatQuickMethodHeader),
+                         GetInstructionSetAlignment(compiled_method->GetInstructionSet()));
+    return offset_ + sizeof(OatQuickMethodHeader) + thumb_offset;
+  }
+
+  // Deduplication is already done on a pointer basis by the compiler driver,
+  // so we can simply compare the pointers to find out if things are duplicated.
+  SafeMap<const CompiledMethod*, uint32_t, CodeOffsetsKeyComparator> dedupe_map_;
+
+  // Cache writer_'s members and compiler options.
+  linker::MultiOatRelativePatcher* relative_patcher_;
+  uint32_t executable_offset_;
+  const bool debuggable_;
+  const bool native_debuggable_;
+  const bool generate_debug_info_;
+};
+
+class OatWriter::InitMapMethodVisitor : public OatDexMethodVisitor {
+ public:
+  InitMapMethodVisitor(OatWriter* writer, size_t offset)
+      : OatDexMethodVisitor(writer, offset) {}
+
+  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it ATTRIBUTE_UNUSED)
+      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
+    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
+    CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
+
+    if (HasCompiledCode(compiled_method)) {
+      DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
+      DCHECK_EQ(oat_class->method_headers_[method_offsets_index_].GetVmapTableOffset(), 0u);
+
+      ArrayRef<const uint8_t> map = compiled_method->GetVmapTable();
+      uint32_t map_size = map.size() * sizeof(map[0]);
+      if (map_size != 0u) {
+        size_t offset = dedupe_map_.GetOrCreate(
+            map.data(),
+            [this, map_size]() {
+              uint32_t new_offset = offset_;
+              offset_ += map_size;
+              return new_offset;
+            });
+        // Code offset is not initialized yet, so set the map offset to 0u-offset.
+        DCHECK_EQ(oat_class->method_offsets_[method_offsets_index_].code_offset_, 0u);
+        oat_class->method_headers_[method_offsets_index_].SetVmapTableOffset(0u - offset);
+      }
+      ++method_offsets_index_;
+    }
+
+    return true;
+  }
+
+ private:
+  // Deduplication is already done on a pointer basis by the compiler driver,
+  // so we can simply compare the pointers to find out if things are duplicated.
+  SafeMap<const uint8_t*, uint32_t> dedupe_map_;
+};
+
+class OatWriter::InitMethodInfoVisitor : public OatDexMethodVisitor {
+ public:
+  InitMethodInfoVisitor(OatWriter* writer, size_t offset) : OatDexMethodVisitor(writer, offset) {}
+
+  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it ATTRIBUTE_UNUSED)
+      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
+    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
+    CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
+
+    if (HasCompiledCode(compiled_method)) {
+      DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
+      DCHECK_EQ(oat_class->method_headers_[method_offsets_index_].GetMethodInfoOffset(), 0u);
+      ArrayRef<const uint8_t> map = compiled_method->GetMethodInfo();
+      const uint32_t map_size = map.size() * sizeof(map[0]);
+      if (map_size != 0u) {
+        size_t offset = dedupe_map_.GetOrCreate(
+            map.data(),
+            [this, map_size]() {
+              uint32_t new_offset = offset_;
+              offset_ += map_size;
+              return new_offset;
+            });
+        // Code offset is not initialized yet, so set the map offset to 0u-offset.
+        DCHECK_EQ(oat_class->method_offsets_[method_offsets_index_].code_offset_, 0u);
+        oat_class->method_headers_[method_offsets_index_].SetMethodInfoOffset(0u - offset);
+      }
+      ++method_offsets_index_;
+    }
+
+    return true;
+  }
+
+ private:
+  // Deduplication is already done on a pointer basis by the compiler driver,
+  // so we can simply compare the pointers to find out if things are duplicated.
+  SafeMap<const uint8_t*, uint32_t> dedupe_map_;
+};
+
+class OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor {
+ public:
+  InitImageMethodVisitor(OatWriter* writer,
+                         size_t offset,
+                         const std::vector<const DexFile*>* dex_files)
+      : OatDexMethodVisitor(writer, offset),
+        pointer_size_(GetInstructionSetPointerSize(writer_->compiler_driver_->GetInstructionSet())),
+        class_loader_(writer->HasImage() ? writer->image_writer_->GetClassLoader() : nullptr),
+        dex_files_(dex_files),
+        class_linker_(Runtime::Current()->GetClassLinker()) {}
+
+  // Handle copied methods here. Copy pointer to quick code from
+  // an origin method to a copied method only if they are
+  // in the same oat file. If the origin and the copied methods are
+  // in different oat files don't touch the copied method.
+  // References to other oat files are not supported yet.
+  bool StartClass(const DexFile* dex_file, size_t class_def_index) OVERRIDE
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    OatDexMethodVisitor::StartClass(dex_file, class_def_index);
+    // Skip classes that are not in the image.
+    if (!IsImageClass()) {
+      return true;
+    }
+    ObjPtr<mirror::DexCache> dex_cache = class_linker_->FindDexCache(Thread::Current(), *dex_file);
+    const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
+    mirror::Class* klass = dex_cache->GetResolvedType(class_def.class_idx_);
+    if (klass != nullptr) {
+      for (ArtMethod& method : klass->GetCopiedMethods(pointer_size_)) {
+        // Find origin method. Declaring class and dex_method_idx
+        // in the copied method should be the same as in the origin
+        // method.
+        mirror::Class* declaring_class = method.GetDeclaringClass();
+        ArtMethod* origin = declaring_class->FindClassMethod(
+            declaring_class->GetDexCache(),
+            method.GetDexMethodIndex(),
+            pointer_size_);
+        CHECK(origin != nullptr);
+        CHECK(!origin->IsDirect());
+        CHECK(origin->GetDeclaringClass() == declaring_class);
+        if (IsInOatFile(&declaring_class->GetDexFile())) {
+          const void* code_ptr =
+              origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size_);
+          if (code_ptr == nullptr) {
+            methods_to_process_.push_back(std::make_pair(&method, origin));
+          } else {
+            method.SetEntryPointFromQuickCompiledCodePtrSize(
+                code_ptr, pointer_size_);
+          }
+        }
+      }
+    }
+    return true;
+  }
+
+  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    // Skip methods that are not in the image.
+    if (!IsImageClass()) {
+      return true;
+    }
+
+    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
+    CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
+
+    OatMethodOffsets offsets(0u);
+    if (HasCompiledCode(compiled_method)) {
+      DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
+      offsets = oat_class->method_offsets_[method_offsets_index_];
+      ++method_offsets_index_;
+    }
+
+    Thread* self = Thread::Current();
+    ObjPtr<mirror::DexCache> dex_cache = class_linker_->FindDexCache(self, *dex_file_);
+    ArtMethod* method;
+    if (writer_->HasBootImage()) {
+      const InvokeType invoke_type = it.GetMethodInvokeType(
+          dex_file_->GetClassDef(class_def_index_));
+      // Unchecked as we hold mutator_lock_ on entry.
+      ScopedObjectAccessUnchecked soa(self);
+      StackHandleScope<1> hs(self);
+      method = class_linker_->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
+          *dex_file_,
+          it.GetMemberIndex(),
+          hs.NewHandle(dex_cache),
+          ScopedNullHandle<mirror::ClassLoader>(),
+          nullptr,
+          invoke_type);
+      if (method == nullptr) {
+        LOG(FATAL_WITHOUT_ABORT) << "Unexpected failure to resolve a method: "
+            << dex_file_->PrettyMethod(it.GetMemberIndex(), true);
+        self->AssertPendingException();
+        mirror::Throwable* exc = self->GetException();
+        std::string dump = exc->Dump();
+        LOG(FATAL) << dump;
+        UNREACHABLE();
+      }
+    } else {
+      // Should already have been resolved by the compiler.
+      // It may not be resolved if the class failed to verify, in this case, don't set the
+      // entrypoint. This is not fatal since we shall use a resolution method.
+      method = class_linker_->LookupResolvedMethod(it.GetMemberIndex(), dex_cache, class_loader_);
+    }
+    if (method != nullptr &&
+        compiled_method != nullptr &&
+        compiled_method->GetQuickCode().size() != 0) {
+      method->SetEntryPointFromQuickCompiledCodePtrSize(
+          reinterpret_cast<void*>(offsets.code_offset_), pointer_size_);
+    }
+
+    return true;
+  }
+
+  // Check whether current class is image class
+  bool IsImageClass() {
+    const DexFile::TypeId& type_id =
+        dex_file_->GetTypeId(dex_file_->GetClassDef(class_def_index_).class_idx_);
+    const char* class_descriptor = dex_file_->GetTypeDescriptor(type_id);
+    return writer_->GetCompilerDriver()->IsImageClass(class_descriptor);
+  }
+
+  // Check whether specified dex file is in the compiled oat file.
+  bool IsInOatFile(const DexFile* dex_file) {
+    return ContainsElement(*dex_files_, dex_file);
+  }
+
+  // Assign a pointer to quick code for copied methods
+  // not handled in the method StartClass
+  void Postprocess() {
+    for (std::pair<ArtMethod*, ArtMethod*>& p : methods_to_process_) {
+      ArtMethod* method = p.first;
+      ArtMethod* origin = p.second;
+      const void* code_ptr =
+          origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size_);
+      if (code_ptr != nullptr) {
+        method->SetEntryPointFromQuickCompiledCodePtrSize(code_ptr, pointer_size_);
+      }
+    }
+  }
+
+ private:
+  const PointerSize pointer_size_;
+  ObjPtr<mirror::ClassLoader> class_loader_;
+  const std::vector<const DexFile*>* dex_files_;
+  ClassLinker* const class_linker_;
+  std::vector<std::pair<ArtMethod*, ArtMethod*>> methods_to_process_;
+};
+
+class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor {
+ public:
+  WriteCodeMethodVisitor(OatWriter* writer, OutputStream* out, const size_t file_offset,
+                         size_t relative_offset) SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
+      : OatDexMethodVisitor(writer, relative_offset),
+        pointer_size_(GetInstructionSetPointerSize(writer_->compiler_driver_->GetInstructionSet())),
+        class_loader_(writer->HasImage() ? writer->image_writer_->GetClassLoader() : nullptr),
+        out_(out),
+        file_offset_(file_offset),
+        soa_(Thread::Current()),
+        no_thread_suspension_("OatWriter patching"),
+        class_linker_(Runtime::Current()->GetClassLinker()),
+        dex_cache_(nullptr) {
+    patched_code_.reserve(16 * KB);
+    if (writer_->HasBootImage()) {
+      // If we're creating the image, the address space must be ready so that we can apply patches.
+      CHECK(writer_->image_writer_->IsImageAddressSpaceReady());
+    }
+  }
+
+  ~WriteCodeMethodVisitor() UNLOCK_FUNCTION(Locks::mutator_lock_) {
+  }
+
+  bool StartClass(const DexFile* dex_file, size_t class_def_index) OVERRIDE
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    OatDexMethodVisitor::StartClass(dex_file, class_def_index);
+    if (writer_->GetCompilerDriver()->GetCompilerOptions().IsAotCompilationEnabled()) {
+      // Only need to set the dex cache if we have compilation. Other modes might have unloaded it.
+      if (dex_cache_ == nullptr || dex_cache_->GetDexFile() != dex_file) {
+        dex_cache_ = class_linker_->FindDexCache(Thread::Current(), *dex_file);
+        DCHECK(dex_cache_ != nullptr);
+      }
+    }
+    return true;
+  }
+
+  bool EndClass() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
+    bool result = OatDexMethodVisitor::EndClass();
+    if (oat_class_index_ == writer_->oat_classes_.size()) {
+      DCHECK(result);  // OatDexMethodVisitor::EndClass() never fails.
+      offset_ = writer_->relative_patcher_->WriteThunks(out_, offset_);
+      if (UNLIKELY(offset_ == 0u)) {
+        PLOG(ERROR) << "Failed to write final relative call thunks";
+        result = false;
+      }
+    }
+    return result;
+  }
+
+  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
+    const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
+
+    // No thread suspension since dex_cache_ that may get invalidated if that occurs.
+    ScopedAssertNoThreadSuspension tsc(__FUNCTION__);
+    if (HasCompiledCode(compiled_method)) {
+      size_t file_offset = file_offset_;
+      OutputStream* out = out_;
+
+      ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode();
+      uint32_t code_size = quick_code.size() * sizeof(uint8_t);
+
+      // Deduplicate code arrays.
+      const OatMethodOffsets& method_offsets = oat_class->method_offsets_[method_offsets_index_];
+      if (method_offsets.code_offset_ > offset_) {
+        offset_ = writer_->relative_patcher_->WriteThunks(out, offset_);
+        if (offset_ == 0u) {
+          ReportWriteFailure("relative call thunk", it);
+          return false;
+        }
+        uint32_t alignment_size = CodeAlignmentSize(offset_, *compiled_method);
+        if (alignment_size != 0) {
+          if (!writer_->WriteCodeAlignment(out, alignment_size)) {
+            ReportWriteFailure("code alignment padding", it);
+            return false;
+          }
+          offset_ += alignment_size;
+          DCHECK_OFFSET_();
+        }
+        DCHECK_ALIGNED_PARAM(offset_ + sizeof(OatQuickMethodHeader),
+                             GetInstructionSetAlignment(compiled_method->GetInstructionSet()));
+        DCHECK_EQ(method_offsets.code_offset_,
+                  offset_ + sizeof(OatQuickMethodHeader) + compiled_method->CodeDelta())
+            << dex_file_->PrettyMethod(it.GetMemberIndex());
+        const OatQuickMethodHeader& method_header =
+            oat_class->method_headers_[method_offsets_index_];
+        if (!out->WriteFully(&method_header, sizeof(method_header))) {
+          ReportWriteFailure("method header", it);
+          return false;
+        }
+        writer_->size_method_header_ += sizeof(method_header);
+        offset_ += sizeof(method_header);
+        DCHECK_OFFSET_();
+
+        if (!compiled_method->GetPatches().empty()) {
+          patched_code_.assign(quick_code.begin(), quick_code.end());
+          quick_code = ArrayRef<const uint8_t>(patched_code_);
+          for (const LinkerPatch& patch : compiled_method->GetPatches()) {
+            uint32_t literal_offset = patch.LiteralOffset();
+            switch (patch.GetType()) {
+              case LinkerPatch::Type::kMethodBssEntry: {
+                uint32_t target_offset =
+                    writer_->bss_start_ + writer_->bss_method_entries_.Get(patch.TargetMethod());
+                writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+                                                                     patch,
+                                                                     offset_ + literal_offset,
+                                                                     target_offset);
+                break;
+              }
+              case LinkerPatch::Type::kCallRelative: {
+                // NOTE: Relative calls across oat files are not supported.
+                uint32_t target_offset = GetTargetOffset(patch);
+                writer_->relative_patcher_->PatchCall(&patched_code_,
+                                                      literal_offset,
+                                                      offset_ + literal_offset,
+                                                      target_offset);
+                break;
+              }
+              case LinkerPatch::Type::kStringRelative: {
+                uint32_t target_offset = GetTargetObjectOffset(GetTargetString(patch));
+                writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+                                                                     patch,
+                                                                     offset_ + literal_offset,
+                                                                     target_offset);
+                break;
+              }
+              case LinkerPatch::Type::kStringInternTable: {
+                uint32_t target_offset = GetInternTableEntryOffset(patch);
+                writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+                                                                     patch,
+                                                                     offset_ + literal_offset,
+                                                                     target_offset);
+                break;
+              }
+              case LinkerPatch::Type::kStringBssEntry: {
+                StringReference ref(patch.TargetStringDexFile(), patch.TargetStringIndex());
+                uint32_t target_offset =
+                    writer_->bss_start_ + writer_->bss_string_entries_.Get(ref);
+                writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+                                                                     patch,
+                                                                     offset_ + literal_offset,
+                                                                     target_offset);
+                break;
+              }
+              case LinkerPatch::Type::kTypeRelative: {
+                uint32_t target_offset = GetTargetObjectOffset(GetTargetType(patch));
+                writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+                                                                     patch,
+                                                                     offset_ + literal_offset,
+                                                                     target_offset);
+                break;
+              }
+              case LinkerPatch::Type::kTypeClassTable: {
+                uint32_t target_offset = GetClassTableEntryOffset(patch);
+                writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+                                                                     patch,
+                                                                     offset_ + literal_offset,
+                                                                     target_offset);
+                break;
+              }
+              case LinkerPatch::Type::kTypeBssEntry: {
+                TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex());
+                uint32_t target_offset = writer_->bss_start_ + writer_->bss_type_entries_.Get(ref);
+                writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+                                                                     patch,
+                                                                     offset_ + literal_offset,
+                                                                     target_offset);
+                break;
+              }
+              case LinkerPatch::Type::kCall: {
+                uint32_t target_offset = GetTargetOffset(patch);
+                PatchCodeAddress(&patched_code_, literal_offset, target_offset);
+                break;
+              }
+              case LinkerPatch::Type::kMethodRelative: {
+                uint32_t target_offset = GetTargetMethodOffset(GetTargetMethod(patch));
+                writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+                                                                     patch,
+                                                                     offset_ + literal_offset,
+                                                                     target_offset);
+                break;
+              }
+              case LinkerPatch::Type::kBakerReadBarrierBranch: {
+                writer_->relative_patcher_->PatchBakerReadBarrierBranch(&patched_code_,
+                                                                        patch,
+                                                                        offset_ + literal_offset);
+                break;
+              }
+              default: {
+                DCHECK(false) << "Unexpected linker patch type: " << patch.GetType();
+                break;
+              }
+            }
+          }
+        }
+
+        if (!out->WriteFully(quick_code.data(), code_size)) {
+          ReportWriteFailure("method code", it);
+          return false;
+        }
+        writer_->size_code_ += code_size;
+        offset_ += code_size;
+      }
+      DCHECK_OFFSET_();
+      ++method_offsets_index_;
+    }
+
+    return true;
+  }
+
+ private:
+  const PointerSize pointer_size_;
+  ObjPtr<mirror::ClassLoader> class_loader_;
+  OutputStream* const out_;
+  const size_t file_offset_;
+  const ScopedObjectAccess soa_;
+  const ScopedAssertNoThreadSuspension no_thread_suspension_;
+  ClassLinker* const class_linker_;
+  ObjPtr<mirror::DexCache> dex_cache_;
+  std::vector<uint8_t> patched_code_;
+
+  void ReportWriteFailure(const char* what, const ClassDataItemIterator& it) {
+    PLOG(ERROR) << "Failed to write " << what << " for "
+        << dex_file_->PrettyMethod(it.GetMemberIndex()) << " to " << out_->GetLocation();
+  }
+
+  ArtMethod* GetTargetMethod(const LinkerPatch& patch)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    MethodReference ref = patch.TargetMethod();
+    ObjPtr<mirror::DexCache> dex_cache =
+        (dex_file_ == ref.dex_file) ? dex_cache_ : class_linker_->FindDexCache(
+            Thread::Current(), *ref.dex_file);
+    ArtMethod* method = class_linker_->LookupResolvedMethod(ref.index, dex_cache, class_loader_);
+    CHECK(method != nullptr);
+    return method;
+  }
+
+  uint32_t GetTargetOffset(const LinkerPatch& patch) REQUIRES_SHARED(Locks::mutator_lock_) {
+    uint32_t target_offset = writer_->relative_patcher_->GetOffset(patch.TargetMethod());
+    // If there's no new compiled code, either we're compiling an app and the target method
+    // is in the boot image, or we need to point to the correct trampoline.
+    if (UNLIKELY(target_offset == 0)) {
+      ArtMethod* target = GetTargetMethod(patch);
+      DCHECK(target != nullptr);
+      const void* oat_code_offset =
+          target->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size_);
+      if (oat_code_offset != 0) {
+        DCHECK(!writer_->HasBootImage());
+        DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickResolutionStub(oat_code_offset));
+        DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickToInterpreterBridge(oat_code_offset));
+        DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickGenericJniStub(oat_code_offset));
+        target_offset = PointerToLowMemUInt32(oat_code_offset);
+      } else {
+        target_offset = target->IsNative()
+            ? writer_->oat_header_->GetQuickGenericJniTrampolineOffset()
+            : writer_->oat_header_->GetQuickToInterpreterBridgeOffset();
+      }
+    }
+    return target_offset;
+  }
+
+  ObjPtr<mirror::DexCache> GetDexCache(const DexFile* target_dex_file)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    return (target_dex_file == dex_file_)
+        ? dex_cache_
+        : class_linker_->FindDexCache(Thread::Current(), *target_dex_file);
+  }
+
+  mirror::Class* GetTargetType(const LinkerPatch& patch) REQUIRES_SHARED(Locks::mutator_lock_) {
+    DCHECK(writer_->HasImage());
+    ObjPtr<mirror::DexCache> dex_cache = GetDexCache(patch.TargetTypeDexFile());
+    ObjPtr<mirror::Class> type =
+        ClassLinker::LookupResolvedType(patch.TargetTypeIndex(), dex_cache, class_loader_);
+    CHECK(type != nullptr);
+    return type.Ptr();
+  }
+
+  mirror::String* GetTargetString(const LinkerPatch& patch) REQUIRES_SHARED(Locks::mutator_lock_) {
+    ClassLinker* linker = Runtime::Current()->GetClassLinker();
+    mirror::String* string = linker->LookupString(*patch.TargetStringDexFile(),
+                                                  patch.TargetStringIndex(),
+                                                  GetDexCache(patch.TargetStringDexFile()));
+    DCHECK(string != nullptr);
+    DCHECK(writer_->HasBootImage() ||
+           Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(string));
+    return string;
+  }
+
+  uint32_t GetTargetMethodOffset(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
+    DCHECK(writer_->HasBootImage());
+    method = writer_->image_writer_->GetImageMethodAddress(method);
+    size_t oat_index = writer_->image_writer_->GetOatIndexForDexFile(dex_file_);
+    uintptr_t oat_data_begin = writer_->image_writer_->GetOatDataBegin(oat_index);
+    // TODO: Clean up offset types. The target offset must be treated as signed.
+    return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(method) - oat_data_begin);
+  }
+
+  uint32_t GetTargetObjectOffset(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_) {
+    DCHECK(writer_->HasBootImage());
+    object = writer_->image_writer_->GetImageAddress(object);
+    size_t oat_index = writer_->image_writer_->GetOatIndexForDexFile(dex_file_);
+    uintptr_t oat_data_begin = writer_->image_writer_->GetOatDataBegin(oat_index);
+    // TODO: Clean up offset types. The target offset must be treated as signed.
+    return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object) - oat_data_begin);
+  }
+
+  void PatchObjectAddress(std::vector<uint8_t>* code, uint32_t offset, mirror::Object* object)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    if (writer_->HasBootImage()) {
+      object = writer_->image_writer_->GetImageAddress(object);
+    } else {
+      // NOTE: We're using linker patches for app->boot references when the image can
+      // be relocated and therefore we need to emit .oat_patches. We're not using this
+      // for app->app references, so check that the object is in the image space.
+      DCHECK(Runtime::Current()->GetHeap()->FindSpaceFromObject(object, false)->IsImageSpace());
+    }
+    // Note: We only patch targeting Objects in image which is in the low 4gb.
+    uint32_t address = PointerToLowMemUInt32(object);
+    DCHECK_LE(offset + 4, code->size());
+    uint8_t* data = &(*code)[offset];
+    data[0] = address & 0xffu;
+    data[1] = (address >> 8) & 0xffu;
+    data[2] = (address >> 16) & 0xffu;
+    data[3] = (address >> 24) & 0xffu;
+  }
+
+  void PatchCodeAddress(std::vector<uint8_t>* code, uint32_t offset, uint32_t target_offset)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    uint32_t address = target_offset;
+    if (writer_->HasBootImage()) {
+      size_t oat_index = writer_->image_writer_->GetOatIndexForDexCache(dex_cache_);
+      // TODO: Clean up offset types.
+      // The target_offset must be treated as signed for cross-oat patching.
+      const void* target = reinterpret_cast<const void*>(
+          writer_->image_writer_->GetOatDataBegin(oat_index) +
+          static_cast<int32_t>(target_offset));
+      address = PointerToLowMemUInt32(target);
+    }
+    DCHECK_LE(offset + 4, code->size());
+    uint8_t* data = &(*code)[offset];
+    data[0] = address & 0xffu;
+    data[1] = (address >> 8) & 0xffu;
+    data[2] = (address >> 16) & 0xffu;
+    data[3] = (address >> 24) & 0xffu;
+  }
+
+  // Calculate the offset of the InternTable slot (GcRoot<String>) when mmapped to the .bss.
+  uint32_t GetInternTableEntryOffset(const LinkerPatch& patch)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    DCHECK(!writer_->HasBootImage());
+    const uint8_t* string_root = writer_->LookupBootImageInternTableSlot(
+        *patch.TargetStringDexFile(), patch.TargetStringIndex());
+    DCHECK(string_root != nullptr);
+    return GetBootImageTableEntryOffset(string_root);
+  }
+
+  // Calculate the offset of the ClassTable::TableSlot when mmapped to the .bss.
+  uint32_t GetClassTableEntryOffset(const LinkerPatch& patch)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    DCHECK(!writer_->HasBootImage());
+    const uint8_t* table_slot =
+        writer_->LookupBootImageClassTableSlot(*patch.TargetTypeDexFile(), patch.TargetTypeIndex());
+    DCHECK(table_slot != nullptr);
+    return GetBootImageTableEntryOffset(table_slot);
+  }
+
+  uint32_t GetBootImageTableEntryOffset(const uint8_t* raw_root) {
+    uint32_t base_offset = writer_->bss_start_;
+    for (gc::space::ImageSpace* space : Runtime::Current()->GetHeap()->GetBootImageSpaces()) {
+      const uint8_t* const_tables_begin =
+          space->Begin() + space->GetImageHeader().GetBootImageConstantTablesOffset();
+      size_t offset = static_cast<size_t>(raw_root - const_tables_begin);
+      if (offset < space->GetImageHeader().GetBootImageConstantTablesSize()) {
+        DCHECK_LE(base_offset + offset, writer_->bss_start_ + writer_->bss_methods_offset_);
+        return base_offset + offset;
+      }
+      base_offset += space->GetImageHeader().GetBootImageConstantTablesSize();
+    }
+    LOG(FATAL) << "Didn't find boot image string in boot image intern tables!";
+    UNREACHABLE();
+  }
+};
+
+class OatWriter::WriteMapMethodVisitor : public OatDexMethodVisitor {
+ public:
+  WriteMapMethodVisitor(OatWriter* writer,
+                        OutputStream* out,
+                        const size_t file_offset,
+                        size_t relative_offset)
+      : OatDexMethodVisitor(writer, relative_offset),
+        out_(out),
+        file_offset_(file_offset) {}
+
+  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE {
+    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
+    const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
+
+    if (HasCompiledCode(compiled_method)) {
+      size_t file_offset = file_offset_;
+      OutputStream* out = out_;
+
+      uint32_t map_offset = oat_class->method_headers_[method_offsets_index_].GetVmapTableOffset();
+      uint32_t code_offset = oat_class->method_offsets_[method_offsets_index_].code_offset_;
+      ++method_offsets_index_;
+
+      DCHECK((compiled_method->GetVmapTable().size() == 0u && map_offset == 0u) ||
+             (compiled_method->GetVmapTable().size() != 0u && map_offset != 0u))
+          << compiled_method->GetVmapTable().size() << " " << map_offset << " "
+          << dex_file_->PrettyMethod(it.GetMemberIndex());
+
+      // If vdex is enabled, only emit the map for compiled code. The quickening info
+      // is emitted in the vdex already.
+      if (map_offset != 0u) {
+        // Transform map_offset to actual oat data offset.
+        map_offset = (code_offset - compiled_method->CodeDelta()) - map_offset;
+        DCHECK_NE(map_offset, 0u);
+        DCHECK_LE(map_offset, offset_) << dex_file_->PrettyMethod(it.GetMemberIndex());
+
+        ArrayRef<const uint8_t> map = compiled_method->GetVmapTable();
+        size_t map_size = map.size() * sizeof(map[0]);
+        if (map_offset == offset_) {
+          // Write deduplicated map (code info for Optimizing or transformation info for dex2dex).
+          if (UNLIKELY(!out->WriteFully(map.data(), map_size))) {
+            ReportWriteFailure(it);
+            return false;
+          }
+          offset_ += map_size;
+        }
+      }
+      DCHECK_OFFSET_();
+    }
+
+    return true;
+  }
+
+ private:
+  OutputStream* const out_;
+  size_t const file_offset_;
+
+  void ReportWriteFailure(const ClassDataItemIterator& it) {
+    PLOG(ERROR) << "Failed to write map for "
+        << dex_file_->PrettyMethod(it.GetMemberIndex()) << " to " << out_->GetLocation();
+  }
+};
+
+class OatWriter::WriteMethodInfoVisitor : public OatDexMethodVisitor {
+ public:
+  WriteMethodInfoVisitor(OatWriter* writer,
+                         OutputStream* out,
+                         const size_t file_offset,
+                         size_t relative_offset)
+      : OatDexMethodVisitor(writer, relative_offset),
+        out_(out),
+        file_offset_(file_offset) {}
+
+  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE {
+    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
+    const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
+
+    if (HasCompiledCode(compiled_method)) {
+      size_t file_offset = file_offset_;
+      OutputStream* out = out_;
+      uint32_t map_offset = oat_class->method_headers_[method_offsets_index_].GetMethodInfoOffset();
+      uint32_t code_offset = oat_class->method_offsets_[method_offsets_index_].code_offset_;
+      ++method_offsets_index_;
+      DCHECK((compiled_method->GetMethodInfo().size() == 0u && map_offset == 0u) ||
+             (compiled_method->GetMethodInfo().size() != 0u && map_offset != 0u))
+          << compiled_method->GetMethodInfo().size() << " " << map_offset << " "
+          << dex_file_->PrettyMethod(it.GetMemberIndex());
+      if (map_offset != 0u) {
+        // Transform map_offset to actual oat data offset.
+        map_offset = (code_offset - compiled_method->CodeDelta()) - map_offset;
+        DCHECK_NE(map_offset, 0u);
+        DCHECK_LE(map_offset, offset_) << dex_file_->PrettyMethod(it.GetMemberIndex());
+
+        ArrayRef<const uint8_t> map = compiled_method->GetMethodInfo();
+        size_t map_size = map.size() * sizeof(map[0]);
+        if (map_offset == offset_) {
+          // Write deduplicated map (code info for Optimizing or transformation info for dex2dex).
+          if (UNLIKELY(!out->WriteFully(map.data(), map_size))) {
+            ReportWriteFailure(it);
+            return false;
+          }
+          offset_ += map_size;
+        }
+      }
+      DCHECK_OFFSET_();
+    }
+
+    return true;
+  }
+
+ private:
+  OutputStream* const out_;
+  size_t const file_offset_;
+
+  void ReportWriteFailure(const ClassDataItemIterator& it) {
+    PLOG(ERROR) << "Failed to write map for "
+        << dex_file_->PrettyMethod(it.GetMemberIndex()) << " to " << out_->GetLocation();
+  }
+};
+
+// Visit all methods from all classes in all dex files with the specified visitor.
+bool OatWriter::VisitDexMethods(DexMethodVisitor* visitor) {
+  for (const DexFile* dex_file : *dex_files_) {
+    const size_t class_def_count = dex_file->NumClassDefs();
+    for (size_t class_def_index = 0; class_def_index != class_def_count; ++class_def_index) {
+      if (UNLIKELY(!visitor->StartClass(dex_file, class_def_index))) {
+        return false;
+      }
+      if (MayHaveCompiledMethods()) {
+        const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
+        const uint8_t* class_data = dex_file->GetClassData(class_def);
+        if (class_data != nullptr) {  // ie not an empty class, such as a marker interface
+          ClassDataItemIterator it(*dex_file, class_data);
+          it.SkipAllFields();
+          size_t class_def_method_index = 0u;
+          while (it.HasNextDirectMethod()) {
+            if (!visitor->VisitMethod(class_def_method_index, it)) {
+              return false;
+            }
+            ++class_def_method_index;
+            it.Next();
+          }
+          while (it.HasNextVirtualMethod()) {
+            if (UNLIKELY(!visitor->VisitMethod(class_def_method_index, it))) {
+              return false;
+            }
+            ++class_def_method_index;
+            it.Next();
+          }
+        }
+      }
+      if (UNLIKELY(!visitor->EndClass())) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+size_t OatWriter::InitOatHeader(InstructionSet instruction_set,
+                                const InstructionSetFeatures* instruction_set_features,
+                                uint32_t num_dex_files,
+                                SafeMap<std::string, std::string>* key_value_store) {
+  TimingLogger::ScopedTiming split("InitOatHeader", timings_);
+  oat_header_.reset(OatHeader::Create(instruction_set,
+                                      instruction_set_features,
+                                      num_dex_files,
+                                      key_value_store));
+  size_oat_header_ += sizeof(OatHeader);
+  size_oat_header_key_value_store_ += oat_header_->GetHeaderSize() - sizeof(OatHeader);
+  return oat_header_->GetHeaderSize();
+}
+
+size_t OatWriter::InitClassOffsets(size_t offset) {
+  // Reserve space for class offsets in OAT and update class_offsets_offset_.
+  for (OatDexFile& oat_dex_file : oat_dex_files_) {
+    DCHECK_EQ(oat_dex_file.class_offsets_offset_, 0u);
+    if (!oat_dex_file.class_offsets_.empty()) {
+      // Class offsets are required to be 4 byte aligned.
+      offset = RoundUp(offset, 4u);
+      oat_dex_file.class_offsets_offset_ = offset;
+      offset += oat_dex_file.GetClassOffsetsRawSize();
+      DCHECK_ALIGNED(offset, 4u);
+    }
+  }
+  return offset;
+}
+
+size_t OatWriter::InitOatClasses(size_t offset) {
+  // calculate the offsets within OatDexFiles to OatClasses
+  InitOatClassesMethodVisitor visitor(this, offset);
+  bool success = VisitDexMethods(&visitor);
+  CHECK(success);
+  offset = visitor.GetOffset();
+
+  // Update oat_dex_files_.
+  auto oat_class_it = oat_class_headers_.begin();
+  for (OatDexFile& oat_dex_file : oat_dex_files_) {
+    for (uint32_t& class_offset : oat_dex_file.class_offsets_) {
+      DCHECK(oat_class_it != oat_class_headers_.end());
+      class_offset = oat_class_it->offset_;
+      ++oat_class_it;
+    }
+  }
+  CHECK(oat_class_it == oat_class_headers_.end());
+
+  return offset;
+}
+
+size_t OatWriter::InitOatMaps(size_t offset) {
+  if (!MayHaveCompiledMethods()) {
+    return offset;
+  }
+  {
+    InitMapMethodVisitor visitor(this, offset);
+    bool success = VisitDexMethods(&visitor);
+    DCHECK(success);
+    offset = visitor.GetOffset();
+  }
+  {
+    InitMethodInfoVisitor visitor(this, offset);
+    bool success = VisitDexMethods(&visitor);
+    DCHECK(success);
+    offset = visitor.GetOffset();
+  }
+  return offset;
+}
+
+size_t OatWriter::InitMethodBssMappings(size_t offset) {
+  size_t number_of_dex_files = 0u;
+  for (size_t i = 0, size = dex_files_->size(); i != size; ++i) {
+    const DexFile* dex_file = (*dex_files_)[i];
+    auto it = bss_method_entry_references_.find(dex_file);
+    if (it != bss_method_entry_references_.end()) {
+      const BitVector& method_indexes = it->second;
+      ++number_of_dex_files;
+      // If there are any classes, the class offsets allocation aligns the offset
+      // and we cannot have method bss mappings without class offsets.
+      static_assert(alignof(MethodBssMapping) == 4u, "MethodBssMapping alignment check.");
+      DCHECK_ALIGNED(offset, 4u);
+      oat_dex_files_[i].method_bss_mapping_offset_ = offset;
+
+      linker::MethodBssMappingEncoder encoder(
+          GetInstructionSetPointerSize(oat_header_->GetInstructionSet()));
+      size_t number_of_entries = 0u;
+      bool first_index = true;
+      for (uint32_t method_index : method_indexes.Indexes()) {
+        uint32_t bss_offset = bss_method_entries_.Get(MethodReference(dex_file, method_index));
+        if (first_index || !encoder.TryMerge(method_index, bss_offset)) {
+          encoder.Reset(method_index, bss_offset);
+          ++number_of_entries;
+          first_index = false;
+        }
+      }
+      DCHECK_NE(number_of_entries, 0u);
+      offset += MethodBssMapping::ComputeSize(number_of_entries);
+    }
+  }
+  // Check that all dex files targeted by method bss entries are in `*dex_files_`.
+  CHECK_EQ(number_of_dex_files, bss_method_entry_references_.size());
+  return offset;
+}
+
+size_t OatWriter::InitOatDexFiles(size_t offset) {
+  // Initialize offsets of oat dex files.
+  for (OatDexFile& oat_dex_file : oat_dex_files_) {
+    oat_dex_file.offset_ = offset;
+    offset += oat_dex_file.SizeOf();
+  }
+  return offset;
+}
+
+size_t OatWriter::InitOatCode(size_t offset) {
+  // calculate the offsets within OatHeader to executable code
+  size_t old_offset = offset;
+  // required to be on a new page boundary
+  offset = RoundUp(offset, kPageSize);
+  oat_header_->SetExecutableOffset(offset);
+  size_executable_offset_alignment_ = offset - old_offset;
+  // TODO: Remove unused trampoline offsets from the OatHeader (requires oat version change).
+  oat_header_->SetInterpreterToInterpreterBridgeOffset(0);
+  oat_header_->SetInterpreterToCompiledCodeBridgeOffset(0);
+  if (compiler_driver_->GetCompilerOptions().IsBootImage()) {
+    InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
+    const bool generate_debug_info = compiler_driver_->GetCompilerOptions().GenerateAnyDebugInfo();
+    size_t adjusted_offset = offset;
+
+    #define DO_TRAMPOLINE(field, fn_name)                                   \
+      offset = CompiledCode::AlignCode(offset, instruction_set);            \
+      adjusted_offset = offset + CompiledCode::CodeDelta(instruction_set);  \
+      oat_header_->Set ## fn_name ## Offset(adjusted_offset);               \
+      (field) = compiler_driver_->Create ## fn_name();                      \
+      if (generate_debug_info) {                                            \
+        debug::MethodDebugInfo info = {};                                   \
+        info.trampoline_name = #fn_name;                                    \
+        info.isa = instruction_set;                                         \
+        info.is_code_address_text_relative = true;                          \
+        /* Use the code offset rather than the `adjusted_offset`. */        \
+        info.code_address = offset - oat_header_->GetExecutableOffset();    \
+        info.code_size = (field)->size();                                   \
+        method_info_.push_back(std::move(info));                            \
+      }                                                                     \
+      offset += (field)->size();
+
+    DO_TRAMPOLINE(jni_dlsym_lookup_, JniDlsymLookup);
+    DO_TRAMPOLINE(quick_generic_jni_trampoline_, QuickGenericJniTrampoline);
+    DO_TRAMPOLINE(quick_imt_conflict_trampoline_, QuickImtConflictTrampoline);
+    DO_TRAMPOLINE(quick_resolution_trampoline_, QuickResolutionTrampoline);
+    DO_TRAMPOLINE(quick_to_interpreter_bridge_, QuickToInterpreterBridge);
+
+    #undef DO_TRAMPOLINE
+  } else {
+    oat_header_->SetJniDlsymLookupOffset(0);
+    oat_header_->SetQuickGenericJniTrampolineOffset(0);
+    oat_header_->SetQuickImtConflictTrampolineOffset(0);
+    oat_header_->SetQuickResolutionTrampolineOffset(0);
+    oat_header_->SetQuickToInterpreterBridgeOffset(0);
+  }
+  return offset;
+}
+
+size_t OatWriter::InitOatCodeDexFiles(size_t offset) {
+  if (!compiler_driver_->GetCompilerOptions().IsAnyCompilationEnabled()) {
+    return offset;
+  }
+  InitCodeMethodVisitor code_visitor(this, offset);
+  bool success = VisitDexMethods(&code_visitor);
+  DCHECK(success);
+  offset = code_visitor.GetOffset();
+
+  if (HasImage()) {
+    InitImageMethodVisitor image_visitor(this, offset, dex_files_);
+    success = VisitDexMethods(&image_visitor);
+    image_visitor.Postprocess();
+    DCHECK(success);
+    offset = image_visitor.GetOffset();
+  }
+
+  return offset;
+}
+
+void OatWriter::InitBssLayout(InstructionSet instruction_set) {
+  {
+    InitBssLayoutMethodVisitor visitor(this);
+    bool success = VisitDexMethods(&visitor);
+    DCHECK(success);
+  }
+
+  DCHECK_EQ(bss_size_, 0u);
+  if (HasBootImage()) {
+    DCHECK(!map_boot_image_tables_to_bss_);
+    DCHECK(bss_string_entries_.empty());
+  }
+  if (!map_boot_image_tables_to_bss_ &&
+      bss_method_entries_.empty() &&
+      bss_type_entries_.empty() &&
+      bss_string_entries_.empty()) {
+    // Nothing to put to the .bss section.
+    return;
+  }
+
+  // Allocate space for boot image tables in the .bss section.
+  PointerSize pointer_size = GetInstructionSetPointerSize(instruction_set);
+  if (map_boot_image_tables_to_bss_) {
+    for (gc::space::ImageSpace* space : Runtime::Current()->GetHeap()->GetBootImageSpaces()) {
+      bss_size_ += space->GetImageHeader().GetBootImageConstantTablesSize();
+    }
+  }
+
+  bss_methods_offset_ = bss_size_;
+
+  // Prepare offsets for .bss ArtMethod entries.
+  for (auto& entry : bss_method_entries_) {
+    DCHECK_EQ(entry.second, 0u);
+    entry.second = bss_size_;
+    bss_size_ += static_cast<size_t>(pointer_size);
+  }
+
+  bss_roots_offset_ = bss_size_;
+
+  // Prepare offsets for .bss Class entries.
+  for (auto& entry : bss_type_entries_) {
+    DCHECK_EQ(entry.second, 0u);
+    entry.second = bss_size_;
+    bss_size_ += sizeof(GcRoot<mirror::Class>);
+  }
+  // Prepare offsets for .bss String entries.
+  for (auto& entry : bss_string_entries_) {
+    DCHECK_EQ(entry.second, 0u);
+    entry.second = bss_size_;
+    bss_size_ += sizeof(GcRoot<mirror::String>);
+  }
+}
+
+bool OatWriter::WriteRodata(OutputStream* out) {
+  CHECK(write_state_ == WriteState::kWriteRoData);
+
+  size_t file_offset = oat_data_offset_;
+  off_t current_offset = out->Seek(0, kSeekCurrent);
+  if (current_offset == static_cast<off_t>(-1)) {
+    PLOG(ERROR) << "Failed to retrieve current position in " << out->GetLocation();
+  }
+  DCHECK_GE(static_cast<size_t>(current_offset), file_offset + oat_header_->GetHeaderSize());
+  size_t relative_offset = current_offset - file_offset;
+
+  // Wrap out to update checksum with each write.
+  ChecksumUpdatingOutputStream checksum_updating_out(out, oat_header_.get());
+  out = &checksum_updating_out;
+
+  relative_offset = WriteClassOffsets(out, file_offset, relative_offset);
+  if (relative_offset == 0) {
+    PLOG(ERROR) << "Failed to write class offsets to " << out->GetLocation();
+    return false;
+  }
+
+  relative_offset = WriteClasses(out, file_offset, relative_offset);
+  if (relative_offset == 0) {
+    PLOG(ERROR) << "Failed to write classes to " << out->GetLocation();
+    return false;
+  }
+
+  relative_offset = WriteMethodBssMappings(out, file_offset, relative_offset);
+  if (relative_offset == 0) {
+    PLOG(ERROR) << "Failed to write method bss mappings to " << out->GetLocation();
+    return false;
+  }
+
+  relative_offset = WriteMaps(out, file_offset, relative_offset);
+  if (relative_offset == 0) {
+    PLOG(ERROR) << "Failed to write oat code to " << out->GetLocation();
+    return false;
+  }
+
+  relative_offset = WriteOatDexFiles(out, file_offset, relative_offset);
+  if (relative_offset == 0) {
+    PLOG(ERROR) << "Failed to write oat dex information to " << out->GetLocation();
+    return false;
+  }
+
+  // Write padding.
+  off_t new_offset = out->Seek(size_executable_offset_alignment_, kSeekCurrent);
+  relative_offset += size_executable_offset_alignment_;
+  DCHECK_EQ(relative_offset, oat_header_->GetExecutableOffset());
+  size_t expected_file_offset = file_offset + relative_offset;
+  if (static_cast<uint32_t>(new_offset) != expected_file_offset) {
+    PLOG(ERROR) << "Failed to seek to oat code section. Actual: " << new_offset
+                << " Expected: " << expected_file_offset << " File: " << out->GetLocation();
+    return 0;
+  }
+  DCHECK_OFFSET();
+
+  write_state_ = WriteState::kWriteText;
+  return true;
+}
+
+class OatWriter::WriteQuickeningInfoMethodVisitor : public DexMethodVisitor {
+ public:
+  WriteQuickeningInfoMethodVisitor(OatWriter* writer,
+                                   OutputStream* out,
+                                   uint32_t offset,
+                                   SafeMap<const uint8_t*, uint32_t>* offset_map)
+      : DexMethodVisitor(writer, offset),
+        out_(out),
+        written_bytes_(0u),
+        offset_map_(offset_map) {}
+
+  bool VisitMethod(size_t class_def_method_index ATTRIBUTE_UNUSED, const ClassDataItemIterator& it)
+      OVERRIDE {
+    uint32_t method_idx = it.GetMemberIndex();
+    CompiledMethod* compiled_method =
+        writer_->compiler_driver_->GetCompiledMethod(MethodReference(dex_file_, method_idx));
+
+    if (HasQuickeningInfo(compiled_method)) {
+      ArrayRef<const uint8_t> map = compiled_method->GetVmapTable();
+      // Deduplication is already done on a pointer basis by the compiler driver,
+      // so we can simply compare the pointers to find out if things are duplicated.
+      if (offset_map_->find(map.data()) == offset_map_->end()) {
+        uint32_t length = map.size() * sizeof(map.front());
+        offset_map_->Put(map.data(), written_bytes_);
+        if (!out_->WriteFully(&length, sizeof(length)) ||
+            !out_->WriteFully(map.data(), length)) {
+          PLOG(ERROR) << "Failed to write quickening info for "
+                      << dex_file_->PrettyMethod(it.GetMemberIndex()) << " to "
+                      << out_->GetLocation();
+          return false;
+        }
+        written_bytes_ += sizeof(length) + length;
+        offset_ += sizeof(length) + length;
+      }
+    }
+
+    return true;
+  }
+
+  size_t GetNumberOfWrittenBytes() const {
+    return written_bytes_;
+  }
+
+ private:
+  OutputStream* const out_;
+  size_t written_bytes_;
+  // Maps quickening map to its offset in the file.
+  SafeMap<const uint8_t*, uint32_t>* offset_map_;
+};
+
+class OatWriter::WriteQuickeningIndicesMethodVisitor {
+ public:
+  WriteQuickeningIndicesMethodVisitor(OutputStream* out,
+                                      uint32_t indices_offset,
+                                      const SafeMap<const uint8_t*, uint32_t>& offset_map,
+                                      std::vector<uint32_t>* dex_files_offset)
+      : out_(out),
+        indices_offset_(indices_offset),
+        written_bytes_(0u),
+        dex_files_offset_(dex_files_offset),
+        offset_map_(offset_map) {}
+
+  bool VisitDexMethods(const std::vector<const DexFile*>& dex_files, const CompilerDriver& driver) {
+    for (const DexFile* dex_file : dex_files) {
+      // Record the offset for this current dex file. It will be written in the vdex file
+      // later.
+      dex_files_offset_->push_back(indices_offset_ + GetNumberOfWrittenBytes());
+      const size_t class_def_count = dex_file->NumClassDefs();
+      for (size_t class_def_index = 0; class_def_index != class_def_count; ++class_def_index) {
+        const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
+        const uint8_t* class_data = dex_file->GetClassData(class_def);
+        if (class_data == nullptr) {
+          continue;
+        }
+        for (ClassDataItemIterator class_it(*dex_file, class_data);
+             class_it.HasNext();
+             class_it.Next()) {
+          if (!class_it.IsAtMethod()) {
+            continue;
+          }
+          uint32_t method_idx = class_it.GetMemberIndex();
+          CompiledMethod* compiled_method =
+              driver.GetCompiledMethod(MethodReference(dex_file, method_idx));
+          if (HasQuickeningInfo(compiled_method)) {
+            uint32_t code_item_offset = class_it.GetMethodCodeItemOffset();
+            uint32_t offset = offset_map_.Get(compiled_method->GetVmapTable().data());
+            if (!out_->WriteFully(&code_item_offset, sizeof(code_item_offset)) ||
+                !out_->WriteFully(&offset, sizeof(offset))) {
+              PLOG(ERROR) << "Failed to write quickening info for "
+                          << dex_file->PrettyMethod(method_idx) << " to "
+                          << out_->GetLocation();
+              return false;
+            }
+            written_bytes_ += sizeof(code_item_offset) + sizeof(offset);
+          }
+        }
+      }
+    }
+    return true;
+  }
+
+  size_t GetNumberOfWrittenBytes() const {
+    return written_bytes_;
+  }
+
+ private:
+  OutputStream* const out_;
+  const uint32_t indices_offset_;
+  size_t written_bytes_;
+  std::vector<uint32_t>* dex_files_offset_;
+  // Maps quickening map to its offset in the file.
+  const SafeMap<const uint8_t*, uint32_t>& offset_map_;
+};
+
+bool OatWriter::WriteQuickeningInfo(OutputStream* vdex_out) {
+  if (!kIsVdexEnabled) {
+    return true;
+  }
+
+  size_t initial_offset = vdex_size_;
+  size_t start_offset = RoundUp(initial_offset, 4u);
+
+  vdex_size_ = start_offset;
+  vdex_quickening_info_offset_ = vdex_size_;
+  size_quickening_info_alignment_ = start_offset - initial_offset;
+
+  off_t actual_offset = vdex_out->Seek(start_offset, kSeekSet);
+  if (actual_offset != static_cast<off_t>(start_offset)) {
+    PLOG(ERROR) << "Failed to seek to quickening info section. Actual: " << actual_offset
+                << " Expected: " << start_offset
+                << " Output: " << vdex_out->GetLocation();
+    return false;
+  }
+
+  if (compiler_driver_->GetCompilerOptions().IsAnyCompilationEnabled()) {
+    std::vector<uint32_t> dex_files_indices;
+    SafeMap<const uint8_t*, uint32_t> offset_map;
+    WriteQuickeningInfoMethodVisitor visitor1(this, vdex_out, start_offset, &offset_map);
+    if (!VisitDexMethods(&visitor1)) {
+      PLOG(ERROR) << "Failed to write the vdex quickening info. File: " << vdex_out->GetLocation();
+      return false;
+    }
+
+    WriteQuickeningIndicesMethodVisitor visitor2(vdex_out,
+                                                 visitor1.GetNumberOfWrittenBytes(),
+                                                 offset_map,
+                                                 &dex_files_indices);
+    if (!visitor2.VisitDexMethods(*dex_files_, *compiler_driver_)) {
+      PLOG(ERROR) << "Failed to write the vdex quickening info. File: " << vdex_out->GetLocation();
+      return false;
+    }
+
+    DCHECK_EQ(dex_files_->size(), dex_files_indices.size());
+    if (!vdex_out->WriteFully(
+            dex_files_indices.data(), sizeof(dex_files_indices[0]) * dex_files_indices.size())) {
+      PLOG(ERROR) << "Failed to write the vdex quickening info. File: " << vdex_out->GetLocation();
+      return false;
+    }
+
+    if (!vdex_out->Flush()) {
+      PLOG(ERROR) << "Failed to flush stream after writing quickening info."
+                  << " File: " << vdex_out->GetLocation();
+      return false;
+    }
+    size_quickening_info_ = visitor1.GetNumberOfWrittenBytes() +
+                            visitor2.GetNumberOfWrittenBytes() +
+                            dex_files_->size() * sizeof(uint32_t);
+  } else {
+    // We know we did not quicken.
+    size_quickening_info_ = 0;
+  }
+
+  vdex_size_ += size_quickening_info_;
+  return true;
+}
+
+bool OatWriter::WriteVerifierDeps(OutputStream* vdex_out, verifier::VerifierDeps* verifier_deps) {
+  if (!kIsVdexEnabled) {
+    return true;
+  }
+
+  if (verifier_deps == nullptr) {
+    // Nothing to write. Record the offset, but no need
+    // for alignment.
+    vdex_verifier_deps_offset_ = vdex_size_;
+    return true;
+  }
+
+  size_t initial_offset = vdex_size_;
+  size_t start_offset = RoundUp(initial_offset, 4u);
+
+  vdex_size_ = start_offset;
+  vdex_verifier_deps_offset_ = vdex_size_;
+  size_verifier_deps_alignment_ = start_offset - initial_offset;
+
+  off_t actual_offset = vdex_out->Seek(start_offset, kSeekSet);
+  if (actual_offset != static_cast<off_t>(start_offset)) {
+    PLOG(ERROR) << "Failed to seek to verifier deps section. Actual: " << actual_offset
+                << " Expected: " << start_offset
+                << " Output: " << vdex_out->GetLocation();
+    return false;
+  }
+
+  std::vector<uint8_t> buffer;
+  verifier_deps->Encode(*dex_files_, &buffer);
+
+  if (!vdex_out->WriteFully(buffer.data(), buffer.size())) {
+    PLOG(ERROR) << "Failed to write verifier deps."
+                << " File: " << vdex_out->GetLocation();
+    return false;
+  }
+  if (!vdex_out->Flush()) {
+    PLOG(ERROR) << "Failed to flush stream after writing verifier deps."
+                << " File: " << vdex_out->GetLocation();
+    return false;
+  }
+
+  size_verifier_deps_ = buffer.size();
+  vdex_size_ += size_verifier_deps_;
+  return true;
+}
+
+bool OatWriter::WriteCode(OutputStream* out) {
+  CHECK(write_state_ == WriteState::kWriteText);
+
+  // Wrap out to update checksum with each write.
+  ChecksumUpdatingOutputStream checksum_updating_out(out, oat_header_.get());
+  out = &checksum_updating_out;
+
+  SetMultiOatRelativePatcherAdjustment();
+
+  const size_t file_offset = oat_data_offset_;
+  size_t relative_offset = oat_header_->GetExecutableOffset();
+  DCHECK_OFFSET();
+
+  relative_offset = WriteCode(out, file_offset, relative_offset);
+  if (relative_offset == 0) {
+    LOG(ERROR) << "Failed to write oat code to " << out->GetLocation();
+    return false;
+  }
+
+  relative_offset = WriteCodeDexFiles(out, file_offset, relative_offset);
+  if (relative_offset == 0) {
+    LOG(ERROR) << "Failed to write oat code for dex files to " << out->GetLocation();
+    return false;
+  }
+
+  const off_t oat_end_file_offset = out->Seek(0, kSeekCurrent);
+  if (oat_end_file_offset == static_cast<off_t>(-1)) {
+    LOG(ERROR) << "Failed to get oat end file offset in " << out->GetLocation();
+    return false;
+  }
+
+  if (kIsDebugBuild) {
+    uint32_t size_total = 0;
+    #define DO_STAT(x) \
+      VLOG(compiler) << #x "=" << PrettySize(x) << " (" << (x) << "B)"; \
+      size_total += (x);
+
+    DO_STAT(size_vdex_header_);
+    DO_STAT(size_vdex_checksums_);
+    DO_STAT(size_dex_file_alignment_);
+    DO_STAT(size_executable_offset_alignment_);
+    DO_STAT(size_oat_header_);
+    DO_STAT(size_oat_header_key_value_store_);
+    DO_STAT(size_dex_file_);
+    DO_STAT(size_verifier_deps_);
+    DO_STAT(size_verifier_deps_alignment_);
+    DO_STAT(size_quickening_info_);
+    DO_STAT(size_quickening_info_alignment_);
+    DO_STAT(size_interpreter_to_interpreter_bridge_);
+    DO_STAT(size_interpreter_to_compiled_code_bridge_);
+    DO_STAT(size_jni_dlsym_lookup_);
+    DO_STAT(size_quick_generic_jni_trampoline_);
+    DO_STAT(size_quick_imt_conflict_trampoline_);
+    DO_STAT(size_quick_resolution_trampoline_);
+    DO_STAT(size_quick_to_interpreter_bridge_);
+    DO_STAT(size_trampoline_alignment_);
+    DO_STAT(size_method_header_);
+    DO_STAT(size_code_);
+    DO_STAT(size_code_alignment_);
+    DO_STAT(size_relative_call_thunks_);
+    DO_STAT(size_misc_thunks_);
+    DO_STAT(size_vmap_table_);
+    DO_STAT(size_method_info_);
+    DO_STAT(size_oat_dex_file_location_size_);
+    DO_STAT(size_oat_dex_file_location_data_);
+    DO_STAT(size_oat_dex_file_location_checksum_);
+    DO_STAT(size_oat_dex_file_offset_);
+    DO_STAT(size_oat_dex_file_class_offsets_offset_);
+    DO_STAT(size_oat_dex_file_lookup_table_offset_);
+    DO_STAT(size_oat_dex_file_dex_layout_sections_offset_);
+    DO_STAT(size_oat_dex_file_dex_layout_sections_);
+    DO_STAT(size_oat_dex_file_dex_layout_sections_alignment_);
+    DO_STAT(size_oat_dex_file_method_bss_mapping_offset_);
+    DO_STAT(size_oat_lookup_table_alignment_);
+    DO_STAT(size_oat_lookup_table_);
+    DO_STAT(size_oat_class_offsets_alignment_);
+    DO_STAT(size_oat_class_offsets_);
+    DO_STAT(size_oat_class_type_);
+    DO_STAT(size_oat_class_status_);
+    DO_STAT(size_oat_class_method_bitmaps_);
+    DO_STAT(size_oat_class_method_offsets_);
+    DO_STAT(size_method_bss_mappings_);
+    #undef DO_STAT
+
+    VLOG(compiler) << "size_total=" << PrettySize(size_total) << " (" << size_total << "B)";
+
+    CHECK_EQ(vdex_size_ + oat_size_, size_total);
+    CHECK_EQ(file_offset + size_total - vdex_size_, static_cast<size_t>(oat_end_file_offset));
+  }
+
+  CHECK_EQ(file_offset + oat_size_, static_cast<size_t>(oat_end_file_offset));
+  CHECK_EQ(oat_size_, relative_offset);
+
+  write_state_ = WriteState::kWriteHeader;
+  return true;
+}
+
+bool OatWriter::WriteHeader(OutputStream* out,
+                            uint32_t image_file_location_oat_checksum,
+                            uintptr_t image_file_location_oat_begin,
+                            int32_t image_patch_delta) {
+  CHECK(write_state_ == WriteState::kWriteHeader);
+
+  oat_header_->SetImageFileLocationOatChecksum(image_file_location_oat_checksum);
+  oat_header_->SetImageFileLocationOatDataBegin(image_file_location_oat_begin);
+  if (compiler_driver_->GetCompilerOptions().IsBootImage()) {
+    CHECK_EQ(image_patch_delta, 0);
+    CHECK_EQ(oat_header_->GetImagePatchDelta(), 0);
+  } else {
+    CHECK_ALIGNED(image_patch_delta, kPageSize);
+    oat_header_->SetImagePatchDelta(image_patch_delta);
+  }
+  oat_header_->UpdateChecksumWithHeaderData();
+
+  const size_t file_offset = oat_data_offset_;
+
+  off_t current_offset = out->Seek(0, kSeekCurrent);
+  if (current_offset == static_cast<off_t>(-1)) {
+    PLOG(ERROR) << "Failed to get current offset from " << out->GetLocation();
+    return false;
+  }
+  if (out->Seek(file_offset, kSeekSet) == static_cast<off_t>(-1)) {
+    PLOG(ERROR) << "Failed to seek to oat header position in " << out->GetLocation();
+    return false;
+  }
+  DCHECK_EQ(file_offset, static_cast<size_t>(out->Seek(0, kSeekCurrent)));
+
+  // Flush all other data before writing the header.
+  if (!out->Flush()) {
+    PLOG(ERROR) << "Failed to flush before writing oat header to " << out->GetLocation();
+    return false;
+  }
+  // Write the header.
+  size_t header_size = oat_header_->GetHeaderSize();
+  if (!out->WriteFully(oat_header_.get(), header_size)) {
+    PLOG(ERROR) << "Failed to write oat header to " << out->GetLocation();
+    return false;
+  }
+  // Flush the header data.
+  if (!out->Flush()) {
+    PLOG(ERROR) << "Failed to flush after writing oat header to " << out->GetLocation();
+    return false;
+  }
+
+  if (out->Seek(current_offset, kSeekSet) == static_cast<off_t>(-1)) {
+    PLOG(ERROR) << "Failed to seek back after writing oat header to " << out->GetLocation();
+    return false;
+  }
+  DCHECK_EQ(current_offset, out->Seek(0, kSeekCurrent));
+
+  write_state_ = WriteState::kDone;
+  return true;
+}
+
+size_t OatWriter::WriteClassOffsets(OutputStream* out, size_t file_offset, size_t relative_offset) {
+  for (OatDexFile& oat_dex_file : oat_dex_files_) {
+    if (oat_dex_file.class_offsets_offset_ != 0u) {
+      // Class offsets are required to be 4 byte aligned.
+      if (UNLIKELY(!IsAligned<4u>(relative_offset))) {
+        size_t padding_size =  RoundUp(relative_offset, 4u) - relative_offset;
+        if (!WriteUpTo16BytesAlignment(out, padding_size, &size_oat_class_offsets_alignment_)) {
+          return 0u;
+        }
+        relative_offset += padding_size;
+      }
+      DCHECK_OFFSET();
+      if (!oat_dex_file.WriteClassOffsets(this, out)) {
+        return 0u;
+      }
+      relative_offset += oat_dex_file.GetClassOffsetsRawSize();
+    }
+  }
+  return relative_offset;
+}
+
+size_t OatWriter::WriteClasses(OutputStream* out, size_t file_offset, size_t relative_offset) {
+  const bool may_have_compiled = MayHaveCompiledMethods();
+  if (may_have_compiled) {
+    CHECK_EQ(oat_class_headers_.size(), oat_classes_.size());
+  }
+  for (size_t i = 0; i < oat_class_headers_.size(); ++i) {
+    // If there are any classes, the class offsets allocation aligns the offset.
+    DCHECK_ALIGNED(relative_offset, 4u);
+    DCHECK_OFFSET();
+    if (!oat_class_headers_[i].Write(this, out, oat_data_offset_)) {
+      return 0u;
+    }
+    relative_offset += oat_class_headers_[i].SizeOf();
+    if (may_have_compiled) {
+      if (!oat_classes_[i].Write(this, out)) {
+        return 0u;
+      }
+      relative_offset += oat_classes_[i].SizeOf();
+    }
+  }
+  return relative_offset;
+}
+
+size_t OatWriter::WriteMaps(OutputStream* out, size_t file_offset, size_t relative_offset) {
+  {
+    size_t vmap_tables_offset = relative_offset;
+    WriteMapMethodVisitor visitor(this, out, file_offset, relative_offset);
+    if (UNLIKELY(!VisitDexMethods(&visitor))) {
+      return 0;
+    }
+    relative_offset = visitor.GetOffset();
+    size_vmap_table_ = relative_offset - vmap_tables_offset;
+  }
+  {
+    size_t method_infos_offset = relative_offset;
+    WriteMethodInfoVisitor visitor(this, out, file_offset, relative_offset);
+    if (UNLIKELY(!VisitDexMethods(&visitor))) {
+      return 0;
+    }
+    relative_offset = visitor.GetOffset();
+    size_method_info_ = relative_offset - method_infos_offset;
+  }
+
+  return relative_offset;
+}
+
+size_t OatWriter::WriteMethodBssMappings(OutputStream* out,
+                                         size_t file_offset,
+                                         size_t relative_offset) {
+  TimingLogger::ScopedTiming split("WriteMethodBssMappings", timings_);
+
+  for (size_t i = 0, size = dex_files_->size(); i != size; ++i) {
+    const DexFile* dex_file = (*dex_files_)[i];
+    OatDexFile* oat_dex_file = &oat_dex_files_[i];
+    auto it = bss_method_entry_references_.find(dex_file);
+    if (it != bss_method_entry_references_.end()) {
+      const BitVector& method_indexes = it->second;
+      // If there are any classes, the class offsets allocation aligns the offset
+      // and we cannot have method bss mappings without class offsets.
+      static_assert(alignof(MethodBssMapping) == sizeof(uint32_t),
+                    "MethodBssMapping alignment check.");
+      DCHECK_ALIGNED(relative_offset, sizeof(uint32_t));
+
+      linker::MethodBssMappingEncoder encoder(
+          GetInstructionSetPointerSize(oat_header_->GetInstructionSet()));
+      // Allocate a sufficiently large MethodBssMapping.
+      size_t number_of_method_indexes = method_indexes.NumSetBits();
+      DCHECK_NE(number_of_method_indexes, 0u);
+      size_t max_mappings_size = MethodBssMapping::ComputeSize(number_of_method_indexes);
+      DCHECK_ALIGNED(max_mappings_size, sizeof(uint32_t));
+      std::unique_ptr<uint32_t[]> storage(new uint32_t[max_mappings_size / sizeof(uint32_t)]);
+      MethodBssMapping* mappings = new(storage.get()) MethodBssMapping(number_of_method_indexes);
+      mappings->ClearPadding();
+      // Encode the MethodBssMapping.
+      auto init_it = mappings->begin();
+      bool first_index = true;
+      for (uint32_t method_index : method_indexes.Indexes()) {
+        size_t bss_offset = bss_method_entries_.Get(MethodReference(dex_file, method_index));
+        if (first_index) {
+          first_index = false;
+          encoder.Reset(method_index, bss_offset);
+        } else if (!encoder.TryMerge(method_index, bss_offset)) {
+          *init_it = encoder.GetEntry();
+          ++init_it;
+          encoder.Reset(method_index, bss_offset);
+        }
+      }
+      // Store the last entry and shrink the mapping to the actual size.
+      *init_it = encoder.GetEntry();
+      ++init_it;
+      DCHECK(init_it <= mappings->end());
+      mappings->SetSize(std::distance(mappings->begin(), init_it));
+      size_t mappings_size = MethodBssMapping::ComputeSize(mappings->size());
+
+      DCHECK_EQ(relative_offset, oat_dex_file->method_bss_mapping_offset_);
+      DCHECK_OFFSET();
+      if (!out->WriteFully(storage.get(), mappings_size)) {
+        return 0u;
+      }
+      size_method_bss_mappings_ += mappings_size;
+      relative_offset += mappings_size;
+    } else {
+      DCHECK_EQ(0u, oat_dex_file->method_bss_mapping_offset_);
+    }
+  }
+  return relative_offset;
+}
+
+size_t OatWriter::WriteOatDexFiles(OutputStream* out, size_t file_offset, size_t relative_offset) {
+  TimingLogger::ScopedTiming split("WriteOatDexFiles", timings_);
+
+  for (size_t i = 0, size = oat_dex_files_.size(); i != size; ++i) {
+    OatDexFile* oat_dex_file = &oat_dex_files_[i];
+    DCHECK_EQ(relative_offset, oat_dex_file->offset_);
+    DCHECK_OFFSET();
+
+    // Write OatDexFile.
+    if (!oat_dex_file->Write(this, out)) {
+      return 0u;
+    }
+    relative_offset += oat_dex_file->SizeOf();
+  }
+
+  return relative_offset;
+}
+
+size_t OatWriter::WriteCode(OutputStream* out, size_t file_offset, size_t relative_offset) {
+  if (compiler_driver_->GetCompilerOptions().IsBootImage()) {
+    InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
+
+    #define DO_TRAMPOLINE(field) \
+      do { \
+        uint32_t aligned_offset = CompiledCode::AlignCode(relative_offset, instruction_set); \
+        uint32_t alignment_padding = aligned_offset - relative_offset; \
+        out->Seek(alignment_padding, kSeekCurrent); \
+        size_trampoline_alignment_ += alignment_padding; \
+        if (!out->WriteFully((field)->data(), (field)->size())) { \
+          PLOG(ERROR) << "Failed to write " # field " to " << out->GetLocation(); \
+          return false; \
+        } \
+        size_ ## field += (field)->size(); \
+        relative_offset += alignment_padding + (field)->size(); \
+        DCHECK_OFFSET(); \
+      } while (false)
+
+    DO_TRAMPOLINE(jni_dlsym_lookup_);
+    DO_TRAMPOLINE(quick_generic_jni_trampoline_);
+    DO_TRAMPOLINE(quick_imt_conflict_trampoline_);
+    DO_TRAMPOLINE(quick_resolution_trampoline_);
+    DO_TRAMPOLINE(quick_to_interpreter_bridge_);
+    #undef DO_TRAMPOLINE
+  }
+  return relative_offset;
+}
+
+size_t OatWriter::WriteCodeDexFiles(OutputStream* out,
+                                    size_t file_offset,
+                                    size_t relative_offset) {
+  #define VISIT(VisitorType)                                              \
+    do {                                                                  \
+      VisitorType visitor(this, out, file_offset, relative_offset);       \
+      if (UNLIKELY(!VisitDexMethods(&visitor))) {                         \
+        return 0;                                                         \
+      }                                                                   \
+      relative_offset = visitor.GetOffset();                              \
+    } while (false)
+
+  VISIT(WriteCodeMethodVisitor);
+
+  #undef VISIT
+
+  size_code_alignment_ += relative_patcher_->CodeAlignmentSize();
+  size_relative_call_thunks_ += relative_patcher_->RelativeCallThunksSize();
+  size_misc_thunks_ += relative_patcher_->MiscThunksSize();
+
+  return relative_offset;
+}
+
+bool OatWriter::RecordOatDataOffset(OutputStream* out) {
+  // Get the elf file offset of the oat file.
+  const off_t raw_file_offset = out->Seek(0, kSeekCurrent);
+  if (raw_file_offset == static_cast<off_t>(-1)) {
+    LOG(ERROR) << "Failed to get file offset in " << out->GetLocation();
+    return false;
+  }
+  oat_data_offset_ = static_cast<size_t>(raw_file_offset);
+  return true;
+}
+
+bool OatWriter::ReadDexFileHeader(File* file, OatDexFile* oat_dex_file) {
+  // Read the dex file header and perform minimal verification.
+  uint8_t raw_header[sizeof(DexFile::Header)];
+  if (!file->ReadFully(&raw_header, sizeof(DexFile::Header))) {
+    PLOG(ERROR) << "Failed to read dex file header. Actual: "
+                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
+    return false;
+  }
+  if (!ValidateDexFileHeader(raw_header, oat_dex_file->GetLocation())) {
+    return false;
+  }
+
+  const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(raw_header);
+  oat_dex_file->dex_file_size_ = header->file_size_;
+  oat_dex_file->dex_file_location_checksum_ = header->checksum_;
+  oat_dex_file->class_offsets_.resize(header->class_defs_size_);
+  return true;
+}
+
+bool OatWriter::ValidateDexFileHeader(const uint8_t* raw_header, const char* location) {
+  if (!DexFile::IsMagicValid(raw_header)) {
+    LOG(ERROR) << "Invalid magic number in dex file header. " << " File: " << location;
+    return false;
+  }
+  if (!DexFile::IsVersionValid(raw_header)) {
+    LOG(ERROR) << "Invalid version number in dex file header. " << " File: " << location;
+    return false;
+  }
+  const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(raw_header);
+  if (header->file_size_ < sizeof(DexFile::Header)) {
+    LOG(ERROR) << "Dex file header specifies file size insufficient to contain the header."
+               << " File: " << location;
+    return false;
+  }
+  return true;
+}
+
+bool OatWriter::WriteDexFiles(OutputStream* out, File* file, bool update_input_vdex) {
+  TimingLogger::ScopedTiming split("Write Dex files", timings_);
+
+  vdex_dex_files_offset_ = vdex_size_;
+
+  // Write dex files.
+  for (OatDexFile& oat_dex_file : oat_dex_files_) {
+    if (!WriteDexFile(out, file, &oat_dex_file, update_input_vdex)) {
+      return false;
+    }
+  }
+
+  CloseSources();
+  return true;
+}
+
+void OatWriter::CloseSources() {
+  for (OatDexFile& oat_dex_file : oat_dex_files_) {
+    oat_dex_file.source_.Clear();  // Get rid of the reference, it's about to be invalidated.
+  }
+  zipped_dex_files_.clear();
+  zip_archives_.clear();
+  raw_dex_files_.clear();
+}
+
+bool OatWriter::WriteDexFile(OutputStream* out,
+                             File* file,
+                             OatDexFile* oat_dex_file,
+                             bool update_input_vdex) {
+  if (!SeekToDexFile(out, file, oat_dex_file)) {
+    return false;
+  }
+  if (profile_compilation_info_ != nullptr) {
+    CHECK(!update_input_vdex) << "We should never update the input vdex when doing dexlayout";
+    if (!LayoutAndWriteDexFile(out, oat_dex_file)) {
+      return false;
+    }
+  } else if (oat_dex_file->source_.IsZipEntry()) {
+    DCHECK(!update_input_vdex);
+    if (!WriteDexFile(out, file, oat_dex_file, oat_dex_file->source_.GetZipEntry())) {
+      return false;
+    }
+  } else if (oat_dex_file->source_.IsRawFile()) {
+    DCHECK(!update_input_vdex);
+    if (!WriteDexFile(out, file, oat_dex_file, oat_dex_file->source_.GetRawFile())) {
+      return false;
+    }
+  } else {
+    DCHECK(oat_dex_file->source_.IsRawData());
+    if (!WriteDexFile(out, oat_dex_file, oat_dex_file->source_.GetRawData(), update_input_vdex)) {
+      return false;
+    }
+  }
+
+  // Update current size and account for the written data.
+  if (kIsVdexEnabled) {
+    DCHECK_EQ(vdex_size_, oat_dex_file->dex_file_offset_);
+    vdex_size_ += oat_dex_file->dex_file_size_;
+  } else {
+    DCHECK(!update_input_vdex);
+    DCHECK_EQ(oat_size_, oat_dex_file->dex_file_offset_);
+    oat_size_ += oat_dex_file->dex_file_size_;
+  }
+  size_dex_file_ += oat_dex_file->dex_file_size_;
+  return true;
+}
+
+bool OatWriter::SeekToDexFile(OutputStream* out, File* file, OatDexFile* oat_dex_file) {
+  // Dex files are required to be 4 byte aligned.
+  size_t initial_offset = kIsVdexEnabled ? vdex_size_ : oat_size_;
+  size_t start_offset = RoundUp(initial_offset, 4);
+  size_t file_offset = kIsVdexEnabled ? start_offset : (oat_data_offset_ + start_offset);
+  size_dex_file_alignment_ += start_offset - initial_offset;
+
+  // Seek to the start of the dex file and flush any pending operations in the stream.
+  // Verify that, after flushing the stream, the file is at the same offset as the stream.
+  off_t actual_offset = out->Seek(file_offset, kSeekSet);
+  if (actual_offset != static_cast<off_t>(file_offset)) {
+    PLOG(ERROR) << "Failed to seek to dex file section. Actual: " << actual_offset
+                << " Expected: " << file_offset
+                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
+    return false;
+  }
+  if (!out->Flush()) {
+    PLOG(ERROR) << "Failed to flush before writing dex file."
+                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
+    return false;
+  }
+  actual_offset = lseek(file->Fd(), 0, SEEK_CUR);
+  if (actual_offset != static_cast<off_t>(file_offset)) {
+    PLOG(ERROR) << "Stream/file position mismatch! Actual: " << actual_offset
+                << " Expected: " << file_offset
+                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
+    return false;
+  }
+
+  if (kIsVdexEnabled) {
+    vdex_size_ = start_offset;
+  } else {
+    oat_size_ = start_offset;
+  }
+  oat_dex_file->dex_file_offset_ = start_offset;
+  return true;
+}
+
+bool OatWriter::LayoutAndWriteDexFile(OutputStream* out, OatDexFile* oat_dex_file) {
+  TimingLogger::ScopedTiming split("Dex Layout", timings_);
+  std::string error_msg;
+  std::string location(oat_dex_file->GetLocation());
+  std::unique_ptr<const DexFile> dex_file;
+  if (oat_dex_file->source_.IsZipEntry()) {
+    ZipEntry* zip_entry = oat_dex_file->source_.GetZipEntry();
+    std::unique_ptr<MemMap> mem_map(
+        zip_entry->ExtractToMemMap(location.c_str(), "classes.dex", &error_msg));
+    if (mem_map == nullptr) {
+      LOG(ERROR) << "Failed to extract dex file to mem map for layout: " << error_msg;
+      return false;
+    }
+    dex_file = DexFile::Open(location,
+                             zip_entry->GetCrc32(),
+                             std::move(mem_map),
+                             /* verify */ true,
+                             /* verify_checksum */ true,
+                             &error_msg);
+  } else if (oat_dex_file->source_.IsRawFile()) {
+    File* raw_file = oat_dex_file->source_.GetRawFile();
+    int dup_fd = dup(raw_file->Fd());
+    if (dup_fd < 0) {
+      PLOG(ERROR) << "Failed to dup dex file descriptor (" << raw_file->Fd() << ") at " << location;
+      return false;
+    }
+    dex_file = DexFile::OpenDex(dup_fd, location, /* verify_checksum */ true, &error_msg);
+  } else {
+    // The source data is a vdex file.
+    CHECK(oat_dex_file->source_.IsRawData())
+        << static_cast<size_t>(oat_dex_file->source_.GetType());
+    const uint8_t* raw_dex_file = oat_dex_file->source_.GetRawData();
+    // Note: The raw data has already been checked to contain the header
+    // and all the data that the header specifies as the file size.
+    DCHECK(raw_dex_file != nullptr);
+    DCHECK(ValidateDexFileHeader(raw_dex_file, oat_dex_file->GetLocation()));
+    const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(raw_dex_file);
+    // Since the source may have had its layout changed, or may be quickened, don't verify it.
+    dex_file = DexFile::Open(raw_dex_file,
+                             header->file_size_,
+                             location,
+                             oat_dex_file->dex_file_location_checksum_,
+                             nullptr,
+                             /* verify */ false,
+                             /* verify_checksum */ false,
+                             &error_msg);
+  }
+  if (dex_file == nullptr) {
+    LOG(ERROR) << "Failed to open dex file for layout: " << error_msg;
+    return false;
+  }
+  Options options;
+  options.output_to_memmap_ = true;
+  DexLayout dex_layout(options, profile_compilation_info_, nullptr);
+  dex_layout.ProcessDexFile(location.c_str(), dex_file.get(), 0);
+  std::unique_ptr<MemMap> mem_map(dex_layout.GetAndReleaseMemMap());
+  if (!WriteDexFile(out, oat_dex_file, mem_map->Begin(), /* update_input_vdex */ false)) {
+    return false;
+  }
+  oat_dex_file->dex_sections_layout_ = dex_layout.GetSections();
+  // Set the checksum of the new oat dex file to be the original file's checksum.
+  oat_dex_file->dex_file_location_checksum_ = dex_file->GetLocationChecksum();
+  return true;
+}
+
+bool OatWriter::WriteDexFile(OutputStream* out,
+                             File* file,
+                             OatDexFile* oat_dex_file,
+                             ZipEntry* dex_file) {
+  size_t start_offset = kIsVdexEnabled ? vdex_size_ : oat_data_offset_ + oat_size_;
+  DCHECK_EQ(static_cast<off_t>(start_offset), out->Seek(0, kSeekCurrent));
+
+  // Extract the dex file and get the extracted size.
+  std::string error_msg;
+  if (!dex_file->ExtractToFile(*file, &error_msg)) {
+    LOG(ERROR) << "Failed to extract dex file from ZIP entry: " << error_msg
+               << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
+    return false;
+  }
+  if (file->Flush() != 0) {
+    PLOG(ERROR) << "Failed to flush dex file from ZIP entry."
+                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
+    return false;
+  }
+  off_t extracted_end = lseek(file->Fd(), 0, SEEK_CUR);
+  if (extracted_end == static_cast<off_t>(-1)) {
+    PLOG(ERROR) << "Failed get end offset after writing dex file from ZIP entry."
+                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
+    return false;
+  }
+  if (extracted_end < static_cast<off_t>(start_offset)) {
+    LOG(ERROR) << "Dex file end position is before start position! End: " << extracted_end
+               << " Start: " << start_offset
+               << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
+    return false;
+  }
+  uint64_t extracted_size = static_cast<uint64_t>(extracted_end - start_offset);
+  if (extracted_size < sizeof(DexFile::Header)) {
+    LOG(ERROR) << "Extracted dex file is shorter than dex file header. size: "
+               << extracted_size << " File: " << oat_dex_file->GetLocation();
+    return false;
+  }
+
+  // Read the dex file header and extract required data to OatDexFile.
+  off_t actual_offset = lseek(file->Fd(), start_offset, SEEK_SET);
+  if (actual_offset != static_cast<off_t>(start_offset)) {
+    PLOG(ERROR) << "Failed to seek back to dex file header. Actual: " << actual_offset
+                << " Expected: " << start_offset
+                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
+    return false;
+  }
+  if (!ReadDexFileHeader(file, oat_dex_file)) {
+    return false;
+  }
+  if (extracted_size < oat_dex_file->dex_file_size_) {
+    LOG(ERROR) << "Extracted truncated dex file. Extracted size: " << extracted_size
+               << " file size from header: " << oat_dex_file->dex_file_size_
+               << " File: " << oat_dex_file->GetLocation();
+    return false;
+  }
+
+  // Override the checksum from header with the CRC from ZIP entry.
+  oat_dex_file->dex_file_location_checksum_ = dex_file->GetCrc32();
+
+  // Seek both file and stream to the end offset.
+  size_t end_offset = start_offset + oat_dex_file->dex_file_size_;
+  actual_offset = lseek(file->Fd(), end_offset, SEEK_SET);
+  if (actual_offset != static_cast<off_t>(end_offset)) {
+    PLOG(ERROR) << "Failed to seek to end of dex file. Actual: " << actual_offset
+                << " Expected: " << end_offset
+                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
+    return false;
+  }
+  actual_offset = out->Seek(end_offset, kSeekSet);
+  if (actual_offset != static_cast<off_t>(end_offset)) {
+    PLOG(ERROR) << "Failed to seek stream to end of dex file. Actual: " << actual_offset
+                << " Expected: " << end_offset << " File: " << oat_dex_file->GetLocation();
+    return false;
+  }
+  if (!out->Flush()) {
+    PLOG(ERROR) << "Failed to flush stream after seeking over dex file."
+                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
+    return false;
+  }
+
+  // If we extracted more than the size specified in the header, truncate the file.
+  if (extracted_size > oat_dex_file->dex_file_size_) {
+    if (file->SetLength(end_offset) != 0) {
+      PLOG(ERROR) << "Failed to truncate excessive dex file length."
+                  << " File: " << oat_dex_file->GetLocation()
+                  << " Output: " << file->GetPath();
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool OatWriter::WriteDexFile(OutputStream* out,
+                             File* file,
+                             OatDexFile* oat_dex_file,
+                             File* dex_file) {
+  size_t start_offset = kIsVdexEnabled ? vdex_size_ : oat_data_offset_ + oat_size_;
+  DCHECK_EQ(static_cast<off_t>(start_offset), out->Seek(0, kSeekCurrent));
+
+  off_t input_offset = lseek(dex_file->Fd(), 0, SEEK_SET);
+  if (input_offset != static_cast<off_t>(0)) {
+    PLOG(ERROR) << "Failed to seek to dex file header. Actual: " << input_offset
+                << " Expected: 0"
+                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
+    return false;
+  }
+  if (!ReadDexFileHeader(dex_file, oat_dex_file)) {
+    return false;
+  }
+
+  // Copy the input dex file using sendfile().
+  if (!file->Copy(dex_file, 0, oat_dex_file->dex_file_size_)) {
+    PLOG(ERROR) << "Failed to copy dex file to oat file."
+                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
+    return false;
+  }
+  if (file->Flush() != 0) {
+    PLOG(ERROR) << "Failed to flush dex file."
+                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
+    return false;
+  }
+
+  // Check file position and seek the stream to the end offset.
+  size_t end_offset = start_offset + oat_dex_file->dex_file_size_;
+  off_t actual_offset = lseek(file->Fd(), 0, SEEK_CUR);
+  if (actual_offset != static_cast<off_t>(end_offset)) {
+    PLOG(ERROR) << "Unexpected file position after copying dex file. Actual: " << actual_offset
+                << " Expected: " << end_offset
+                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
+    return false;
+  }
+  actual_offset = out->Seek(end_offset, kSeekSet);
+  if (actual_offset != static_cast<off_t>(end_offset)) {
+    PLOG(ERROR) << "Failed to seek stream to end of dex file. Actual: " << actual_offset
+                << " Expected: " << end_offset << " File: " << oat_dex_file->GetLocation();
+    return false;
+  }
+  if (!out->Flush()) {
+    PLOG(ERROR) << "Failed to flush stream after seeking over dex file."
+                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
+    return false;
+  }
+
+  return true;
+}
+
+bool OatWriter::WriteDexFile(OutputStream* out,
+                             OatDexFile* oat_dex_file,
+                             const uint8_t* dex_file,
+                             bool update_input_vdex) {
+  // Note: The raw data has already been checked to contain the header
+  // and all the data that the header specifies as the file size.
+  DCHECK(dex_file != nullptr);
+  DCHECK(ValidateDexFileHeader(dex_file, oat_dex_file->GetLocation()));
+  const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(dex_file);
+
+  if (update_input_vdex) {
+    // The vdex already contains the dex code, no need to write it again.
+  } else {
+    if (!out->WriteFully(dex_file, header->file_size_)) {
+      PLOG(ERROR) << "Failed to write dex file " << oat_dex_file->GetLocation()
+                  << " to " << out->GetLocation();
+      return false;
+    }
+    if (!out->Flush()) {
+      PLOG(ERROR) << "Failed to flush stream after writing dex file."
+                  << " File: " << oat_dex_file->GetLocation();
+      return false;
+    }
+  }
+
+  // Update dex file size and resize class offsets in the OatDexFile.
+  // Note: For raw data, the checksum is passed directly to AddRawDexFileSource().
+  // Note: For vdex, the checksum is copied from the existing vdex file.
+  oat_dex_file->dex_file_size_ = header->file_size_;
+  oat_dex_file->class_offsets_.resize(header->class_defs_size_);
+  return true;
+}
+
+bool OatWriter::OpenDexFiles(
+    File* file,
+    bool verify,
+    /*out*/ std::unique_ptr<MemMap>* opened_dex_files_map,
+    /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files) {
+  TimingLogger::ScopedTiming split("OpenDexFiles", timings_);
+
+  if (oat_dex_files_.empty()) {
+    // Nothing to do.
+    return true;
+  }
+
+  size_t map_offset = oat_dex_files_[0].dex_file_offset_;
+  size_t length = kIsVdexEnabled ? (vdex_size_ - map_offset) : (oat_size_ - map_offset);
+
+  std::string error_msg;
+  std::unique_ptr<MemMap> dex_files_map(MemMap::MapFile(
+      length,
+      PROT_READ | PROT_WRITE,
+      MAP_SHARED,
+      file->Fd(),
+      kIsVdexEnabled ? map_offset : (oat_data_offset_ + map_offset),
+      /* low_4gb */ false,
+      file->GetPath().c_str(),
+      &error_msg));
+  if (dex_files_map == nullptr) {
+    LOG(ERROR) << "Failed to mmap() dex files from oat file. File: " << file->GetPath()
+               << " error: " << error_msg;
+    return false;
+  }
+  std::vector<std::unique_ptr<const DexFile>> dex_files;
+  for (OatDexFile& oat_dex_file : oat_dex_files_) {
+    // Make sure no one messed with input files while we were copying data.
+    // At the very least we need consistent file size and number of class definitions.
+    const uint8_t* raw_dex_file =
+        dex_files_map->Begin() + oat_dex_file.dex_file_offset_ - map_offset;
+    if (!ValidateDexFileHeader(raw_dex_file, oat_dex_file.GetLocation())) {
+      // Note: ValidateDexFileHeader() already logged an error message.
+      LOG(ERROR) << "Failed to verify written dex file header!"
+          << " Output: " << file->GetPath() << " ~ " << std::hex << map_offset
+          << " ~ " << static_cast<const void*>(raw_dex_file);
+      return false;
+    }
+    const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(raw_dex_file);
+    if (header->file_size_ != oat_dex_file.dex_file_size_) {
+      LOG(ERROR) << "File size mismatch in written dex file header! Expected: "
+          << oat_dex_file.dex_file_size_ << " Actual: " << header->file_size_
+          << " Output: " << file->GetPath();
+      return false;
+    }
+    if (header->class_defs_size_ != oat_dex_file.class_offsets_.size()) {
+      LOG(ERROR) << "Class defs size mismatch in written dex file header! Expected: "
+          << oat_dex_file.class_offsets_.size() << " Actual: " << header->class_defs_size_
+          << " Output: " << file->GetPath();
+      return false;
+    }
+
+    // Now, open the dex file.
+    dex_files.emplace_back(DexFile::Open(raw_dex_file,
+                                         oat_dex_file.dex_file_size_,
+                                         oat_dex_file.GetLocation(),
+                                         oat_dex_file.dex_file_location_checksum_,
+                                         /* oat_dex_file */ nullptr,
+                                         verify,
+                                         verify,
+                                         &error_msg));
+    if (dex_files.back() == nullptr) {
+      LOG(ERROR) << "Failed to open dex file from oat file. File: " << oat_dex_file.GetLocation()
+                 << " Error: " << error_msg;
+      return false;
+    }
+  }
+
+  *opened_dex_files_map = std::move(dex_files_map);
+  *opened_dex_files = std::move(dex_files);
+  return true;
+}
+
+bool OatWriter::WriteTypeLookupTables(
+    OutputStream* oat_rodata,
+    const std::vector<std::unique_ptr<const DexFile>>& opened_dex_files) {
+  TimingLogger::ScopedTiming split("WriteTypeLookupTables", timings_);
+
+  uint32_t expected_offset = oat_data_offset_ + oat_size_;
+  off_t actual_offset = oat_rodata->Seek(expected_offset, kSeekSet);
+  if (static_cast<uint32_t>(actual_offset) != expected_offset) {
+    PLOG(ERROR) << "Failed to seek to TypeLookupTable section. Actual: " << actual_offset
+                << " Expected: " << expected_offset << " File: " << oat_rodata->GetLocation();
+    return false;
+  }
+
+  DCHECK_EQ(opened_dex_files.size(), oat_dex_files_.size());
+  for (size_t i = 0, size = opened_dex_files.size(); i != size; ++i) {
+    OatDexFile* oat_dex_file = &oat_dex_files_[i];
+    DCHECK_EQ(oat_dex_file->lookup_table_offset_, 0u);
+
+    if (oat_dex_file->create_type_lookup_table_ != CreateTypeLookupTable::kCreate ||
+        oat_dex_file->class_offsets_.empty()) {
+      continue;
+    }
+
+    size_t table_size = TypeLookupTable::RawDataLength(oat_dex_file->class_offsets_.size());
+    if (table_size == 0u) {
+      continue;
+    }
+
+    // Create the lookup table. When `nullptr` is given as the storage buffer,
+    // TypeLookupTable allocates its own and OatDexFile takes ownership.
+    const DexFile& dex_file = *opened_dex_files[i];
+    {
+      std::unique_ptr<TypeLookupTable> type_lookup_table =
+          TypeLookupTable::Create(dex_file, /* storage */ nullptr);
+      type_lookup_table_oat_dex_files_.push_back(
+          std::make_unique<art::OatDexFile>(std::move(type_lookup_table)));
+      dex_file.SetOatDexFile(type_lookup_table_oat_dex_files_.back().get());
+    }
+    TypeLookupTable* const table = type_lookup_table_oat_dex_files_.back()->GetTypeLookupTable();
+
+    // Type tables are required to be 4 byte aligned.
+    size_t initial_offset = oat_size_;
+    size_t rodata_offset = RoundUp(initial_offset, 4);
+    size_t padding_size = rodata_offset - initial_offset;
+
+    if (padding_size != 0u) {
+      std::vector<uint8_t> buffer(padding_size, 0u);
+      if (!oat_rodata->WriteFully(buffer.data(), padding_size)) {
+        PLOG(ERROR) << "Failed to write lookup table alignment padding."
+                    << " File: " << oat_dex_file->GetLocation()
+                    << " Output: " << oat_rodata->GetLocation();
+        return false;
+      }
+    }
+
+    DCHECK_EQ(oat_data_offset_ + rodata_offset,
+              static_cast<size_t>(oat_rodata->Seek(0u, kSeekCurrent)));
+    DCHECK_EQ(table_size, table->RawDataLength());
+
+    if (!oat_rodata->WriteFully(table->RawData(), table_size)) {
+      PLOG(ERROR) << "Failed to write lookup table."
+                  << " File: " << oat_dex_file->GetLocation()
+                  << " Output: " << oat_rodata->GetLocation();
+      return false;
+    }
+
+    oat_dex_file->lookup_table_offset_ = rodata_offset;
+
+    oat_size_ += padding_size + table_size;
+    size_oat_lookup_table_ += table_size;
+    size_oat_lookup_table_alignment_ += padding_size;
+  }
+
+  if (!oat_rodata->Flush()) {
+    PLOG(ERROR) << "Failed to flush stream after writing type lookup tables."
+                << " File: " << oat_rodata->GetLocation();
+    return false;
+  }
+
+  return true;
+}
+
+bool OatWriter::WriteDexLayoutSections(
+    OutputStream* oat_rodata,
+    const std::vector<std::unique_ptr<const DexFile>>& opened_dex_files) {
+  TimingLogger::ScopedTiming split(__FUNCTION__, timings_);
+
+  if (!kWriteDexLayoutInfo) {
+    return true;;
+  }
+
+  uint32_t expected_offset = oat_data_offset_ + oat_size_;
+  off_t actual_offset = oat_rodata->Seek(expected_offset, kSeekSet);
+  if (static_cast<uint32_t>(actual_offset) != expected_offset) {
+    PLOG(ERROR) << "Failed to seek to dex layout section offset section. Actual: " << actual_offset
+                << " Expected: " << expected_offset << " File: " << oat_rodata->GetLocation();
+    return false;
+  }
+
+  DCHECK_EQ(opened_dex_files.size(), oat_dex_files_.size());
+  size_t rodata_offset = oat_size_;
+  for (size_t i = 0, size = opened_dex_files.size(); i != size; ++i) {
+    OatDexFile* oat_dex_file = &oat_dex_files_[i];
+    DCHECK_EQ(oat_dex_file->dex_sections_layout_offset_, 0u);
+
+    // Write dex layout section alignment bytes.
+    const size_t padding_size =
+        RoundUp(rodata_offset, alignof(DexLayoutSections)) - rodata_offset;
+    if (padding_size != 0u) {
+      std::vector<uint8_t> buffer(padding_size, 0u);
+      if (!oat_rodata->WriteFully(buffer.data(), padding_size)) {
+        PLOG(ERROR) << "Failed to write lookup table alignment padding."
+                    << " File: " << oat_dex_file->GetLocation()
+                    << " Output: " << oat_rodata->GetLocation();
+        return false;
+      }
+      size_oat_dex_file_dex_layout_sections_alignment_ += padding_size;
+      rodata_offset += padding_size;
+    }
+
+    DCHECK_ALIGNED(rodata_offset, alignof(DexLayoutSections));
+    DCHECK_EQ(oat_data_offset_ + rodata_offset,
+              static_cast<size_t>(oat_rodata->Seek(0u, kSeekCurrent)));
+    DCHECK(oat_dex_file != nullptr);
+    if (!oat_rodata->WriteFully(&oat_dex_file->dex_sections_layout_,
+                                sizeof(oat_dex_file->dex_sections_layout_))) {
+      PLOG(ERROR) << "Failed to write dex layout sections."
+                  << " File: " << oat_dex_file->GetLocation()
+                  << " Output: " << oat_rodata->GetLocation();
+      return false;
+    }
+    oat_dex_file->dex_sections_layout_offset_ = rodata_offset;
+    size_oat_dex_file_dex_layout_sections_ += sizeof(oat_dex_file->dex_sections_layout_);
+    rodata_offset += sizeof(oat_dex_file->dex_sections_layout_);
+  }
+  oat_size_ = rodata_offset;
+
+  if (!oat_rodata->Flush()) {
+    PLOG(ERROR) << "Failed to flush stream after writing type dex layout sections."
+                << " File: " << oat_rodata->GetLocation();
+    return false;
+  }
+
+  return true;
+}
+
+bool OatWriter::WriteChecksumsAndVdexHeader(OutputStream* vdex_out) {
+  if (!kIsVdexEnabled) {
+    return true;
+  }
+  // Write checksums
+  off_t actual_offset = vdex_out->Seek(sizeof(VdexFile::Header), kSeekSet);
+  if (actual_offset != sizeof(VdexFile::Header)) {
+    PLOG(ERROR) << "Failed to seek to the checksum location of vdex file. Actual: " << actual_offset
+                << " File: " << vdex_out->GetLocation();
+    return false;
+  }
+
+  for (size_t i = 0, size = oat_dex_files_.size(); i != size; ++i) {
+    OatDexFile* oat_dex_file = &oat_dex_files_[i];
+    if (!vdex_out->WriteFully(
+            &oat_dex_file->dex_file_location_checksum_, sizeof(VdexFile::VdexChecksum))) {
+      PLOG(ERROR) << "Failed to write dex file location checksum. File: "
+                  << vdex_out->GetLocation();
+      return false;
+    }
+    size_vdex_checksums_ += sizeof(VdexFile::VdexChecksum);
+  }
+
+  // Write header.
+  actual_offset = vdex_out->Seek(0, kSeekSet);
+  if (actual_offset != 0) {
+    PLOG(ERROR) << "Failed to seek to the beginning of vdex file. Actual: " << actual_offset
+                << " File: " << vdex_out->GetLocation();
+    return false;
+  }
+
+  DCHECK_NE(vdex_dex_files_offset_, 0u);
+  DCHECK_NE(vdex_verifier_deps_offset_, 0u);
+
+  size_t dex_section_size = vdex_verifier_deps_offset_ - vdex_dex_files_offset_;
+  size_t verifier_deps_section_size = vdex_quickening_info_offset_ - vdex_verifier_deps_offset_;
+  size_t quickening_info_section_size = vdex_size_ - vdex_quickening_info_offset_;
+
+  VdexFile::Header vdex_header(oat_dex_files_.size(),
+                               dex_section_size,
+                               verifier_deps_section_size,
+                               quickening_info_section_size);
+  if (!vdex_out->WriteFully(&vdex_header, sizeof(VdexFile::Header))) {
+    PLOG(ERROR) << "Failed to write vdex header. File: " << vdex_out->GetLocation();
+    return false;
+  }
+  size_vdex_header_ = sizeof(VdexFile::Header);
+
+  if (!vdex_out->Flush()) {
+    PLOG(ERROR) << "Failed to flush stream after writing to vdex file."
+                << " File: " << vdex_out->GetLocation();
+    return false;
+  }
+
+  return true;
+}
+
+bool OatWriter::WriteCodeAlignment(OutputStream* out, uint32_t aligned_code_delta) {
+  return WriteUpTo16BytesAlignment(out, aligned_code_delta, &size_code_alignment_);
+}
+
+bool OatWriter::WriteUpTo16BytesAlignment(OutputStream* out, uint32_t size, uint32_t* stat) {
+  static const uint8_t kPadding[] = {
+      0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u
+  };
+  DCHECK_LE(size, sizeof(kPadding));
+  if (UNLIKELY(!out->WriteFully(kPadding, size))) {
+    return false;
+  }
+  *stat += size;
+  return true;
+}
+
+void OatWriter::SetMultiOatRelativePatcherAdjustment() {
+  DCHECK(dex_files_ != nullptr);
+  DCHECK(relative_patcher_ != nullptr);
+  DCHECK_NE(oat_data_offset_, 0u);
+  if (image_writer_ != nullptr && !dex_files_->empty()) {
+    // The oat data begin may not be initialized yet but the oat file offset is ready.
+    size_t oat_index = image_writer_->GetOatIndexForDexFile(dex_files_->front());
+    size_t elf_file_offset = image_writer_->GetOatFileOffset(oat_index);
+    relative_patcher_->StartOatFile(elf_file_offset + oat_data_offset_);
+  }
+}
+
+OatWriter::OatDexFile::OatDexFile(const char* dex_file_location,
+                                  DexFileSource source,
+                                  CreateTypeLookupTable create_type_lookup_table)
+    : source_(source),
+      create_type_lookup_table_(create_type_lookup_table),
+      dex_file_size_(0),
+      offset_(0),
+      dex_file_location_size_(strlen(dex_file_location)),
+      dex_file_location_data_(dex_file_location),
+      dex_file_location_checksum_(0u),
+      dex_file_offset_(0u),
+      class_offsets_offset_(0u),
+      lookup_table_offset_(0u),
+      method_bss_mapping_offset_(0u),
+      dex_sections_layout_offset_(0u),
+      class_offsets_() {
+}
+
+size_t OatWriter::OatDexFile::SizeOf() const {
+  return sizeof(dex_file_location_size_)
+          + dex_file_location_size_
+          + sizeof(dex_file_location_checksum_)
+          + sizeof(dex_file_offset_)
+          + sizeof(class_offsets_offset_)
+          + sizeof(lookup_table_offset_)
+          + sizeof(method_bss_mapping_offset_)
+          + sizeof(dex_sections_layout_offset_);
+}
+
+bool OatWriter::OatDexFile::Write(OatWriter* oat_writer, OutputStream* out) const {
+  const size_t file_offset = oat_writer->oat_data_offset_;
+  DCHECK_OFFSET_();
+
+  if (!out->WriteFully(&dex_file_location_size_, sizeof(dex_file_location_size_))) {
+    PLOG(ERROR) << "Failed to write dex file location length to " << out->GetLocation();
+    return false;
+  }
+  oat_writer->size_oat_dex_file_location_size_ += sizeof(dex_file_location_size_);
+
+  if (!out->WriteFully(dex_file_location_data_, dex_file_location_size_)) {
+    PLOG(ERROR) << "Failed to write dex file location data to " << out->GetLocation();
+    return false;
+  }
+  oat_writer->size_oat_dex_file_location_data_ += dex_file_location_size_;
+
+  if (!out->WriteFully(&dex_file_location_checksum_, sizeof(dex_file_location_checksum_))) {
+    PLOG(ERROR) << "Failed to write dex file location checksum to " << out->GetLocation();
+    return false;
+  }
+  oat_writer->size_oat_dex_file_location_checksum_ += sizeof(dex_file_location_checksum_);
+
+  if (!out->WriteFully(&dex_file_offset_, sizeof(dex_file_offset_))) {
+    PLOG(ERROR) << "Failed to write dex file offset to " << out->GetLocation();
+    return false;
+  }
+  oat_writer->size_oat_dex_file_offset_ += sizeof(dex_file_offset_);
+
+  if (!out->WriteFully(&class_offsets_offset_, sizeof(class_offsets_offset_))) {
+    PLOG(ERROR) << "Failed to write class offsets offset to " << out->GetLocation();
+    return false;
+  }
+  oat_writer->size_oat_dex_file_class_offsets_offset_ += sizeof(class_offsets_offset_);
+
+  if (!out->WriteFully(&lookup_table_offset_, sizeof(lookup_table_offset_))) {
+    PLOG(ERROR) << "Failed to write lookup table offset to " << out->GetLocation();
+    return false;
+  }
+  oat_writer->size_oat_dex_file_lookup_table_offset_ += sizeof(lookup_table_offset_);
+
+  if (!out->WriteFully(&dex_sections_layout_offset_, sizeof(dex_sections_layout_offset_))) {
+    PLOG(ERROR) << "Failed to write dex section layout info to " << out->GetLocation();
+    return false;
+  }
+  oat_writer->size_oat_dex_file_dex_layout_sections_offset_ += sizeof(dex_sections_layout_offset_);
+
+  if (!out->WriteFully(&method_bss_mapping_offset_, sizeof(method_bss_mapping_offset_))) {
+    PLOG(ERROR) << "Failed to write method bss mapping offset to " << out->GetLocation();
+    return false;
+  }
+  oat_writer->size_oat_dex_file_method_bss_mapping_offset_ += sizeof(method_bss_mapping_offset_);
+
+  return true;
+}
+
+bool OatWriter::OatDexFile::WriteClassOffsets(OatWriter* oat_writer, OutputStream* out) {
+  if (!out->WriteFully(class_offsets_.data(), GetClassOffsetsRawSize())) {
+    PLOG(ERROR) << "Failed to write oat class offsets for " << GetLocation()
+                << " to " << out->GetLocation();
+    return false;
+  }
+  oat_writer->size_oat_class_offsets_ += GetClassOffsetsRawSize();
+  return true;
+}
+
+OatWriter::OatClass::OatClass(const dchecked_vector<CompiledMethod*>& compiled_methods,
+                              uint32_t compiled_methods_with_code,
+                              uint16_t oat_class_type)
+    : compiled_methods_(compiled_methods) {
+  const uint32_t num_methods = compiled_methods.size();
+  CHECK_LE(compiled_methods_with_code, num_methods);
+
+  oat_method_offsets_offsets_from_oat_class_.resize(num_methods);
+
+  method_offsets_.resize(compiled_methods_with_code);
+  method_headers_.resize(compiled_methods_with_code);
+
+  uint32_t oat_method_offsets_offset_from_oat_class = OatClassHeader::SizeOf();
+  // We only create this instance if there are at least some compiled.
+  if (oat_class_type == kOatClassSomeCompiled) {
+    method_bitmap_.reset(new BitVector(num_methods, false, Allocator::GetMallocAllocator()));
+    method_bitmap_size_ = method_bitmap_->GetSizeOf();
+    oat_method_offsets_offset_from_oat_class += sizeof(method_bitmap_size_);
+    oat_method_offsets_offset_from_oat_class += method_bitmap_size_;
+  } else {
+    method_bitmap_ = nullptr;
+    method_bitmap_size_ = 0;
+  }
+
+  for (size_t i = 0; i < num_methods; i++) {
+    CompiledMethod* compiled_method = compiled_methods_[i];
+    if (HasCompiledCode(compiled_method)) {
+      oat_method_offsets_offsets_from_oat_class_[i] = oat_method_offsets_offset_from_oat_class;
+      oat_method_offsets_offset_from_oat_class += sizeof(OatMethodOffsets);
+      if (oat_class_type == kOatClassSomeCompiled) {
+        method_bitmap_->SetBit(i);
+      }
+    } else {
+      oat_method_offsets_offsets_from_oat_class_[i] = 0;
+    }
+  }
+}
+
+size_t OatWriter::OatClass::SizeOf() const {
+  return ((method_bitmap_size_ == 0) ? 0 : sizeof(method_bitmap_size_))
+          + method_bitmap_size_
+          + (sizeof(method_offsets_[0]) * method_offsets_.size());
+}
+
+bool OatWriter::OatClassHeader::Write(OatWriter* oat_writer,
+                                      OutputStream* out,
+                                      const size_t file_offset) const {
+  DCHECK_OFFSET_();
+  if (!out->WriteFully(&status_, sizeof(status_))) {
+    PLOG(ERROR) << "Failed to write class status to " << out->GetLocation();
+    return false;
+  }
+  oat_writer->size_oat_class_status_ += sizeof(status_);
+
+  if (!out->WriteFully(&type_, sizeof(type_))) {
+    PLOG(ERROR) << "Failed to write oat class type to " << out->GetLocation();
+    return false;
+  }
+  oat_writer->size_oat_class_type_ += sizeof(type_);
+  return true;
+}
+
+bool OatWriter::OatClass::Write(OatWriter* oat_writer, OutputStream* out) const {
+  if (method_bitmap_size_ != 0) {
+    if (!out->WriteFully(&method_bitmap_size_, sizeof(method_bitmap_size_))) {
+      PLOG(ERROR) << "Failed to write method bitmap size to " << out->GetLocation();
+      return false;
+    }
+    oat_writer->size_oat_class_method_bitmaps_ += sizeof(method_bitmap_size_);
+
+    if (!out->WriteFully(method_bitmap_->GetRawStorage(), method_bitmap_size_)) {
+      PLOG(ERROR) << "Failed to write method bitmap to " << out->GetLocation();
+      return false;
+    }
+    oat_writer->size_oat_class_method_bitmaps_ += method_bitmap_size_;
+  }
+
+  if (!out->WriteFully(method_offsets_.data(), GetMethodOffsetsRawSize())) {
+    PLOG(ERROR) << "Failed to write method offsets to " << out->GetLocation();
+    return false;
+  }
+  oat_writer->size_oat_class_method_offsets_ += GetMethodOffsetsRawSize();
+  return true;
+}
+
+const uint8_t* OatWriter::LookupBootImageInternTableSlot(const DexFile& dex_file,
+                                                         dex::StringIndex string_idx)
+    NO_THREAD_SAFETY_ANALYSIS {  // Single-threaded OatWriter can avoid locking.
+  uint32_t utf16_length;
+  const char* utf8_data = dex_file.StringDataAndUtf16LengthByIdx(string_idx, &utf16_length);
+  DCHECK_EQ(utf16_length, CountModifiedUtf8Chars(utf8_data));
+  InternTable::Utf8String string(utf16_length,
+                                 utf8_data,
+                                 ComputeUtf16HashFromModifiedUtf8(utf8_data, utf16_length));
+  const InternTable* intern_table = Runtime::Current()->GetClassLinker()->intern_table_;
+  for (const InternTable::Table::UnorderedSet& table : intern_table->strong_interns_.tables_) {
+    auto it = table.Find(string);
+    if (it != table.end()) {
+      return reinterpret_cast<const uint8_t*>(std::addressof(*it));
+    }
+  }
+  LOG(FATAL) << "Did not find boot image string " << utf8_data;
+  UNREACHABLE();
+}
+
+const uint8_t* OatWriter::LookupBootImageClassTableSlot(const DexFile& dex_file,
+                                                        dex::TypeIndex type_idx)
+    NO_THREAD_SAFETY_ANALYSIS {  // Single-threaded OatWriter can avoid locking.
+  const char* descriptor = dex_file.StringByTypeIdx(type_idx);
+  ClassTable::DescriptorHashPair pair(descriptor, ComputeModifiedUtf8Hash(descriptor));
+  ClassTable* table = Runtime::Current()->GetClassLinker()->boot_class_table_.get();
+  for (const ClassTable::ClassSet& class_set : table->classes_) {
+    auto it = class_set.Find(pair);
+    if (it != class_set.end()) {
+      return reinterpret_cast<const uint8_t*>(std::addressof(*it));
+    }
+  }
+  LOG(FATAL) << "Did not find boot image class " << descriptor;
+  UNREACHABLE();
+}
+
+}  // namespace linker
+}  // namespace art
diff --git a/dex2oat/linker/oat_writer.h b/dex2oat/linker/oat_writer.h
new file mode 100644
index 0000000..a93dd23
--- /dev/null
+++ b/dex2oat/linker/oat_writer.h
@@ -0,0 +1,495 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_DEX2OAT_LINKER_OAT_WRITER_H_
+#define ART_DEX2OAT_LINKER_OAT_WRITER_H_
+
+#include <stdint.h>
+#include <cstddef>
+#include <memory>
+
+#include "base/array_ref.h"
+#include "base/dchecked_vector.h"
+#include "linker/relative_patcher.h"  // For RelativePatcherTargetProvider.
+#include "mem_map.h"
+#include "method_reference.h"
+#include "mirror/class.h"
+#include "oat.h"
+#include "os.h"
+#include "safe_map.h"
+#include "string_reference.h"
+#include "type_reference.h"
+
+namespace art {
+
+class BitVector;
+class CompiledMethod;
+class CompilerDriver;
+class ProfileCompilationInfo;
+class TimingLogger;
+class TypeLookupTable;
+class VdexFile;
+class ZipEntry;
+
+namespace debug {
+struct MethodDebugInfo;
+}  // namespace debug
+
+namespace verifier {
+class VerifierDeps;
+}  // namespace verifier
+
+namespace linker {
+
+class ImageWriter;
+class MultiOatRelativePatcher;
+class OutputStream;
+
+// OatHeader         variable length with count of D OatDexFiles
+//
+// TypeLookupTable[0] one descriptor to class def index hash table for each OatDexFile.
+// TypeLookupTable[1]
+// ...
+// TypeLookupTable[D]
+//
+// ClassOffsets[0]   one table of OatClass offsets for each class def for each OatDexFile.
+// ClassOffsets[1]
+// ...
+// ClassOffsets[D]
+//
+// OatClass[0]       one variable sized OatClass for each of C DexFile::ClassDefs
+// OatClass[1]       contains OatClass entries with class status, offsets to code, etc.
+// ...
+// OatClass[C]
+//
+// MethodBssMapping  one variable sized MethodBssMapping for each dex file, optional.
+// MethodBssMapping
+// ...
+// MethodBssMapping
+//
+// VmapTable         one variable sized VmapTable blob (CodeInfo or QuickeningInfo).
+// VmapTable         VmapTables are deduplicated.
+// ...
+// VmapTable
+//
+// MethodInfo        one variable sized blob with MethodInfo.
+// MethodInfo        MethodInfos are deduplicated.
+// ...
+// MethodInfo
+//
+// OatDexFile[0]     one variable sized OatDexFile with offsets to Dex and OatClasses
+// OatDexFile[1]
+// ...
+// OatDexFile[D]
+//
+// padding           if necessary so that the following code will be page aligned
+//
+// OatMethodHeader   fixed size header for a CompiledMethod including the size of the MethodCode.
+// MethodCode        one variable sized blob with the code of a CompiledMethod.
+// OatMethodHeader   (OatMethodHeader, MethodCode) pairs are deduplicated.
+// MethodCode
+// ...
+// OatMethodHeader
+// MethodCode
+//
+class OatWriter {
+ public:
+  enum class CreateTypeLookupTable {
+    kCreate,
+    kDontCreate,
+    kDefault = kCreate
+  };
+
+  OatWriter(bool compiling_boot_image, TimingLogger* timings, ProfileCompilationInfo* info);
+
+  // To produce a valid oat file, the user must first add sources with any combination of
+  //   - AddDexFileSource(),
+  //   - AddZippedDexFilesSource(),
+  //   - AddRawDexFileSource(),
+  //   - AddVdexDexFilesSource().
+  // Then the user must call in order
+  //   - WriteAndOpenDexFiles()
+  //   - Initialize()
+  //   - WriteVerifierDeps()
+  //   - WriteQuickeningInfo()
+  //   - WriteChecksumsAndVdexHeader()
+  //   - PrepareLayout(),
+  //   - WriteRodata(),
+  //   - WriteCode(),
+  //   - WriteHeader().
+
+  // Add dex file source(s) from a file, either a plain dex file or
+  // a zip file with one or more dex files.
+  bool AddDexFileSource(
+      const char* filename,
+      const char* location,
+      CreateTypeLookupTable create_type_lookup_table = CreateTypeLookupTable::kDefault);
+  // Add dex file source(s) from a zip file specified by a file handle.
+  bool AddZippedDexFilesSource(
+      File&& zip_fd,
+      const char* location,
+      CreateTypeLookupTable create_type_lookup_table = CreateTypeLookupTable::kDefault);
+  // Add dex file source from raw memory.
+  bool AddRawDexFileSource(
+      const ArrayRef<const uint8_t>& data,
+      const char* location,
+      uint32_t location_checksum,
+      CreateTypeLookupTable create_type_lookup_table = CreateTypeLookupTable::kDefault);
+  // Add dex file source(s) from a vdex file.
+  bool AddVdexDexFilesSource(
+      const VdexFile& vdex_file,
+      const char* location,
+      CreateTypeLookupTable create_type_lookup_table = CreateTypeLookupTable::kDefault);
+  dchecked_vector<std::string> GetSourceLocations() const;
+
+  // Write raw dex files to the vdex file, mmap the file and open the dex files from it.
+  // Supporting data structures are written into the .rodata section of the oat file.
+  // The `verify` setting dictates whether the dex file verifier should check the dex files.
+  // This is generally the case, and should only be false for tests.
+  // If `update_input_vdex` is true, then this method won't actually write the dex files,
+  // and the compiler will just re-use the existing vdex file.
+  bool WriteAndOpenDexFiles(File* vdex_file,
+                            OutputStream* oat_rodata,
+                            InstructionSet instruction_set,
+                            const InstructionSetFeatures* instruction_set_features,
+                            SafeMap<std::string, std::string>* key_value_store,
+                            bool verify,
+                            bool update_input_vdex,
+                            /*out*/ std::unique_ptr<MemMap>* opened_dex_files_map,
+                            /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files);
+  bool WriteQuickeningInfo(OutputStream* vdex_out);
+  bool WriteVerifierDeps(OutputStream* vdex_out, verifier::VerifierDeps* verifier_deps);
+  bool WriteChecksumsAndVdexHeader(OutputStream* vdex_out);
+  // Initialize the writer with the given parameters.
+  void Initialize(const CompilerDriver* compiler,
+                  ImageWriter* image_writer,
+                  const std::vector<const DexFile*>& dex_files) {
+    compiler_driver_ = compiler;
+    image_writer_ = image_writer;
+    dex_files_ = &dex_files;
+  }
+
+  // Prepare layout of remaining data.
+  void PrepareLayout(MultiOatRelativePatcher* relative_patcher);
+  // Write the rest of .rodata section (ClassOffsets[], OatClass[], maps).
+  bool WriteRodata(OutputStream* out);
+  // Write the code to the .text section.
+  bool WriteCode(OutputStream* out);
+  // Write the oat header. This finalizes the oat file.
+  bool WriteHeader(OutputStream* out,
+                   uint32_t image_file_location_oat_checksum,
+                   uintptr_t image_file_location_oat_begin,
+                   int32_t image_patch_delta);
+
+  // Returns whether the oat file has an associated image.
+  bool HasImage() const {
+    // Since the image is being created at the same time as the oat file,
+    // check if there's an image writer.
+    return image_writer_ != nullptr;
+  }
+
+  bool HasBootImage() const {
+    return compiling_boot_image_;
+  }
+
+  const OatHeader& GetOatHeader() const {
+    return *oat_header_;
+  }
+
+  size_t GetOatSize() const {
+    return oat_size_;
+  }
+
+  size_t GetBssSize() const {
+    return bss_size_;
+  }
+
+  size_t GetBssMethodsOffset() const {
+    return bss_methods_offset_;
+  }
+
+  size_t GetBssRootsOffset() const {
+    return bss_roots_offset_;
+  }
+
+  size_t GetOatDataOffset() const {
+    return oat_data_offset_;
+  }
+
+  ~OatWriter();
+
+  ArrayRef<const debug::MethodDebugInfo> GetMethodDebugInfo() const {
+    return ArrayRef<const debug::MethodDebugInfo>(method_info_);
+  }
+
+  const CompilerDriver* GetCompilerDriver() const {
+    return compiler_driver_;
+  }
+
+ private:
+  class DexFileSource;
+  class OatClassHeader;
+  class OatClass;
+  class OatDexFile;
+
+  // The function VisitDexMethods() below iterates through all the methods in all
+  // the compiled dex files in order of their definitions. The method visitor
+  // classes provide individual bits of processing for each of the passes we need to
+  // first collect the data we want to write to the oat file and then, in later passes,
+  // to actually write it.
+  class DexMethodVisitor;
+  class OatDexMethodVisitor;
+  class InitBssLayoutMethodVisitor;
+  class InitOatClassesMethodVisitor;
+  class InitCodeMethodVisitor;
+  class InitMapMethodVisitor;
+  class InitMethodInfoVisitor;
+  class InitImageMethodVisitor;
+  class WriteCodeMethodVisitor;
+  class WriteMapMethodVisitor;
+  class WriteMethodInfoVisitor;
+  class WriteQuickeningInfoMethodVisitor;
+  class WriteQuickeningIndicesMethodVisitor;
+
+  // Visit all the methods in all the compiled dex files in their definition order
+  // with a given DexMethodVisitor.
+  bool VisitDexMethods(DexMethodVisitor* visitor);
+
+  // If `update_input_vdex` is true, then this method won't actually write the dex files,
+  // and the compiler will just re-use the existing vdex file.
+  bool WriteDexFiles(OutputStream* out, File* file, bool update_input_vdex);
+  bool WriteDexFile(OutputStream* out,
+                    File* file,
+                    OatDexFile* oat_dex_file,
+                    bool update_input_vdex);
+  bool SeekToDexFile(OutputStream* out, File* file, OatDexFile* oat_dex_file);
+  bool LayoutAndWriteDexFile(OutputStream* out, OatDexFile* oat_dex_file);
+  bool WriteDexFile(OutputStream* out,
+                    File* file,
+                    OatDexFile* oat_dex_file,
+                    ZipEntry* dex_file);
+  bool WriteDexFile(OutputStream* out,
+                    File* file,
+                    OatDexFile* oat_dex_file,
+                    File* dex_file);
+  bool WriteDexFile(OutputStream* out,
+                    OatDexFile* oat_dex_file,
+                    const uint8_t* dex_file,
+                    bool update_input_vdex);
+  bool OpenDexFiles(File* file,
+                    bool verify,
+                    /*out*/ std::unique_ptr<MemMap>* opened_dex_files_map,
+                    /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files);
+
+  size_t InitOatHeader(InstructionSet instruction_set,
+                       const InstructionSetFeatures* instruction_set_features,
+                       uint32_t num_dex_files,
+                       SafeMap<std::string, std::string>* key_value_store);
+  size_t InitClassOffsets(size_t offset);
+  size_t InitOatClasses(size_t offset);
+  size_t InitOatMaps(size_t offset);
+  size_t InitMethodBssMappings(size_t offset);
+  size_t InitOatDexFiles(size_t offset);
+  size_t InitOatCode(size_t offset);
+  size_t InitOatCodeDexFiles(size_t offset);
+  void InitBssLayout(InstructionSet instruction_set);
+
+  size_t WriteClassOffsets(OutputStream* out, size_t file_offset, size_t relative_offset);
+  size_t WriteClasses(OutputStream* out, size_t file_offset, size_t relative_offset);
+  size_t WriteMaps(OutputStream* out, size_t file_offset, size_t relative_offset);
+  size_t WriteMethodBssMappings(OutputStream* out, size_t file_offset, size_t relative_offset);
+  size_t WriteOatDexFiles(OutputStream* out, size_t file_offset, size_t relative_offset);
+  size_t WriteCode(OutputStream* out, size_t file_offset, size_t relative_offset);
+  size_t WriteCodeDexFiles(OutputStream* out, size_t file_offset, size_t relative_offset);
+
+  bool RecordOatDataOffset(OutputStream* out);
+  bool ReadDexFileHeader(File* oat_file, OatDexFile* oat_dex_file);
+  bool ValidateDexFileHeader(const uint8_t* raw_header, const char* location);
+  bool WriteTypeLookupTables(OutputStream* oat_rodata,
+                             const std::vector<std::unique_ptr<const DexFile>>& opened_dex_files);
+  bool WriteDexLayoutSections(OutputStream* oat_rodata,
+                              const std::vector<std::unique_ptr<const DexFile>>& opened_dex_files);
+  bool WriteCodeAlignment(OutputStream* out, uint32_t aligned_code_delta);
+  bool WriteUpTo16BytesAlignment(OutputStream* out, uint32_t size, uint32_t* stat);
+  void SetMultiOatRelativePatcherAdjustment();
+  void CloseSources();
+
+  bool MayHaveCompiledMethods() const;
+
+  // Find the address of the GcRoot<String> in the InternTable for a boot image string.
+  const uint8_t* LookupBootImageInternTableSlot(const DexFile& dex_file,
+                                                dex::StringIndex string_idx);
+  // Find the address of the ClassTable::TableSlot for a boot image class.
+  const uint8_t* LookupBootImageClassTableSlot(const DexFile& dex_file, dex::TypeIndex type_idx);
+
+  enum class WriteState {
+    kAddingDexFileSources,
+    kPrepareLayout,
+    kWriteRoData,
+    kWriteText,
+    kWriteHeader,
+    kDone
+  };
+
+  WriteState write_state_;
+  TimingLogger* timings_;
+
+  std::vector<std::unique_ptr<File>> raw_dex_files_;
+  std::vector<std::unique_ptr<ZipArchive>> zip_archives_;
+  std::vector<std::unique_ptr<ZipEntry>> zipped_dex_files_;
+
+  // Using std::list<> which doesn't move elements around on push/emplace_back().
+  // We need this because we keep plain pointers to the strings' c_str().
+  std::list<std::string> zipped_dex_file_locations_;
+
+  dchecked_vector<debug::MethodDebugInfo> method_info_;
+
+  const CompilerDriver* compiler_driver_;
+  ImageWriter* image_writer_;
+  const bool compiling_boot_image_;
+
+  // note OatFile does not take ownership of the DexFiles
+  const std::vector<const DexFile*>* dex_files_;
+
+  // Size required for Vdex data structures.
+  size_t vdex_size_;
+
+  // Offset of section holding Dex files inside Vdex.
+  size_t vdex_dex_files_offset_;
+
+  // Offset of section holding VerifierDeps inside Vdex.
+  size_t vdex_verifier_deps_offset_;
+
+  // Offset of section holding quickening info inside Vdex.
+  size_t vdex_quickening_info_offset_;
+
+  // Size required for Oat data structures.
+  size_t oat_size_;
+
+  // The start of the required .bss section.
+  size_t bss_start_;
+
+  // The size of the required .bss section holding the DexCache data and GC roots.
+  size_t bss_size_;
+
+  // The offset of the methods in .bss section.
+  size_t bss_methods_offset_;
+
+  // The offset of the GC roots in .bss section.
+  size_t bss_roots_offset_;
+
+  // Map for recording references to ArtMethod entries in .bss.
+  SafeMap<const DexFile*, BitVector> bss_method_entry_references_;
+
+  // Map for allocating ArtMethod entries in .bss. Indexed by MethodReference for the target
+  // method in the dex file with the "method reference value comparator" for deduplication.
+  // The value is the target offset for patching, starting at `bss_start_ + bss_methods_offset_`.
+  SafeMap<MethodReference, size_t, MethodReferenceValueComparator> bss_method_entries_;
+
+  // Map for allocating Class entries in .bss. Indexed by TypeReference for the source
+  // type in the dex file with the "type value comparator" for deduplication. The value
+  // is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`.
+  SafeMap<TypeReference, size_t, TypeReferenceValueComparator> bss_type_entries_;
+
+  // Map for allocating String entries in .bss. Indexed by StringReference for the source
+  // string in the dex file with the "string value comparator" for deduplication. The value
+  // is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`.
+  SafeMap<StringReference, size_t, StringReferenceValueComparator> bss_string_entries_;
+
+  // Whether boot image tables should be mapped to the .bss. This is needed for compiled
+  // code that reads from these tables with PC-relative instructions.
+  bool map_boot_image_tables_to_bss_;
+
+  // Offset of the oat data from the start of the mmapped region of the elf file.
+  size_t oat_data_offset_;
+
+  // Fake OatDexFiles to hold type lookup tables for the compiler.
+  std::vector<std::unique_ptr<art::OatDexFile>> type_lookup_table_oat_dex_files_;
+
+  // data to write
+  std::unique_ptr<OatHeader> oat_header_;
+  dchecked_vector<OatDexFile> oat_dex_files_;
+  dchecked_vector<OatClassHeader> oat_class_headers_;
+  dchecked_vector<OatClass> oat_classes_;
+  std::unique_ptr<const std::vector<uint8_t>> jni_dlsym_lookup_;
+  std::unique_ptr<const std::vector<uint8_t>> quick_generic_jni_trampoline_;
+  std::unique_ptr<const std::vector<uint8_t>> quick_imt_conflict_trampoline_;
+  std::unique_ptr<const std::vector<uint8_t>> quick_resolution_trampoline_;
+  std::unique_ptr<const std::vector<uint8_t>> quick_to_interpreter_bridge_;
+
+  // output stats
+  uint32_t size_vdex_header_;
+  uint32_t size_vdex_checksums_;
+  uint32_t size_dex_file_alignment_;
+  uint32_t size_executable_offset_alignment_;
+  uint32_t size_oat_header_;
+  uint32_t size_oat_header_key_value_store_;
+  uint32_t size_dex_file_;
+  uint32_t size_verifier_deps_;
+  uint32_t size_verifier_deps_alignment_;
+  uint32_t size_quickening_info_;
+  uint32_t size_quickening_info_alignment_;
+  uint32_t size_interpreter_to_interpreter_bridge_;
+  uint32_t size_interpreter_to_compiled_code_bridge_;
+  uint32_t size_jni_dlsym_lookup_;
+  uint32_t size_quick_generic_jni_trampoline_;
+  uint32_t size_quick_imt_conflict_trampoline_;
+  uint32_t size_quick_resolution_trampoline_;
+  uint32_t size_quick_to_interpreter_bridge_;
+  uint32_t size_trampoline_alignment_;
+  uint32_t size_method_header_;
+  uint32_t size_code_;
+  uint32_t size_code_alignment_;
+  uint32_t size_relative_call_thunks_;
+  uint32_t size_misc_thunks_;
+  uint32_t size_vmap_table_;
+  uint32_t size_method_info_;
+  uint32_t size_oat_dex_file_location_size_;
+  uint32_t size_oat_dex_file_location_data_;
+  uint32_t size_oat_dex_file_location_checksum_;
+  uint32_t size_oat_dex_file_offset_;
+  uint32_t size_oat_dex_file_class_offsets_offset_;
+  uint32_t size_oat_dex_file_lookup_table_offset_;
+  uint32_t size_oat_dex_file_dex_layout_sections_offset_;
+  uint32_t size_oat_dex_file_dex_layout_sections_;
+  uint32_t size_oat_dex_file_dex_layout_sections_alignment_;
+  uint32_t size_oat_dex_file_method_bss_mapping_offset_;
+  uint32_t size_oat_lookup_table_alignment_;
+  uint32_t size_oat_lookup_table_;
+  uint32_t size_oat_class_offsets_alignment_;
+  uint32_t size_oat_class_offsets_;
+  uint32_t size_oat_class_type_;
+  uint32_t size_oat_class_status_;
+  uint32_t size_oat_class_method_bitmaps_;
+  uint32_t size_oat_class_method_offsets_;
+  uint32_t size_method_bss_mappings_;
+
+  // The helper for processing relative patches is external so that we can patch across oat files.
+  MultiOatRelativePatcher* relative_patcher_;
+
+  // The locations of absolute patches relative to the start of the executable section.
+  dchecked_vector<uintptr_t> absolute_patch_locations_;
+
+  // Profile info used to generate new layout of files.
+  ProfileCompilationInfo* profile_compilation_info_;
+
+  DISALLOW_COPY_AND_ASSIGN(OatWriter);
+};
+
+}  // namespace linker
+}  // namespace art
+
+#endif  // ART_DEX2OAT_LINKER_OAT_WRITER_H_
diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc
new file mode 100644
index 0000000..0600ceb
--- /dev/null
+++ b/dex2oat/linker/oat_writer_test.cc
@@ -0,0 +1,872 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "android-base/stringprintf.h"
+
+#include "arch/instruction_set_features.h"
+#include "art_method-inl.h"
+#include "base/enums.h"
+#include "base/stl_util.h"
+#include "base/unix_file/fd_file.h"
+#include "class_linker.h"
+#include "common_compiler_test.h"
+#include "compiled_method.h"
+#include "compiler.h"
+#include "debug/method_debug_info.h"
+#include "dex/quick_compiler_callbacks.h"
+#include "dex/verification_results.h"
+#include "driver/compiler_driver.h"
+#include "driver/compiler_options.h"
+#include "entrypoints/quick/quick_entrypoints.h"
+#include "linker/buffered_output_stream.h"
+#include "linker/elf_writer.h"
+#include "linker/elf_writer_quick.h"
+#include "linker/file_output_stream.h"
+#include "linker/multi_oat_relative_patcher.h"
+#include "linker/vector_output_stream.h"
+#include "mirror/class-inl.h"
+#include "mirror/object-inl.h"
+#include "mirror/object_array-inl.h"
+#include "oat_file-inl.h"
+#include "oat_writer.h"
+#include "scoped_thread_state_change-inl.h"
+#include "utils/test_dex_file_builder.h"
+
+namespace art {
+namespace linker {
+
+NO_RETURN static void Usage(const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  std::string error;
+  android::base::StringAppendV(&error, fmt, ap);
+  LOG(FATAL) << error;
+  va_end(ap);
+  UNREACHABLE();
+}
+
+class OatTest : public CommonCompilerTest {
+ protected:
+  static const bool kCompile = false;  // DISABLED_ due to the time to compile libcore
+
+  void CheckMethod(ArtMethod* method,
+                   const OatFile::OatMethod& oat_method,
+                   const DexFile& dex_file)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    const CompiledMethod* compiled_method =
+        compiler_driver_->GetCompiledMethod(MethodReference(&dex_file,
+                                                            method->GetDexMethodIndex()));
+
+    if (compiled_method == nullptr) {
+      EXPECT_TRUE(oat_method.GetQuickCode() == nullptr) << method->PrettyMethod() << " "
+                                                        << oat_method.GetQuickCode();
+      EXPECT_EQ(oat_method.GetFrameSizeInBytes(), 0U);
+      EXPECT_EQ(oat_method.GetCoreSpillMask(), 0U);
+      EXPECT_EQ(oat_method.GetFpSpillMask(), 0U);
+    } else {
+      const void* quick_oat_code = oat_method.GetQuickCode();
+      EXPECT_TRUE(quick_oat_code != nullptr) << method->PrettyMethod();
+      EXPECT_EQ(oat_method.GetFrameSizeInBytes(), compiled_method->GetFrameSizeInBytes());
+      EXPECT_EQ(oat_method.GetCoreSpillMask(), compiled_method->GetCoreSpillMask());
+      EXPECT_EQ(oat_method.GetFpSpillMask(), compiled_method->GetFpSpillMask());
+      uintptr_t oat_code_aligned = RoundDown(reinterpret_cast<uintptr_t>(quick_oat_code), 2);
+      quick_oat_code = reinterpret_cast<const void*>(oat_code_aligned);
+      ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode();
+      EXPECT_FALSE(quick_code.empty());
+      size_t code_size = quick_code.size() * sizeof(quick_code[0]);
+      EXPECT_EQ(0, memcmp(quick_oat_code, &quick_code[0], code_size))
+          << method->PrettyMethod() << " " << code_size;
+      CHECK_EQ(0, memcmp(quick_oat_code, &quick_code[0], code_size));
+    }
+  }
+
+  void SetupCompiler(Compiler::Kind compiler_kind,
+                     InstructionSet insn_set,
+                     const std::vector<std::string>& compiler_options,
+                     /*out*/std::string* error_msg) {
+    ASSERT_TRUE(error_msg != nullptr);
+    insn_features_ = InstructionSetFeatures::FromVariant(insn_set, "default", error_msg);
+    ASSERT_TRUE(insn_features_ != nullptr) << error_msg;
+    compiler_options_.reset(new CompilerOptions);
+    for (const std::string& option : compiler_options) {
+      compiler_options_->ParseCompilerOption(option, Usage);
+    }
+    verification_results_.reset(new VerificationResults(compiler_options_.get()));
+    callbacks_.reset(new QuickCompilerCallbacks(CompilerCallbacks::CallbackMode::kCompileApp));
+    callbacks_->SetVerificationResults(verification_results_.get());
+    Runtime::Current()->SetCompilerCallbacks(callbacks_.get());
+    timer_.reset(new CumulativeLogger("Compilation times"));
+    compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
+                                              verification_results_.get(),
+                                              compiler_kind,
+                                              insn_set,
+                                              insn_features_.get(),
+                                              /* image_classes */ nullptr,
+                                              /* compiled_classes */ nullptr,
+                                              /* compiled_methods */ nullptr,
+                                              /* thread_count */ 2,
+                                              /* dump_stats */ true,
+                                              /* dump_passes */ true,
+                                              timer_.get(),
+                                              /* swap_fd */ -1,
+                                              /* profile_compilation_info */ nullptr));
+  }
+
+  bool WriteElf(File* vdex_file,
+                File* oat_file,
+                const std::vector<const DexFile*>& dex_files,
+                SafeMap<std::string, std::string>& key_value_store,
+                bool verify) {
+    TimingLogger timings("WriteElf", false, false);
+    OatWriter oat_writer(/*compiling_boot_image*/false,
+                         &timings,
+                         /*profile_compilation_info*/nullptr);
+    for (const DexFile* dex_file : dex_files) {
+      ArrayRef<const uint8_t> raw_dex_file(
+          reinterpret_cast<const uint8_t*>(&dex_file->GetHeader()),
+          dex_file->GetHeader().file_size_);
+      if (!oat_writer.AddRawDexFileSource(raw_dex_file,
+                                          dex_file->GetLocation().c_str(),
+                                          dex_file->GetLocationChecksum())) {
+        return false;
+      }
+    }
+    return DoWriteElf(vdex_file, oat_file, oat_writer, key_value_store, verify);
+  }
+
+  bool WriteElf(File* vdex_file,
+                File* oat_file,
+                const std::vector<const char*>& dex_filenames,
+                SafeMap<std::string, std::string>& key_value_store,
+                bool verify,
+                ProfileCompilationInfo* profile_compilation_info) {
+    TimingLogger timings("WriteElf", false, false);
+    OatWriter oat_writer(/*compiling_boot_image*/false, &timings, profile_compilation_info);
+    for (const char* dex_filename : dex_filenames) {
+      if (!oat_writer.AddDexFileSource(dex_filename, dex_filename)) {
+        return false;
+      }
+    }
+    return DoWriteElf(vdex_file, oat_file, oat_writer, key_value_store, verify);
+  }
+
+  bool WriteElf(File* vdex_file,
+                File* oat_file,
+                File&& zip_fd,
+                const char* location,
+                SafeMap<std::string, std::string>& key_value_store,
+                bool verify) {
+    TimingLogger timings("WriteElf", false, false);
+    OatWriter oat_writer(/*compiling_boot_image*/false,
+                         &timings,
+                         /*profile_compilation_info*/nullptr);
+    if (!oat_writer.AddZippedDexFilesSource(std::move(zip_fd), location)) {
+      return false;
+    }
+    return DoWriteElf(vdex_file, oat_file, oat_writer, key_value_store, verify);
+  }
+
+  bool DoWriteElf(File* vdex_file,
+                  File* oat_file,
+                  OatWriter& oat_writer,
+                  SafeMap<std::string, std::string>& key_value_store,
+                  bool verify) {
+    std::unique_ptr<ElfWriter> elf_writer = CreateElfWriterQuick(
+        compiler_driver_->GetInstructionSet(),
+        compiler_driver_->GetInstructionSetFeatures(),
+        &compiler_driver_->GetCompilerOptions(),
+        oat_file);
+    elf_writer->Start();
+    OutputStream* oat_rodata = elf_writer->StartRoData();
+    std::unique_ptr<MemMap> opened_dex_files_map;
+    std::vector<std::unique_ptr<const DexFile>> opened_dex_files;
+    if (!oat_writer.WriteAndOpenDexFiles(kIsVdexEnabled ? vdex_file : oat_file,
+                                         oat_rodata,
+                                         compiler_driver_->GetInstructionSet(),
+                                         compiler_driver_->GetInstructionSetFeatures(),
+                                         &key_value_store,
+                                         verify,
+                                         /* update_input_vdex */ false,
+                                         &opened_dex_files_map,
+                                         &opened_dex_files)) {
+      return false;
+    }
+
+    Runtime* runtime = Runtime::Current();
+    ClassLinker* const class_linker = runtime->GetClassLinker();
+    std::vector<const DexFile*> dex_files;
+    for (const std::unique_ptr<const DexFile>& dex_file : opened_dex_files) {
+      dex_files.push_back(dex_file.get());
+      ScopedObjectAccess soa(Thread::Current());
+      class_linker->RegisterDexFile(*dex_file, nullptr);
+    }
+    MultiOatRelativePatcher patcher(compiler_driver_->GetInstructionSet(),
+                                    instruction_set_features_.get());
+    oat_writer.Initialize(compiler_driver_.get(), nullptr, dex_files);
+    oat_writer.PrepareLayout(&patcher);
+    size_t rodata_size = oat_writer.GetOatHeader().GetExecutableOffset();
+    size_t text_size = oat_writer.GetOatSize() - rodata_size;
+    elf_writer->PrepareDynamicSection(rodata_size,
+                                      text_size,
+                                      oat_writer.GetBssSize(),
+                                      oat_writer.GetBssMethodsOffset(),
+                                      oat_writer.GetBssRootsOffset());
+
+    if (kIsVdexEnabled) {
+      std::unique_ptr<BufferedOutputStream> vdex_out =
+            std::make_unique<BufferedOutputStream>(std::make_unique<FileOutputStream>(vdex_file));
+      if (!oat_writer.WriteVerifierDeps(vdex_out.get(), nullptr)) {
+        return false;
+      }
+      if (!oat_writer.WriteChecksumsAndVdexHeader(vdex_out.get())) {
+        return false;
+      }
+    }
+
+    if (!oat_writer.WriteRodata(oat_rodata)) {
+      return false;
+    }
+    elf_writer->EndRoData(oat_rodata);
+
+    OutputStream* text = elf_writer->StartText();
+    if (!oat_writer.WriteCode(text)) {
+      return false;
+    }
+    elf_writer->EndText(text);
+
+    if (!oat_writer.WriteHeader(elf_writer->GetStream(), 42U, 4096U, 0)) {
+      return false;
+    }
+
+    elf_writer->WriteDynamicSection();
+    elf_writer->WriteDebugInfo(oat_writer.GetMethodDebugInfo());
+
+    if (!elf_writer->End()) {
+      return false;
+    }
+
+    opened_dex_files_maps_.emplace_back(std::move(opened_dex_files_map));
+    for (std::unique_ptr<const DexFile>& dex_file : opened_dex_files) {
+      opened_dex_files_.emplace_back(dex_file.release());
+    }
+    return true;
+  }
+
+  void TestDexFileInput(bool verify, bool low_4gb, bool use_profile);
+  void TestZipFileInput(bool verify);
+  void TestZipFileInputWithEmptyDex();
+
+  std::unique_ptr<const InstructionSetFeatures> insn_features_;
+  std::unique_ptr<QuickCompilerCallbacks> callbacks_;
+
+  std::vector<std::unique_ptr<MemMap>> opened_dex_files_maps_;
+  std::vector<std::unique_ptr<const DexFile>> opened_dex_files_;
+};
+
+class ZipBuilder {
+ public:
+  explicit ZipBuilder(File* zip_file) : zip_file_(zip_file) { }
+
+  bool AddFile(const char* location, const void* data, size_t size) {
+    off_t offset = lseek(zip_file_->Fd(), 0, SEEK_CUR);
+    if (offset == static_cast<off_t>(-1)) {
+      return false;
+    }
+
+    ZipFileHeader file_header;
+    file_header.crc32 = crc32(0u, reinterpret_cast<const Bytef*>(data), size);
+    file_header.compressed_size = size;
+    file_header.uncompressed_size = size;
+    file_header.filename_length = strlen(location);
+
+    if (!zip_file_->WriteFully(&file_header, sizeof(file_header)) ||
+        !zip_file_->WriteFully(location, file_header.filename_length) ||
+        !zip_file_->WriteFully(data, size)) {
+      return false;
+    }
+
+    CentralDirectoryFileHeader cdfh;
+    cdfh.crc32 = file_header.crc32;
+    cdfh.compressed_size = size;
+    cdfh.uncompressed_size = size;
+    cdfh.filename_length = file_header.filename_length;
+    cdfh.relative_offset_of_local_file_header = offset;
+    file_data_.push_back(FileData { cdfh, location });
+    return true;
+  }
+
+  bool Finish() {
+    off_t offset = lseek(zip_file_->Fd(), 0, SEEK_CUR);
+    if (offset == static_cast<off_t>(-1)) {
+      return false;
+    }
+
+    size_t central_directory_size = 0u;
+    for (const FileData& file_data : file_data_) {
+      if (!zip_file_->WriteFully(&file_data.cdfh, sizeof(file_data.cdfh)) ||
+          !zip_file_->WriteFully(file_data.location, file_data.cdfh.filename_length)) {
+        return false;
+      }
+      central_directory_size += sizeof(file_data.cdfh) + file_data.cdfh.filename_length;
+    }
+    EndOfCentralDirectoryRecord eocd_record;
+    eocd_record.number_of_central_directory_records_on_this_disk = file_data_.size();
+    eocd_record.total_number_of_central_directory_records = file_data_.size();
+    eocd_record.size_of_central_directory = central_directory_size;
+    eocd_record.offset_of_start_of_central_directory = offset;
+    return
+        zip_file_->WriteFully(&eocd_record, sizeof(eocd_record)) &&
+        zip_file_->Flush() == 0;
+  }
+
+ private:
+  struct PACKED(1) ZipFileHeader {
+    uint32_t signature = 0x04034b50;
+    uint16_t version_needed_to_extract = 10;
+    uint16_t general_purpose_bit_flag = 0;
+    uint16_t compression_method = 0;            // 0 = store only.
+    uint16_t file_last_modification_time = 0u;
+    uint16_t file_last_modification_date = 0u;
+    uint32_t crc32;
+    uint32_t compressed_size;
+    uint32_t uncompressed_size;
+    uint16_t filename_length;
+    uint16_t extra_field_length = 0u;           // No extra fields.
+  };
+
+  struct PACKED(1) CentralDirectoryFileHeader {
+    uint32_t signature = 0x02014b50;
+    uint16_t version_made_by = 10;
+    uint16_t version_needed_to_extract = 10;
+    uint16_t general_purpose_bit_flag = 0;
+    uint16_t compression_method = 0;            // 0 = store only.
+    uint16_t file_last_modification_time = 0u;
+    uint16_t file_last_modification_date = 0u;
+    uint32_t crc32;
+    uint32_t compressed_size;
+    uint32_t uncompressed_size;
+    uint16_t filename_length;
+    uint16_t extra_field_length = 0u;           // No extra fields.
+    uint16_t file_comment_length = 0u;          // No file comment.
+    uint16_t disk_number_where_file_starts = 0u;
+    uint16_t internal_file_attributes = 0u;
+    uint32_t external_file_attributes = 0u;
+    uint32_t relative_offset_of_local_file_header;
+  };
+
+  struct PACKED(1) EndOfCentralDirectoryRecord {
+    uint32_t signature = 0x06054b50;
+    uint16_t number_of_this_disk = 0u;
+    uint16_t disk_where_central_directory_starts = 0u;
+    uint16_t number_of_central_directory_records_on_this_disk;
+    uint16_t total_number_of_central_directory_records;
+    uint32_t size_of_central_directory;
+    uint32_t offset_of_start_of_central_directory;
+    uint16_t comment_length = 0u;               // No file comment.
+  };
+
+  struct FileData {
+    CentralDirectoryFileHeader cdfh;
+    const char* location;
+  };
+
+  File* zip_file_;
+  std::vector<FileData> file_data_;
+};
+
+TEST_F(OatTest, WriteRead) {
+  TimingLogger timings("OatTest::WriteRead", false, false);
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+
+  // TODO: make selectable.
+  Compiler::Kind compiler_kind = Compiler::kQuick;
+  InstructionSet insn_set = kIsTargetBuild ? kThumb2 : kX86;
+  std::string error_msg;
+  SetupCompiler(compiler_kind, insn_set, std::vector<std::string>(), /*out*/ &error_msg);
+
+  jobject class_loader = nullptr;
+  if (kCompile) {
+    TimingLogger timings2("OatTest::WriteRead", false, false);
+    compiler_driver_->SetDexFilesForOatFile(class_linker->GetBootClassPath());
+    compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath(), &timings2);
+  }
+
+  ScratchFile tmp_oat, tmp_vdex(tmp_oat, ".vdex");
+  SafeMap<std::string, std::string> key_value_store;
+  key_value_store.Put(OatHeader::kImageLocationKey, "lue.art");
+  bool success = WriteElf(tmp_vdex.GetFile(),
+                          tmp_oat.GetFile(),
+                          class_linker->GetBootClassPath(),
+                          key_value_store,
+                          false);
+  ASSERT_TRUE(success);
+
+  if (kCompile) {  // OatWriter strips the code, regenerate to compare
+    compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath(), &timings);
+  }
+  std::unique_ptr<OatFile> oat_file(OatFile::Open(tmp_oat.GetFilename(),
+                                                  tmp_oat.GetFilename(),
+                                                  nullptr,
+                                                  nullptr,
+                                                  false,
+                                                  /*low_4gb*/true,
+                                                  nullptr,
+                                                  &error_msg));
+  ASSERT_TRUE(oat_file.get() != nullptr) << error_msg;
+  const OatHeader& oat_header = oat_file->GetOatHeader();
+  ASSERT_TRUE(oat_header.IsValid());
+  ASSERT_EQ(class_linker->GetBootClassPath().size(), oat_header.GetDexFileCount());  // core
+  ASSERT_EQ(42U, oat_header.GetImageFileLocationOatChecksum());
+  ASSERT_EQ(4096U, oat_header.GetImageFileLocationOatDataBegin());
+  ASSERT_EQ("lue.art", std::string(oat_header.GetStoreValueByKey(OatHeader::kImageLocationKey)));
+
+  ASSERT_TRUE(java_lang_dex_file_ != nullptr);
+  const DexFile& dex_file = *java_lang_dex_file_;
+  uint32_t dex_file_checksum = dex_file.GetLocationChecksum();
+  const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation().c_str(),
+                                                                    &dex_file_checksum);
+  ASSERT_TRUE(oat_dex_file != nullptr);
+  CHECK_EQ(dex_file.GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum());
+  ScopedObjectAccess soa(Thread::Current());
+  auto pointer_size = class_linker->GetImagePointerSize();
+  for (size_t i = 0; i < dex_file.NumClassDefs(); i++) {
+    const DexFile::ClassDef& class_def = dex_file.GetClassDef(i);
+    const uint8_t* class_data = dex_file.GetClassData(class_def);
+
+    size_t num_virtual_methods = 0;
+    if (class_data != nullptr) {
+      ClassDataItemIterator it(dex_file, class_data);
+      num_virtual_methods = it.NumVirtualMethods();
+    }
+
+    const char* descriptor = dex_file.GetClassDescriptor(class_def);
+    mirror::Class* klass = class_linker->FindClass(soa.Self(),
+                                                   descriptor,
+                                                   ScopedNullHandle<mirror::ClassLoader>());
+
+    const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(i);
+    CHECK_EQ(mirror::Class::Status::kStatusNotReady, oat_class.GetStatus()) << descriptor;
+    CHECK_EQ(kCompile ? OatClassType::kOatClassAllCompiled : OatClassType::kOatClassNoneCompiled,
+             oat_class.GetType()) << descriptor;
+
+    size_t method_index = 0;
+    for (auto& m : klass->GetDirectMethods(pointer_size)) {
+      CheckMethod(&m, oat_class.GetOatMethod(method_index), dex_file);
+      ++method_index;
+    }
+    size_t visited_virtuals = 0;
+    // TODO We should also check copied methods in this test.
+    for (auto& m : klass->GetDeclaredVirtualMethods(pointer_size)) {
+      if (!klass->IsInterface()) {
+        EXPECT_FALSE(m.IsCopied());
+      }
+      CheckMethod(&m, oat_class.GetOatMethod(method_index), dex_file);
+      ++method_index;
+      ++visited_virtuals;
+    }
+    EXPECT_EQ(visited_virtuals, num_virtual_methods);
+  }
+}
+
+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(76U, sizeof(OatHeader));
+  EXPECT_EQ(4U, sizeof(OatMethodOffsets));
+  EXPECT_EQ(24U, sizeof(OatQuickMethodHeader));
+  EXPECT_EQ(161 * static_cast<size_t>(GetInstructionSetPointerSize(kRuntimeISA)),
+            sizeof(QuickEntryPoints));
+}
+
+TEST_F(OatTest, OatHeaderIsValid) {
+  InstructionSet insn_set = kX86;
+  std::string error_msg;
+  std::unique_ptr<const InstructionSetFeatures> insn_features(
+    InstructionSetFeatures::FromVariant(insn_set, "default", &error_msg));
+  ASSERT_TRUE(insn_features.get() != nullptr) << error_msg;
+  std::unique_ptr<OatHeader> oat_header(OatHeader::Create(insn_set,
+                                                          insn_features.get(),
+                                                          0u,
+                                                          nullptr));
+  ASSERT_NE(oat_header.get(), nullptr);
+  ASSERT_TRUE(oat_header->IsValid());
+
+  char* magic = const_cast<char*>(oat_header->GetMagic());
+  strcpy(magic, "");  // bad magic
+  ASSERT_FALSE(oat_header->IsValid());
+  strcpy(magic, "oat\n000");  // bad version
+  ASSERT_FALSE(oat_header->IsValid());
+}
+
+TEST_F(OatTest, EmptyTextSection) {
+  TimingLogger timings("OatTest::EmptyTextSection", false, false);
+
+  // TODO: make selectable.
+  Compiler::Kind compiler_kind = Compiler::kQuick;
+  InstructionSet insn_set = kRuntimeISA;
+  if (insn_set == kArm) insn_set = kThumb2;
+  std::string error_msg;
+  std::vector<std::string> compiler_options;
+  compiler_options.push_back("--compiler-filter=extract");
+  SetupCompiler(compiler_kind, insn_set, compiler_options, /*out*/ &error_msg);
+
+  jobject class_loader;
+  {
+    ScopedObjectAccess soa(Thread::Current());
+    class_loader = LoadDex("Main");
+  }
+  ASSERT_TRUE(class_loader != nullptr);
+  std::vector<const DexFile*> dex_files = GetDexFiles(class_loader);
+  ASSERT_TRUE(!dex_files.empty());
+
+  ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
+  for (const DexFile* dex_file : dex_files) {
+    ScopedObjectAccess soa(Thread::Current());
+    class_linker->RegisterDexFile(*dex_file,
+                                  soa.Decode<mirror::ClassLoader>(class_loader).Ptr());
+  }
+  compiler_driver_->SetDexFilesForOatFile(dex_files);
+  compiler_driver_->CompileAll(class_loader, dex_files, &timings);
+
+  ScratchFile tmp_oat, tmp_vdex(tmp_oat, ".vdex");
+  SafeMap<std::string, std::string> key_value_store;
+  key_value_store.Put(OatHeader::kImageLocationKey, "test.art");
+  bool success = WriteElf(tmp_vdex.GetFile(), tmp_oat.GetFile(), dex_files, key_value_store, false);
+  ASSERT_TRUE(success);
+
+  std::unique_ptr<OatFile> oat_file(OatFile::Open(tmp_oat.GetFilename(),
+                                                  tmp_oat.GetFilename(),
+                                                  nullptr,
+                                                  nullptr,
+                                                  false,
+                                                  /*low_4gb*/false,
+                                                  nullptr,
+                                                  &error_msg));
+  ASSERT_TRUE(oat_file != nullptr);
+  EXPECT_LT(static_cast<size_t>(oat_file->Size()),
+            static_cast<size_t>(tmp_oat.GetFile()->GetLength()));
+}
+
+static void MaybeModifyDexFileToFail(bool verify, std::unique_ptr<const DexFile>& data) {
+  // If in verify mode (= fail the verifier mode), make sure we fail early. We'll fail already
+  // because of the missing map, but that may lead to out of bounds reads.
+  if (verify) {
+    const_cast<DexFile::Header*>(&data->GetHeader())->checksum_++;
+  }
+}
+
+void OatTest::TestDexFileInput(bool verify, bool low_4gb, bool use_profile) {
+  TimingLogger timings("OatTest::DexFileInput", false, false);
+
+  std::vector<const char*> input_filenames;
+
+  ScratchFile dex_file1;
+  TestDexFileBuilder builder1;
+  builder1.AddField("Lsome.TestClass;", "int", "someField");
+  builder1.AddMethod("Lsome.TestClass;", "()I", "foo");
+  std::unique_ptr<const DexFile> dex_file1_data = builder1.Build(dex_file1.GetFilename());
+
+  MaybeModifyDexFileToFail(verify, dex_file1_data);
+
+  bool success = dex_file1.GetFile()->WriteFully(&dex_file1_data->GetHeader(),
+                                                 dex_file1_data->GetHeader().file_size_);
+  ASSERT_TRUE(success);
+  success = dex_file1.GetFile()->Flush() == 0;
+  ASSERT_TRUE(success);
+  input_filenames.push_back(dex_file1.GetFilename().c_str());
+
+  ScratchFile dex_file2;
+  TestDexFileBuilder builder2;
+  builder2.AddField("Land.AnotherTestClass;", "boolean", "someOtherField");
+  builder2.AddMethod("Land.AnotherTestClass;", "()J", "bar");
+  std::unique_ptr<const DexFile> dex_file2_data = builder2.Build(dex_file2.GetFilename());
+
+  MaybeModifyDexFileToFail(verify, dex_file2_data);
+
+  success = dex_file2.GetFile()->WriteFully(&dex_file2_data->GetHeader(),
+                                            dex_file2_data->GetHeader().file_size_);
+  ASSERT_TRUE(success);
+  success = dex_file2.GetFile()->Flush() == 0;
+  ASSERT_TRUE(success);
+  input_filenames.push_back(dex_file2.GetFilename().c_str());
+
+  ScratchFile oat_file, vdex_file(oat_file, ".vdex");
+  SafeMap<std::string, std::string> key_value_store;
+  key_value_store.Put(OatHeader::kImageLocationKey, "test.art");
+  std::unique_ptr<ProfileCompilationInfo>
+      profile_compilation_info(use_profile ? new ProfileCompilationInfo() : nullptr);
+  success = WriteElf(vdex_file.GetFile(),
+                     oat_file.GetFile(),
+                     input_filenames,
+                     key_value_store,
+                     verify,
+                     profile_compilation_info.get());
+
+  // In verify mode, we expect failure.
+  if (verify) {
+    ASSERT_FALSE(success);
+    return;
+  }
+
+  ASSERT_TRUE(success);
+
+  std::string error_msg;
+  std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(oat_file.GetFilename(),
+                                                         oat_file.GetFilename(),
+                                                         nullptr,
+                                                         nullptr,
+                                                         false,
+                                                         low_4gb,
+                                                         nullptr,
+                                                         &error_msg));
+  if (low_4gb) {
+    uintptr_t begin = reinterpret_cast<uintptr_t>(opened_oat_file->Begin());
+    EXPECT_EQ(begin, static_cast<uint32_t>(begin));
+  }
+  ASSERT_TRUE(opened_oat_file != nullptr);
+  ASSERT_EQ(2u, opened_oat_file->GetOatDexFiles().size());
+  std::unique_ptr<const DexFile> opened_dex_file1 =
+      opened_oat_file->GetOatDexFiles()[0]->OpenDexFile(&error_msg);
+  std::unique_ptr<const DexFile> opened_dex_file2 =
+      opened_oat_file->GetOatDexFiles()[1]->OpenDexFile(&error_msg);
+
+  ASSERT_EQ(dex_file1_data->GetHeader().file_size_, opened_dex_file1->GetHeader().file_size_);
+  ASSERT_EQ(0, memcmp(&dex_file1_data->GetHeader(),
+                      &opened_dex_file1->GetHeader(),
+                      dex_file1_data->GetHeader().file_size_));
+  ASSERT_EQ(dex_file1_data->GetLocation(), opened_dex_file1->GetLocation());
+
+  ASSERT_EQ(dex_file2_data->GetHeader().file_size_, opened_dex_file2->GetHeader().file_size_);
+  ASSERT_EQ(0, memcmp(&dex_file2_data->GetHeader(),
+                      &opened_dex_file2->GetHeader(),
+                      dex_file2_data->GetHeader().file_size_));
+  ASSERT_EQ(dex_file2_data->GetLocation(), opened_dex_file2->GetLocation());
+}
+
+TEST_F(OatTest, DexFileInputCheckOutput) {
+  TestDexFileInput(/*verify*/false, /*low_4gb*/false, /*use_profile*/false);
+}
+
+TEST_F(OatTest, DexFileInputCheckOutputLow4GB) {
+  TestDexFileInput(/*verify*/false, /*low_4gb*/true, /*use_profile*/false);
+}
+
+TEST_F(OatTest, DexFileInputCheckVerifier) {
+  TestDexFileInput(/*verify*/true, /*low_4gb*/false, /*use_profile*/false);
+}
+
+TEST_F(OatTest, DexFileFailsVerifierWithLayout) {
+  TestDexFileInput(/*verify*/true, /*low_4gb*/false, /*use_profile*/true);
+}
+
+void OatTest::TestZipFileInput(bool verify) {
+  TimingLogger timings("OatTest::DexFileInput", false, false);
+
+  ScratchFile zip_file;
+  ZipBuilder zip_builder(zip_file.GetFile());
+
+  ScratchFile dex_file1;
+  TestDexFileBuilder builder1;
+  builder1.AddField("Lsome.TestClass;", "long", "someField");
+  builder1.AddMethod("Lsome.TestClass;", "()D", "foo");
+  std::unique_ptr<const DexFile> dex_file1_data = builder1.Build(dex_file1.GetFilename());
+
+  MaybeModifyDexFileToFail(verify, dex_file1_data);
+
+  bool success = dex_file1.GetFile()->WriteFully(&dex_file1_data->GetHeader(),
+                                                 dex_file1_data->GetHeader().file_size_);
+  ASSERT_TRUE(success);
+  success = dex_file1.GetFile()->Flush() == 0;
+  ASSERT_TRUE(success);
+  success = zip_builder.AddFile("classes.dex",
+                                &dex_file1_data->GetHeader(),
+                                dex_file1_data->GetHeader().file_size_);
+  ASSERT_TRUE(success);
+
+  ScratchFile dex_file2;
+  TestDexFileBuilder builder2;
+  builder2.AddField("Land.AnotherTestClass;", "boolean", "someOtherField");
+  builder2.AddMethod("Land.AnotherTestClass;", "()J", "bar");
+  std::unique_ptr<const DexFile> dex_file2_data = builder2.Build(dex_file2.GetFilename());
+
+  MaybeModifyDexFileToFail(verify, dex_file2_data);
+
+  success = dex_file2.GetFile()->WriteFully(&dex_file2_data->GetHeader(),
+                                            dex_file2_data->GetHeader().file_size_);
+  ASSERT_TRUE(success);
+  success = dex_file2.GetFile()->Flush() == 0;
+  ASSERT_TRUE(success);
+  success = zip_builder.AddFile("classes2.dex",
+                                &dex_file2_data->GetHeader(),
+                                dex_file2_data->GetHeader().file_size_);
+  ASSERT_TRUE(success);
+
+  success = zip_builder.Finish();
+  ASSERT_TRUE(success) << strerror(errno);
+
+  SafeMap<std::string, std::string> key_value_store;
+  key_value_store.Put(OatHeader::kImageLocationKey, "test.art");
+  {
+    // Test using the AddDexFileSource() interface with the zip file.
+    std::vector<const char*> input_filenames { zip_file.GetFilename().c_str() };  // NOLINT [readability/braces] [4]
+
+    ScratchFile oat_file, vdex_file(oat_file, ".vdex");
+    success = WriteElf(vdex_file.GetFile(), oat_file.GetFile(), input_filenames,
+                       key_value_store, verify, /*profile_compilation_info*/nullptr);
+
+    if (verify) {
+      ASSERT_FALSE(success);
+    } else {
+      ASSERT_TRUE(success);
+
+      std::string error_msg;
+      std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(oat_file.GetFilename(),
+                                                             oat_file.GetFilename(),
+                                                             nullptr,
+                                                             nullptr,
+                                                             false,
+                                                             /*low_4gb*/false,
+                                                             nullptr,
+                                                             &error_msg));
+      ASSERT_TRUE(opened_oat_file != nullptr);
+      ASSERT_EQ(2u, opened_oat_file->GetOatDexFiles().size());
+      std::unique_ptr<const DexFile> opened_dex_file1 =
+          opened_oat_file->GetOatDexFiles()[0]->OpenDexFile(&error_msg);
+      std::unique_ptr<const DexFile> opened_dex_file2 =
+          opened_oat_file->GetOatDexFiles()[1]->OpenDexFile(&error_msg);
+
+      ASSERT_EQ(dex_file1_data->GetHeader().file_size_, opened_dex_file1->GetHeader().file_size_);
+      ASSERT_EQ(0, memcmp(&dex_file1_data->GetHeader(),
+                          &opened_dex_file1->GetHeader(),
+                          dex_file1_data->GetHeader().file_size_));
+      ASSERT_EQ(DexFile::GetMultiDexLocation(0, zip_file.GetFilename().c_str()),
+                opened_dex_file1->GetLocation());
+
+      ASSERT_EQ(dex_file2_data->GetHeader().file_size_, opened_dex_file2->GetHeader().file_size_);
+      ASSERT_EQ(0, memcmp(&dex_file2_data->GetHeader(),
+                          &opened_dex_file2->GetHeader(),
+                          dex_file2_data->GetHeader().file_size_));
+      ASSERT_EQ(DexFile::GetMultiDexLocation(1, zip_file.GetFilename().c_str()),
+                opened_dex_file2->GetLocation());
+    }
+  }
+
+  {
+    // Test using the AddZipDexFileSource() interface with the zip file handle.
+    File zip_fd(dup(zip_file.GetFd()), /* check_usage */ false);
+    ASSERT_NE(-1, zip_fd.Fd());
+
+    ScratchFile oat_file, vdex_file(oat_file, ".vdex");
+    success = WriteElf(vdex_file.GetFile(),
+                       oat_file.GetFile(),
+                       std::move(zip_fd),
+                       zip_file.GetFilename().c_str(),
+                       key_value_store,
+                       verify);
+    if (verify) {
+      ASSERT_FALSE(success);
+    } else {
+      ASSERT_TRUE(success);
+
+      std::string error_msg;
+      std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(oat_file.GetFilename(),
+                                                             oat_file.GetFilename(),
+                                                             nullptr,
+                                                             nullptr,
+                                                             false,
+                                                             /*low_4gb*/false,
+                                                             nullptr,
+                                                             &error_msg));
+      ASSERT_TRUE(opened_oat_file != nullptr);
+      ASSERT_EQ(2u, opened_oat_file->GetOatDexFiles().size());
+      std::unique_ptr<const DexFile> opened_dex_file1 =
+          opened_oat_file->GetOatDexFiles()[0]->OpenDexFile(&error_msg);
+      std::unique_ptr<const DexFile> opened_dex_file2 =
+          opened_oat_file->GetOatDexFiles()[1]->OpenDexFile(&error_msg);
+
+      ASSERT_EQ(dex_file1_data->GetHeader().file_size_, opened_dex_file1->GetHeader().file_size_);
+      ASSERT_EQ(0, memcmp(&dex_file1_data->GetHeader(),
+                          &opened_dex_file1->GetHeader(),
+                          dex_file1_data->GetHeader().file_size_));
+      ASSERT_EQ(DexFile::GetMultiDexLocation(0, zip_file.GetFilename().c_str()),
+                opened_dex_file1->GetLocation());
+
+      ASSERT_EQ(dex_file2_data->GetHeader().file_size_, opened_dex_file2->GetHeader().file_size_);
+      ASSERT_EQ(0, memcmp(&dex_file2_data->GetHeader(),
+                          &opened_dex_file2->GetHeader(),
+                          dex_file2_data->GetHeader().file_size_));
+      ASSERT_EQ(DexFile::GetMultiDexLocation(1, zip_file.GetFilename().c_str()),
+                opened_dex_file2->GetLocation());
+    }
+  }
+}
+
+TEST_F(OatTest, ZipFileInputCheckOutput) {
+  TestZipFileInput(false);
+}
+
+TEST_F(OatTest, ZipFileInputCheckVerifier) {
+  TestZipFileInput(true);
+}
+
+void OatTest::TestZipFileInputWithEmptyDex() {
+  ScratchFile zip_file;
+  ZipBuilder zip_builder(zip_file.GetFile());
+  bool success = zip_builder.AddFile("classes.dex", nullptr, 0);
+  ASSERT_TRUE(success);
+  success = zip_builder.Finish();
+  ASSERT_TRUE(success) << strerror(errno);
+
+  SafeMap<std::string, std::string> key_value_store;
+  key_value_store.Put(OatHeader::kImageLocationKey, "test.art");
+  std::vector<const char*> input_filenames { zip_file.GetFilename().c_str() };  // NOLINT [readability/braces] [4]
+  ScratchFile oat_file, vdex_file(oat_file, ".vdex");
+  std::unique_ptr<ProfileCompilationInfo> profile_compilation_info(new ProfileCompilationInfo());
+  success = WriteElf(vdex_file.GetFile(), oat_file.GetFile(), input_filenames,
+                     key_value_store, /*verify*/false, profile_compilation_info.get());
+  ASSERT_FALSE(success);
+}
+
+TEST_F(OatTest, ZipFileInputWithEmptyDex) {
+  TestZipFileInputWithEmptyDex();
+}
+
+TEST_F(OatTest, UpdateChecksum) {
+  InstructionSet insn_set = kX86;
+  std::string error_msg;
+  std::unique_ptr<const InstructionSetFeatures> insn_features(
+    InstructionSetFeatures::FromVariant(insn_set, "default", &error_msg));
+  ASSERT_TRUE(insn_features.get() != nullptr) << error_msg;
+  std::unique_ptr<OatHeader> oat_header(OatHeader::Create(insn_set,
+                                                          insn_features.get(),
+                                                          0u,
+                                                          nullptr));
+  // The starting adler32 value is 1.
+  EXPECT_EQ(1U, oat_header->GetChecksum());
+
+  oat_header->UpdateChecksum(OatHeader::kOatMagic, sizeof(OatHeader::kOatMagic));
+  EXPECT_EQ(64291151U, oat_header->GetChecksum());
+
+  // Make sure that null data does not reset the checksum.
+  oat_header->UpdateChecksum(nullptr, 0);
+  EXPECT_EQ(64291151U, oat_header->GetChecksum());
+
+  oat_header->UpdateChecksum(OatHeader::kOatMagic, sizeof(OatHeader::kOatMagic));
+  EXPECT_EQ(216138397U, oat_header->GetChecksum());
+}
+
+}  // namespace linker
+}  // namespace art
