| """ |
| Test that we can backtrace correctly when AArch64 PAC is enabled |
| """ |
| |
| import lldb |
| from lldbsuite.test.decorators import * |
| from lldbsuite.test.lldbtest import * |
| from lldbsuite.test import lldbutil |
| |
| |
| class AArch64UnwindPAC(TestBase): |
| @skipIf(archs=no_match(["aarch64"])) |
| @skipIf(oslist=no_match(["linux"])) |
| def test(self): |
| """Test that we can backtrace correctly when AArch64 PAC is enabled""" |
| if not self.isAArch64PAuth(): |
| self.skipTest("Target must support Pointer Authentication.") |
| |
| self.build() |
| |
| self.line = line_number("main.c", "// Frame func_c") |
| |
| exe = self.getBuildArtifact("a.out") |
| self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) |
| |
| lldbutil.run_break_set_by_file_and_line( |
| self, "main.c", self.line, num_expected_locations=1 |
| ) |
| self.runCmd("run", RUN_SUCCEEDED) |
| self.expect( |
| "thread backtrace", |
| STOPPED_DUE_TO_BREAKPOINT, |
| substrs=["stop reason = breakpoint 1."], |
| ) |
| |
| target = self.dbg.GetSelectedTarget() |
| process = target.GetProcess() |
| thread = process.GetThreadAtIndex(0) |
| |
| backtrace = [ |
| "func_c", |
| "func_b", |
| "func_a", |
| "main", |
| ] |
| |
| libc_backtrace = [ |
| "__libc_start_main", |
| "_start", |
| ] |
| |
| self.assertTrue(thread.GetNumFrames() >= (len(backtrace) + len(libc_backtrace))) |
| |
| # Strictly check frames that are in the test program's source. |
| for frame_idx, frame in enumerate(thread.frames[:len(backtrace)]): |
| self.assertTrue(frame) |
| self.assertEqual(frame.GetFunctionName(), backtrace[frame_idx]) |
| self.assertEqual( |
| frame.GetLineEntry().GetLine(), |
| line_number("main.c", "Frame " + backtrace[frame_idx]), |
| ) |
| |
| # After the program comes some libc frames. The number varies by |
| # system, so ensure we have at least these two in this order, |
| # skipping frames in between. |
| start_idx = frame_idx + 1 |
| for frame_idx, frame in enumerate(thread.frames[start_idx:], start=start_idx): |
| self.assertTrue(frame) |
| if libc_backtrace[0] == frame.GetFunctionName(): |
| libc_backtrace.pop(0) |
| |
| self.assertFalse(libc_backtrace, "Did not find expected libc frames.") |