Merge "Fix missing load bias."
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 5423de5..a0a6b4f 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -246,6 +246,7 @@
"tests/files/offline/jit_debug_x86/*",
"tests/files/offline/jit_map_arm/*",
"tests/files/offline/gnu_debugdata_arm/*",
+ "tests/files/offline/load_bias_ro_rx_x86_64/*",
"tests/files/offline/offset_arm/*",
"tests/files/offline/shared_lib_in_apk_arm64/*",
"tests/files/offline/shared_lib_in_apk_memory_only_arm64/*",
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index f0e4138..bdfee01 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -197,6 +197,7 @@
template <typename EhdrType, typename PhdrType>
void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias) {
uint64_t offset = ehdr.e_phoff;
+ bool first_exec_load_header = true;
for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
PhdrType phdr;
if (!memory_->ReadFully(offset, &phdr, sizeof(phdr))) {
@@ -212,9 +213,11 @@
pt_loads_[phdr.p_offset] = LoadInfo{phdr.p_offset, phdr.p_vaddr,
static_cast<size_t>(phdr.p_memsz)};
- if (phdr.p_offset == 0) {
- *load_bias = phdr.p_vaddr;
+ // Only set the load bias from the first executable load header.
+ if (first_exec_load_header && phdr.p_vaddr > phdr.p_offset) {
+ *load_bias = phdr.p_vaddr - phdr.p_offset;
}
+ first_exec_load_header = false;
break;
}
diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp
index cdc927a..f9ee9eb 100644
--- a/libunwindstack/tests/ElfInterfaceTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceTest.cpp
@@ -360,7 +360,7 @@
uint64_t load_bias = 0;
ASSERT_TRUE(elf->Init(&load_bias));
- EXPECT_EQ(0U, load_bias);
+ EXPECT_EQ(0x1001U, load_bias);
const std::unordered_map<uint64_t, LoadInfo>& pt_loads = elf->pt_loads();
ASSERT_EQ(1U, pt_loads.size());
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index baada82..e6158a2 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -1457,4 +1457,77 @@
EXPECT_EQ(0xc2044218, unwinder.frames()[0].sp);
}
+TEST_F(UnwindOfflineTest, load_bias_ro_rx_x86_64) {
+ ASSERT_NO_FATAL_FAILURE(Init("load_bias_ro_rx_x86_64/", ARCH_X86_64));
+
+ Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
+ unwinder.Unwind();
+
+ std::string frame_info(DumpFrames(unwinder));
+ ASSERT_EQ(17U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+ EXPECT_EQ(
+ " #00 pc 00000000000e9dd4 libc.so (__write+20)\n"
+ " #01 pc 000000000007ab9c libc.so (_IO_file_write+44)\n"
+ " #02 pc 0000000000079f3e libc.so\n"
+ " #03 pc 000000000007bce8 libc.so (_IO_do_write+24)\n"
+ " #04 pc 000000000007b26e libc.so (_IO_file_xsputn+270)\n"
+ " #05 pc 000000000004f7f9 libc.so (_IO_vfprintf+1945)\n"
+ " #06 pc 0000000000057cb5 libc.so (_IO_printf+165)\n"
+ " #07 pc 0000000000ed1796 perfetto_unittests "
+ "(testing::internal::PrettyUnitTestResultPrinter::OnTestIterationStart(testing::UnitTest "
+ "const&, int)+374)\n"
+ " #08 pc 0000000000ed30fd perfetto_unittests "
+ "(testing::internal::TestEventRepeater::OnTestIterationStart(testing::UnitTest const&, "
+ "int)+125)\n"
+ " #09 pc 0000000000ed5e25 perfetto_unittests "
+ "(testing::internal::UnitTestImpl::RunAllTests()+581)\n"
+ " #10 pc 0000000000ef63f3 perfetto_unittests "
+ "(_ZN7testing8internal38HandleSehExceptionsInMethodIfSupportedINS0_12UnitTestImplEbEET0_PT_"
+ "MS4_FS3_vEPKc+131)\n"
+ " #11 pc 0000000000ee2a21 perfetto_unittests "
+ "(_ZN7testing8internal35HandleExceptionsInMethodIfSupportedINS0_12UnitTestImplEbEET0_PT_MS4_"
+ "FS3_vEPKc+113)\n"
+ " #12 pc 0000000000ed5bb9 perfetto_unittests (testing::UnitTest::Run()+185)\n"
+ " #13 pc 0000000000e900f0 perfetto_unittests (RUN_ALL_TESTS()+16)\n"
+ " #14 pc 0000000000e900d8 perfetto_unittests (main+56)\n"
+ " #15 pc 000000000002352a libc.so (__libc_start_main+234)\n"
+ " #16 pc 0000000000919029 perfetto_unittests (_start+41)\n",
+ frame_info);
+
+ EXPECT_EQ(0x7f9326a57dd4ULL, unwinder.frames()[0].pc);
+ EXPECT_EQ(0x7ffd224153c8ULL, unwinder.frames()[0].sp);
+ EXPECT_EQ(0x7f93269e8b9cULL, unwinder.frames()[1].pc);
+ EXPECT_EQ(0x7ffd224153d0ULL, unwinder.frames()[1].sp);
+ EXPECT_EQ(0x7f93269e7f3eULL, unwinder.frames()[2].pc);
+ EXPECT_EQ(0x7ffd22415400ULL, unwinder.frames()[2].sp);
+ EXPECT_EQ(0x7f93269e9ce8ULL, unwinder.frames()[3].pc);
+ EXPECT_EQ(0x7ffd22415440ULL, unwinder.frames()[3].sp);
+ EXPECT_EQ(0x7f93269e926eULL, unwinder.frames()[4].pc);
+ EXPECT_EQ(0x7ffd22415450ULL, unwinder.frames()[4].sp);
+ EXPECT_EQ(0x7f93269bd7f9ULL, unwinder.frames()[5].pc);
+ EXPECT_EQ(0x7ffd22415490ULL, unwinder.frames()[5].sp);
+ EXPECT_EQ(0x7f93269c5cb5ULL, unwinder.frames()[6].pc);
+ EXPECT_EQ(0x7ffd22415a10ULL, unwinder.frames()[6].sp);
+ EXPECT_EQ(0xed1796ULL, unwinder.frames()[7].pc);
+ EXPECT_EQ(0x7ffd22415af0ULL, unwinder.frames()[7].sp);
+ EXPECT_EQ(0xed30fdULL, unwinder.frames()[8].pc);
+ EXPECT_EQ(0x7ffd22415b70ULL, unwinder.frames()[8].sp);
+ EXPECT_EQ(0xed5e25ULL, unwinder.frames()[9].pc);
+ EXPECT_EQ(0x7ffd22415bb0ULL, unwinder.frames()[9].sp);
+ EXPECT_EQ(0xef63f3ULL, unwinder.frames()[10].pc);
+ EXPECT_EQ(0x7ffd22415c60ULL, unwinder.frames()[10].sp);
+ EXPECT_EQ(0xee2a21ULL, unwinder.frames()[11].pc);
+ EXPECT_EQ(0x7ffd22415cc0ULL, unwinder.frames()[11].sp);
+ EXPECT_EQ(0xed5bb9ULL, unwinder.frames()[12].pc);
+ EXPECT_EQ(0x7ffd22415d40ULL, unwinder.frames()[12].sp);
+ EXPECT_EQ(0xe900f0ULL, unwinder.frames()[13].pc);
+ EXPECT_EQ(0x7ffd22415d90ULL, unwinder.frames()[13].sp);
+ EXPECT_EQ(0xe900d8ULL, unwinder.frames()[14].pc);
+ EXPECT_EQ(0x7ffd22415da0ULL, unwinder.frames()[14].sp);
+ EXPECT_EQ(0x7f932699152aULL, unwinder.frames()[15].pc);
+ EXPECT_EQ(0x7ffd22415dd0ULL, unwinder.frames()[15].sp);
+ EXPECT_EQ(0x919029ULL, unwinder.frames()[16].pc);
+ EXPECT_EQ(0x7ffd22415e90ULL, unwinder.frames()[16].sp);
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/libc.so b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/libc.so
new file mode 100644
index 0000000..63383d0
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/maps.txt b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/maps.txt
new file mode 100644
index 0000000..ba5a31b
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/maps.txt
@@ -0,0 +1,3 @@
+200000-919000 r--p 0 00:00 0 perfetto_unittests
+919000-1a0c000 r-xp 719000 00:00 0 perfetto_unittests
+7f932696e000-7f9326b23000 r-xp 0 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/perfetto_unittests b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/perfetto_unittests
new file mode 100644
index 0000000..a30e599
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/perfetto_unittests
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/regs.txt b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/regs.txt
new file mode 100644
index 0000000..6cb4055
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/regs.txt
@@ -0,0 +1,17 @@
+rax: 3b
+rbx: 3b
+rcx: 7f9326a57dd4
+rdx: 3b
+r8: 7ffd22415b09
+r9: 7ffd224155e0
+r10: 0
+r11: 246
+r12: 7f9326d28760
+r13: 3b
+r14: 7f9326d23760
+r15: 3b
+rdi: 1
+rsi: 2678850
+rbp: 2678850
+rsp: 7ffd224153c8
+rip: 7f9326a57dd4
diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/stack.data b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/stack.data
new file mode 100644
index 0000000..4edfe07
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/stack.data
Binary files differ