Fix handling of PT_GNU_EH_FRAME.
The bias for the PT_GNU_EH_FRAME was using the paddr instead of vaddr. This doesn't match the way the load bias is calculated, which always use vaddr - offset, so change to use vaddr. Found on an old x86 device that has a vdso that sets vaddr differently from paddr. Add a new offline test to catch this case and update the elf interface unit tests. Also, fix a small bug in the unwind_for_offline tool. Bug: 142365899 Test: Unit tests pass. Change-Id: I5f0bf062dd8ee45aa8553189ba493ec962e0b059
This commit is contained in:
parent
d1a6d75d29
commit
5838e53b97
11 changed files with 64 additions and 2 deletions
|
@ -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/*",
|
||||
|
|
|
@ -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<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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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 <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
|
||||
|
|
BIN
libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so
Normal file
BIN
libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so
Normal file
Binary file not shown.
|
@ -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
|
|
@ -0,0 +1,9 @@
|
|||
eax: fffffffc
|
||||
ebx: 4
|
||||
ecx: eb290180
|
||||
edx: 20
|
||||
ebp: 8
|
||||
edi: 0
|
||||
esi: ffffffff
|
||||
esp: fffe1a30
|
||||
eip: ffffe430
|
BIN
libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data
Normal file
BIN
libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data
Normal file
Binary file not shown.
BIN
libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned
Normal file
BIN
libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned
Normal file
Binary file not shown.
BIN
libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so
Normal file
BIN
libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so
Normal file
Binary file not shown.
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue