Small behavioral changes to the unwinder.

- Be a little more lenient when reading the cies/fdes. If next entry data
  winds up incorrect, don't fail, simply stop processing the entries. This
  only applies when reading all of the cies/fdes at once.
- Fail to init an eh_frame with no entries and fallback to assuming the
  eh_frame has no header instead.
- Change the step to always try debug_frame first which has the most
  accurate information.
- Add small unit tests and a couple of offline unit tests to verify
  this behavior.

These changes are needed to support offline unwinding since it depends
on this new behavior.

Bug: 65682279

Test: Ran new unit tests.
Change-Id: I3529f1b0c8e14cd7409494e5de2f3c9e78d0855e
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index 0e3ab2c..17cc16a 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -126,22 +126,26 @@
   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.
+  }
+
+  if (eh_frame_.get() == nullptr && eh_frame_offset_ != 0) {
+    // If there is an eh_frame section without an eh_frame_hdr section,
+    // or using the frame hdr object failed to init.
     eh_frame_.reset(new DwarfEhFrame<AddressType>(memory_));
     if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_)) {
       eh_frame_.reset(nullptr);
-      eh_frame_offset_ = 0;
-      eh_frame_size_ = static_cast<uint64_t>(-1);
     }
   }
 
+  if (eh_frame_.get() == nullptr) {
+    eh_frame_hdr_offset_ = 0;
+    eh_frame_hdr_size_ = static_cast<uint64_t>(-1);
+    eh_frame_offset_ = 0;
+    eh_frame_size_ = static_cast<uint64_t>(-1);
+  }
+
   if (debug_frame_offset_ != 0) {
     debug_frame_.reset(new DwarfDebugFrame<AddressType>(memory_));
     if (!debug_frame_->Init(debug_frame_offset_, debug_frame_size_)) {
@@ -436,15 +440,16 @@
   }
   uint64_t adjusted_pc = pc - load_bias;
 
-  // Try the eh_frame first.
-  DwarfSection* eh_frame = eh_frame_.get();
-  if (eh_frame != nullptr && eh_frame->Step(adjusted_pc, regs, process_memory, finished)) {
+  // Try the debug_frame first since it contains the most specific unwind
+  // information.
+  DwarfSection* debug_frame = debug_frame_.get();
+  if (debug_frame != nullptr && debug_frame->Step(adjusted_pc, regs, process_memory, finished)) {
     return true;
   }
 
-  // Try the debug_frame next.
-  DwarfSection* debug_frame = debug_frame_.get();
-  if (debug_frame != nullptr && debug_frame->Step(adjusted_pc, regs, process_memory, finished)) {
+  // Try the eh_frame next.
+  DwarfSection* eh_frame = eh_frame_.get();
+  if (eh_frame != nullptr && eh_frame->Step(adjusted_pc, regs, process_memory, finished)) {
     return true;
   }