Add support for only a .eh_frame.

Static executables only have a .eh_frame section and no .eh_frame_hdr
section. Add support for this by rearranging the class hierarchy and
creating a DwarfEhFrameWithHdr class and a DwarfEhFrame class to handle
the different cases.

Add new unit tests for DwarfEhFrame and for the new functionality.

Bug: 68820189

Test: Passes new unit tests, unwinds static executables.
Change-Id: I63d7cb8c52a686e96579a2266e18c0d06bbb6e63
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index 20cc1b0..d5d158f 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -32,6 +32,7 @@
 
 #include "DwarfDebugFrame.h"
 #include "DwarfEhFrame.h"
+#include "DwarfEhFrameWithHdr.h"
 #include "Symbols.h"
 
 namespace unwindstack {
@@ -98,7 +99,17 @@
 
 template <typename AddressType>
 void ElfInterface::InitHeadersWithTemplate() {
-  if (eh_frame_offset_ != 0) {
+  if (eh_frame_hdr_offset_ != 0) {
+    eh_frame_.reset(new DwarfEhFrameWithHdr<AddressType>(memory_));
+    if (!eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_)) {
+      // Even if the eh_frame_offset_ is non-zero, do not bother
+      // trying to read that since something has gone wrong.
+      eh_frame_.reset(nullptr);
+      eh_frame_hdr_offset_ = 0;
+      eh_frame_hdr_size_ = static_cast<uint64_t>(-1);
+    }
+  } else if (eh_frame_offset_ != 0) {
+    // If there is a eh_frame section without a eh_frame_hdr section.
     eh_frame_.reset(new DwarfEhFrame<AddressType>(memory_));
     if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_)) {
       eh_frame_.reset(nullptr);
@@ -181,11 +192,12 @@
       if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) {
         return false;
       }
-      eh_frame_offset_ = phdr.p_offset;
+      // This is really the pointer to the .eh_frame_hdr section.
+      eh_frame_hdr_offset_ = phdr.p_offset;
       if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) {
         return false;
       }
-      eh_frame_size_ = phdr.p_memsz;
+      eh_frame_hdr_size_ = phdr.p_memsz;
       break;
 
     case PT_DYNAMIC:
@@ -271,6 +283,12 @@
           } else if (name == ".gnu_debugdata") {
             offset_ptr = &gnu_debugdata_offset_;
             size_ptr = &gnu_debugdata_size_;
+          } else if (name == ".eh_frame") {
+            offset_ptr = &eh_frame_offset_;
+            size_ptr = &eh_frame_size_;
+          } else if (eh_frame_hdr_offset_ == 0 && name == ".eh_frame_hdr") {
+            offset_ptr = &eh_frame_hdr_offset_;
+            size_ptr = &eh_frame_hdr_size_;
           }
           if (offset_ptr != nullptr &&
               memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) &&