Refactor linker files from compiler/ to dex2oat/.

This shifts some code from the libart-compiler.so to dex2oat
and reduces memory needed for JIT. We also avoid loading the
libart-dexlayout.so for JIT but the memory savings are
minimal (one shared clean page, two shared dirty pages and
some per-app kernel mmap data) as the code has never been
needed in memory by JIT.

aosp_angler-userdebug file sizes (stripped):
  lib64/libart-compiler.so: 2989112 -> 2671888 (-310KiB)
  lib/libart-compiler.so: 2160816 -> 1939276 (-216KiB)
  bin/dex2oat: 141868 -> 368808 (+222KiB)
LOAD/executable elf mapping sizes:
  lib64/libart-compiler.so: 2866308 -> 2555500 (-304KiB)
  lib/libart-compiler.so: 2050960 -> 1834836 (-211KiB)
  bin/dex2oat: 129316 -> 345916 (+212KiB)

Test: m test-art-host-gtest
Test: testrunner.py --host
Test: cd art/; mma; cd -
Change-Id: If62f02847a6cbb208eaf7e1f3e91af4663fa4a5f
diff --git a/compiler/linker/buffered_output_stream.cc b/compiler/linker/buffered_output_stream.cc
index 4c66c76..07066b7 100644
--- a/compiler/linker/buffered_output_stream.cc
+++ b/compiler/linker/buffered_output_stream.cc
@@ -19,6 +19,7 @@
 #include <string.h>
 
 namespace art {
+namespace linker {
 
 BufferedOutputStream::BufferedOutputStream(std::unique_ptr<OutputStream> out)
     : OutputStream(out->GetLocation()),  // Before out is moved to out_.
@@ -67,4 +68,5 @@
   return out_->Seek(offset, whence);
 }
 
+}  // namespace linker
 }  // namespace art
diff --git a/compiler/linker/buffered_output_stream.h b/compiler/linker/buffered_output_stream.h
index a2eefbb..66994e8 100644
--- a/compiler/linker/buffered_output_stream.h
+++ b/compiler/linker/buffered_output_stream.h
@@ -24,6 +24,7 @@
 #include "globals.h"
 
 namespace art {
+namespace linker {
 
 class BufferedOutputStream FINAL : public OutputStream {
  public:
@@ -49,6 +50,7 @@
   DISALLOW_COPY_AND_ASSIGN(BufferedOutputStream);
 };
 
+}  // namespace linker
 }  // namespace art
 
 #endif  // ART_COMPILER_LINKER_BUFFERED_OUTPUT_STREAM_H_
diff --git a/compiler/linker/elf_builder.h b/compiler/linker/elf_builder.h
new file mode 100644
index 0000000..7941237
--- /dev/null
+++ b/compiler/linker/elf_builder.h
@@ -0,0 +1,1028 @@
+/*
+ * Copyright (C) 2015 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_COMPILER_LINKER_ELF_BUILDER_H_
+#define ART_COMPILER_LINKER_ELF_BUILDER_H_
+
+#include <vector>
+
+#include "arch/instruction_set.h"
+#include "arch/mips/instruction_set_features_mips.h"
+#include "base/array_ref.h"
+#include "base/bit_utils.h"
+#include "base/casts.h"
+#include "base/unix_file/fd_file.h"
+#include "elf_utils.h"
+#include "leb128.h"
+#include "linker/error_delaying_output_stream.h"
+
+namespace art {
+namespace linker {
+
+// Writes ELF file.
+//
+// The basic layout of the elf file:
+//   Elf_Ehdr                    - The ELF header.
+//   Elf_Phdr[]                  - Program headers for the linker.
+//   .note.gnu.build-id          - Optional build ID section (SHA-1 digest).
+//   .rodata                     - DEX files and oat metadata.
+//   .text                       - Compiled code.
+//   .bss                        - Zero-initialized writeable section.
+//   .MIPS.abiflags              - MIPS specific section.
+//   .dynstr                     - Names for .dynsym.
+//   .dynsym                     - A few oat-specific dynamic symbols.
+//   .hash                       - Hash-table for .dynsym.
+//   .dynamic                    - Tags which let the linker locate .dynsym.
+//   .strtab                     - Names for .symtab.
+//   .symtab                     - Debug symbols.
+//   .eh_frame                   - Unwind information (CFI).
+//   .eh_frame_hdr               - Index of .eh_frame.
+//   .debug_frame                - Unwind information (CFI).
+//   .debug_frame.oat_patches    - Addresses for relocation.
+//   .debug_info                 - Debug information.
+//   .debug_info.oat_patches     - Addresses for relocation.
+//   .debug_abbrev               - Decoding information for .debug_info.
+//   .debug_str                  - Strings for .debug_info.
+//   .debug_line                 - Line number tables.
+//   .debug_line.oat_patches     - Addresses for relocation.
+//   .text.oat_patches           - Addresses for relocation.
+//   .shstrtab                   - Names of ELF sections.
+//   Elf_Shdr[]                  - Section headers.
+//
+// Some section are optional (the debug sections in particular).
+//
+// We try write the section data directly into the file without much
+// in-memory buffering.  This means we generally write sections based on the
+// dependency order (e.g. .dynamic points to .dynsym which points to .text).
+//
+// In the cases where we need to buffer, we write the larger section first
+// and buffer the smaller one (e.g. .strtab is bigger than .symtab).
+//
+// The debug sections are written last for easier stripping.
+//
+template <typename ElfTypes>
+class ElfBuilder FINAL {
+ public:
+  static constexpr size_t kMaxProgramHeaders = 16;
+  // SHA-1 digest.  Not using SHA_DIGEST_LENGTH from openssl/sha.h to avoid
+  // spreading this header dependency for just this single constant.
+  static constexpr size_t kBuildIdLen = 20;
+
+  using Elf_Addr = typename ElfTypes::Addr;
+  using Elf_Off = typename ElfTypes::Off;
+  using Elf_Word = typename ElfTypes::Word;
+  using Elf_Sword = typename ElfTypes::Sword;
+  using Elf_Ehdr = typename ElfTypes::Ehdr;
+  using Elf_Shdr = typename ElfTypes::Shdr;
+  using Elf_Sym = typename ElfTypes::Sym;
+  using Elf_Phdr = typename ElfTypes::Phdr;
+  using Elf_Dyn = typename ElfTypes::Dyn;
+
+  // Base class of all sections.
+  class Section : public OutputStream {
+   public:
+    Section(ElfBuilder<ElfTypes>* owner,
+            const std::string& name,
+            Elf_Word type,
+            Elf_Word flags,
+            const Section* link,
+            Elf_Word info,
+            Elf_Word align,
+            Elf_Word entsize)
+        : OutputStream(name),
+          owner_(owner),
+          header_(),
+          section_index_(0),
+          name_(name),
+          link_(link),
+          started_(false),
+          finished_(false),
+          phdr_flags_(PF_R),
+          phdr_type_(0) {
+      DCHECK_GE(align, 1u);
+      header_.sh_type = type;
+      header_.sh_flags = flags;
+      header_.sh_info = info;
+      header_.sh_addralign = align;
+      header_.sh_entsize = entsize;
+    }
+
+    // Start writing of this section.
+    void Start() {
+      CHECK(!started_);
+      CHECK(!finished_);
+      started_ = true;
+      auto& sections = owner_->sections_;
+      // Check that the previous section is complete.
+      CHECK(sections.empty() || sections.back()->finished_);
+      // The first ELF section index is 1. Index 0 is reserved for NULL.
+      section_index_ = sections.size() + 1;
+      // Page-align if we switch between allocated and non-allocated sections,
+      // or if we change the type of allocation (e.g. executable vs non-executable).
+      if (!sections.empty()) {
+        if (header_.sh_flags != sections.back()->header_.sh_flags) {
+          header_.sh_addralign = kPageSize;
+        }
+      }
+      // Align file position.
+      if (header_.sh_type != SHT_NOBITS) {
+        header_.sh_offset = owner_->AlignFileOffset(header_.sh_addralign);
+      } else {
+        header_.sh_offset = 0;
+      }
+      // Align virtual memory address.
+      if ((header_.sh_flags & SHF_ALLOC) != 0) {
+        header_.sh_addr = owner_->AlignVirtualAddress(header_.sh_addralign);
+      } else {
+        header_.sh_addr = 0;
+      }
+      // Push this section on the list of written sections.
+      sections.push_back(this);
+    }
+
+    // Finish writing of this section.
+    void End() {
+      CHECK(started_);
+      CHECK(!finished_);
+      finished_ = true;
+      if (header_.sh_type == SHT_NOBITS) {
+        CHECK_GT(header_.sh_size, 0u);
+      } else {
+        // Use the current file position to determine section size.
+        off_t file_offset = owner_->stream_.Seek(0, kSeekCurrent);
+        CHECK_GE(file_offset, (off_t)header_.sh_offset);
+        header_.sh_size = file_offset - header_.sh_offset;
+      }
+      if ((header_.sh_flags & SHF_ALLOC) != 0) {
+        owner_->virtual_address_ += header_.sh_size;
+      }
+    }
+
+    // Get the location of this section in virtual memory.
+    Elf_Addr GetAddress() const {
+      CHECK(started_);
+      return header_.sh_addr;
+    }
+
+    // Returns the size of the content of this section.
+    Elf_Word GetSize() const {
+      if (finished_) {
+        return header_.sh_size;
+      } else {
+        CHECK(started_);
+        CHECK_NE(header_.sh_type, (Elf_Word)SHT_NOBITS);
+        return owner_->stream_.Seek(0, kSeekCurrent) - header_.sh_offset;
+      }
+    }
+
+    // Write this section as "NOBITS" section. (used for the .bss section)
+    // This means that the ELF file does not contain the initial data for this section
+    // and it will be zero-initialized when the ELF file is loaded in the running program.
+    void WriteNoBitsSection(Elf_Word size) {
+      DCHECK_NE(header_.sh_flags & SHF_ALLOC, 0u);
+      header_.sh_type = SHT_NOBITS;
+      Start();
+      header_.sh_size = size;
+      End();
+    }
+
+    // This function always succeeds to simplify code.
+    // Use builder's Good() to check the actual status.
+    bool WriteFully(const void* buffer, size_t byte_count) OVERRIDE {
+      CHECK(started_);
+      CHECK(!finished_);
+      return owner_->stream_.WriteFully(buffer, byte_count);
+    }
+
+    // This function always succeeds to simplify code.
+    // Use builder's Good() to check the actual status.
+    off_t Seek(off_t offset, Whence whence) OVERRIDE {
+      // Forward the seek as-is and trust the caller to use it reasonably.
+      return owner_->stream_.Seek(offset, whence);
+    }
+
+    // This function flushes the output and returns whether it succeeded.
+    // If there was a previous failure, this does nothing and returns false, i.e. failed.
+    bool Flush() OVERRIDE {
+      return owner_->stream_.Flush();
+    }
+
+    Elf_Word GetSectionIndex() const {
+      DCHECK(started_);
+      DCHECK_NE(section_index_, 0u);
+      return section_index_;
+    }
+
+   private:
+    ElfBuilder<ElfTypes>* owner_;
+    Elf_Shdr header_;
+    Elf_Word section_index_;
+    const std::string name_;
+    const Section* const link_;
+    bool started_;
+    bool finished_;
+    Elf_Word phdr_flags_;
+    Elf_Word phdr_type_;
+
+    friend class ElfBuilder;
+
+    DISALLOW_COPY_AND_ASSIGN(Section);
+  };
+
+  class CachedSection : public Section {
+   public:
+    CachedSection(ElfBuilder<ElfTypes>* owner,
+                  const std::string& name,
+                  Elf_Word type,
+                  Elf_Word flags,
+                  const Section* link,
+                  Elf_Word info,
+                  Elf_Word align,
+                  Elf_Word entsize)
+        : Section(owner, name, type, flags, link, info, align, entsize), cache_() { }
+
+    Elf_Word Add(const void* data, size_t length) {
+      Elf_Word offset = cache_.size();
+      const uint8_t* d = reinterpret_cast<const uint8_t*>(data);
+      cache_.insert(cache_.end(), d, d + length);
+      return offset;
+    }
+
+    Elf_Word GetCacheSize() {
+      return cache_.size();
+    }
+
+    void Write() {
+      this->WriteFully(cache_.data(), cache_.size());
+      cache_.clear();
+      cache_.shrink_to_fit();
+    }
+
+    void WriteCachedSection() {
+      this->Start();
+      Write();
+      this->End();
+    }
+
+   private:
+    std::vector<uint8_t> cache_;
+  };
+
+  // Writer of .dynstr section.
+  class CachedStringSection FINAL : public CachedSection {
+   public:
+    CachedStringSection(ElfBuilder<ElfTypes>* owner,
+                        const std::string& name,
+                        Elf_Word flags,
+                        Elf_Word align)
+        : CachedSection(owner,
+                        name,
+                        SHT_STRTAB,
+                        flags,
+                        /* link */ nullptr,
+                        /* info */ 0,
+                        align,
+                        /* entsize */ 0) { }
+
+    Elf_Word Add(const std::string& name) {
+      if (CachedSection::GetCacheSize() == 0u) {
+        DCHECK(name.empty());
+      }
+      return CachedSection::Add(name.c_str(), name.length() + 1);
+    }
+  };
+
+  // Writer of .strtab and .shstrtab sections.
+  class StringSection FINAL : public Section {
+   public:
+    StringSection(ElfBuilder<ElfTypes>* owner,
+                  const std::string& name,
+                  Elf_Word flags,
+                  Elf_Word align)
+        : Section(owner,
+                  name,
+                  SHT_STRTAB,
+                  flags,
+                  /* link */ nullptr,
+                  /* info */ 0,
+                  align,
+                  /* entsize */ 0),
+          current_offset_(0) {
+    }
+
+    Elf_Word Write(const std::string& name) {
+      if (current_offset_ == 0) {
+        DCHECK(name.empty());
+      }
+      Elf_Word offset = current_offset_;
+      this->WriteFully(name.c_str(), name.length() + 1);
+      current_offset_ += name.length() + 1;
+      return offset;
+    }
+
+   private:
+    Elf_Word current_offset_;
+  };
+
+  // Writer of .dynsym and .symtab sections.
+  class SymbolSection FINAL : public CachedSection {
+   public:
+    SymbolSection(ElfBuilder<ElfTypes>* owner,
+                  const std::string& name,
+                  Elf_Word type,
+                  Elf_Word flags,
+                  Section* strtab)
+        : CachedSection(owner,
+                        name,
+                        type,
+                        flags,
+                        strtab,
+                        /* info */ 0,
+                        sizeof(Elf_Off),
+                        sizeof(Elf_Sym)) {
+      // The symbol table always has to start with NULL symbol.
+      Elf_Sym null_symbol = Elf_Sym();
+      CachedSection::Add(&null_symbol, sizeof(null_symbol));
+    }
+
+    // Buffer symbol for this section.  It will be written later.
+    // If the symbol's section is null, it will be considered absolute (SHN_ABS).
+    // (we use this in JIT to reference code which is stored outside the debug ELF file)
+    void Add(Elf_Word name,
+             const Section* section,
+             Elf_Addr addr,
+             Elf_Word size,
+             uint8_t binding,
+             uint8_t type) {
+      Elf_Word section_index;
+      if (section != nullptr) {
+        DCHECK_LE(section->GetAddress(), addr);
+        DCHECK_LE(addr, section->GetAddress() + section->GetSize());
+        section_index = section->GetSectionIndex();
+      } else {
+        section_index = static_cast<Elf_Word>(SHN_ABS);
+      }
+      Add(name, section_index, addr, size, binding, type);
+    }
+
+    void Add(Elf_Word name,
+             Elf_Word section_index,
+             Elf_Addr addr,
+             Elf_Word size,
+             uint8_t binding,
+             uint8_t type) {
+      Elf_Sym sym = Elf_Sym();
+      sym.st_name = name;
+      sym.st_value = addr;
+      sym.st_size = size;
+      sym.st_other = 0;
+      sym.st_shndx = section_index;
+      sym.st_info = (binding << 4) + (type & 0xf);
+      CachedSection::Add(&sym, sizeof(sym));
+    }
+  };
+
+  class AbiflagsSection FINAL : public Section {
+   public:
+    // Section with Mips abiflag info.
+    static constexpr uint8_t MIPS_AFL_REG_NONE =         0;  // no registers
+    static constexpr uint8_t MIPS_AFL_REG_32 =           1;  // 32-bit registers
+    static constexpr uint8_t MIPS_AFL_REG_64 =           2;  // 64-bit registers
+    static constexpr uint32_t MIPS_AFL_FLAGS1_ODDSPREG = 1;  // Uses odd single-prec fp regs
+    static constexpr uint8_t MIPS_ABI_FP_DOUBLE =        1;  // -mdouble-float
+    static constexpr uint8_t MIPS_ABI_FP_XX =            5;  // -mfpxx
+    static constexpr uint8_t MIPS_ABI_FP_64A =           7;  // -mips32r* -mfp64 -mno-odd-spreg
+
+    AbiflagsSection(ElfBuilder<ElfTypes>* owner,
+                    const std::string& name,
+                    Elf_Word type,
+                    Elf_Word flags,
+                    const Section* link,
+                    Elf_Word info,
+                    Elf_Word align,
+                    Elf_Word entsize,
+                    InstructionSet isa,
+                    const InstructionSetFeatures* features)
+        : Section(owner, name, type, flags, link, info, align, entsize) {
+      if (isa == kMips || isa == kMips64) {
+        bool fpu32 = false;    // assume mips64 values
+        uint8_t isa_rev = 6;   // assume mips64 values
+        if (isa == kMips) {
+          // adjust for mips32 values
+          fpu32 = features->AsMipsInstructionSetFeatures()->Is32BitFloatingPoint();
+          isa_rev = features->AsMipsInstructionSetFeatures()->IsR6()
+              ? 6
+              : features->AsMipsInstructionSetFeatures()->IsMipsIsaRevGreaterThanEqual2()
+                  ? (fpu32 ? 2 : 5)
+                  : 1;
+        }
+        abiflags_.version = 0;  // version of flags structure
+        abiflags_.isa_level = (isa == kMips) ? 32 : 64;
+        abiflags_.isa_rev = isa_rev;
+        abiflags_.gpr_size = (isa == kMips) ? MIPS_AFL_REG_32 : MIPS_AFL_REG_64;
+        abiflags_.cpr1_size = fpu32 ? MIPS_AFL_REG_32 : MIPS_AFL_REG_64;
+        abiflags_.cpr2_size = MIPS_AFL_REG_NONE;
+        // Set the fp_abi to MIPS_ABI_FP_64A for mips32 with 64-bit FPUs (ie: mips32 R5 and R6).
+        // Otherwise set to MIPS_ABI_FP_DOUBLE.
+        abiflags_.fp_abi = (isa == kMips && !fpu32) ? MIPS_ABI_FP_64A : MIPS_ABI_FP_DOUBLE;
+        abiflags_.isa_ext = 0;
+        abiflags_.ases = 0;
+        // To keep the code simple, we are not using odd FP reg for single floats for both
+        // mips32 and mips64 ART. Therefore we are not setting the MIPS_AFL_FLAGS1_ODDSPREG bit.
+        abiflags_.flags1 = 0;
+        abiflags_.flags2 = 0;
+      }
+    }
+
+    Elf_Word GetSize() const {
+      return sizeof(abiflags_);
+    }
+
+    void Write() {
+      this->WriteFully(&abiflags_, sizeof(abiflags_));
+    }
+
+   private:
+    struct {
+      uint16_t version;  // version of this structure
+      uint8_t  isa_level, isa_rev, gpr_size, cpr1_size, cpr2_size;
+      uint8_t  fp_abi;
+      uint32_t isa_ext, ases, flags1, flags2;
+    } abiflags_;
+  };
+
+  class BuildIdSection FINAL : public Section {
+   public:
+    BuildIdSection(ElfBuilder<ElfTypes>* owner,
+                   const std::string& name,
+                   Elf_Word type,
+                   Elf_Word flags,
+                   const Section* link,
+                   Elf_Word info,
+                   Elf_Word align,
+                   Elf_Word entsize)
+        : Section(owner, name, type, flags, link, info, align, entsize),
+          digest_start_(-1) {
+    }
+
+    void Write() {
+      // The size fields are 32-bit on both 32-bit and 64-bit systems, confirmed
+      // with the 64-bit linker and libbfd code. The size of name and desc must
+      // be a multiple of 4 and it currently is.
+      this->WriteUint32(4);  // namesz.
+      this->WriteUint32(kBuildIdLen);  // descsz.
+      this->WriteUint32(3);  // type = NT_GNU_BUILD_ID.
+      this->WriteFully("GNU", 4);  // name.
+      digest_start_ = this->Seek(0, kSeekCurrent);
+      static_assert(kBuildIdLen % 4 == 0, "expecting a mutliple of 4 for build ID length");
+      this->WriteFully(std::string(kBuildIdLen, '\0').c_str(), kBuildIdLen);  // desc.
+    }
+
+    off_t GetDigestStart() {
+      CHECK_GT(digest_start_, 0);
+      return digest_start_;
+    }
+
+   private:
+    bool WriteUint32(uint32_t v) {
+      return this->WriteFully(&v, sizeof(v));
+    }
+
+    // File offset where the build ID digest starts.
+    // Populated with zeros first, then updated with the actual value as the
+    // very last thing in the output file creation.
+    off_t digest_start_;
+  };
+
+  ElfBuilder(InstructionSet isa, const InstructionSetFeatures* features, OutputStream* output)
+      : isa_(isa),
+        features_(features),
+        stream_(output),
+        rodata_(this, ".rodata", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0),
+        text_(this, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, nullptr, 0, kPageSize, 0),
+        bss_(this, ".bss", SHT_NOBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0),
+        dynstr_(this, ".dynstr", SHF_ALLOC, kPageSize),
+        dynsym_(this, ".dynsym", SHT_DYNSYM, SHF_ALLOC, &dynstr_),
+        hash_(this, ".hash", SHT_HASH, SHF_ALLOC, &dynsym_, 0, sizeof(Elf_Word), sizeof(Elf_Word)),
+        dynamic_(this, ".dynamic", SHT_DYNAMIC, SHF_ALLOC, &dynstr_, 0, kPageSize, sizeof(Elf_Dyn)),
+        eh_frame_(this, ".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0),
+        eh_frame_hdr_(this, ".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0),
+        strtab_(this, ".strtab", 0, 1),
+        symtab_(this, ".symtab", SHT_SYMTAB, 0, &strtab_),
+        debug_frame_(this, ".debug_frame", SHT_PROGBITS, 0, nullptr, 0, sizeof(Elf_Addr), 0),
+        debug_info_(this, ".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0),
+        debug_line_(this, ".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0),
+        shstrtab_(this, ".shstrtab", 0, 1),
+        abiflags_(this, ".MIPS.abiflags", SHT_MIPS_ABIFLAGS, SHF_ALLOC, nullptr, 0, kPageSize, 0,
+                  isa, features),
+        build_id_(this, ".note.gnu.build-id", SHT_NOTE, SHF_ALLOC, nullptr, 0, 4, 0),
+        started_(false),
+        write_program_headers_(false),
+        loaded_size_(0u),
+        virtual_address_(0) {
+    text_.phdr_flags_ = PF_R | PF_X;
+    bss_.phdr_flags_ = PF_R | PF_W;
+    dynamic_.phdr_flags_ = PF_R | PF_W;
+    dynamic_.phdr_type_ = PT_DYNAMIC;
+    eh_frame_hdr_.phdr_type_ = PT_GNU_EH_FRAME;
+    abiflags_.phdr_type_ = PT_MIPS_ABIFLAGS;
+    build_id_.phdr_type_ = PT_NOTE;
+  }
+  ~ElfBuilder() {}
+
+  InstructionSet GetIsa() { return isa_; }
+  Section* GetRoData() { return &rodata_; }
+  Section* GetText() { return &text_; }
+  Section* GetBss() { return &bss_; }
+  StringSection* GetStrTab() { return &strtab_; }
+  SymbolSection* GetSymTab() { return &symtab_; }
+  Section* GetEhFrame() { return &eh_frame_; }
+  Section* GetEhFrameHdr() { return &eh_frame_hdr_; }
+  Section* GetDebugFrame() { return &debug_frame_; }
+  Section* GetDebugInfo() { return &debug_info_; }
+  Section* GetDebugLine() { return &debug_line_; }
+
+  // Encode patch locations as LEB128 list of deltas between consecutive addresses.
+  // (exposed publicly for tests)
+  static void EncodeOatPatches(const ArrayRef<const uintptr_t>& locations,
+                               std::vector<uint8_t>* buffer) {
+    buffer->reserve(buffer->size() + locations.size() * 2);  // guess 2 bytes per ULEB128.
+    uintptr_t address = 0;  // relative to start of section.
+    for (uintptr_t location : locations) {
+      DCHECK_GE(location, address) << "Patch locations are not in sorted order";
+      EncodeUnsignedLeb128(buffer, dchecked_integral_cast<uint32_t>(location - address));
+      address = location;
+    }
+  }
+
+  void WritePatches(const char* name, const ArrayRef<const uintptr_t>& patch_locations) {
+    std::vector<uint8_t> buffer;
+    EncodeOatPatches(patch_locations, &buffer);
+    std::unique_ptr<Section> s(new Section(this, name, SHT_OAT_PATCH, 0, nullptr, 0, 1, 0));
+    s->Start();
+    s->WriteFully(buffer.data(), buffer.size());
+    s->End();
+    other_sections_.push_back(std::move(s));
+  }
+
+  void WriteSection(const char* name, const std::vector<uint8_t>* buffer) {
+    std::unique_ptr<Section> s(new Section(this, name, SHT_PROGBITS, 0, nullptr, 0, 1, 0));
+    s->Start();
+    s->WriteFully(buffer->data(), buffer->size());
+    s->End();
+    other_sections_.push_back(std::move(s));
+  }
+
+  // Reserve space for ELF header and program headers.
+  // We do not know the number of headers until later, so
+  // it is easiest to just reserve a fixed amount of space.
+  // Program headers are required for loading by the linker.
+  // It is possible to omit them for ELF files used for debugging.
+  void Start(bool write_program_headers = true) {
+    int size = sizeof(Elf_Ehdr);
+    if (write_program_headers) {
+      size += sizeof(Elf_Phdr) * kMaxProgramHeaders;
+    }
+    stream_.Seek(size, kSeekSet);
+    started_ = true;
+    virtual_address_ += size;
+    write_program_headers_ = write_program_headers;
+  }
+
+  void End() {
+    DCHECK(started_);
+
+    // Note: loaded_size_ == 0 for tests that don't write .rodata, .text, .bss,
+    // .dynstr, dynsym, .hash and .dynamic. These tests should not read loaded_size_.
+    // TODO: Either refactor the .eh_frame creation so that it counts towards loaded_size_,
+    // or remove all support for .eh_frame. (The currently unused .eh_frame counts towards
+    // the virtual_address_ but we don't consider it for loaded_size_.)
+    CHECK(loaded_size_ == 0 || loaded_size_ == RoundUp(virtual_address_, kPageSize))
+        << loaded_size_ << " " << virtual_address_;
+
+    // Write section names and finish the section headers.
+    shstrtab_.Start();
+    shstrtab_.Write("");
+    for (auto* section : sections_) {
+      section->header_.sh_name = shstrtab_.Write(section->name_);
+      if (section->link_ != nullptr) {
+        section->header_.sh_link = section->link_->GetSectionIndex();
+      }
+    }
+    shstrtab_.End();
+
+    // Write section headers at the end of the ELF file.
+    std::vector<Elf_Shdr> shdrs;
+    shdrs.reserve(1u + sections_.size());
+    shdrs.push_back(Elf_Shdr());  // NULL at index 0.
+    for (auto* section : sections_) {
+      shdrs.push_back(section->header_);
+    }
+    Elf_Off section_headers_offset;
+    section_headers_offset = AlignFileOffset(sizeof(Elf_Off));
+    stream_.WriteFully(shdrs.data(), shdrs.size() * sizeof(shdrs[0]));
+
+    // Flush everything else before writing the program headers. This should prevent
+    // the OS from reordering writes, so that we don't end up with valid headers
+    // and partially written data if we suddenly lose power, for example.
+    stream_.Flush();
+
+    // The main ELF header.
+    Elf_Ehdr elf_header = MakeElfHeader(isa_, features_);
+    elf_header.e_shoff = section_headers_offset;
+    elf_header.e_shnum = shdrs.size();
+    elf_header.e_shstrndx = shstrtab_.GetSectionIndex();
+
+    // Program headers (i.e. mmap instructions).
+    std::vector<Elf_Phdr> phdrs;
+    if (write_program_headers_) {
+      phdrs = MakeProgramHeaders();
+      CHECK_LE(phdrs.size(), kMaxProgramHeaders);
+      elf_header.e_phoff = sizeof(Elf_Ehdr);
+      elf_header.e_phnum = phdrs.size();
+    }
+
+    stream_.Seek(0, kSeekSet);
+    stream_.WriteFully(&elf_header, sizeof(elf_header));
+    stream_.WriteFully(phdrs.data(), phdrs.size() * sizeof(phdrs[0]));
+    stream_.Flush();
+  }
+
+  // The running program does not have access to section headers
+  // and the loader is not supposed to use them either.
+  // The dynamic sections therefore replicates some of the layout
+  // information like the address and size of .rodata and .text.
+  // It also contains other metadata like the SONAME.
+  // The .dynamic section is found using the PT_DYNAMIC program header.
+  void PrepareDynamicSection(const std::string& elf_file_path,
+                             Elf_Word rodata_size,
+                             Elf_Word text_size,
+                             Elf_Word bss_size,
+                             Elf_Word bss_methods_offset,
+                             Elf_Word bss_roots_offset) {
+    std::string soname(elf_file_path);
+    size_t directory_separator_pos = soname.rfind('/');
+    if (directory_separator_pos != std::string::npos) {
+      soname = soname.substr(directory_separator_pos + 1);
+    }
+
+    // Calculate addresses of .text, .bss and .dynstr.
+    DCHECK_EQ(rodata_.header_.sh_addralign, static_cast<Elf_Word>(kPageSize));
+    DCHECK_EQ(text_.header_.sh_addralign, static_cast<Elf_Word>(kPageSize));
+    DCHECK_EQ(bss_.header_.sh_addralign, static_cast<Elf_Word>(kPageSize));
+    DCHECK_EQ(dynstr_.header_.sh_addralign, static_cast<Elf_Word>(kPageSize));
+    Elf_Word rodata_address = rodata_.GetAddress();
+    Elf_Word text_address = RoundUp(rodata_address + rodata_size, kPageSize);
+    Elf_Word bss_address = RoundUp(text_address + text_size, kPageSize);
+    Elf_Word abiflags_address = RoundUp(bss_address + bss_size, kPageSize);
+    Elf_Word abiflags_size = 0;
+    if (isa_ == kMips || isa_ == kMips64) {
+      abiflags_size = abiflags_.GetSize();
+    }
+    Elf_Word dynstr_address = RoundUp(abiflags_address + abiflags_size, kPageSize);
+
+    // Cache .dynstr, .dynsym and .hash data.
+    dynstr_.Add("");  // dynstr should start with empty string.
+    Elf_Word rodata_index = rodata_.GetSectionIndex();
+    Elf_Word oatdata = dynstr_.Add("oatdata");
+    dynsym_.Add(oatdata, rodata_index, rodata_address, rodata_size, STB_GLOBAL, STT_OBJECT);
+    if (text_size != 0u) {
+      Elf_Word text_index = rodata_index + 1u;
+      Elf_Word oatexec = dynstr_.Add("oatexec");
+      dynsym_.Add(oatexec, text_index, text_address, text_size, STB_GLOBAL, STT_OBJECT);
+      Elf_Word oatlastword = dynstr_.Add("oatlastword");
+      Elf_Word oatlastword_address = text_address + text_size - 4;
+      dynsym_.Add(oatlastword, text_index, oatlastword_address, 4, STB_GLOBAL, STT_OBJECT);
+    } else if (rodata_size != 0) {
+      // rodata_ can be size 0 for dwarf_test.
+      Elf_Word oatlastword = dynstr_.Add("oatlastword");
+      Elf_Word oatlastword_address = rodata_address + rodata_size - 4;
+      dynsym_.Add(oatlastword, rodata_index, oatlastword_address, 4, STB_GLOBAL, STT_OBJECT);
+    }
+    DCHECK_LE(bss_roots_offset, bss_size);
+    if (bss_size != 0u) {
+      Elf_Word bss_index = rodata_index + 1u + (text_size != 0 ? 1u : 0u);
+      Elf_Word oatbss = dynstr_.Add("oatbss");
+      dynsym_.Add(oatbss, bss_index, bss_address, bss_roots_offset, STB_GLOBAL, STT_OBJECT);
+      DCHECK_LE(bss_methods_offset, bss_roots_offset);
+      DCHECK_LE(bss_roots_offset, bss_size);
+      // Add a symbol marking the start of the methods part of the .bss, if not empty.
+      if (bss_methods_offset != bss_roots_offset) {
+        Elf_Word bss_methods_address = bss_address + bss_methods_offset;
+        Elf_Word bss_methods_size = bss_roots_offset - bss_methods_offset;
+        Elf_Word oatbssroots = dynstr_.Add("oatbssmethods");
+        dynsym_.Add(
+            oatbssroots, bss_index, bss_methods_address, bss_methods_size, STB_GLOBAL, STT_OBJECT);
+      }
+      // Add a symbol marking the start of the GC roots part of the .bss, if not empty.
+      if (bss_roots_offset != bss_size) {
+        Elf_Word bss_roots_address = bss_address + bss_roots_offset;
+        Elf_Word bss_roots_size = bss_size - bss_roots_offset;
+        Elf_Word oatbssroots = dynstr_.Add("oatbssroots");
+        dynsym_.Add(
+            oatbssroots, bss_index, bss_roots_address, bss_roots_size, STB_GLOBAL, STT_OBJECT);
+      }
+      Elf_Word oatbsslastword = dynstr_.Add("oatbsslastword");
+      Elf_Word bsslastword_address = bss_address + bss_size - 4;
+      dynsym_.Add(oatbsslastword, bss_index, bsslastword_address, 4, STB_GLOBAL, STT_OBJECT);
+    }
+    Elf_Word soname_offset = dynstr_.Add(soname);
+
+    // We do not really need a hash-table since there is so few entries.
+    // However, the hash-table is the only way the linker can actually
+    // determine the number of symbols in .dynsym so it is required.
+    int count = dynsym_.GetCacheSize() / sizeof(Elf_Sym);  // Includes NULL.
+    std::vector<Elf_Word> hash;
+    hash.push_back(1);  // Number of buckets.
+    hash.push_back(count);  // Number of chains.
+    // Buckets.  Having just one makes it linear search.
+    hash.push_back(1);  // Point to first non-NULL symbol.
+    // Chains.  This creates linked list of symbols.
+    hash.push_back(0);  // Dummy entry for the NULL symbol.
+    for (int i = 1; i < count - 1; i++) {
+      hash.push_back(i + 1);  // Each symbol points to the next one.
+    }
+    hash.push_back(0);  // Last symbol terminates the chain.
+    hash_.Add(hash.data(), hash.size() * sizeof(hash[0]));
+
+    // Calculate addresses of .dynsym, .hash and .dynamic.
+    DCHECK_EQ(dynstr_.header_.sh_flags, dynsym_.header_.sh_flags);
+    DCHECK_EQ(dynsym_.header_.sh_flags, hash_.header_.sh_flags);
+    Elf_Word dynsym_address =
+        RoundUp(dynstr_address + dynstr_.GetCacheSize(), dynsym_.header_.sh_addralign);
+    Elf_Word hash_address =
+        RoundUp(dynsym_address + dynsym_.GetCacheSize(), hash_.header_.sh_addralign);
+    DCHECK_EQ(dynamic_.header_.sh_addralign, static_cast<Elf_Word>(kPageSize));
+    Elf_Word dynamic_address = RoundUp(hash_address + dynsym_.GetCacheSize(), kPageSize);
+
+    Elf_Dyn dyns[] = {
+      { DT_HASH, { hash_address } },
+      { DT_STRTAB, { dynstr_address } },
+      { DT_SYMTAB, { dynsym_address } },
+      { DT_SYMENT, { sizeof(Elf_Sym) } },
+      { DT_STRSZ, { dynstr_.GetCacheSize() } },
+      { DT_SONAME, { soname_offset } },
+      { DT_NULL, { 0 } },
+    };
+    dynamic_.Add(&dyns, sizeof(dyns));
+
+    loaded_size_ = RoundUp(dynamic_address + dynamic_.GetCacheSize(), kPageSize);
+  }
+
+  void WriteDynamicSection() {
+    dynstr_.WriteCachedSection();
+    dynsym_.WriteCachedSection();
+    hash_.WriteCachedSection();
+    dynamic_.WriteCachedSection();
+
+    CHECK_EQ(loaded_size_, RoundUp(dynamic_.GetAddress() + dynamic_.GetSize(), kPageSize));
+  }
+
+  Elf_Word GetLoadedSize() {
+    CHECK_NE(loaded_size_, 0u);
+    return loaded_size_;
+  }
+
+  void WriteMIPSabiflagsSection() {
+    abiflags_.Start();
+    abiflags_.Write();
+    abiflags_.End();
+  }
+
+  void WriteBuildIdSection() {
+    build_id_.Start();
+    build_id_.Write();
+    build_id_.End();
+  }
+
+  void WriteBuildId(uint8_t build_id[kBuildIdLen]) {
+    stream_.Seek(build_id_.GetDigestStart(), kSeekSet);
+    stream_.WriteFully(build_id, kBuildIdLen);
+  }
+
+  // Returns true if all writes and seeks on the output stream succeeded.
+  bool Good() {
+    return stream_.Good();
+  }
+
+  // Returns the builder's internal stream.
+  OutputStream* GetStream() {
+    return &stream_;
+  }
+
+  off_t AlignFileOffset(size_t alignment) {
+     return stream_.Seek(RoundUp(stream_.Seek(0, kSeekCurrent), alignment), kSeekSet);
+  }
+
+  Elf_Addr AlignVirtualAddress(size_t alignment) {
+     return virtual_address_ = RoundUp(virtual_address_, alignment);
+  }
+
+ private:
+  static Elf_Ehdr MakeElfHeader(InstructionSet isa, const InstructionSetFeatures* features) {
+    Elf_Ehdr elf_header = Elf_Ehdr();
+    switch (isa) {
+      case kArm:
+        // Fall through.
+      case kThumb2: {
+        elf_header.e_machine = EM_ARM;
+        elf_header.e_flags = EF_ARM_EABI_VER5;
+        break;
+      }
+      case kArm64: {
+        elf_header.e_machine = EM_AARCH64;
+        elf_header.e_flags = 0;
+        break;
+      }
+      case kX86: {
+        elf_header.e_machine = EM_386;
+        elf_header.e_flags = 0;
+        break;
+      }
+      case kX86_64: {
+        elf_header.e_machine = EM_X86_64;
+        elf_header.e_flags = 0;
+        break;
+      }
+      case kMips: {
+        elf_header.e_machine = EM_MIPS;
+        elf_header.e_flags = (EF_MIPS_NOREORDER |
+                              EF_MIPS_PIC       |
+                              EF_MIPS_CPIC      |
+                              EF_MIPS_ABI_O32   |
+                              (features->AsMipsInstructionSetFeatures()->IsR6()
+                                   ? EF_MIPS_ARCH_32R6
+                                   : EF_MIPS_ARCH_32R2));
+        break;
+      }
+      case kMips64: {
+        elf_header.e_machine = EM_MIPS;
+        elf_header.e_flags = (EF_MIPS_NOREORDER |
+                              EF_MIPS_PIC       |
+                              EF_MIPS_CPIC      |
+                              EF_MIPS_ARCH_64R6);
+        break;
+      }
+      case kNone: {
+        LOG(FATAL) << "No instruction set";
+        break;
+      }
+      default: {
+        LOG(FATAL) << "Unknown instruction set " << isa;
+      }
+    }
+
+    elf_header.e_ident[EI_MAG0]       = ELFMAG0;
+    elf_header.e_ident[EI_MAG1]       = ELFMAG1;
+    elf_header.e_ident[EI_MAG2]       = ELFMAG2;
+    elf_header.e_ident[EI_MAG3]       = ELFMAG3;
+    elf_header.e_ident[EI_CLASS]      = (sizeof(Elf_Addr) == sizeof(Elf32_Addr))
+                                         ? ELFCLASS32 : ELFCLASS64;
+    elf_header.e_ident[EI_DATA]       = ELFDATA2LSB;
+    elf_header.e_ident[EI_VERSION]    = EV_CURRENT;
+    elf_header.e_ident[EI_OSABI]      = ELFOSABI_LINUX;
+    elf_header.e_ident[EI_ABIVERSION] = 0;
+    elf_header.e_type = ET_DYN;
+    elf_header.e_version = 1;
+    elf_header.e_entry = 0;
+    elf_header.e_ehsize = sizeof(Elf_Ehdr);
+    elf_header.e_phentsize = sizeof(Elf_Phdr);
+    elf_header.e_shentsize = sizeof(Elf_Shdr);
+    elf_header.e_phoff = sizeof(Elf_Ehdr);
+    return elf_header;
+  }
+
+  // Create program headers based on written sections.
+  std::vector<Elf_Phdr> MakeProgramHeaders() {
+    CHECK(!sections_.empty());
+    std::vector<Elf_Phdr> phdrs;
+    {
+      // The program headers must start with PT_PHDR which is used in
+      // loaded process to determine the number of program headers.
+      Elf_Phdr phdr = Elf_Phdr();
+      phdr.p_type    = PT_PHDR;
+      phdr.p_flags   = PF_R;
+      phdr.p_offset  = phdr.p_vaddr = phdr.p_paddr = sizeof(Elf_Ehdr);
+      phdr.p_filesz  = phdr.p_memsz = 0;  // We need to fill this later.
+      phdr.p_align   = sizeof(Elf_Off);
+      phdrs.push_back(phdr);
+      // Tell the linker to mmap the start of file to memory.
+      Elf_Phdr load = Elf_Phdr();
+      load.p_type    = PT_LOAD;
+      load.p_flags   = PF_R;
+      load.p_offset  = load.p_vaddr = load.p_paddr = 0;
+      load.p_filesz  = load.p_memsz = sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * kMaxProgramHeaders;
+      load.p_align   = kPageSize;
+      phdrs.push_back(load);
+    }
+    // Create program headers for sections.
+    for (auto* section : sections_) {
+      const Elf_Shdr& shdr = section->header_;
+      if ((shdr.sh_flags & SHF_ALLOC) != 0 && shdr.sh_size != 0) {
+        // PT_LOAD tells the linker to mmap part of the file.
+        // The linker can only mmap page-aligned sections.
+        // Single PT_LOAD may contain several ELF sections.
+        Elf_Phdr& prev = phdrs.back();
+        Elf_Phdr load = Elf_Phdr();
+        load.p_type   = PT_LOAD;
+        load.p_flags  = section->phdr_flags_;
+        load.p_offset = shdr.sh_offset;
+        load.p_vaddr  = load.p_paddr = shdr.sh_addr;
+        load.p_filesz = (shdr.sh_type != SHT_NOBITS ? shdr.sh_size : 0u);
+        load.p_memsz  = shdr.sh_size;
+        load.p_align  = shdr.sh_addralign;
+        if (prev.p_type == load.p_type &&
+            prev.p_flags == load.p_flags &&
+            prev.p_filesz == prev.p_memsz &&  // Do not merge .bss
+            load.p_filesz == load.p_memsz) {  // Do not merge .bss
+          // Merge this PT_LOAD with the previous one.
+          Elf_Word size = shdr.sh_offset + shdr.sh_size - prev.p_offset;
+          prev.p_filesz = size;
+          prev.p_memsz  = size;
+        } else {
+          // If we are adding new load, it must be aligned.
+          CHECK_EQ(shdr.sh_addralign, (Elf_Word)kPageSize);
+          phdrs.push_back(load);
+        }
+      }
+    }
+    for (auto* section : sections_) {
+      const Elf_Shdr& shdr = section->header_;
+      if ((shdr.sh_flags & SHF_ALLOC) != 0 && shdr.sh_size != 0) {
+        // Other PT_* types allow the program to locate interesting
+        // parts of memory at runtime. They must overlap with PT_LOAD.
+        if (section->phdr_type_ != 0) {
+          Elf_Phdr phdr = Elf_Phdr();
+          phdr.p_type   = section->phdr_type_;
+          phdr.p_flags  = section->phdr_flags_;
+          phdr.p_offset = shdr.sh_offset;
+          phdr.p_vaddr  = phdr.p_paddr = shdr.sh_addr;
+          phdr.p_filesz = phdr.p_memsz = shdr.sh_size;
+          phdr.p_align  = shdr.sh_addralign;
+          phdrs.push_back(phdr);
+        }
+      }
+    }
+    // Set the size of the initial PT_PHDR.
+    CHECK_EQ(phdrs[0].p_type, (Elf_Word)PT_PHDR);
+    phdrs[0].p_filesz = phdrs[0].p_memsz = phdrs.size() * sizeof(Elf_Phdr);
+
+    return phdrs;
+  }
+
+  InstructionSet isa_;
+  const InstructionSetFeatures* features_;
+
+  ErrorDelayingOutputStream stream_;
+
+  Section rodata_;
+  Section text_;
+  Section bss_;
+  CachedStringSection dynstr_;
+  SymbolSection dynsym_;
+  CachedSection hash_;
+  CachedSection dynamic_;
+  Section eh_frame_;
+  Section eh_frame_hdr_;
+  StringSection strtab_;
+  SymbolSection symtab_;
+  Section debug_frame_;
+  Section debug_info_;
+  Section debug_line_;
+  StringSection shstrtab_;
+  AbiflagsSection abiflags_;
+  BuildIdSection build_id_;
+  std::vector<std::unique_ptr<Section>> other_sections_;
+
+  // List of used section in the order in which they were written.
+  std::vector<Section*> sections_;
+
+  bool started_;
+  bool write_program_headers_;
+
+  // The size of the memory taken by the ELF file when loaded.
+  size_t loaded_size_;
+
+  // Used for allocation of virtual address space.
+  Elf_Addr virtual_address_;
+
+  DISALLOW_COPY_AND_ASSIGN(ElfBuilder);
+};
+
+}  // namespace linker
+}  // namespace art
+
+#endif  // ART_COMPILER_LINKER_ELF_BUILDER_H_
diff --git a/compiler/linker/error_delaying_output_stream.h b/compiler/linker/error_delaying_output_stream.h
index 99410e4..33e6b5a 100644
--- a/compiler/linker/error_delaying_output_stream.h
+++ b/compiler/linker/error_delaying_output_stream.h
@@ -22,6 +22,7 @@
 #include "base/logging.h"
 
 namespace art {
+namespace linker {
 
 // OutputStream wrapper that delays reporting an error until Flush().
 class ErrorDelayingOutputStream FINAL : public OutputStream {
@@ -96,6 +97,7 @@
   off_t output_offset_;  // Keep track of the current position in the stream.
 };
 
+}  // namespace linker
 }  // namespace art
 
 #endif  // ART_COMPILER_LINKER_ERROR_DELAYING_OUTPUT_STREAM_H_
diff --git a/compiler/linker/file_output_stream.cc b/compiler/linker/file_output_stream.cc
index bbfbdfd..477846e 100644
--- a/compiler/linker/file_output_stream.cc
+++ b/compiler/linker/file_output_stream.cc
@@ -22,6 +22,7 @@
 #include "base/unix_file/fd_file.h"
 
 namespace art {
+namespace linker {
 
 FileOutputStream::FileOutputStream(File* file) : OutputStream(file->GetPath()), file_(file) {}
 
@@ -37,4 +38,5 @@
   return file_->Flush() == 0;
 }
 
+}  // namespace linker
 }  // namespace art
diff --git a/compiler/linker/file_output_stream.h b/compiler/linker/file_output_stream.h
index f2d8453..28296a4 100644
--- a/compiler/linker/file_output_stream.h
+++ b/compiler/linker/file_output_stream.h
@@ -22,6 +22,7 @@
 #include "os.h"
 
 namespace art {
+namespace linker {
 
 class FileOutputStream FINAL : public OutputStream {
  public:
@@ -41,6 +42,7 @@
   DISALLOW_COPY_AND_ASSIGN(FileOutputStream);
 };
 
+}  // namespace linker
 }  // namespace art
 
 #endif  // ART_COMPILER_LINKER_FILE_OUTPUT_STREAM_H_
diff --git a/compiler/linker/multi_oat_relative_patcher.cc b/compiler/linker/multi_oat_relative_patcher.cc
deleted file mode 100644
index 4ae75d6..0000000
--- a/compiler/linker/multi_oat_relative_patcher.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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_(
-          linker::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/compiler/linker/multi_oat_relative_patcher.h b/compiler/linker/multi_oat_relative_patcher.h
deleted file mode 100644
index 02cd4b0..0000000
--- a/compiler/linker/multi_oat_relative_patcher.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * 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_COMPILER_LINKER_MULTI_OAT_RELATIVE_PATCHER_H_
-#define ART_COMPILER_LINKER_MULTI_OAT_RELATIVE_PATCHER_H_
-
-#include "arch/instruction_set.h"
-#include "debug/method_debug_info.h"
-#include "method_reference.h"
-#include "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 linker::RelativePatcherTargetProvider.
-  class MethodOffsetMap : public linker::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_COMPILER_LINKER_MULTI_OAT_RELATIVE_PATCHER_H_
diff --git a/compiler/linker/multi_oat_relative_patcher_test.cc b/compiler/linker/multi_oat_relative_patcher_test.cc
deleted file mode 100644
index 5c359dc..0000000
--- a/compiler/linker/multi_oat_relative_patcher_test.cc
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * 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 "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/compiler/linker/output_stream.cc b/compiler/linker/output_stream.cc
index a8b64ca..f5a1913 100644
--- a/compiler/linker/output_stream.cc
+++ b/compiler/linker/output_stream.cc
@@ -17,6 +17,7 @@
 #include "output_stream.h"
 
 namespace art {
+namespace linker {
 
 std::ostream& operator<<(std::ostream& os, const Whence& rhs) {
   switch (rhs) {
@@ -28,4 +29,5 @@
   return os;
 }
 
+}  // namespace linker
 }  // namespace art
diff --git a/compiler/linker/output_stream.h b/compiler/linker/output_stream.h
index 96a5f48..5310e2f 100644
--- a/compiler/linker/output_stream.h
+++ b/compiler/linker/output_stream.h
@@ -23,6 +23,7 @@
 #include "base/macros.h"
 
 namespace art {
+namespace linker {
 
 enum Whence {
   kSeekSet = SEEK_SET,
@@ -59,6 +60,7 @@
   DISALLOW_COPY_AND_ASSIGN(OutputStream);
 };
 
+}  // namespace linker
 }  // namespace art
 
 #endif  // ART_COMPILER_LINKER_OUTPUT_STREAM_H_
diff --git a/compiler/linker/output_stream_test.cc b/compiler/linker/output_stream_test.cc
index 87cb100..ad29840 100644
--- a/compiler/linker/output_stream_test.cc
+++ b/compiler/linker/output_stream_test.cc
@@ -23,6 +23,7 @@
 #include "common_runtime_test.h"
 
 namespace art {
+namespace linker {
 
 class OutputStreamTest : public CommonRuntimeTest {
  protected:
@@ -133,4 +134,5 @@
   ASSERT_TRUE(checking_output_stream->flush_called);
 }
 
+}  // namespace linker
 }  // namespace art
diff --git a/compiler/linker/relative_patcher.h b/compiler/linker/relative_patcher.h
index 53a0966..e079946 100644
--- a/compiler/linker/relative_patcher.h
+++ b/compiler/linker/relative_patcher.h
@@ -29,7 +29,6 @@
 
 class CompiledMethod;
 class LinkerPatch;
-class OutputStream;
 
 namespace debug {
 struct MethodDebugInfo;
@@ -37,6 +36,8 @@
 
 namespace linker {
 
+class OutputStream;
+
 /**
  * @class RelativePatcherTargetProvider
  * @brief Interface for providing method offsets for relative call targets.
diff --git a/compiler/linker/relative_patcher_test.h b/compiler/linker/relative_patcher_test.h
index ca8743a..f7dbc1e 100644
--- a/compiler/linker/relative_patcher_test.h
+++ b/compiler/linker/relative_patcher_test.h
@@ -252,8 +252,8 @@
   }
 
   // Map method reference to assinged offset.
-  // Wrap the map in a class implementing linker::RelativePatcherTargetProvider.
-  class MethodOffsetMap FINAL : public linker::RelativePatcherTargetProvider {
+  // Wrap the map in a class implementing RelativePatcherTargetProvider.
+  class MethodOffsetMap FINAL : public RelativePatcherTargetProvider {
    public:
     std::pair<bool, uint32_t> FindMethodOffset(MethodReference ref) OVERRIDE {
       auto it = map.find(ref);
diff --git a/compiler/linker/vector_output_stream.cc b/compiler/linker/vector_output_stream.cc
index f758005..75f90e5 100644
--- a/compiler/linker/vector_output_stream.cc
+++ b/compiler/linker/vector_output_stream.cc
@@ -19,6 +19,7 @@
 #include "base/logging.h"
 
 namespace art {
+namespace linker {
 
 VectorOutputStream::VectorOutputStream(const std::string& location, std::vector<uint8_t>* vector)
     : OutputStream(location), offset_(vector->size()), vector_(vector) {}
@@ -45,4 +46,5 @@
   return offset_;
 }
 
+}  // namespace linker
 }  // namespace art
diff --git a/compiler/linker/vector_output_stream.h b/compiler/linker/vector_output_stream.h
index a9b93e7..92caf59 100644
--- a/compiler/linker/vector_output_stream.h
+++ b/compiler/linker/vector_output_stream.h
@@ -24,6 +24,7 @@
 #include <vector>
 
 namespace art {
+namespace linker {
 
 class VectorOutputStream FINAL : public OutputStream {
  public:
@@ -64,6 +65,7 @@
   DISALLOW_COPY_AND_ASSIGN(VectorOutputStream);
 };
 
+}  // namespace linker
 }  // namespace art
 
 #endif  // ART_COMPILER_LINKER_VECTOR_OUTPUT_STREAM_H_