Support generation of CFI in .debug_frame format.

.debug_frame section is almost identical to .eh_frame section.
There are only minor differences in the CIE and FDE headers.
The main difference is that .eh_frame is intended to be used
at runtime for exception handling and is therefore allocated
within the running program whereas .debug_frame is not.

This makes .debug_frame easier to remove using standard tools.
"objcopy --strip-debug" removes .debug_frame, but not .eh_frame.
(although objcopy can be still be forced to remove .eh_frame)

Similarly, we might want to separate the CFI to separate debug
file or include it as compressed .gnu_debugdata section.
It is more appropriate to use .debug_frame for this purpose.

Bug:20556771
Change-Id: I9d91a333b9fb37523fd6fafccfad89b21d2477af
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index 79f9955..96dd7ca 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -37,6 +37,14 @@
 
 namespace art {
 
+// .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.
+constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_EH_FRAME_FORMAT;
+
 template <typename ElfTypes>
 bool ElfWriterQuick<ElfTypes>::Create(File* elf_file,
                                       OatWriter* oat_writer,
@@ -161,12 +169,17 @@
   using RawSection = typename ElfBuilder<ElfTypes>::RawSection;
   const auto* text = builder->GetText();
   const bool is64bit = Is64BitInstructionSet(isa);
+  const int pointer_size = GetInstructionSetPointerSize(isa);
   RawSection eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0,
                       is64bit ? Patch<Elf_Addr, uint64_t, kPointerRelativeAddress> :
                                 Patch<Elf_Addr, uint32_t, kPointerRelativeAddress>,
                       text);
   RawSection eh_frame_hdr(".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0,
                           Patch<Elf_Addr, uint32_t, kSectionRelativeAddress>, text);
+  RawSection debug_frame(".debug_frame", SHT_PROGBITS, 0, nullptr, 0, pointer_size, 0,
+                         is64bit ? Patch<Elf_Addr, uint64_t, kAbsoluteAddress> :
+                                   Patch<Elf_Addr, uint32_t, kAbsoluteAddress>,
+                         text);
   RawSection debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0,
                         Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text);
   RawSection debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
@@ -175,12 +188,25 @@
                         Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text);
   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(), eh_frame_hdr.GetPatchLocations());
-      builder->RegisterSection(&eh_frame);
-      builder->RegisterSection(&eh_frame_hdr);
+      if (kCFIFormat == dwarf::DW_EH_FRAME_FORMAT) {
+        dwarf::WriteCFISection(
+            compiler_driver_, oat_writer,
+            dwarf::DW_EH_PE_pcrel, kCFIFormat,
+            eh_frame.GetBuffer(), eh_frame.GetPatchLocations(),
+            eh_frame_hdr.GetBuffer(), eh_frame_hdr.GetPatchLocations());
+        builder->RegisterSection(&eh_frame);
+        builder->RegisterSection(&eh_frame_hdr);
+      } else {
+        DCHECK(kCFIFormat == dwarf::DW_DEBUG_FRAME_FORMAT);
+        dwarf::WriteCFISection(
+            compiler_driver_, oat_writer,
+            dwarf::DW_EH_PE_absptr, kCFIFormat,
+            debug_frame.GetBuffer(), debug_frame.GetPatchLocations(),
+            nullptr, nullptr);
+        builder->RegisterSection(&debug_frame);
+        *oat_writer->GetAbsolutePatchLocationsFor(".debug_frame") =
+            *debug_frame.GetPatchLocations();
+      }
     }
     if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
       // Add methods to .symtab.