Major refactoring of ElfBuilder.

Simplify ElfBuilder by removing duplicated or redundant code.
Many of the repeated code patterns were replaced by just
looping over the list of all sections.

Methods Init() and Write() have been merged into one.
The split between those was rather arbitrary, but it was there
for a reason.  It allowed creation of raw sections between
the calls which may have depended on layout decisions done in
Init(), but not in Write() (e.g. knowing of offset of .text).

This has been replaced by more generic solution.
All sections are asked about their size first and complete
file layout is calculated.  Then the sections are asked to
write their content (potentially using the layout information).

This should be pure refactoring CL - the compiler should
produce bit for bit identical output as before.

Change-Id: I281d13d469801bd8288b36b360d200d98a3e92d7
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index 9ff94e9..d679468 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -21,7 +21,6 @@
 
 #include "base/logging.h"
 #include "base/unix_file/fd_file.h"
-#include "buffered_output_stream.h"
 #include "compiled_method.h"
 #include "dex_file-inl.h"
 #include "driver/compiler_driver.h"
@@ -30,7 +29,6 @@
 #include "elf_file.h"
 #include "elf_utils.h"
 #include "elf_writer_debug.h"
-#include "file_output_stream.h"
 #include "globals.h"
 #include "leb128.h"
 #include "oat.h"
@@ -50,20 +48,6 @@
   return elf_writer.Write(oat_writer, dex_files, android_root, is_host);
 }
 
-class OatWriterWrapper FINAL : public CodeOutput {
- public:
-  explicit OatWriterWrapper(OatWriter* oat_writer) : oat_writer_(oat_writer) {}
-
-  void SetCodeOffset(size_t offset) {
-    oat_writer_->SetOatDataOffset(offset);
-  }
-  bool Write(OutputStream* out) OVERRIDE {
-    return oat_writer_->Write(out);
-  }
- private:
-  OatWriter* const oat_writer_;
-};
-
 template <typename ElfTypes>
 static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, OatWriter* oat_writer);
 
@@ -99,18 +83,29 @@
   buffer->push_back(0);  // End of sections.
 }
 
-template<typename AddressType, bool SubtractPatchLocation = false>
-static void PatchAddresses(const std::vector<uintptr_t>* patch_locations,
-                           AddressType delta, std::vector<uint8_t>* buffer) {
-  // Addresses in .debug_* sections are unaligned.
-  typedef __attribute__((__aligned__(1))) AddressType UnalignedAddressType;
-  if (patch_locations != nullptr) {
-    for (uintptr_t patch_location : *patch_locations) {
-      *reinterpret_cast<UnalignedAddressType*>(buffer->data() + patch_location) +=
-          delta - (SubtractPatchLocation ? patch_location : 0);
-    }
+class RodataWriter FINAL : public CodeOutput {
+ public:
+  explicit RodataWriter(OatWriter* oat_writer) : oat_writer_(oat_writer) {}
+
+  bool Write(OutputStream* out) OVERRIDE {
+    return oat_writer_->WriteRodata(out);
   }
-}
+
+ private:
+  OatWriter* oat_writer_;
+};
+
+class TextWriter FINAL : public CodeOutput {
+ public:
+  explicit TextWriter(OatWriter* oat_writer) : oat_writer_(oat_writer) {}
+
+  bool Write(OutputStream* out) OVERRIDE {
+    return oat_writer_->WriteCode(out);
+  }
+
+ private:
+  OatWriter* oat_writer_;
+};
 
 template <typename ElfTypes>
 bool ElfWriterQuick<ElfTypes>::Write(
@@ -118,106 +113,82 @@
     const std::vector<const DexFile*>& dex_files_unused ATTRIBUTE_UNUSED,
     const std::string& android_root_unused ATTRIBUTE_UNUSED,
     bool is_host_unused ATTRIBUTE_UNUSED) {
-  constexpr bool debug = false;
-  const OatHeader& oat_header = oat_writer->GetOatHeader();
-  typename ElfTypes::Word oat_data_size = oat_header.GetExecutableOffset();
-  uint32_t oat_exec_size = oat_writer->GetSize() - oat_data_size;
-  uint32_t oat_bss_size = oat_writer->GetBssSize();
+  const InstructionSet isa = compiler_driver_->GetInstructionSet();
 
-  OatWriterWrapper wrapper(oat_writer);
-
+  // Setup the builder with the main OAT sections (.rodata .text .bss).
+  const size_t rodata_size = oat_writer->GetOatHeader().GetExecutableOffset();
+  const size_t text_size = oat_writer->GetSize() - rodata_size;
+  const size_t bss_size = oat_writer->GetBssSize();
+  RodataWriter rodata_writer(oat_writer);
+  TextWriter text_writer(oat_writer);
   std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(
-      &wrapper,
-      elf_file_,
-      compiler_driver_->GetInstructionSet(),
-      0,
-      oat_data_size,
-      oat_data_size,
-      oat_exec_size,
-      RoundUp(oat_data_size + oat_exec_size, kPageSize),
-      oat_bss_size,
-      compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols(),
-      debug));
+      isa, rodata_size, &rodata_writer, text_size, &text_writer, bss_size));
 
-  InstructionSet isa = compiler_driver_->GetInstructionSet();
-  int alignment = GetInstructionSetPointerSize(isa);
-  typedef typename ElfBuilder<ElfTypes>::ElfRawSectionBuilder RawSection;
-  RawSection eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, alignment, 0);
-  RawSection eh_frame_hdr(".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0);
-  RawSection debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
-  RawSection debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
-  RawSection debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
-  RawSection debug_line(".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
+  // Add debug sections.
+  // They are stack allocated here (in the same scope as the builder),
+  // but they are registred with the builder only if they are used.
+  using RawSection = typename ElfBuilder<ElfTypes>::RawSection;
+  const int pointer_size = GetInstructionSetPointerSize(isa);
+  const auto* text = builder->GetText();
+  constexpr bool absolute = false;  // patch to make absolute addresses.
+  constexpr bool relative = true;  // patch to make relative addresses.
+  const bool is64bit = Is64BitInstructionSet(isa);
+  RawSection eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC,
+                      nullptr, 0, pointer_size, 0, text, relative, is64bit);
+  RawSection eh_frame_hdr(".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC,
+                          nullptr, 0, 4, 0);
+  RawSection debug_info(".debug_info", SHT_PROGBITS, 0,
+                        nullptr, 0, 1, 0, text, absolute, false /* 32bit */);
+  RawSection debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0,
+                          nullptr, 0, 1, 0);
+  RawSection debug_str(".debug_str", SHT_PROGBITS, 0,
+                       nullptr, 0, 1, 0);
+  RawSection debug_line(".debug_line", SHT_PROGBITS, 0,
+                        nullptr, 0, 1, 0, text, absolute, false /* 32bit */);
+  if (!oat_writer->GetMethodDebugInfo().empty()) {
+    if (compiler_driver_->GetCompilerOptions().GetIncludeCFI()) {
+      dwarf::WriteEhFrame(
+          compiler_driver_, oat_writer, dwarf::DW_EH_PE_pcrel,
+          eh_frame.GetBuffer(), eh_frame.GetPatchLocations(),
+          eh_frame_hdr.GetBuffer());
+      builder->RegisterSection(&eh_frame);
+      builder->RegisterSection(&eh_frame_hdr);
+    }
+    if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
+      // Add methods to .symtab.
+      WriteDebugSymbols(builder.get(), oat_writer);
+      // Generate DWARF .debug_* sections.
+      dwarf::WriteDebugSections(
+          compiler_driver_, oat_writer,
+          debug_info.GetBuffer(), debug_info.GetPatchLocations(),
+          debug_abbrev.GetBuffer(),
+          debug_str.GetBuffer(),
+          debug_line.GetBuffer(), debug_line.GetPatchLocations());
+      builder->RegisterSection(&debug_info);
+      builder->RegisterSection(&debug_abbrev);
+      builder->RegisterSection(&debug_str);
+      builder->RegisterSection(&debug_line);
+      *oat_writer->GetAbsolutePatchLocationsFor(".debug_info") =
+          *debug_info.GetPatchLocations();
+      *oat_writer->GetAbsolutePatchLocationsFor(".debug_line") =
+          *debug_line.GetPatchLocations();
+    }
+  }
+
+  // Add relocation section.
   RawSection oat_patches(".oat_patches", SHT_OAT_PATCH, 0, nullptr, 0, 1, 0);
-
-  // Do not add to .oat_patches since we will make the addresses relative.
-  std::vector<uintptr_t> eh_frame_patches;
-  if (compiler_driver_->GetCompilerOptions().GetIncludeCFI() &&
-      !oat_writer->GetMethodDebugInfo().empty()) {
-    dwarf::WriteEhFrame(compiler_driver_, oat_writer,
-                        dwarf::DW_EH_PE_pcrel,
-                        eh_frame.GetBuffer(), &eh_frame_patches,
-                        eh_frame_hdr.GetBuffer());
-    builder->RegisterRawSection(&eh_frame);
-    builder->RegisterRawSection(&eh_frame_hdr);
-  }
-
-  // Must be done after .eh_frame is created since it is used in the Elf layout.
-  if (!builder->Init()) {
-    return false;
-  }
-
-  std::vector<uintptr_t>* debug_info_patches = nullptr;
-  std::vector<uintptr_t>* debug_line_patches = nullptr;
-  if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols() &&
-      !oat_writer->GetMethodDebugInfo().empty()) {
-    // Add methods to .symtab.
-    WriteDebugSymbols(builder.get(), oat_writer);
-    // Generate DWARF .debug_* sections.
-    debug_info_patches = oat_writer->GetAbsolutePatchLocationsFor(".debug_info");
-    debug_line_patches = oat_writer->GetAbsolutePatchLocationsFor(".debug_line");
-    dwarf::WriteDebugSections(compiler_driver_, oat_writer,
-                              debug_info.GetBuffer(), debug_info_patches,
-                              debug_abbrev.GetBuffer(),
-                              debug_str.GetBuffer(),
-                              debug_line.GetBuffer(), debug_line_patches);
-    builder->RegisterRawSection(&debug_info);
-    builder->RegisterRawSection(&debug_abbrev);
-    builder->RegisterRawSection(&debug_str);
-    builder->RegisterRawSection(&debug_line);
-  }
-
   if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation() ||
       // ElfWriter::Fixup will be called regardless and it needs to be able
       // to patch debug sections so we have to include patches for them.
       compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
     EncodeOatPatches(oat_writer->GetAbsolutePatchLocations(), oat_patches.GetBuffer());
-    builder->RegisterRawSection(&oat_patches);
+    builder->RegisterSection(&oat_patches);
   }
 
-  // We know where .text and .eh_frame will be located, so patch the addresses.
-  typename ElfTypes::Addr text_addr = builder->GetTextBuilder().GetSection()->sh_addr;
-  // TODO: Simplify once we use Elf64 - we can use ElfTypes::Addr instead of branching.
-  if (Is64BitInstructionSet(compiler_driver_->GetInstructionSet())) {
-    // relative_address = (text_addr + address) - (eh_frame_addr + patch_location);
-    PatchAddresses<uint64_t, true>(&eh_frame_patches,
-        text_addr - eh_frame.GetSection()->sh_addr, eh_frame.GetBuffer());
-    PatchAddresses<uint64_t>(debug_info_patches, text_addr, debug_info.GetBuffer());
-    PatchAddresses<uint64_t>(debug_line_patches, text_addr, debug_line.GetBuffer());
-  } else {
-    // relative_address = (text_addr + address) - (eh_frame_addr + patch_location);
-    PatchAddresses<uint32_t, true>(&eh_frame_patches,
-        text_addr - eh_frame.GetSection()->sh_addr, eh_frame.GetBuffer());
-    PatchAddresses<uint32_t>(debug_info_patches, text_addr, debug_info.GetBuffer());
-    PatchAddresses<uint32_t>(debug_line_patches, text_addr, debug_line.GetBuffer());
-  }
-
-  return builder->Write();
+  return builder->Write(elf_file_);
 }
 
 template <typename ElfTypes>
-// Do not inline to avoid Clang stack frame problems. b/18738594
-NO_INLINE
 static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, OatWriter* oat_writer) {
   const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetMethodDebugInfo();
 
@@ -230,7 +201,7 @@
     }
   }
 
-  auto* symtab = builder->GetSymtabBuilder();
+  auto* symtab = builder->GetSymtab();
   for (auto it = method_info.begin(); it != method_info.end(); ++it) {
     std::string name = PrettyMethod(it->dex_method_index_, *it->dex_file_, true);
     if (deduped_addresses.find(it->low_pc_) != deduped_addresses.end()) {
@@ -240,13 +211,13 @@
     uint32_t low_pc = it->low_pc_;
     // Add in code delta, e.g., thumb bit 0 for Thumb2 code.
     low_pc += it->compiled_method_->CodeDelta();
-    symtab->AddSymbol(name, &builder->GetTextBuilder(), low_pc,
+    symtab->AddSymbol(name, builder->GetText(), low_pc,
                       true, it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC);
 
     // Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2
     // instructions, so that disassembler tools can correctly disassemble.
     if (it->compiled_method_->GetInstructionSet() == kThumb2) {
-      symtab->AddSymbol("$t", &builder->GetTextBuilder(), it->low_pc_ & ~1, true,
+      symtab->AddSymbol("$t", builder->GetText(), it->low_pc_ & ~1, true,
                         0, STB_LOCAL, STT_NOTYPE);
     }
   }