2 Test that line information is recalculated properly for a frame when it moves
3 from the middle of the backtrace to a zero index.
5 This is a regression test for a StackFrame bug, where whether frame is zero or
6 not depends on an internal field. When LLDB was updating its frame list value
7 of the field wasn't copied into existing StackFrame instances, so those
8 StackFrame instances, would use an incorrect line entry evaluation logic in
9 situations if it was in the middle of the stack frame list (not zeroth), and
10 then moved to the top position. The difference in logic is that for zeroth
11 frames line entry is returned for program counter, while for other frame
12 (except for those that "behave like zeroth") it is for the instruction
13 preceding PC, as PC points to the next instruction after function call. When
14 the bug is present, when execution stops at the second breakpoint
15 SBFrame.GetLineEntry() returns line entry for the previous line, rather than
16 the one with a breakpoint. Note that this is specific to
17 SBFrame.GetLineEntry(), SBFrame.GetPCAddress().GetLineEntry() would return
20 This bug doesn't reproduce through an LLDB interpretator, however it happens
21 when using API directly, for example in LLDB-MI.
25 from lldbsuite
.test
.decorators
import *
26 from lldbsuite
.test
.lldbtest
import *
27 from lldbsuite
.test
import lldbutil
30 class ZerothFrame(TestBase
):
33 Test that line information is recalculated properly for a frame when it moves
34 from the middle of the backtrace to a zero index.
37 self
.setTearDownCleanup()
39 exe
= self
.getBuildArtifact("a.out")
40 target
= self
.dbg
.CreateTarget(exe
)
41 self
.assertTrue(target
, VALID_TARGET
)
43 bp1_line
= line_number("main.c", "// Set breakpoint 1 here")
44 bp2_line
= line_number("main.c", "// Set breakpoint 2 here")
46 lldbutil
.run_break_set_by_file_and_line(
47 self
, "main.c", bp1_line
, num_expected_locations
=1
49 lldbutil
.run_break_set_by_file_and_line(
50 self
, "main.c", bp2_line
, num_expected_locations
=1
53 process
= target
.LaunchSimple(None, None, self
.get_process_working_directory())
54 self
.assertTrue(process
, VALID_PROCESS
)
56 thread
= process
.GetThreadAtIndex(0)
58 print("Backtrace at the first breakpoint:")
59 for f
in thread
.frames
:
61 # Check that we have stopped at correct breakpoint.
63 process
.GetThreadAtIndex(0).frame
[0].GetLineEntry().GetLine(),
65 "LLDB reported incorrect line number.",
68 # Important to use SBProcess::Continue() instead of
69 # self.runCmd('continue'), because the problem doesn't reproduce with
73 thread
= process
.GetThreadAtIndex(0)
75 print("Backtrace at the second breakpoint:")
76 for f
in thread
.frames
:
78 # Check that we have stopped at the breakpoint
80 thread
.frame
[0].GetLineEntry().GetLine(),
82 "LLDB reported incorrect line number.",
84 # Double-check with GetPCAddress()
86 thread
.frame
[0].GetLineEntry().GetLine(),
87 thread
.frame
[0].GetPCAddress().GetLineEntry().GetLine(),
88 "LLDB reported incorrect line number.",