xref: /llvm-project/lldb/test/API/functionalities/unwind/zeroth_frame/TestZerothFrame.py (revision 4c23625357b0b6091bc97478a79d522a832c2b21)
10a840ef8STatyana Krasnukha"""
20a840ef8STatyana KrasnukhaTest that line information is recalculated properly for a frame when it moves
30a840ef8STatyana Krasnukhafrom the middle of the backtrace to a zero index.
40a840ef8STatyana Krasnukha
50a840ef8STatyana KrasnukhaThis is a regression test for a StackFrame bug, where whether frame is zero or
60a840ef8STatyana Krasnukhanot depends on an internal field. When LLDB was updating its frame list value
70a840ef8STatyana Krasnukhaof the field wasn't copied into existing StackFrame instances, so those
80a840ef8STatyana KrasnukhaStackFrame instances, would use an incorrect line entry evaluation logic in
90a840ef8STatyana Krasnukhasituations if it was in the middle of the stack frame list (not zeroth), and
100a840ef8STatyana Krasnukhathen moved to the top position. The difference in logic is that for zeroth
110a840ef8STatyana Krasnukhaframes line entry is returned for program counter, while for other frame
120a840ef8STatyana Krasnukha(except for those that "behave like zeroth") it is for the instruction
130a840ef8STatyana Krasnukhapreceding PC, as PC points to the next instruction after function call. When
140a840ef8STatyana Krasnukhathe bug is present, when execution stops at the second breakpoint
150a840ef8STatyana KrasnukhaSBFrame.GetLineEntry() returns line entry for the previous line, rather than
160a840ef8STatyana Krasnukhathe one with a breakpoint. Note that this is specific to
170a840ef8STatyana KrasnukhaSBFrame.GetLineEntry(), SBFrame.GetPCAddress().GetLineEntry() would return
180a840ef8STatyana Krasnukhacorrect entry.
190a840ef8STatyana Krasnukha
200a840ef8STatyana KrasnukhaThis bug doesn't reproduce through an LLDB interpretator, however it happens
210a840ef8STatyana Krasnukhawhen using API directly, for example in LLDB-MI.
220a840ef8STatyana Krasnukha"""
230a840ef8STatyana Krasnukha
240a840ef8STatyana Krasnukhaimport lldb
250a840ef8STatyana Krasnukhafrom lldbsuite.test.decorators import *
260a840ef8STatyana Krasnukhafrom lldbsuite.test.lldbtest import *
270a840ef8STatyana Krasnukhafrom lldbsuite.test import lldbutil
280a840ef8STatyana Krasnukha
290a840ef8STatyana Krasnukha
300a840ef8STatyana Krasnukhaclass ZerothFrame(TestBase):
310a840ef8STatyana Krasnukha    def test(self):
320a840ef8STatyana Krasnukha        """
330a840ef8STatyana Krasnukha        Test that line information is recalculated properly for a frame when it moves
340a840ef8STatyana Krasnukha        from the middle of the backtrace to a zero index.
350a840ef8STatyana Krasnukha        """
360a840ef8STatyana Krasnukha        self.build()
370a840ef8STatyana Krasnukha        self.setTearDownCleanup()
380a840ef8STatyana Krasnukha
390a840ef8STatyana Krasnukha        exe = self.getBuildArtifact("a.out")
400a840ef8STatyana Krasnukha        target = self.dbg.CreateTarget(exe)
410a840ef8STatyana Krasnukha        self.assertTrue(target, VALID_TARGET)
420a840ef8STatyana Krasnukha
43*4c236253SKendal Harland        main_dot_c = lldb.SBFileSpec("main.c")
44*4c236253SKendal Harland        bp1 = target.BreakpointCreateBySourceRegex(
45*4c236253SKendal Harland            "// Set breakpoint 1 here", main_dot_c
462238dcc3SJonas Devlieghere        )
47*4c236253SKendal Harland        bp2 = target.BreakpointCreateBySourceRegex(
48*4c236253SKendal Harland            "// Set breakpoint 2 here", main_dot_c
492238dcc3SJonas Devlieghere        )
500a840ef8STatyana Krasnukha
512238dcc3SJonas Devlieghere        process = target.LaunchSimple(None, None, self.get_process_working_directory())
520a840ef8STatyana Krasnukha        self.assertTrue(process, VALID_PROCESS)
530a840ef8STatyana Krasnukha
54*4c236253SKendal Harland        thread = self.thread()
55*4c236253SKendal Harland
560a840ef8STatyana Krasnukha        if self.TraceOn():
570a840ef8STatyana Krasnukha            print("Backtrace at the first breakpoint:")
580a840ef8STatyana Krasnukha            for f in thread.frames:
590a840ef8STatyana Krasnukha                print(f)
60*4c236253SKendal Harland
610a840ef8STatyana Krasnukha        # Check that we have stopped at correct breakpoint.
620a840ef8STatyana Krasnukha        self.assertEqual(
63*4c236253SKendal Harland            thread.frame[0].GetLineEntry().GetLine(),
64*4c236253SKendal Harland            bp1.GetLocationAtIndex(0).GetAddress().GetLineEntry().GetLine(),
652238dcc3SJonas Devlieghere            "LLDB reported incorrect line number.",
662238dcc3SJonas Devlieghere        )
670a840ef8STatyana Krasnukha
680a840ef8STatyana Krasnukha        # Important to use SBProcess::Continue() instead of
690a840ef8STatyana Krasnukha        # self.runCmd('continue'), because the problem doesn't reproduce with
700a840ef8STatyana Krasnukha        # 'continue' command.
710a840ef8STatyana Krasnukha        process.Continue()
720a840ef8STatyana Krasnukha
730a840ef8STatyana Krasnukha        if self.TraceOn():
740a840ef8STatyana Krasnukha            print("Backtrace at the second breakpoint:")
750a840ef8STatyana Krasnukha            for f in thread.frames:
760a840ef8STatyana Krasnukha                print(f)
770a840ef8STatyana Krasnukha        # Check that we have stopped at the breakpoint
780a840ef8STatyana Krasnukha        self.assertEqual(
790a840ef8STatyana Krasnukha            thread.frame[0].GetLineEntry().GetLine(),
80*4c236253SKendal Harland            bp2.GetLocationAtIndex(0).GetAddress().GetLineEntry().GetLine(),
812238dcc3SJonas Devlieghere            "LLDB reported incorrect line number.",
822238dcc3SJonas Devlieghere        )
830a840ef8STatyana Krasnukha        # Double-check with GetPCAddress()
840a840ef8STatyana Krasnukha        self.assertEqual(
850a840ef8STatyana Krasnukha            thread.frame[0].GetLineEntry().GetLine(),
860a840ef8STatyana Krasnukha            thread.frame[0].GetPCAddress().GetLineEntry().GetLine(),
872238dcc3SJonas Devlieghere            "LLDB reported incorrect line number.",
882238dcc3SJonas Devlieghere        )
89