diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp index b0f37867f..2573b1cbc 100644 --- a/libunwindstack/Android.bp +++ b/libunwindstack/Android.bp @@ -239,6 +239,7 @@ cc_defaults { "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 e34273cd5..e863f2230 100644 --- a/libunwindstack/ElfInterface.cpp +++ b/libunwindstack/ElfInterface.cpp @@ -228,7 +228,7 @@ void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, int64_t* load_bias) 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(phdr.p_paddr) - phdr.p_offset; + eh_frame_hdr_section_bias_ = static_cast(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 b048b178f..ea27e3ec6 100644 --- a/libunwindstack/tests/ElfInterfaceTest.cpp +++ b/libunwindstack/tests/ElfInterfaceTest.cpp @@ -1310,7 +1310,7 @@ void ElfInterfaceTest::CheckGnuEhFrame(uint64_t addr, uint64_t offset, int64_t e 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 72eef3e0b..0d58c09be 100644 --- a/libunwindstack/tests/UnwindOfflineTest.cpp +++ b/libunwindstack/tests/UnwindOfflineTest.cpp @@ -1583,4 +1583,50 @@ TEST_F(UnwindOfflineTest, load_bias_different_section_bias_arm64) { 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 \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 000000000..f3eb6153d Binary files /dev/null and b/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so 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 000000000..7d5248393 --- /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 000000000..821928e79 --- /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 000000000..b95bfac9e Binary files /dev/null and b/libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data 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 000000000..aefdb6b4c Binary files /dev/null and b/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned 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 000000000..c71dcfbe5 Binary files /dev/null and b/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so differ diff --git a/libunwindstack/tools/unwind_for_offline.cpp b/libunwindstack/tools/unwind_for_offline.cpp index 4f67d679f..64b58a83a 100644 --- a/libunwindstack/tools/unwind_for_offline.cpp +++ b/libunwindstack/tools/unwind_for_offline.cpp @@ -275,6 +275,9 @@ int SaveData(pid_t pid) { 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;