diff options
-rw-r--r-- | libunwindstack/Android.bp | 1 | ||||
-rw-r--r-- | libunwindstack/ElfInterface.cpp | 27 | ||||
-rw-r--r-- | libunwindstack/offline_files/apk_soname_at_end_arm64/libc.so.gz | bin | 0 -> 453288 bytes | |||
-rw-r--r-- | libunwindstack/offline_files/apk_soname_at_end_arm64/maps.txt | 6 | ||||
-rw-r--r-- | libunwindstack/offline_files/apk_soname_at_end_arm64/output.txt | 3 | ||||
-rw-r--r-- | libunwindstack/offline_files/apk_soname_at_end_arm64/regs.txt | 34 | ||||
-rw-r--r-- | libunwindstack/offline_files/apk_soname_at_end_arm64/stack.data | bin | 0 -> 5240 bytes | |||
-rw-r--r-- | libunwindstack/offline_files/apk_soname_at_end_arm64/unwinder.apk.gz | bin | 0 -> 1817 bytes | |||
-rw-r--r-- | libunwindstack/offline_files/apk_soname_at_end_arm64/unwinder.gz | bin | 0 -> 1923 bytes | |||
-rw-r--r-- | libunwindstack/tests/UnwindOfflineTest.cpp | 27 |
10 files changed, 95 insertions, 3 deletions
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp index bed17e4..3c1eeb8 100644 --- a/libunwindstack/Android.bp +++ b/libunwindstack/Android.bp @@ -361,6 +361,7 @@ cc_defaults { "offline_files/apk_rorx_unreadable_arm64/*", "offline_files/apk_rx_arm64/*", "offline_files/apk_rx_unreadable_arm64/*", + "offline_files/apk_soname_at_end_arm64/*", "offline_files/art_quick_osr_stub_arm/*", "offline_files/bad_eh_frame_hdr_arm64/*", "offline_files/debug_frame_first_x86/*", diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp index 0389198..43f1218 100644 --- a/libunwindstack/ElfInterface.cpp +++ b/libunwindstack/ElfInterface.cpp @@ -520,12 +520,33 @@ template <typename ElfTypes> void ElfInterfaceImpl<ElfTypes>::GetMaxSize(Memory* memory, uint64_t* size) { EhdrType ehdr; if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) { + *size = 0; return; } - if (ehdr.e_shnum == 0) { - return; + + // If this winds up as zero, the PT_LOAD reading will get a better value. + uint64_t elf_size = ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum; + + // Search through the PT_LOAD values and if any result in a larger elf + // size, use that. + uint64_t offset = ehdr.e_phoff; + for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) { + PhdrType phdr; + if (!memory->ReadFully(offset, &phdr, sizeof(phdr))) { + break; + } + if (phdr.p_type == PT_LOAD) { + uint64_t end_offset; + if (__builtin_add_overflow(phdr.p_offset, phdr.p_memsz, &end_offset)) { + continue; + } + if (end_offset > elf_size) { + elf_size = end_offset; + } + } } - *size = ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum; + + *size = elf_size; } template <typename EhdrType, typename ShdrType> diff --git a/libunwindstack/offline_files/apk_soname_at_end_arm64/libc.so.gz b/libunwindstack/offline_files/apk_soname_at_end_arm64/libc.so.gz Binary files differnew file mode 100644 index 0000000..7f8b791 --- /dev/null +++ b/libunwindstack/offline_files/apk_soname_at_end_arm64/libc.so.gz diff --git a/libunwindstack/offline_files/apk_soname_at_end_arm64/maps.txt b/libunwindstack/offline_files/apk_soname_at_end_arm64/maps.txt new file mode 100644 index 0000000..0f17200 --- /dev/null +++ b/libunwindstack/offline_files/apk_soname_at_end_arm64/maps.txt @@ -0,0 +1,6 @@ +580e17c000-580e17d000 r--p 0 00:00 0 unwinder +580e17d000-580e17e000 r-xp 1000 00:00 0 unwinder +7c0064a000-7c0064b000 r--p a000 00:00 0 unwinder.apk +7c0064b000-7c0064c000 r-xp b000 00:00 0 unwinder.apk +7e90877000-7e908ba000 r--p 0 00:00 0 libc.so +7e908ba000-7e9094c000 r-xp 43000 00:00 0 libc.so diff --git a/libunwindstack/offline_files/apk_soname_at_end_arm64/output.txt b/libunwindstack/offline_files/apk_soname_at_end_arm64/output.txt new file mode 100644 index 0000000..557dda7 --- /dev/null +++ b/libunwindstack/offline_files/apk_soname_at_end_arm64/output.txt @@ -0,0 +1,3 @@ + #00 pc 000000000000113c unwinder.apk!libunwindstack_local.so (offset 0xa000) (WaitForever+60) + #01 pc 00000000000010f0 unwinder (main+144) + #02 pc 0000000000052cc8 libc.so (__libc_init+104) diff --git a/libunwindstack/offline_files/apk_soname_at_end_arm64/regs.txt b/libunwindstack/offline_files/apk_soname_at_end_arm64/regs.txt new file mode 100644 index 0000000..26dc38a --- /dev/null +++ b/libunwindstack/offline_files/apk_soname_at_end_arm64/regs.txt @@ -0,0 +1,34 @@ +x0: 7ff9ec4b94 +x1: 0 +x2: 0 +x3: 0 +x4: 10 +x5: b400007d8087e0c9 +x6: a +x7: 7f7f7f7f7f7f7f7f +x8: 1 +x9: fbf40ad8e3dbed37 +x10: 10ec +x11: 10ec +x12: 163 +x13: 7ff9ec44c4 +x14: 0 +x15: 2 +x16: 7e9094ec00 +x17: 7e90941e30 +x18: 7e918d4000 +x19: 7c0064b100 +x20: 7e91416000 +x21: 1 +x22: 7ff9ec4c78 +x23: 0 +x24: 0 +x25: 0 +x26: 0 +x27: 0 +x28: 0 +x29: 7ff9ec4ba0 +lr: 7c0064b148 +sp: 7ff9ec4b90 +pc: 7c0064b13c +pst: 60001000 diff --git a/libunwindstack/offline_files/apk_soname_at_end_arm64/stack.data b/libunwindstack/offline_files/apk_soname_at_end_arm64/stack.data Binary files differnew file mode 100644 index 0000000..19079b1 --- /dev/null +++ b/libunwindstack/offline_files/apk_soname_at_end_arm64/stack.data diff --git a/libunwindstack/offline_files/apk_soname_at_end_arm64/unwinder.apk.gz b/libunwindstack/offline_files/apk_soname_at_end_arm64/unwinder.apk.gz Binary files differnew file mode 100644 index 0000000..f38d8f1 --- /dev/null +++ b/libunwindstack/offline_files/apk_soname_at_end_arm64/unwinder.apk.gz diff --git a/libunwindstack/offline_files/apk_soname_at_end_arm64/unwinder.gz b/libunwindstack/offline_files/apk_soname_at_end_arm64/unwinder.gz Binary files differnew file mode 100644 index 0000000..90eb389 --- /dev/null +++ b/libunwindstack/offline_files/apk_soname_at_end_arm64/unwinder.gz diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp index 0d6fa1d..0306b29 100644 --- a/libunwindstack/tests/UnwindOfflineTest.cpp +++ b/libunwindstack/tests/UnwindOfflineTest.cpp @@ -1658,5 +1658,32 @@ TEST_F(UnwindOfflineTest, apk_rx_unreadable_arm64) { VerifyApkRX(unwinder); } +TEST_F(UnwindOfflineTest, apk_soname_at_end_arm64) { + std::string error_msg; + if (!offline_utils_.Init({.offline_files_dir = "apk_soname_at_end_arm64/", .arch = ARCH_ARM64}, + &error_msg)) + FAIL() << error_msg; + + Regs* regs = offline_utils_.GetRegs(); + std::unique_ptr<Regs> regs_copy(regs->Clone()); + Unwinder unwinder(128, offline_utils_.GetMaps(), regs, offline_utils_.GetProcessMemory()); + unwinder.Unwind(); + + size_t expected_num_frames; + if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg; + std::string expected_frame_info; + if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg; + + std::string frame_info(DumpFrames(unwinder)); + ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info; + EXPECT_EQ(expected_frame_info, frame_info); + EXPECT_EQ(0x7c0064b13cULL, unwinder.frames()[0].pc); + EXPECT_EQ(0x7ff9ec4b90ULL, unwinder.frames()[0].sp); + EXPECT_EQ(0x580e17d0f0ULL, unwinder.frames()[1].pc); + EXPECT_EQ(0x7ff9ec4bb0ULL, unwinder.frames()[1].sp); + EXPECT_EQ(0x7e908c9cc8ULL, unwinder.frames()[2].pc); + EXPECT_EQ(0x7ff9ec4c10ULL, unwinder.frames()[2].sp); +} + } // namespace } // namespace unwindstack |