Multiple bugfixes, small restructuring.

- Move the load bias stored out of ElfInterface into Elf. For the compressed
  sections, the load bias was not the same as the data from the uncompressed
  section.
- Move the initialization of the compressed section into Init. It was too easy
  to forget to call the init of the compressed section.
- Do not automatically add in load bias to the pc before calling ElfInterface
  code. Do all of the pc manipulations in the Elf object.
- Change the interface GetFunctionName code to pass in the load_bias instead
  of modifying the pc inside the code.
- Modify the Step function to pass in the elf offset, not add it to the pc.
  It is necessary to have two different relative values when executing the
  Step: a pc that is relative to the beginning of the elf for the reading data
  the actual instructions when trying to determine if this is in a signal
  frame, and a pc that is relative to the map for finding the appropriate
  unwind information.
- Add a feature to Unwinder so that an unwind can be stopped if it ends up
  in map that has a specified suffix. This is so that the ART unwinding
  code doesn't require skipping the compressed section. Instead, stop at
  if trying to unwind through a known suffix code that means the code is
  in java code. This is important because the compressed section data is
  not only used by the jave compiled code, so that will continue to work.
- Fix tests for restructuring, add new tests for new functionality.

Test: Ran art test 137-cfi using new unwinder as default.
Test: Ran new unit tests.
Change-Id: I42e658c64c5e14f698ba34944a3043afac967884
diff --git a/libunwindstack/tests/ElfFake.cpp b/libunwindstack/tests/ElfFake.cpp
index 71f7f6b..b94a8a4 100644
--- a/libunwindstack/tests/ElfFake.cpp
+++ b/libunwindstack/tests/ElfFake.cpp
@@ -32,7 +32,7 @@
 std::deque<FunctionData> ElfInterfaceFake::functions_;
 std::deque<StepData> ElfInterfaceFake::steps_;
 
-bool ElfInterfaceFake::GetFunctionName(uint64_t, std::string* name, uint64_t* offset) {
+bool ElfInterfaceFake::GetFunctionName(uint64_t, uint64_t, std::string* name, uint64_t* offset) {
   if (functions_.empty()) {
     return false;
   }
diff --git a/libunwindstack/tests/ElfFake.h b/libunwindstack/tests/ElfFake.h
index 4359bca..565b13f 100644
--- a/libunwindstack/tests/ElfFake.h
+++ b/libunwindstack/tests/ElfFake.h
@@ -27,6 +27,8 @@
 #include <unwindstack/Memory.h>
 #include <unwindstack/Regs.h>
 
+#include "ElfInterfaceArm.h"
+
 namespace unwindstack {
 
 struct StepData {
@@ -48,6 +50,10 @@
   ElfFake(Memory* memory) : Elf(memory) { valid_ = true; }
   virtual ~ElfFake() = default;
 
+  void FakeSetValid(bool valid) { valid_ = valid; }
+
+  void FakeSetLoadBias(uint64_t load_bias) { load_bias_ = load_bias; }
+
   void FakeSetInterface(ElfInterface* interface) { interface_.reset(interface); }
 };
 
@@ -56,15 +62,14 @@
   ElfInterfaceFake(Memory* memory) : ElfInterface(memory) {}
   virtual ~ElfInterfaceFake() = default;
 
-  bool Init() override { return false; }
+  bool Init(uint64_t*) override { return false; }
   void InitHeaders() override {}
   bool GetSoname(std::string*) override { return false; }
 
-  bool GetFunctionName(uint64_t, std::string*, uint64_t*) override;
+  bool GetFunctionName(uint64_t, uint64_t, std::string*, uint64_t*) override;
 
   bool Step(uint64_t, Regs*, Memory*, bool*) override;
 
-  void FakeSetLoadBias(uint64_t load_bias) { load_bias_ = load_bias; }
 
   static void FakePushFunctionData(const FunctionData data) { functions_.push_back(data); }
   static void FakePushStepData(const StepData data) { steps_.push_back(data); }
@@ -79,6 +84,37 @@
   static std::deque<StepData> steps_;
 };
 
+class ElfInterface32Fake : public ElfInterface32 {
+ public:
+  ElfInterface32Fake(Memory* memory) : ElfInterface32(memory) {}
+  virtual ~ElfInterface32Fake() = default;
+
+  void FakeSetEhFrameOffset(uint64_t offset) { eh_frame_offset_ = offset; }
+  void FakeSetEhFrameSize(uint64_t size) { eh_frame_size_ = size; }
+  void FakeSetDebugFrameOffset(uint64_t offset) { debug_frame_offset_ = offset; }
+  void FakeSetDebugFrameSize(uint64_t size) { debug_frame_size_ = size; }
+};
+
+class ElfInterface64Fake : public ElfInterface64 {
+ public:
+  ElfInterface64Fake(Memory* memory) : ElfInterface64(memory) {}
+  virtual ~ElfInterface64Fake() = default;
+
+  void FakeSetEhFrameOffset(uint64_t offset) { eh_frame_offset_ = offset; }
+  void FakeSetEhFrameSize(uint64_t size) { eh_frame_size_ = size; }
+  void FakeSetDebugFrameOffset(uint64_t offset) { debug_frame_offset_ = offset; }
+  void FakeSetDebugFrameSize(uint64_t size) { debug_frame_size_ = size; }
+};
+
+class ElfInterfaceArmFake : public ElfInterfaceArm {
+ public:
+  ElfInterfaceArmFake(Memory* memory) : ElfInterfaceArm(memory) {}
+  virtual ~ElfInterfaceArmFake() = default;
+
+  void FakeSetStartOffset(uint64_t offset) { start_offset_ = offset; }
+  void FakeSetTotalEntries(size_t entries) { total_entries_ = entries; }
+};
+
 }  // namespace unwindstack
 
 #endif  // _LIBUNWINDSTACK_TESTS_ELF_FAKE_H
diff --git a/libunwindstack/tests/ElfInterfaceArmTest.cpp b/libunwindstack/tests/ElfInterfaceArmTest.cpp
index 4df7e1c..feb24ce 100644
--- a/libunwindstack/tests/ElfInterfaceArmTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceArmTest.cpp
@@ -25,6 +25,7 @@
 #include "ElfInterfaceArm.h"
 #include "Machine.h"
 
+#include "ElfFake.h"
 #include "MemoryFake.h"
 
 namespace unwindstack {
@@ -41,7 +42,7 @@
 };
 
 TEST_F(ElfInterfaceArmTest, GetPrel32Addr) {
-  ElfInterfaceArm interface(&memory_);
+  ElfInterfaceArmFake interface(&memory_);
   memory_.SetData32(0x1000, 0x230000);
 
   uint32_t value;
@@ -58,36 +59,36 @@
 }
 
 TEST_F(ElfInterfaceArmTest, FindEntry_start_zero) {
-  ElfInterfaceArm interface(&memory_);
-  interface.set_start_offset(0);
-  interface.set_total_entries(10);
+  ElfInterfaceArmFake interface(&memory_);
+  interface.FakeSetStartOffset(0);
+  interface.FakeSetTotalEntries(10);
 
   uint64_t entry_offset;
   ASSERT_FALSE(interface.FindEntry(0x1000, &entry_offset));
 }
 
 TEST_F(ElfInterfaceArmTest, FindEntry_no_entries) {
-  ElfInterfaceArm interface(&memory_);
-  interface.set_start_offset(0x100);
-  interface.set_total_entries(0);
+  ElfInterfaceArmFake interface(&memory_);
+  interface.FakeSetStartOffset(0x100);
+  interface.FakeSetTotalEntries(0);
 
   uint64_t entry_offset;
   ASSERT_FALSE(interface.FindEntry(0x1000, &entry_offset));
 }
 
 TEST_F(ElfInterfaceArmTest, FindEntry_no_valid_memory) {
-  ElfInterfaceArm interface(&memory_);
-  interface.set_start_offset(0x100);
-  interface.set_total_entries(2);
+  ElfInterfaceArmFake interface(&memory_);
+  interface.FakeSetStartOffset(0x100);
+  interface.FakeSetTotalEntries(2);
 
   uint64_t entry_offset;
   ASSERT_FALSE(interface.FindEntry(0x1000, &entry_offset));
 }
 
 TEST_F(ElfInterfaceArmTest, FindEntry_ip_before_first) {
-  ElfInterfaceArm interface(&memory_);
-  interface.set_start_offset(0x1000);
-  interface.set_total_entries(1);
+  ElfInterfaceArmFake interface(&memory_);
+  interface.FakeSetStartOffset(0x1000);
+  interface.FakeSetTotalEntries(1);
   memory_.SetData32(0x1000, 0x6000);
 
   uint64_t entry_offset;
@@ -95,9 +96,9 @@
 }
 
 TEST_F(ElfInterfaceArmTest, FindEntry_single_entry_negative_value) {
-  ElfInterfaceArm interface(&memory_);
-  interface.set_start_offset(0x8000);
-  interface.set_total_entries(1);
+  ElfInterfaceArmFake interface(&memory_);
+  interface.FakeSetStartOffset(0x8000);
+  interface.FakeSetTotalEntries(1);
   memory_.SetData32(0x8000, 0x7fffff00);
 
   uint64_t entry_offset;
@@ -106,9 +107,9 @@
 }
 
 TEST_F(ElfInterfaceArmTest, FindEntry_two_entries) {
-  ElfInterfaceArm interface(&memory_);
-  interface.set_start_offset(0x1000);
-  interface.set_total_entries(2);
+  ElfInterfaceArmFake interface(&memory_);
+  interface.FakeSetStartOffset(0x1000);
+  interface.FakeSetTotalEntries(2);
   memory_.SetData32(0x1000, 0x6000);
   memory_.SetData32(0x1008, 0x7000);
 
@@ -117,11 +118,10 @@
   ASSERT_EQ(0x1000U, entry_offset);
 }
 
-
 TEST_F(ElfInterfaceArmTest, FindEntry_last_check_single_entry) {
-  ElfInterfaceArm interface(&memory_);
-  interface.set_start_offset(0x1000);
-  interface.set_total_entries(1);
+  ElfInterfaceArmFake interface(&memory_);
+  interface.FakeSetStartOffset(0x1000);
+  interface.FakeSetTotalEntries(1);
   memory_.SetData32(0x1000, 0x6000);
 
   uint64_t entry_offset;
@@ -136,9 +136,9 @@
 }
 
 TEST_F(ElfInterfaceArmTest, FindEntry_last_check_multiple_entries) {
-  ElfInterfaceArm interface(&memory_);
-  interface.set_start_offset(0x1000);
-  interface.set_total_entries(2);
+  ElfInterfaceArmFake interface(&memory_);
+  interface.FakeSetStartOffset(0x1000);
+  interface.FakeSetTotalEntries(2);
   memory_.SetData32(0x1000, 0x6000);
   memory_.SetData32(0x1008, 0x8000);
 
@@ -155,9 +155,9 @@
 }
 
 TEST_F(ElfInterfaceArmTest, FindEntry_multiple_entries_even) {
-  ElfInterfaceArm interface(&memory_);
-  interface.set_start_offset(0x1000);
-  interface.set_total_entries(4);
+  ElfInterfaceArmFake interface(&memory_);
+  interface.FakeSetStartOffset(0x1000);
+  interface.FakeSetTotalEntries(4);
   memory_.SetData32(0x1000, 0x6000);
   memory_.SetData32(0x1008, 0x7000);
   memory_.SetData32(0x1010, 0x8000);
@@ -178,9 +178,9 @@
 }
 
 TEST_F(ElfInterfaceArmTest, FindEntry_multiple_entries_odd) {
-  ElfInterfaceArm interface(&memory_);
-  interface.set_start_offset(0x1000);
-  interface.set_total_entries(5);
+  ElfInterfaceArmFake interface(&memory_);
+  interface.FakeSetStartOffset(0x1000);
+  interface.FakeSetTotalEntries(5);
   memory_.SetData32(0x1000, 0x5000);
   memory_.SetData32(0x1008, 0x6000);
   memory_.SetData32(0x1010, 0x7000);
@@ -203,9 +203,9 @@
 }
 
 TEST_F(ElfInterfaceArmTest, iterate) {
-  ElfInterfaceArm interface(&memory_);
-  interface.set_start_offset(0x1000);
-  interface.set_total_entries(5);
+  ElfInterfaceArmFake interface(&memory_);
+  interface.FakeSetStartOffset(0x1000);
+  interface.FakeSetTotalEntries(5);
   memory_.SetData32(0x1000, 0x5000);
   memory_.SetData32(0x1008, 0x6000);
   memory_.SetData32(0x1010, 0x7000);
@@ -242,56 +242,36 @@
   ASSERT_EQ(0xa020U, entries[4]);
 }
 
-TEST_F(ElfInterfaceArmTest, FindEntry_load_bias) {
-  ElfInterfaceArm interface(&memory_);
-  interface.set_start_offset(0x1000);
-  interface.set_total_entries(2);
-  memory_.SetData32(0x1000, 0x6000);
-  memory_.SetData32(0x1008, 0x8000);
-
-  uint64_t entry_offset;
-  interface.set_load_bias(0x2000);
-  ASSERT_FALSE(interface.FindEntry(0x1000, &entry_offset));
-  ASSERT_FALSE(interface.FindEntry(0x8000, &entry_offset));
-  ASSERT_FALSE(interface.FindEntry(0x8fff, &entry_offset));
-  ASSERT_TRUE(interface.FindEntry(0x9000, &entry_offset));
-  ASSERT_EQ(0x1000U, entry_offset);
-  ASSERT_TRUE(interface.FindEntry(0xb007, &entry_offset));
-  ASSERT_EQ(0x1000U, entry_offset);
-  ASSERT_TRUE(interface.FindEntry(0xb008, &entry_offset));
-  ASSERT_EQ(0x1008U, entry_offset);
-}
-
 TEST_F(ElfInterfaceArmTest, HandleType_not_arm_exidx) {
-  ElfInterfaceArm interface(&memory_);
+  ElfInterfaceArmFake interface(&memory_);
 
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_NULL));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_LOAD));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_DYNAMIC));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_INTERP));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_NOTE));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_SHLIB));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_PHDR));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_TLS));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_LOOS));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_HIOS));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_LOPROC));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_HIPROC));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_GNU_EH_FRAME));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_GNU_STACK));
+  ASSERT_FALSE(interface.HandleType(0x1000, PT_NULL, 0));
+  ASSERT_FALSE(interface.HandleType(0x1000, PT_LOAD, 0));
+  ASSERT_FALSE(interface.HandleType(0x1000, PT_DYNAMIC, 0));
+  ASSERT_FALSE(interface.HandleType(0x1000, PT_INTERP, 0));
+  ASSERT_FALSE(interface.HandleType(0x1000, PT_NOTE, 0));
+  ASSERT_FALSE(interface.HandleType(0x1000, PT_SHLIB, 0));
+  ASSERT_FALSE(interface.HandleType(0x1000, PT_PHDR, 0));
+  ASSERT_FALSE(interface.HandleType(0x1000, PT_TLS, 0));
+  ASSERT_FALSE(interface.HandleType(0x1000, PT_LOOS, 0));
+  ASSERT_FALSE(interface.HandleType(0x1000, PT_HIOS, 0));
+  ASSERT_FALSE(interface.HandleType(0x1000, PT_LOPROC, 0));
+  ASSERT_FALSE(interface.HandleType(0x1000, PT_HIPROC, 0));
+  ASSERT_FALSE(interface.HandleType(0x1000, PT_GNU_EH_FRAME, 0));
+  ASSERT_FALSE(interface.HandleType(0x1000, PT_GNU_STACK, 0));
 }
 
 TEST_F(ElfInterfaceArmTest, HandleType_arm_exidx) {
-  ElfInterfaceArm interface(&memory_);
+  ElfInterfaceArmFake interface(&memory_);
 
   Elf32_Phdr phdr;
-  interface.set_start_offset(0x1000);
-  interface.set_total_entries(100);
+  interface.FakeSetStartOffset(0x1000);
+  interface.FakeSetTotalEntries(100);
   phdr.p_vaddr = 0x2000;
   phdr.p_memsz = 0xa00;
 
   // Verify that if reads fail, we don't set the values but still get true.
-  ASSERT_TRUE(interface.HandleType(0x1000, 0x70000001));
+  ASSERT_TRUE(interface.HandleType(0x1000, 0x70000001, 0));
   ASSERT_EQ(0x1000U, interface.start_offset());
   ASSERT_EQ(100U, interface.total_entries());
 
@@ -299,7 +279,7 @@
   memory_.SetData32(
       0x1000 + reinterpret_cast<uint64_t>(&phdr.p_vaddr) - reinterpret_cast<uint64_t>(&phdr),
       phdr.p_vaddr);
-  ASSERT_TRUE(interface.HandleType(0x1000, 0x70000001));
+  ASSERT_TRUE(interface.HandleType(0x1000, 0x70000001, 0));
   ASSERT_EQ(0x1000U, interface.start_offset());
   ASSERT_EQ(100U, interface.total_entries());
 
@@ -307,27 +287,26 @@
   memory_.SetData32(
       0x1000 + reinterpret_cast<uint64_t>(&phdr.p_memsz) - reinterpret_cast<uint64_t>(&phdr),
       phdr.p_memsz);
-  ASSERT_TRUE(interface.HandleType(0x1000, 0x70000001));
+  ASSERT_TRUE(interface.HandleType(0x1000, 0x70000001, 0));
   ASSERT_EQ(0x2000U, interface.start_offset());
   ASSERT_EQ(320U, interface.total_entries());
 
   // Non-zero load bias.
-  interface.set_load_bias(0x1000);
-  ASSERT_TRUE(interface.HandleType(0x1000, 0x70000001));
+  ASSERT_TRUE(interface.HandleType(0x1000, 0x70000001, 0x1000));
   ASSERT_EQ(0x1000U, interface.start_offset());
   ASSERT_EQ(320U, interface.total_entries());
 }
 
 TEST_F(ElfInterfaceArmTest, StepExidx) {
-  ElfInterfaceArm interface(&memory_);
+  ElfInterfaceArmFake interface(&memory_);
 
   // FindEntry fails.
   bool finished;
   ASSERT_FALSE(interface.StepExidx(0x7000, nullptr, nullptr, &finished));
 
   // ExtractEntry should fail.
-  interface.set_start_offset(0x1000);
-  interface.set_total_entries(2);
+  interface.FakeSetStartOffset(0x1000);
+  interface.FakeSetTotalEntries(2);
   memory_.SetData32(0x1000, 0x6000);
   memory_.SetData32(0x1008, 0x8000);
 
@@ -353,10 +332,10 @@
 }
 
 TEST_F(ElfInterfaceArmTest, StepExidx_pc_set) {
-  ElfInterfaceArm interface(&memory_);
+  ElfInterfaceArmFake interface(&memory_);
 
-  interface.set_start_offset(0x1000);
-  interface.set_total_entries(2);
+  interface.FakeSetStartOffset(0x1000);
+  interface.FakeSetTotalEntries(2);
   memory_.SetData32(0x1000, 0x6000);
   memory_.SetData32(0x1004, 0x808800b0);
   memory_.SetData32(0x1008, 0x8000);
@@ -379,10 +358,10 @@
 }
 
 TEST_F(ElfInterfaceArmTest, StepExidx_cant_unwind) {
-  ElfInterfaceArm interface(&memory_);
+  ElfInterfaceArmFake interface(&memory_);
 
-  interface.set_start_offset(0x1000);
-  interface.set_total_entries(1);
+  interface.FakeSetStartOffset(0x1000);
+  interface.FakeSetTotalEntries(1);
   memory_.SetData32(0x1000, 0x6000);
   memory_.SetData32(0x1004, 1);
 
@@ -401,10 +380,10 @@
 }
 
 TEST_F(ElfInterfaceArmTest, StepExidx_refuse_unwind) {
-  ElfInterfaceArm interface(&memory_);
+  ElfInterfaceArmFake interface(&memory_);
 
-  interface.set_start_offset(0x1000);
-  interface.set_total_entries(1);
+  interface.FakeSetStartOffset(0x1000);
+  interface.FakeSetTotalEntries(1);
   memory_.SetData32(0x1000, 0x6000);
   memory_.SetData32(0x1004, 0x808000b0);
 
diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp
index acb7320..2752e99 100644
--- a/libunwindstack/tests/ElfInterfaceTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceTest.cpp
@@ -25,6 +25,7 @@
 #include "DwarfEncoding.h"
 #include "ElfInterfaceArm.h"
 
+#include "ElfFake.h"
 #include "MemoryFake.h"
 
 #if !defined(PT_ARM_EXIDX)
@@ -134,7 +135,9 @@
   phdr.p_align = 0x1000;
   memory_.SetMemory(0x100, &phdr, sizeof(phdr));
 
-  ASSERT_TRUE(elf->Init());
+  uint64_t load_bias = 0;
+  ASSERT_TRUE(elf->Init(&load_bias));
+  EXPECT_EQ(0x2000U, load_bias);
 
   const std::unordered_map<uint64_t, LoadInfo>& pt_loads = elf->pt_loads();
   ASSERT_EQ(1U, pt_loads.size());
@@ -190,7 +193,9 @@
   phdr.p_align = 0x1002;
   memory_.SetMemory(0x100 + 2 * sizeof(phdr), &phdr, sizeof(phdr));
 
-  ASSERT_TRUE(elf->Init());
+  uint64_t load_bias = 0;
+  ASSERT_TRUE(elf->Init(&load_bias));
+  EXPECT_EQ(0x2000U, load_bias);
 
   const std::unordered_map<uint64_t, LoadInfo>& pt_loads = elf->pt_loads();
   ASSERT_EQ(3U, pt_loads.size());
@@ -257,7 +262,9 @@
   phdr.p_align = 0x1002;
   memory_.SetMemory(0x100 + 2 * (sizeof(phdr) + 100), &phdr, sizeof(phdr));
 
-  ASSERT_TRUE(elf->Init());
+  uint64_t load_bias = 0;
+  ASSERT_TRUE(elf->Init(&load_bias));
+  EXPECT_EQ(0x2000U, load_bias);
 
   const std::unordered_map<uint64_t, LoadInfo>& pt_loads = elf->pt_loads();
   ASSERT_EQ(3U, pt_loads.size());
@@ -326,7 +333,9 @@
   phdr.p_align = 0x1002;
   memory_.SetMemory(0x100 + 2 * sizeof(phdr), &phdr, sizeof(phdr));
 
-  ASSERT_TRUE(elf->Init());
+  uint64_t load_bias = 0;
+  ASSERT_TRUE(elf->Init(&load_bias));
+  EXPECT_EQ(0U, load_bias);
 
   const std::unordered_map<uint64_t, LoadInfo>& pt_loads = elf->pt_loads();
   ASSERT_EQ(1U, pt_loads.size());
@@ -398,7 +407,9 @@
   memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr));
   phdr_offset += sizeof(phdr);
 
-  ASSERT_TRUE(elf->Init());
+  uint64_t load_bias = 0;
+  ASSERT_TRUE(elf->Init(&load_bias));
+  EXPECT_EQ(0x2000U, load_bias);
 
   const std::unordered_map<uint64_t, LoadInfo>& pt_loads = elf->pt_loads();
   ASSERT_EQ(1U, pt_loads.size());
@@ -438,7 +449,9 @@
   memory_.SetData32(0x2000, 0x1000);
   memory_.SetData32(0x2008, 0x1000);
 
-  ASSERT_TRUE(elf_arm.Init());
+  uint64_t load_bias = 0;
+  ASSERT_TRUE(elf_arm.Init(&load_bias));
+  EXPECT_EQ(0U, load_bias);
 
   std::vector<uint32_t> entries;
   for (auto addr : elf_arm) {
@@ -493,7 +506,10 @@
 
   SetStringMemory(0x10010, "fake_soname.so");
 
-  ASSERT_TRUE(elf->Init());
+  uint64_t load_bias = 0;
+  ASSERT_TRUE(elf->Init(&load_bias));
+  EXPECT_EQ(0U, load_bias);
+
   std::string name;
   ASSERT_TRUE(elf->GetSoname(&name));
   ASSERT_STREQ("fake_soname.so", name.c_str());
@@ -549,7 +565,10 @@
 
   SetStringMemory(0x10010, "fake_soname.so");
 
-  ASSERT_TRUE(elf->Init());
+  uint64_t load_bias = 0;
+  ASSERT_TRUE(elf->Init(&load_bias));
+  EXPECT_EQ(0U, load_bias);
+
   std::string name;
   ASSERT_FALSE(elf->GetSoname(&name));
 }
@@ -603,7 +622,10 @@
 
   SetStringMemory(0x10010, "fake_soname.so");
 
-  ASSERT_TRUE(elf->Init());
+  uint64_t load_bias = 0;
+  ASSERT_TRUE(elf->Init(&load_bias));
+  EXPECT_EQ(0U, load_bias);
+
   std::string name;
   ASSERT_FALSE(elf->GetSoname(&name));
 }
@@ -616,38 +638,14 @@
   SonameSize<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>();
 }
 
-class MockElfInterface32 : public ElfInterface32 {
- public:
-  MockElfInterface32(Memory* memory) : ElfInterface32(memory) {}
-  virtual ~MockElfInterface32() = default;
-
-  void TestSetEhFrameOffset(uint64_t offset) { eh_frame_offset_ = offset; }
-  void TestSetEhFrameSize(uint64_t size) { eh_frame_size_ = size; }
-
-  void TestSetDebugFrameOffset(uint64_t offset) { debug_frame_offset_ = offset; }
-  void TestSetDebugFrameSize(uint64_t size) { debug_frame_size_ = size; }
-};
-
-class MockElfInterface64 : public ElfInterface64 {
- public:
-  MockElfInterface64(Memory* memory) : ElfInterface64(memory) {}
-  virtual ~MockElfInterface64() = default;
-
-  void TestSetEhFrameOffset(uint64_t offset) { eh_frame_offset_ = offset; }
-  void TestSetEhFrameSize(uint64_t size) { eh_frame_size_ = size; }
-
-  void TestSetDebugFrameOffset(uint64_t offset) { debug_frame_offset_ = offset; }
-  void TestSetDebugFrameSize(uint64_t size) { debug_frame_size_ = size; }
-};
-
 template <typename ElfType>
 void ElfInterfaceTest::InitHeadersEhFrameTest() {
   ElfType elf(&memory_);
 
-  elf.TestSetEhFrameOffset(0x10000);
-  elf.TestSetEhFrameSize(0);
-  elf.TestSetDebugFrameOffset(0);
-  elf.TestSetDebugFrameSize(0);
+  elf.FakeSetEhFrameOffset(0x10000);
+  elf.FakeSetEhFrameSize(0);
+  elf.FakeSetDebugFrameOffset(0);
+  elf.FakeSetDebugFrameSize(0);
 
   memory_.SetMemory(0x10000,
                     std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata2, DW_EH_PE_udata2});
@@ -661,21 +659,21 @@
 }
 
 TEST_F(ElfInterfaceTest, init_headers_eh_frame32) {
-  InitHeadersEhFrameTest<MockElfInterface32>();
+  InitHeadersEhFrameTest<ElfInterface32Fake>();
 }
 
 TEST_F(ElfInterfaceTest, init_headers_eh_frame64) {
-  InitHeadersEhFrameTest<MockElfInterface64>();
+  InitHeadersEhFrameTest<ElfInterface64Fake>();
 }
 
 template <typename ElfType>
 void ElfInterfaceTest::InitHeadersDebugFrame() {
   ElfType elf(&memory_);
 
-  elf.TestSetEhFrameOffset(0);
-  elf.TestSetEhFrameSize(0);
-  elf.TestSetDebugFrameOffset(0x5000);
-  elf.TestSetDebugFrameSize(0x200);
+  elf.FakeSetEhFrameOffset(0);
+  elf.FakeSetEhFrameSize(0);
+  elf.FakeSetDebugFrameOffset(0x5000);
+  elf.FakeSetDebugFrameSize(0x200);
 
   memory_.SetData32(0x5000, 0xfc);
   memory_.SetData32(0x5004, 0xffffffff);
@@ -694,21 +692,21 @@
 }
 
 TEST_F(ElfInterfaceTest, init_headers_debug_frame32) {
-  InitHeadersDebugFrame<MockElfInterface32>();
+  InitHeadersDebugFrame<ElfInterface32Fake>();
 }
 
 TEST_F(ElfInterfaceTest, init_headers_debug_frame64) {
-  InitHeadersDebugFrame<MockElfInterface64>();
+  InitHeadersDebugFrame<ElfInterface64Fake>();
 }
 
 template <typename ElfType>
 void ElfInterfaceTest::InitHeadersEhFrameFail() {
   ElfType elf(&memory_);
 
-  elf.TestSetEhFrameOffset(0x1000);
-  elf.TestSetEhFrameSize(0x100);
-  elf.TestSetDebugFrameOffset(0);
-  elf.TestSetDebugFrameSize(0);
+  elf.FakeSetEhFrameOffset(0x1000);
+  elf.FakeSetEhFrameSize(0x100);
+  elf.FakeSetDebugFrameOffset(0);
+  elf.FakeSetDebugFrameSize(0);
 
   elf.InitHeaders();
 
@@ -719,21 +717,21 @@
 }
 
 TEST_F(ElfInterfaceTest, init_headers_eh_frame32_fail) {
-  InitHeadersEhFrameFail<MockElfInterface32>();
+  InitHeadersEhFrameFail<ElfInterface32Fake>();
 }
 
 TEST_F(ElfInterfaceTest, init_headers_eh_frame64_fail) {
-  InitHeadersEhFrameFail<MockElfInterface64>();
+  InitHeadersEhFrameFail<ElfInterface64Fake>();
 }
 
 template <typename ElfType>
 void ElfInterfaceTest::InitHeadersDebugFrameFail() {
   ElfType elf(&memory_);
 
-  elf.TestSetEhFrameOffset(0);
-  elf.TestSetEhFrameSize(0);
-  elf.TestSetDebugFrameOffset(0x1000);
-  elf.TestSetDebugFrameSize(0x100);
+  elf.FakeSetEhFrameOffset(0);
+  elf.FakeSetEhFrameSize(0);
+  elf.FakeSetDebugFrameOffset(0x1000);
+  elf.FakeSetDebugFrameSize(0x100);
 
   elf.InitHeaders();
 
@@ -744,11 +742,11 @@
 }
 
 TEST_F(ElfInterfaceTest, init_headers_debug_frame32_fail) {
-  InitHeadersDebugFrameFail<MockElfInterface32>();
+  InitHeadersDebugFrameFail<ElfInterface32Fake>();
 }
 
 TEST_F(ElfInterfaceTest, init_headers_debug_frame64_fail) {
-  InitHeadersDebugFrameFail<MockElfInterface64>();
+  InitHeadersDebugFrameFail<ElfInterface64Fake>();
 }
 
 template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
@@ -762,7 +760,9 @@
   ehdr.e_shentsize = sizeof(Shdr);
   memory_.SetMemory(0, &ehdr, sizeof(ehdr));
 
-  ASSERT_TRUE(elf->Init());
+  uint64_t load_bias = 0;
+  ASSERT_TRUE(elf->Init(&load_bias));
+  EXPECT_EQ(0U, load_bias);
 }
 
 TEST_F(ElfInterfaceTest, init_section_headers_malformed32) {
@@ -827,7 +827,9 @@
   InitSym<Sym>(0x5000, 0x90000, 0x1000, 0x100, 0xf000, "function_one");
   InitSym<Sym>(0x6000, 0xd0000, 0x1000, 0x300, 0xf000, "function_two");
 
-  ASSERT_TRUE(elf->Init());
+  uint64_t load_bias = 0;
+  ASSERT_TRUE(elf->Init(&load_bias));
+  EXPECT_EQ(0U, load_bias);
   EXPECT_EQ(0U, elf->debug_frame_offset());
   EXPECT_EQ(0U, elf->debug_frame_size());
   EXPECT_EQ(0U, elf->gnu_debugdata_offset());
@@ -836,10 +838,10 @@
   // Look in the first symbol table.
   std::string name;
   uint64_t name_offset;
-  ASSERT_TRUE(elf->GetFunctionName(0x90010, &name, &name_offset));
+  ASSERT_TRUE(elf->GetFunctionName(0x90010, 0, &name, &name_offset));
   EXPECT_EQ("function_one", name);
   EXPECT_EQ(16U, name_offset);
-  ASSERT_TRUE(elf->GetFunctionName(0xd0020, &name, &name_offset));
+  ASSERT_TRUE(elf->GetFunctionName(0xd0020, 0, &name, &name_offset));
   EXPECT_EQ("function_two", name);
   EXPECT_EQ(32U, name_offset);
 }
@@ -911,7 +913,9 @@
   memory_.SetMemory(0xf100, ".debug_frame", sizeof(".debug_frame"));
   memory_.SetMemory(0xf200, ".gnu_debugdata", sizeof(".gnu_debugdata"));
 
-  ASSERT_TRUE(elf->Init());
+  uint64_t load_bias = 0;
+  ASSERT_TRUE(elf->Init(&load_bias));
+  EXPECT_EQ(0U, load_bias);
   EXPECT_EQ(0x6000U, elf->debug_frame_offset());
   EXPECT_EQ(0x500U, elf->debug_frame_size());
   EXPECT_EQ(0x5000U, elf->gnu_debugdata_offset());
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index 42a0246..4e48fa1 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -20,11 +20,13 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
 #include <unwindstack/Elf.h>
 #include <unwindstack/MapInfo.h>
 
+#include "ElfFake.h"
 #include "ElfTestUtils.h"
 #include "LogFake.h"
 #include "MemoryFake.h"
@@ -107,7 +109,7 @@
 TEST_F(ElfTest, invalid_memory) {
   Elf elf(memory_);
 
-  ASSERT_FALSE(elf.Init());
+  ASSERT_FALSE(elf.Init(false));
   ASSERT_FALSE(elf.valid());
 }
 
@@ -119,7 +121,7 @@
   // Corrupt the ELF signature.
   memory_->SetData32(0, 0x7f000000);
 
-  ASSERT_FALSE(elf.Init());
+  ASSERT_FALSE(elf.Init(false));
   ASSERT_FALSE(elf.valid());
   ASSERT_TRUE(elf.interface() == nullptr);
 
@@ -130,7 +132,7 @@
   ASSERT_FALSE(elf.GetFunctionName(0, &name, &func_offset));
 
   bool finished;
-  ASSERT_FALSE(elf.Step(0, nullptr, nullptr, &finished));
+  ASSERT_FALSE(elf.Step(0, 0, nullptr, nullptr, &finished));
 }
 
 TEST_F(ElfTest, elf32_invalid_machine) {
@@ -139,7 +141,7 @@
   InitElf32(EM_PPC);
 
   ResetLogs();
-  ASSERT_FALSE(elf.Init());
+  ASSERT_FALSE(elf.Init(false));
 
   ASSERT_EQ("", GetFakeLogBuf());
   ASSERT_EQ("4 unwind 32 bit elf that is neither arm nor x86: e_machine = 20\n\n",
@@ -152,7 +154,7 @@
   InitElf64(EM_PPC64);
 
   ResetLogs();
-  ASSERT_FALSE(elf.Init());
+  ASSERT_FALSE(elf.Init(false));
 
   ASSERT_EQ("", GetFakeLogBuf());
   ASSERT_EQ("4 unwind 64 bit elf that is neither aarch64 nor x86_64: e_machine = 21\n\n",
@@ -164,7 +166,7 @@
 
   InitElf32(EM_ARM);
 
-  ASSERT_TRUE(elf.Init());
+  ASSERT_TRUE(elf.Init(false));
   ASSERT_TRUE(elf.valid());
   ASSERT_EQ(static_cast<uint32_t>(EM_ARM), elf.machine_type());
   ASSERT_EQ(ELFCLASS32, elf.class_type());
@@ -176,7 +178,7 @@
 
   InitElf32(EM_386);
 
-  ASSERT_TRUE(elf.Init());
+  ASSERT_TRUE(elf.Init(false));
   ASSERT_TRUE(elf.valid());
   ASSERT_EQ(static_cast<uint32_t>(EM_386), elf.machine_type());
   ASSERT_EQ(ELFCLASS32, elf.class_type());
@@ -188,7 +190,7 @@
 
   InitElf64(EM_AARCH64);
 
-  ASSERT_TRUE(elf.Init());
+  ASSERT_TRUE(elf.Init(false));
   ASSERT_TRUE(elf.valid());
   ASSERT_EQ(static_cast<uint32_t>(EM_AARCH64), elf.machine_type());
   ASSERT_EQ(ELFCLASS64, elf.class_type());
@@ -200,7 +202,7 @@
 
   InitElf64(EM_X86_64);
 
-  ASSERT_TRUE(elf.Init());
+  ASSERT_TRUE(elf.Init(false));
   ASSERT_TRUE(elf.valid());
   ASSERT_EQ(static_cast<uint32_t>(EM_X86_64), elf.machine_type());
   ASSERT_EQ(ELFCLASS64, elf.class_type());
@@ -214,7 +216,7 @@
                                                });
 
   Elf elf(memory_);
-  ASSERT_TRUE(elf.Init());
+  ASSERT_TRUE(elf.Init(false));
   ASSERT_TRUE(elf.interface() != nullptr);
   ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
   EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset());
@@ -228,7 +230,7 @@
                                                });
 
   Elf elf(memory_);
-  ASSERT_TRUE(elf.Init());
+  ASSERT_TRUE(elf.Init(false));
   ASSERT_TRUE(elf.interface() != nullptr);
   ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
   EXPECT_EQ(0x200U, elf.interface()->gnu_debugdata_offset());
@@ -242,14 +244,11 @@
                                                });
 
   Elf elf(memory_);
-  ASSERT_TRUE(elf.Init());
+  ASSERT_TRUE(elf.Init(true));
   ASSERT_TRUE(elf.interface() != nullptr);
-  ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
+  ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
   EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset());
   EXPECT_EQ(0x8cU, elf.interface()->gnu_debugdata_size());
-
-  elf.InitGnuDebugdata();
-  ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
 }
 
 TEST_F(ElfTest, gnu_debugdata_init64) {
@@ -259,42 +258,109 @@
                                                });
 
   Elf elf(memory_);
-  ASSERT_TRUE(elf.Init());
+  ASSERT_TRUE(elf.Init(true));
   ASSERT_TRUE(elf.interface() != nullptr);
-  ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
+  ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
   EXPECT_EQ(0x200U, elf.interface()->gnu_debugdata_offset());
   EXPECT_EQ(0x90U, elf.interface()->gnu_debugdata_size());
-
-  elf.InitGnuDebugdata();
-  ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
 }
 
-class MockElf : public Elf {
- public:
-  MockElf(Memory* memory) : Elf(memory) {}
-  virtual ~MockElf() = default;
-
-  void set_valid(bool valid) { valid_ = valid; }
-  void set_elf_interface(ElfInterface* interface) { interface_.reset(interface); }
-};
-
 TEST_F(ElfTest, rel_pc) {
-  MockElf elf(memory_);
+  ElfFake elf(memory_);
 
-  ElfInterface* interface = new ElfInterface32(memory_);
-  elf.set_elf_interface(interface);
+  ElfInterfaceFake* interface = new ElfInterfaceFake(memory_);
+  elf.FakeSetInterface(interface);
 
-  elf.set_valid(true);
-  interface->set_load_bias(0);
+  elf.FakeSetValid(true);
+  elf.FakeSetLoadBias(0);
   MapInfo map_info{.start = 0x1000, .end = 0x2000};
 
   ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
 
-  interface->set_load_bias(0x3000);
+  elf.FakeSetLoadBias(0x3000);
   ASSERT_EQ(0x3101U, elf.GetRelPc(0x1101, &map_info));
 
-  elf.set_valid(false);
+  elf.FakeSetValid(false);
+  elf.FakeSetLoadBias(0);
   ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
 }
 
+TEST_F(ElfTest, step_in_signal_map) {
+  ElfFake elf(memory_);
+
+  RegsArm regs;
+  regs[13] = 0x50000;
+  regs[15] = 0x8000;
+  regs.SetFromRaw();
+
+  ElfInterfaceFake* interface = new ElfInterfaceFake(memory_);
+  elf.FakeSetInterface(interface);
+
+  memory_->SetData32(0x3000, 0xdf0027ad);
+  MemoryFake process_memory;
+  process_memory.SetData32(0x50000, 0);
+  for (size_t i = 0; i < 16; i++) {
+    process_memory.SetData32(0x500a0 + i * sizeof(uint32_t), i);
+  }
+
+  elf.FakeSetValid(true);
+  elf.FakeSetLoadBias(0);
+  bool finished;
+  ASSERT_TRUE(elf.Step(0x1000, 0x2000, &regs, &process_memory, &finished));
+  EXPECT_FALSE(finished);
+  EXPECT_EQ(15U, regs.pc());
+  EXPECT_EQ(13U, regs.sp());
+}
+
+class ElfInterfaceMock : public ElfInterface {
+ public:
+  ElfInterfaceMock(Memory* memory) : ElfInterface(memory) {}
+  virtual ~ElfInterfaceMock() = default;
+
+  bool Init(uint64_t*) override { return false; }
+  void InitHeaders() override {}
+  bool GetSoname(std::string*) override { return false; }
+  bool GetFunctionName(uint64_t, uint64_t, std::string*, uint64_t*) override { return false; }
+  MOCK_METHOD4(Step, bool(uint64_t, Regs*, Memory*, bool*));
+};
+
+TEST_F(ElfTest, step_in_interface) {
+  ElfFake elf(memory_);
+  elf.FakeSetValid(true);
+  elf.FakeSetLoadBias(0);
+
+  RegsArm regs;
+
+  ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
+  elf.FakeSetInterface(interface);
+  MemoryFake process_memory;
+
+  bool finished;
+  EXPECT_CALL(*interface, Step(0x1000, &regs, &process_memory, &finished))
+      .WillOnce(::testing::Return(true));
+
+  ASSERT_TRUE(elf.Step(0x1000, 0x2000, &regs, &process_memory, &finished));
+}
+
+TEST_F(ElfTest, step_in_interface_non_zero_load_bias) {
+  ElfFake elf(memory_);
+  elf.FakeSetValid(true);
+  elf.FakeSetLoadBias(0x4000);
+
+  RegsArm regs;
+
+  ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
+  elf.FakeSetInterface(interface);
+  MemoryFake process_memory;
+
+  // Invalid relative pc given load_bias.
+  bool finished;
+  ASSERT_FALSE(elf.Step(0x1000, 0x2000, &regs, &process_memory, &finished));
+
+  EXPECT_CALL(*interface, Step(0x3300, &regs, &process_memory, &finished))
+      .WillOnce(::testing::Return(true));
+
+  ASSERT_TRUE(elf.Step(0x7300, 0x2000, &regs, &process_memory, &finished));
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp
index 3b9f92b..2a02669 100644
--- a/libunwindstack/tests/RegsTest.cpp
+++ b/libunwindstack/tests/RegsTest.cpp
@@ -115,7 +115,7 @@
   RegsArm arm;
 
   // Check fence posts.
-  elf_interface_->FakeSetLoadBias(0);
+  elf_->FakeSetLoadBias(0);
   ASSERT_EQ(3U,  arm.GetAdjustedPc(0x5, elf_.get()));
   ASSERT_EQ(4U,  arm.GetAdjustedPc(0x4, elf_.get()));
   ASSERT_EQ(3U,  arm.GetAdjustedPc(0x3, elf_.get()));
@@ -123,7 +123,7 @@
   ASSERT_EQ(1U,  arm.GetAdjustedPc(0x1, elf_.get()));
   ASSERT_EQ(0U,  arm.GetAdjustedPc(0x0, elf_.get()));
 
-  elf_interface_->FakeSetLoadBias(0x100);
+  elf_->FakeSetLoadBias(0x100);
   ASSERT_EQ(0xffU,  arm.GetAdjustedPc(0xff, elf_.get()));
   ASSERT_EQ(0x103U,  arm.GetAdjustedPc(0x105, elf_.get()));
   ASSERT_EQ(0x104U,  arm.GetAdjustedPc(0x104, elf_.get()));
@@ -133,13 +133,13 @@
   ASSERT_EQ(0x100U,  arm.GetAdjustedPc(0x100, elf_.get()));
 
   // Check thumb instructions handling.
-  elf_interface_->FakeSetLoadBias(0);
+  elf_->FakeSetLoadBias(0);
   memory_->SetData32(0x2000, 0);
   ASSERT_EQ(0x2003U,  arm.GetAdjustedPc(0x2005, elf_.get()));
   memory_->SetData32(0x2000, 0xe000f000);
   ASSERT_EQ(0x2001U,  arm.GetAdjustedPc(0x2005, elf_.get()));
 
-  elf_interface_->FakeSetLoadBias(0x400);
+  elf_->FakeSetLoadBias(0x400);
   memory_->SetData32(0x2100, 0);
   ASSERT_EQ(0x2503U,  arm.GetAdjustedPc(0x2505, elf_.get()));
   memory_->SetData32(0x2100, 0xf111f111);
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index 16640a1..8384473 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -96,6 +96,15 @@
     elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
     maps_.FakeAddMapInfo(info);
 
+    info.name = "/fake/compressed.so";
+    info.start = 0x33000;
+    info.end = 0x34000;
+    info.flags = PROT_READ | PROT_WRITE;
+    elf = new ElfFake(nullptr);
+    info.elf = elf;
+    elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
+    maps_.FakeAddMapInfo(info);
+
     info.name = "/fake/fake.apk";
     info.start = 0x43000;
     info.end = 0x44000;
@@ -105,6 +114,14 @@
     info.elf = elf;
     elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
     maps_.FakeAddMapInfo(info);
+
+    info.name = "/fake/fake.oat";
+    info.start = 0x53000;
+    info.end = 0x54000;
+    info.offset = 0;
+    info.flags = PROT_READ | PROT_WRITE;
+    info.elf = nullptr;
+    maps_.FakeAddMapInfo(info);
   }
 
   void SetUp() override {
@@ -345,7 +362,7 @@
   ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
 
   regs_.FakeSetPc(0x1000);
-  regs_.FakeSetSp(0x53000);
+  regs_.FakeSetSp(0x63000);
   ElfInterfaceFake::FakePushStepData(StepData(0x21002, 0x50020, false));
   ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
 
@@ -358,7 +375,7 @@
   EXPECT_EQ(0U, frame->num);
   EXPECT_EQ(0U, frame->rel_pc);
   EXPECT_EQ(0x1000U, frame->pc);
-  EXPECT_EQ(0x53000U, frame->sp);
+  EXPECT_EQ(0x63000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
   EXPECT_EQ("/system/fake/libc.so", frame->map_name);
@@ -540,6 +557,59 @@
   EXPECT_EQ(0, frame->map_flags);
 }
 
+// Verify that an unwind stops when a frame is in given suffix.
+TEST_F(UnwinderTest, map_ignore_suffixes) {
+  ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
+  ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
+  ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
+  ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3));
+
+  // Fake as if code called a nullptr function.
+  regs_.FakeSetPc(0x1000);
+  regs_.FakeSetSp(0x10000);
+  ElfInterfaceFake::FakePushStepData(StepData(0x43402, 0x10010, false));
+  ElfInterfaceFake::FakePushStepData(StepData(0x53502, 0x10020, false));
+  ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
+
+  Unwinder unwinder(64, &maps_, &regs_, process_memory_);
+  std::set<std::string> suffixes{"oat"};
+  unwinder.Unwind(nullptr, &suffixes);
+
+  ASSERT_EQ(2U, unwinder.NumFrames());
+  // Make sure the elf was not initialized.
+  MapInfo* map_info = maps_.Find(0x53000);
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_TRUE(map_info->elf == nullptr);
+
+  auto* frame = &unwinder.frames()[0];
+  EXPECT_EQ(0U, frame->num);
+  EXPECT_EQ(0U, frame->rel_pc);
+  EXPECT_EQ(0x1000U, frame->pc);
+  EXPECT_EQ(0x10000U, frame->sp);
+  EXPECT_EQ("Frame0", frame->function_name);
+  EXPECT_EQ(0U, frame->function_offset);
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
+
+  frame = &unwinder.frames()[1];
+  EXPECT_EQ(1U, frame->num);
+  EXPECT_EQ(0x400U, frame->rel_pc);
+  EXPECT_EQ(0x43400U, frame->pc);
+  EXPECT_EQ(0x10010U, frame->sp);
+  EXPECT_EQ("Frame1", frame->function_name);
+  EXPECT_EQ(1U, frame->function_offset);
+  EXPECT_EQ("/fake/fake.apk", frame->map_name);
+  EXPECT_EQ(0x1d000U, frame->map_offset);
+  EXPECT_EQ(0x43000U, frame->map_start);
+  EXPECT_EQ(0x44000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
+}
+
 // Verify format frame code.
 TEST_F(UnwinderTest, format_frame_static) {
   FrameData frame;