Fix issues in libunwindstack.

- Add a load_bias field in MapInfo so that it can be loaded offline,
  and also so it can be cached.
- Add an Add function to the Maps class so that it's possible to manually
  create a map.
- Remove the OfflineMaps class since I haven't found a reason for this to
  exist.
- Add a pointer to the gnu debugdata compressed section in the interface
  itself and modify the step path to try eh_frame, then debug_frame, then
  gnu_debugdata. This way arm can add exidx as the last step behind
  gnu_debugdata. Add an offline test to verify the order of unwind.
- Fix x86_64_ucontext_t since it was a different size on 32 bit and 64 bit
  systems.

Test: Pass new unit tests.
Change-Id: I978b70d6c244bd307c62a29886d24c1a8cb2af23
diff --git a/libunwindstack/tests/ElfFake.cpp b/libunwindstack/tests/ElfFake.cpp
index b94a8a4..68de797 100644
--- a/libunwindstack/tests/ElfFake.cpp
+++ b/libunwindstack/tests/ElfFake.cpp
@@ -43,7 +43,7 @@
   return true;
 }
 
-bool ElfInterfaceFake::Step(uint64_t, Regs* regs, Memory*, bool* finished) {
+bool ElfInterfaceFake::Step(uint64_t, uint64_t, Regs* regs, Memory*, bool* finished) {
   if (steps_.empty()) {
     return false;
   }
diff --git a/libunwindstack/tests/ElfFake.h b/libunwindstack/tests/ElfFake.h
index 565b13f..abf9927 100644
--- a/libunwindstack/tests/ElfFake.h
+++ b/libunwindstack/tests/ElfFake.h
@@ -68,8 +68,7 @@
 
   bool GetFunctionName(uint64_t, uint64_t, std::string*, uint64_t*) override;
 
-  bool Step(uint64_t, Regs*, Memory*, bool*) override;
-
+  bool Step(uint64_t, uint64_t, Regs*, Memory*, bool*) override;
 
   static void FakePushFunctionData(const FunctionData data) { functions_.push_back(data); }
   static void FakePushStepData(const StepData data) { steps_.push_back(data); }
diff --git a/libunwindstack/tests/ElfInterfaceArmTest.cpp b/libunwindstack/tests/ElfInterfaceArmTest.cpp
index 5f7cf60..e6763ab 100644
--- a/libunwindstack/tests/ElfInterfaceArmTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceArmTest.cpp
@@ -302,7 +302,7 @@
 
   // FindEntry fails.
   bool finished;
-  ASSERT_FALSE(interface.StepExidx(0x7000, nullptr, nullptr, &finished));
+  ASSERT_FALSE(interface.StepExidx(0x7000, 0, nullptr, nullptr, &finished));
 
   // ExtractEntry should fail.
   interface.FakeSetStartOffset(0x1000);
@@ -315,20 +315,26 @@
   regs[ARM_REG_LR] = 0x20000;
   regs.set_sp(regs[ARM_REG_SP]);
   regs.set_pc(0x1234);
-  ASSERT_FALSE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
+  ASSERT_FALSE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished));
 
   // Eval should fail.
   memory_.SetData32(0x1004, 0x81000000);
-  ASSERT_FALSE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
+  ASSERT_FALSE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished));
 
   // Everything should pass.
   memory_.SetData32(0x1004, 0x80b0b0b0);
-  ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
+  ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished));
   ASSERT_FALSE(finished);
   ASSERT_EQ(0x1000U, regs.sp());
   ASSERT_EQ(0x1000U, regs[ARM_REG_SP]);
   ASSERT_EQ(0x20000U, regs.pc());
   ASSERT_EQ(0x20000U, regs[ARM_REG_PC]);
+
+  // Load bias is non-zero.
+  ASSERT_TRUE(interface.StepExidx(0x8000, 0x1000, &regs, &process_memory_, &finished));
+
+  // Pc too small.
+  ASSERT_FALSE(interface.StepExidx(0x8000, 0x9000, &regs, &process_memory_, &finished));
 }
 
 TEST_F(ElfInterfaceArmTest, StepExidx_pc_set) {
@@ -349,7 +355,7 @@
 
   // Everything should pass.
   bool finished;
-  ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
+  ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished));
   ASSERT_FALSE(finished);
   ASSERT_EQ(0x10004U, regs.sp());
   ASSERT_EQ(0x10004U, regs[ARM_REG_SP]);
@@ -372,7 +378,7 @@
   regs.set_pc(0x1234);
 
   bool finished;
-  ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
+  ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished));
   ASSERT_TRUE(finished);
   ASSERT_EQ(0x10000U, regs.sp());
   ASSERT_EQ(0x10000U, regs[ARM_REG_SP]);
@@ -394,7 +400,7 @@
   regs.set_pc(0x1234);
 
   bool finished;
-  ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
+  ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished));
   ASSERT_TRUE(finished);
   ASSERT_EQ(0x10000U, regs.sp());
   ASSERT_EQ(0x10000U, regs[ARM_REG_SP]);
@@ -420,7 +426,7 @@
   regs.set_pc(0x1234);
 
   bool finished;
-  ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
+  ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished));
   ASSERT_TRUE(finished);
   ASSERT_EQ(0U, regs.pc());
 
@@ -432,7 +438,7 @@
   regs.set_sp(regs[ARM_REG_SP]);
   regs.set_pc(0x1234);
 
-  ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
+  ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished));
   ASSERT_TRUE(finished);
   ASSERT_EQ(0U, regs.pc());
 }
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index 7491d40..5e808ef 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -346,7 +346,7 @@
   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*));
+  MOCK_METHOD5(Step, bool(uint64_t, uint64_t, Regs*, Memory*, bool*));
 };
 
 TEST_F(ElfTest, step_in_interface) {
@@ -361,7 +361,7 @@
   MemoryFake process_memory;
 
   bool finished;
-  EXPECT_CALL(*interface, Step(0x1000, &regs, &process_memory, &finished))
+  EXPECT_CALL(*interface, Step(0x1000, 0, &regs, &process_memory, &finished))
       .WillOnce(::testing::Return(true));
 
   ASSERT_TRUE(elf.Step(0x1004, 0x1000, 0x2000, &regs, &process_memory, &finished));
@@ -382,7 +382,7 @@
   bool finished;
   ASSERT_FALSE(elf.Step(0x1004, 0x1000, 0x2000, &regs, &process_memory, &finished));
 
-  EXPECT_CALL(*interface, Step(0x3300, &regs, &process_memory, &finished))
+  EXPECT_CALL(*interface, Step(0x7300, 0x4000, &regs, &process_memory, &finished))
       .WillOnce(::testing::Return(true));
 
   ASSERT_TRUE(elf.Step(0x7304, 0x7300, 0x2000, &regs, &process_memory, &finished));
diff --git a/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp b/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp
index 44a73a8..631036b 100644
--- a/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp
+++ b/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp
@@ -68,12 +68,23 @@
   EXPECT_EQ(0U, info.GetLoadBias(process_memory_));
 }
 
+TEST_F(MapInfoGetLoadBiasTest, load_bias_cached_from_elf) {
+  map_info_->elf = elf_container_.release();
+
+  elf_->FakeSetLoadBias(0);
+  EXPECT_EQ(0U, map_info_->GetLoadBias(process_memory_));
+
+  elf_->FakeSetLoadBias(0x1000);
+  EXPECT_EQ(0U, map_info_->GetLoadBias(process_memory_));
+}
+
 TEST_F(MapInfoGetLoadBiasTest, elf_exists) {
   map_info_->elf = elf_container_.release();
 
   elf_->FakeSetLoadBias(0);
   EXPECT_EQ(0U, map_info_->GetLoadBias(process_memory_));
 
+  map_info_->load_bias = static_cast<uint64_t>(-1);
   elf_->FakeSetLoadBias(0x1000);
   EXPECT_EQ(0x1000U, map_info_->GetLoadBias(process_memory_));
 }
@@ -141,6 +152,15 @@
   EXPECT_EQ(0xe000U, map_info_->GetLoadBias(process_memory_));
 }
 
+TEST_F(MapInfoGetLoadBiasTest, elf_exists_in_memory_cached) {
+  InitElfData(memory_, map_info_->start);
+
+  EXPECT_EQ(0xe000U, map_info_->GetLoadBias(process_memory_));
+
+  memory_->Clear();
+  EXPECT_EQ(0xe000U, map_info_->GetLoadBias(process_memory_));
+}
+
 TEST_F(MapInfoGetLoadBiasTest, multiple_thread_elf_exists_in_memory) {
   InitElfData(memory_, map_info_->start);
 
diff --git a/libunwindstack/tests/MapsTest.cpp b/libunwindstack/tests/MapsTest.cpp
index 8dc884f..9622ba5 100644
--- a/libunwindstack/tests/MapsTest.cpp
+++ b/libunwindstack/tests/MapsTest.cpp
@@ -44,6 +44,24 @@
   }
 }
 
+TEST(MapsTest, map_add) {
+  Maps maps;
+
+  maps.Add(0x1000, 0x2000, 0, PROT_READ, "fake_map", 0);
+  maps.Add(0x3000, 0x4000, 0x10, 0, "", 0x1234);
+  maps.Add(0x5000, 0x6000, 1, 2, "fake_map2", static_cast<uint64_t>(-1));
+
+  ASSERT_EQ(3U, maps.Total());
+  MapInfo* info = maps.Get(0);
+  ASSERT_EQ(0x1000U, info->start);
+  ASSERT_EQ(0x2000U, info->end);
+  ASSERT_EQ(0U, info->offset);
+  ASSERT_EQ(PROT_READ, info->flags);
+  ASSERT_EQ("fake_map", info->name);
+  ASSERT_EQ(0U, info->elf_offset);
+  ASSERT_EQ(0U, info->load_bias.load());
+}
+
 TEST(MapsTest, verify_parse_line) {
   MapInfo info;
 
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index 962f744..8f28036 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -96,6 +96,54 @@
       frame_info);
 }
 
+TEST(UnwindOfflineTest, pc_in_gnu_debugdata_arm32) {
+  std::string dir(TestGetFileDirectory() + "offline/gnu_debugdata_arm32/");
+
+  MemoryOffline* memory = new MemoryOffline;
+  ASSERT_TRUE(memory->Init((dir + "stack.data").c_str(), 0));
+
+  FILE* fp = fopen((dir + "regs.txt").c_str(), "r");
+  ASSERT_TRUE(fp != nullptr);
+  RegsArm regs;
+  uint64_t reg_value;
+  ASSERT_EQ(1, fscanf(fp, "pc: %" SCNx64 "\n", &reg_value));
+  regs[ARM_REG_PC] = reg_value;
+  ASSERT_EQ(1, fscanf(fp, "sp: %" SCNx64 "\n", &reg_value));
+  regs[ARM_REG_SP] = reg_value;
+  regs.SetFromRaw();
+  fclose(fp);
+
+  fp = fopen((dir + "maps.txt").c_str(), "r");
+  ASSERT_TRUE(fp != nullptr);
+  // The file is guaranteed to be less than 4096 bytes.
+  std::vector<char> buffer(4096);
+  ASSERT_NE(0U, fread(buffer.data(), 1, buffer.size(), fp));
+  fclose(fp);
+
+  BufferMaps maps(buffer.data());
+  ASSERT_TRUE(maps.Parse());
+
+  ASSERT_EQ(ARCH_ARM, regs.Arch());
+
+  std::shared_ptr<Memory> process_memory(memory);
+
+  char* cwd = getcwd(nullptr, 0);
+  ASSERT_EQ(0, chdir(dir.c_str()));
+  Unwinder unwinder(128, &maps, &regs, process_memory);
+  unwinder.Unwind();
+  ASSERT_EQ(0, chdir(cwd));
+  free(cwd);
+
+  std::string frame_info(DumpFrames(unwinder));
+  ASSERT_EQ(2U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 0006dc49  libandroid_runtime.so "
+      "(_ZN7android14AndroidRuntime15javaThreadShellEPv+80)\n"
+      "  #01 pc 0006dce5  libandroid_runtime.so "
+      "(_ZN7android14AndroidRuntime19javaCreateThreadEtcEPFiPvES1_PKcijPS1_)\n",
+      frame_info);
+}
+
 TEST(UnwindOfflineTest, pc_straddle_arm64) {
   std::string dir(TestGetFileDirectory() + "offline/straddle_arm64/");
 
diff --git a/libunwindstack/tests/files/offline/gnu_debugdata_arm32/libandroid_runtime.so b/libunwindstack/tests/files/offline/gnu_debugdata_arm32/libandroid_runtime.so
new file mode 100644
index 0000000..e4283e6
--- /dev/null
+++ b/libunwindstack/tests/files/offline/gnu_debugdata_arm32/libandroid_runtime.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/gnu_debugdata_arm32/maps.txt b/libunwindstack/tests/files/offline/gnu_debugdata_arm32/maps.txt
new file mode 100644
index 0000000..1bcddb6
--- /dev/null
+++ b/libunwindstack/tests/files/offline/gnu_debugdata_arm32/maps.txt
@@ -0,0 +1 @@
+f1f10000-f2049000 r-xp 00000000 00:00 0   libandroid_runtime.so
diff --git a/libunwindstack/tests/files/offline/gnu_debugdata_arm32/regs.txt b/libunwindstack/tests/files/offline/gnu_debugdata_arm32/regs.txt
new file mode 100644
index 0000000..c6a93dc
--- /dev/null
+++ b/libunwindstack/tests/files/offline/gnu_debugdata_arm32/regs.txt
@@ -0,0 +1,2 @@
+pc: f1f6dc49
+sp: d8fe6930
diff --git a/libunwindstack/tests/files/offline/gnu_debugdata_arm32/stack.data b/libunwindstack/tests/files/offline/gnu_debugdata_arm32/stack.data
new file mode 100644
index 0000000..19cdf2d
--- /dev/null
+++ b/libunwindstack/tests/files/offline/gnu_debugdata_arm32/stack.data
Binary files differ