Merge "Fix handling of PT_GNU_EH_FRAME." am: d76932ffa5 am: ec79999dbf
am: 84bd232f65

Change-Id: I0319d8c2436a08dc62fc44a1d0b8dfa158f27115
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index b0f3786..2573b1c 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -239,6 +239,7 @@
         "tests/files/offline/bad_eh_frame_hdr_arm64/*",
         "tests/files/offline/debug_frame_first_x86/*",
         "tests/files/offline/debug_frame_load_bias_arm/*",
+        "tests/files/offline/eh_frame_bias_x86/*",
         "tests/files/offline/eh_frame_hdr_begin_x86_64/*",
         "tests/files/offline/invalid_elf_offset_arm/*",
         "tests/files/offline/jit_debug_arm/*",
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index e34273c..e863f22 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -228,7 +228,7 @@
     case PT_GNU_EH_FRAME:
       // This is really the pointer to the .eh_frame_hdr section.
       eh_frame_hdr_offset_ = phdr.p_offset;
-      eh_frame_hdr_section_bias_ = static_cast<uint64_t>(phdr.p_paddr) - phdr.p_offset;
+      eh_frame_hdr_section_bias_ = static_cast<uint64_t>(phdr.p_vaddr) - phdr.p_offset;
       eh_frame_hdr_size_ = phdr.p_memsz;
       break;
 
diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp
index b048b17..ea27e3e 100644
--- a/libunwindstack/tests/ElfInterfaceTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceTest.cpp
@@ -1310,7 +1310,7 @@
 
   memset(&phdr, 0, sizeof(phdr));
   phdr.p_type = PT_GNU_EH_FRAME;
-  phdr.p_paddr = addr;
+  phdr.p_vaddr = addr;
   phdr.p_offset = offset;
   memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr));
 
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index 72eef3e..0d58c09 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -1583,4 +1583,50 @@
   EXPECT_EQ(0x7fdd4a4170ULL, unwinder.frames()[11].sp);
 }
 
+TEST_F(UnwindOfflineTest, eh_frame_bias_x86) {
+  ASSERT_NO_FATAL_FAILURE(Init("eh_frame_bias_x86/", ARCH_X86));
+
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
+  unwinder.Unwind();
+
+  std::string frame_info(DumpFrames(unwinder));
+  ASSERT_EQ(11U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc ffffe430  vdso.so (__kernel_vsyscall+16)\n"
+      "  #01 pc 00082a4b  libc.so (__epoll_pwait+43)\n"
+      "  #02 pc 000303a3  libc.so (epoll_pwait+115)\n"
+      "  #03 pc 000303ed  libc.so (epoll_wait+45)\n"
+      "  #04 pc 00010ea2  tombstoned (epoll_dispatch+226)\n"
+      "  #05 pc 0000c5e7  tombstoned (event_base_loop+1095)\n"
+      "  #06 pc 0000c193  tombstoned (event_base_dispatch+35)\n"
+      "  #07 pc 00005c77  tombstoned (main+884)\n"
+      "  #08 pc 00015f66  libc.so (__libc_init+102)\n"
+      "  #09 pc 0000360e  tombstoned (_start+98)\n"
+      "  #10 pc 00000001  <unknown>\n",
+      frame_info);
+
+  EXPECT_EQ(0xffffe430ULL, unwinder.frames()[0].pc);
+  EXPECT_EQ(0xfffe1a30ULL, unwinder.frames()[0].sp);
+  EXPECT_EQ(0xeb585a4bULL, unwinder.frames()[1].pc);
+  EXPECT_EQ(0xfffe1a40ULL, unwinder.frames()[1].sp);
+  EXPECT_EQ(0xeb5333a3ULL, unwinder.frames()[2].pc);
+  EXPECT_EQ(0xfffe1a60ULL, unwinder.frames()[2].sp);
+  EXPECT_EQ(0xeb5333edULL, unwinder.frames()[3].pc);
+  EXPECT_EQ(0xfffe1ab0ULL, unwinder.frames()[3].sp);
+  EXPECT_EQ(0xeb841ea2ULL, unwinder.frames()[4].pc);
+  EXPECT_EQ(0xfffe1ae0ULL, unwinder.frames()[4].sp);
+  EXPECT_EQ(0xeb83d5e7ULL, unwinder.frames()[5].pc);
+  EXPECT_EQ(0xfffe1b30ULL, unwinder.frames()[5].sp);
+  EXPECT_EQ(0xeb83d193ULL, unwinder.frames()[6].pc);
+  EXPECT_EQ(0xfffe1bd0ULL, unwinder.frames()[6].sp);
+  EXPECT_EQ(0xeb836c77ULL, unwinder.frames()[7].pc);
+  EXPECT_EQ(0xfffe1c00ULL, unwinder.frames()[7].sp);
+  EXPECT_EQ(0xeb518f66ULL, unwinder.frames()[8].pc);
+  EXPECT_EQ(0xfffe1d00ULL, unwinder.frames()[8].sp);
+  EXPECT_EQ(0xeb83460eULL, unwinder.frames()[9].pc);
+  EXPECT_EQ(0xfffe1d40ULL, unwinder.frames()[9].sp);
+  EXPECT_EQ(0x00000001ULL, unwinder.frames()[10].pc);
+  EXPECT_EQ(0xfffe1d74ULL, unwinder.frames()[10].sp);
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so b/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so
new file mode 100644
index 0000000..f3eb615
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/maps.txt b/libunwindstack/tests/files/offline/eh_frame_bias_x86/maps.txt
new file mode 100644
index 0000000..7d52483
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/maps.txt
@@ -0,0 +1,3 @@
+eb503000-eb5e8000 r-xp 0 00:00 0   libc.so
+eb831000-eb852000 r-xp 0 00:00 0   tombstoned
+ffffe000-fffff000 r-xp 0 00:00 0   vdso.so
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/regs.txt b/libunwindstack/tests/files/offline/eh_frame_bias_x86/regs.txt
new file mode 100644
index 0000000..821928e
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/regs.txt
@@ -0,0 +1,9 @@
+eax: fffffffc
+ebx: 4
+ecx: eb290180
+edx: 20
+ebp: 8
+edi: 0
+esi: ffffffff
+esp: fffe1a30
+eip: ffffe430
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data b/libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data
new file mode 100644
index 0000000..b95bfac
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned b/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned
new file mode 100644
index 0000000..aefdb6b
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so b/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so
new file mode 100644
index 0000000..c71dcfb
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so
Binary files differ
diff --git a/libunwindstack/tools/unwind_for_offline.cpp b/libunwindstack/tools/unwind_for_offline.cpp
index 4f67d67..64b58a8 100644
--- a/libunwindstack/tools/unwind_for_offline.cpp
+++ b/libunwindstack/tools/unwind_for_offline.cpp
@@ -275,6 +275,9 @@
 
     if (maps_by_start.count(frame.map_start) == 0) {
       map_info = maps->Find(frame.map_start);
+      if (map_info == nullptr) {
+        continue;
+      }
 
       auto info = FillInAndGetMapInfo(maps_by_start, map_info);
       bool file_copied = false;