libunwindstack: Support signal frame CIEs.
Mark a CIE with a S in its augmentation string as signal frame.
This allows the code to properly handle signal frame data if none
of the signal frame pattern matchers work.
For a signal frame, DwarfSectionImpl<AddressType>::Eval needs to
continue the unwinding even if PC is zero. A zero PC means that the
program has crashed, and we should try to recover the real PC using the
return address on the stack or LR. This behavior is tested by
UnwindOffline.signal_{x86,x86_64}, which modify the libc.so files
so that the signal frame pattern matcher fails and the CIE/FDE
data is used instead.
Test: libunwindstack_test
Change-Id: I4655b070028fd984345311a5e743796f8c30ed36
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index 0c6f9f8..ab427b5 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -1736,4 +1736,158 @@
EXPECT_EQ(0x7ffb6c0f30U, unwinder.frames()[6].sp);
}
+// This test has a libc.so where the __restore has been changed so
+// that the signal handler match does not occur and it uses the
+// fde to do the unwind.
+TEST_F(UnwindOfflineTest, signal_fde_x86) {
+ ASSERT_NO_FATAL_FAILURE(Init("signal_fde_x86/", ARCH_X86));
+
+ Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
+ unwinder.Unwind();
+
+ std::string frame_info(DumpFrames(unwinder));
+ ASSERT_EQ(20U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+ EXPECT_EQ(
+ " #00 pc 007914d9 libunwindstack_test (SignalInnerFunction+25)\n"
+ " #01 pc 007914fc libunwindstack_test (SignalMiddleFunction+28)\n"
+ " #02 pc 0079152c libunwindstack_test (SignalOuterFunction+28)\n"
+ " #03 pc 0079af62 libunwindstack_test (unwindstack::SignalCallerHandler(int, siginfo*, "
+ "void*)+50)\n"
+ " #04 pc 00058fb0 libc.so (__restore)\n"
+ " #05 pc 00000000 <unknown>\n"
+ " #06 pc 0079161a libunwindstack_test (InnerFunction+218)\n"
+ " #07 pc 007923aa libunwindstack_test (MiddleFunction+42)\n"
+ " #08 pc 007923ea libunwindstack_test (OuterFunction+42)\n"
+ " #09 pc 00797444 libunwindstack_test (unwindstack::RemoteThroughSignal(int, unsigned "
+ "int)+868)\n"
+ " #10 pc 007985b8 libunwindstack_test "
+ "(unwindstack::UnwindTest_remote_through_signal_with_invalid_func_Test::TestBody()+56)\n"
+ " #11 pc 00817a19 libunwindstack_test\n"
+ " #12 pc 008178c5 libunwindstack_test (testing::Test::Run()+277)\n"
+ " #13 pc 00818d3e libunwindstack_test (testing::TestInfo::Run()+318)\n"
+ " #14 pc 008198b4 libunwindstack_test (testing::TestSuite::Run()+436)\n"
+ " #15 pc 00828cb0 libunwindstack_test "
+ "(testing::internal::UnitTestImpl::RunAllTests()+1216)\n"
+ " #16 pc 0082870f libunwindstack_test (testing::UnitTest::Run()+367)\n"
+ " #17 pc 0084031e libunwindstack_test (IsolateMain+2334)\n"
+ " #18 pc 0083f9e9 libunwindstack_test (main+41)\n"
+ " #19 pc 00050646 libc.so (__libc_init+118)\n",
+ frame_info);
+
+ EXPECT_EQ(0x5ae0d4d9U, unwinder.frames()[0].pc);
+ EXPECT_EQ(0xecb37188U, unwinder.frames()[0].sp);
+ EXPECT_EQ(0x5ae0d4fcU, unwinder.frames()[1].pc);
+ EXPECT_EQ(0xecb37190U, unwinder.frames()[1].sp);
+ EXPECT_EQ(0x5ae0d52cU, unwinder.frames()[2].pc);
+ EXPECT_EQ(0xecb371b0U, unwinder.frames()[2].sp);
+ EXPECT_EQ(0x5ae16f62U, unwinder.frames()[3].pc);
+ EXPECT_EQ(0xecb371d0U, unwinder.frames()[3].sp);
+ EXPECT_EQ(0xec169fb0U, unwinder.frames()[4].pc);
+ EXPECT_EQ(0xecb371f0U, unwinder.frames()[4].sp);
+ EXPECT_EQ(0x0U, unwinder.frames()[5].pc);
+ EXPECT_EQ(0xffcfac6cU, unwinder.frames()[5].sp);
+ EXPECT_EQ(0x5ae0d61aU, unwinder.frames()[6].pc);
+ EXPECT_EQ(0xffcfac6cU, unwinder.frames()[6].sp);
+ EXPECT_EQ(0x5ae0e3aaU, unwinder.frames()[7].pc);
+ EXPECT_EQ(0xffcfad60U, unwinder.frames()[7].sp);
+ EXPECT_EQ(0x5ae0e3eaU, unwinder.frames()[8].pc);
+ EXPECT_EQ(0xffcfad90U, unwinder.frames()[8].sp);
+ EXPECT_EQ(0x5ae13444U, unwinder.frames()[9].pc);
+ EXPECT_EQ(0xffcfadc0U, unwinder.frames()[9].sp);
+ EXPECT_EQ(0x5ae145b8U, unwinder.frames()[10].pc);
+ EXPECT_EQ(0xffcfb020U, unwinder.frames()[10].sp);
+ EXPECT_EQ(0x5ae93a19U, unwinder.frames()[11].pc);
+ EXPECT_EQ(0xffcfb050U, unwinder.frames()[11].sp);
+ EXPECT_EQ(0x5ae938c5U, unwinder.frames()[12].pc);
+ EXPECT_EQ(0xffcfb090U, unwinder.frames()[12].sp);
+ EXPECT_EQ(0x5ae94d3eU, unwinder.frames()[13].pc);
+ EXPECT_EQ(0xffcfb0f0U, unwinder.frames()[13].sp);
+ EXPECT_EQ(0x5ae958b4U, unwinder.frames()[14].pc);
+ EXPECT_EQ(0xffcfb160U, unwinder.frames()[14].sp);
+ EXPECT_EQ(0x5aea4cb0U, unwinder.frames()[15].pc);
+ EXPECT_EQ(0xffcfb1d0U, unwinder.frames()[15].sp);
+ EXPECT_EQ(0x5aea470fU, unwinder.frames()[16].pc);
+ EXPECT_EQ(0xffcfb270U, unwinder.frames()[16].sp);
+ EXPECT_EQ(0x5aebc31eU, unwinder.frames()[17].pc);
+ EXPECT_EQ(0xffcfb2c0U, unwinder.frames()[17].sp);
+ EXPECT_EQ(0x5aebb9e9U, unwinder.frames()[18].pc);
+ EXPECT_EQ(0xffcfc3c0U, unwinder.frames()[18].sp);
+ EXPECT_EQ(0xec161646U, unwinder.frames()[19].pc);
+ EXPECT_EQ(0xffcfc3f0U, unwinder.frames()[19].sp);
+}
+
+// This test has a libc.so where the __restore_rt has been changed so
+// that the signal handler match does not occur and it uses the
+// fde to do the unwind.
+TEST_F(UnwindOfflineTest, signal_fde_x86_64) {
+ ASSERT_NO_FATAL_FAILURE(Init("signal_fde_x86_64/", ARCH_X86_64));
+
+ Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
+ unwinder.Unwind();
+
+ std::string frame_info(DumpFrames(unwinder));
+ ASSERT_EQ(18U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+ EXPECT_EQ(
+ " #00 pc 000000000058415b libunwindstack_test (SignalInnerFunction+11)\n"
+ " #01 pc 0000000000584168 libunwindstack_test (SignalMiddleFunction+8)\n"
+ " #02 pc 0000000000584178 libunwindstack_test (SignalOuterFunction+8)\n"
+ " #03 pc 000000000058ac77 libunwindstack_test (unwindstack::SignalCallerHandler(int, "
+ "siginfo*, void*)+23)\n"
+ " #04 pc 0000000000057d10 libc.so (__restore_rt)\n"
+ " #05 pc 0000000000000000 <unknown>\n"
+ " #06 pc 0000000000584244 libunwindstack_test (InnerFunction+196)\n"
+ " #07 pc 0000000000584b44 libunwindstack_test (MiddleFunction+20)\n"
+ " #08 pc 0000000000584b64 libunwindstack_test (OuterFunction+20)\n"
+ " #09 pc 0000000000588457 libunwindstack_test (unwindstack::RemoteThroughSignal(int, "
+ "unsigned int)+583)\n"
+ " #10 pc 0000000000588f67 libunwindstack_test "
+ "(unwindstack::UnwindTest_remote_through_signal_with_invalid_func_Test::TestBody()+23)\n"
+ " #11 pc 00000000005d9c38 libunwindstack_test (testing::Test::Run()+216)\n"
+ " #12 pc 00000000005daf9a libunwindstack_test (testing::TestInfo::Run()+266)\n"
+ " #13 pc 00000000005dba46 libunwindstack_test (testing::TestSuite::Run()+390)\n"
+ " #14 pc 00000000005ea4c6 libunwindstack_test "
+ "(testing::internal::UnitTestImpl::RunAllTests()+1190)\n"
+ " #15 pc 00000000005e9f61 libunwindstack_test (testing::UnitTest::Run()+337)\n"
+ " #16 pc 0000000000600155 libunwindstack_test (IsolateMain+2037)\n"
+ " #17 pc 000000000004e405 libc.so (__libc_init+101)\n",
+ frame_info);
+
+ EXPECT_EQ(0x5bb41271e15bU, unwinder.frames()[0].pc);
+ EXPECT_EQ(0x707eb5aa8320U, unwinder.frames()[0].sp);
+ EXPECT_EQ(0x5bb41271e168U, unwinder.frames()[1].pc);
+ EXPECT_EQ(0x707eb5aa8330U, unwinder.frames()[1].sp);
+ EXPECT_EQ(0x5bb41271e178U, unwinder.frames()[2].pc);
+ EXPECT_EQ(0x707eb5aa8340U, unwinder.frames()[2].sp);
+ EXPECT_EQ(0x5bb412724c77U, unwinder.frames()[3].pc);
+ EXPECT_EQ(0x707eb5aa8350U, unwinder.frames()[3].sp);
+ EXPECT_EQ(0x707eb2ca5d10U, unwinder.frames()[4].pc);
+ EXPECT_EQ(0x707eb5aa8380U, unwinder.frames()[4].sp);
+ EXPECT_EQ(0x0U, unwinder.frames()[5].pc);
+ EXPECT_EQ(0x7ffcaadde078U, unwinder.frames()[5].sp);
+ EXPECT_EQ(0x5bb41271e244U, unwinder.frames()[6].pc);
+ EXPECT_EQ(0x7ffcaadde078U, unwinder.frames()[6].sp);
+ EXPECT_EQ(0x5bb41271eb44U, unwinder.frames()[7].pc);
+ EXPECT_EQ(0x7ffcaadde1a0U, unwinder.frames()[7].sp);
+ EXPECT_EQ(0x5bb41271eb64U, unwinder.frames()[8].pc);
+ EXPECT_EQ(0x7ffcaadde1c0U, unwinder.frames()[8].sp);
+ EXPECT_EQ(0x5bb412722457U, unwinder.frames()[9].pc);
+ EXPECT_EQ(0x7ffcaadde1e0U, unwinder.frames()[9].sp);
+ EXPECT_EQ(0x5bb412722f67U, unwinder.frames()[10].pc);
+ EXPECT_EQ(0x7ffcaadde510U, unwinder.frames()[10].sp);
+ EXPECT_EQ(0x5bb412773c38U, unwinder.frames()[11].pc);
+ EXPECT_EQ(0x7ffcaadde530U, unwinder.frames()[11].sp);
+ EXPECT_EQ(0x5bb412774f9aU, unwinder.frames()[12].pc);
+ EXPECT_EQ(0x7ffcaadde560U, unwinder.frames()[12].sp);
+ EXPECT_EQ(0x5bb412775a46U, unwinder.frames()[13].pc);
+ EXPECT_EQ(0x7ffcaadde5b0U, unwinder.frames()[13].sp);
+ EXPECT_EQ(0x5bb4127844c6U, unwinder.frames()[14].pc);
+ EXPECT_EQ(0x7ffcaadde5f0U, unwinder.frames()[14].sp);
+ EXPECT_EQ(0x5bb412783f61U, unwinder.frames()[15].pc);
+ EXPECT_EQ(0x7ffcaadde6c0U, unwinder.frames()[15].sp);
+ EXPECT_EQ(0x5bb41279a155U, unwinder.frames()[16].pc);
+ EXPECT_EQ(0x7ffcaadde720U, unwinder.frames()[16].sp);
+ EXPECT_EQ(0x707eb2c9c405U, unwinder.frames()[17].pc);
+ EXPECT_EQ(0x7ffcaaddf870U, unwinder.frames()[17].sp);
+}
+
} // namespace unwindstack