Refactor ElfDebugReader.

Make the code more flexible, which I will need for
future mini-debug-info work.

Bug: 110133331
Test: ./art/test.py -b -r -t 137
Change-Id: I8b0fe3c43537f546f2ff103bff3c63a59a0f940a
diff --git a/compiler/debug/elf_debug_writer.cc b/compiler/debug/elf_debug_writer.cc
index fd638b7..3b7363b 100644
--- a/compiler/debug/elf_debug_writer.cc
+++ b/compiler/debug/elf_debug_writer.cc
@@ -203,25 +203,26 @@
   // Verify the ELF file by reading it back using the trivial reader.
   if (kIsDebugBuild) {
     using Elf_Sym = typename ElfTypes::Sym;
-    using Elf_Addr = typename ElfTypes::Addr;
     size_t num_syms = 0;
-    size_t num_cfis = 0;
-    ReadElfSymbols<ElfTypes>(
-        buffer.data(),
-        [&](Elf_Sym sym, const char*) {
-          DCHECK_EQ(sym.st_value, method_info.code_address + CompiledMethod::CodeDelta(isa));
-          DCHECK_EQ(sym.st_size, method_info.code_size);
-          num_syms++;
-        },
-        [&](Elf_Addr addr, Elf_Addr size, ArrayRef<const uint8_t> opcodes) {
-          DCHECK_EQ(addr, method_info.code_address);
-          DCHECK_EQ(size, method_info.code_size);
-          DCHECK_GE(opcodes.size(), method_info.cfi.size());
-          DCHECK_EQ(memcmp(opcodes.data(), method_info.cfi.data(), method_info.cfi.size()), 0);
-          num_cfis++;
-        });
+    size_t num_cies = 0;
+    size_t num_fdes = 0;
+    using Reader = ElfDebugReader<ElfTypes>;
+    Reader reader(buffer);
+    reader.VisitFunctionSymbols([&](Elf_Sym sym, const char*) {
+      DCHECK_EQ(sym.st_value, method_info.code_address + CompiledMethod::CodeDelta(isa));
+      DCHECK_EQ(sym.st_size, method_info.code_size);
+      num_syms++;
+    });
+    reader.VisitDebugFrame([&](const Reader::CIE* cie ATTRIBUTE_UNUSED) {
+      num_cies++;
+    }, [&](const Reader::FDE* fde, const Reader::CIE* cie ATTRIBUTE_UNUSED) {
+      DCHECK_EQ(fde->sym_addr, method_info.code_address);
+      DCHECK_EQ(fde->sym_size, method_info.code_size);
+      num_fdes++;
+    });
     DCHECK_EQ(num_syms, 1u);
-    DCHECK_EQ(num_cfis, 1u);
+    DCHECK_LE(num_cies, 1u);
+    DCHECK_LE(num_fdes, 1u);
   }
   return buffer;
 }
@@ -230,14 +231,13 @@
 std::vector<uint8_t> PackElfFileForJIT(
     InstructionSet isa,
     const InstructionSetFeatures* features,
-    std::vector<const uint8_t*>& added_elf_files,
+    std::vector<ArrayRef<const uint8_t>>& added_elf_files,
     std::vector<const void*>& removed_symbols,
     /*out*/ size_t* num_symbols) {
   using ElfTypes = ElfRuntimeTypes;
   using Elf_Addr = typename ElfTypes::Addr;
   using Elf_Sym = typename ElfTypes::Sym;
   CHECK_EQ(sizeof(Elf_Addr), static_cast<size_t>(GetInstructionSetPointerSize(isa)));
-  const bool is64bit = Is64BitInstructionSet(isa);
   auto is_removed_symbol = [&removed_symbols](Elf_Addr addr) {
     const void* code_ptr = reinterpret_cast<const void*>(addr);
     return std::binary_search(removed_symbols.begin(), removed_symbols.end(), code_ptr);
@@ -259,35 +259,26 @@
     auto* symtab = builder->GetSymTab();
     auto* debug_frame = builder->GetDebugFrame();
     std::deque<Elf_Sym> symbols;
-    std::vector<uint8_t> debug_frame_buffer;
-    WriteCIE(isa, &debug_frame_buffer);
+
+    using Reader = ElfDebugReader<ElfTypes>;
+    std::deque<Reader> readers;
+    for (ArrayRef<const uint8_t> added_elf_file : added_elf_files) {
+      readers.emplace_back(added_elf_file);
+    }
 
     // Write symbols names. All other data is buffered.
     strtab->Start();
     strtab->Write("");  // strtab should start with empty string.
-    for (const uint8_t* added_elf_file : added_elf_files) {
-      ReadElfSymbols<ElfTypes>(
-          added_elf_file,
-          [&](Elf_Sym sym, const char* name) {
-              if (is_removed_symbol(sym.st_value)) {
-                return;
-              }
-              sym.st_name = strtab->Write(name);
-              symbols.push_back(sym);
-              min_address = std::min<uint64_t>(min_address, sym.st_value);
-              max_address = std::max<uint64_t>(max_address, sym.st_value + sym.st_size);
-          },
-          [&](Elf_Addr addr, Elf_Addr size, ArrayRef<const uint8_t> opcodes) {
-              if (is_removed_symbol(addr)) {
-                return;
-              }
-              dwarf::WriteFDE(is64bit,
-                              /* cie_pointer= */ 0,
-                              addr,
-                              size,
-                              opcodes,
-                              &debug_frame_buffer);
-          });
+    for (Reader& reader : readers) {
+      reader.VisitFunctionSymbols([&](Elf_Sym sym, const char* name) {
+          if (is_removed_symbol(sym.st_value)) {
+            return;
+          }
+          sym.st_name = strtab->Write(name);
+          symbols.push_back(sym);
+          min_address = std::min<uint64_t>(min_address, sym.st_value);
+          max_address = std::max<uint64_t>(max_address, sym.st_value + sym.st_size);
+      });
     }
     strtab->End();
 
@@ -305,7 +296,22 @@
 
     // Add the CFI/unwind section.
     debug_frame->Start();
-    debug_frame->WriteFully(debug_frame_buffer.data(), debug_frame_buffer.size());
+    // ART always produces the same CIE, so we copy the first one and ignore the rest.
+    bool copied_cie = false;
+    for (Reader& reader : readers) {
+      reader.VisitDebugFrame([&](const Reader::CIE* cie) {
+        if (!copied_cie) {
+          debug_frame->WriteFully(cie->data(), cie->size());
+          copied_cie = true;
+        }
+      }, [&](const Reader::FDE* fde, const Reader::CIE* cie ATTRIBUTE_UNUSED) {
+        DCHECK(copied_cie);
+        DCHECK_EQ(fde->cie_pointer, 0);
+        if (!is_removed_symbol(fde->sym_addr)) {
+          debug_frame->WriteFully(fde->data(), fde->size());
+        }
+      });
+    }
     debug_frame->End();
 
     builder->End();