xref: /llvm-project/lldb/test/API/functionalities/step-avoids-no-debug/TestStepNoDebug.py (revision 9c2468821ec51defd09c246fea4a47886fff8c01)
1"""
2Test thread step-in, step-over and step-out work with the "Avoid no debug" option.
3"""
4
5
6import lldb
7from lldbsuite.test.decorators import *
8from lldbsuite.test.lldbtest import *
9from lldbsuite.test import lldbutil
10
11
12class StepAvoidsNoDebugTestCase(TestBase):
13    @add_test_categories(["pyapi"])
14    @expectedFailureAll(
15        archs=["aarch64"], oslist=["windows"], bugnumber="llvm.org/pr56292"
16    )
17    def test_step_out_with_python(self):
18        """Test stepping out using avoid-no-debug with dsyms."""
19        self.build()
20        self.get_to_starting_point()
21        self.do_step_out_past_nodebug()
22
23    @add_test_categories(["pyapi"])
24    @decorators.expectedFailureAll(compiler="gcc", bugnumber="llvm.org/pr28549")
25    @decorators.expectedFailureAll(
26        compiler="clang",
27        compiler_version=[">=", "3.9"],
28        archs=["i386"],
29        oslist=no_match(["freebsd"]),
30        bugnumber="llvm.org/pr28549",
31    )
32    @expectedFailureAll(
33        archs=["aarch64"], oslist=["windows"], bugnumber="llvm.org/pr56292"
34    )
35    def test_step_over_with_python(self):
36        """Test stepping over using avoid-no-debug with dwarf."""
37        self.build()
38        self.get_to_starting_point()
39        self.do_step_over_past_nodebug()
40
41    @add_test_categories(["pyapi"])
42    @decorators.expectedFailureAll(compiler="gcc", bugnumber="llvm.org/pr28549")
43    @decorators.expectedFailureAll(
44        compiler="clang",
45        compiler_version=[">=", "3.9"],
46        archs=["i386"],
47        oslist=no_match(["freebsd"]),
48        bugnumber="llvm.org/pr28549",
49    )
50    @expectedFailureAll(
51        archs=["aarch64"], oslist=["windows"], bugnumber="llvm.org/pr56292"
52    )
53    def test_step_in_with_python(self):
54        """Test stepping in using avoid-no-debug with dwarf."""
55        self.build()
56        self.get_to_starting_point()
57        self.do_step_in_past_nodebug()
58
59    def setUp(self):
60        TestBase.setUp(self)
61        self.main_source = "with-debug.c"
62        self.main_source_spec = lldb.SBFileSpec("with-debug.c")
63        self.dbg.HandleCommand(
64            "settings set target.process.thread.step-out-avoid-nodebug true"
65        )
66
67    def tearDown(self):
68        self.dbg.HandleCommand(
69            "settings set target.process.thread.step-out-avoid-nodebug false"
70        )
71        TestBase.tearDown(self)
72
73    def hit_correct_line(self, pattern):
74        target_line = line_number(self.main_source, pattern)
75        self.assertNotEqual(target_line, 0, "Could not find source pattern " + pattern)
76        cur_line = self.thread.frames[0].GetLineEntry().GetLine()
77        self.assertEqual(
78            cur_line,
79            target_line,
80            "Stepped to line %d instead of expected %d with pattern '%s'."
81            % (cur_line, target_line, pattern),
82        )
83
84    def hit_correct_function(self, pattern):
85        name = self.thread.frames[0].GetFunctionName()
86        self.assertIn(
87            pattern,
88            name,
89            "Got to '%s' not the expected function '%s'." % (name, pattern),
90        )
91
92    def get_to_starting_point(self):
93        exe = self.getBuildArtifact("a.out")
94        error = lldb.SBError()
95
96        self.target = self.dbg.CreateTarget(exe)
97        self.assertTrue(self.target, VALID_TARGET)
98
99        inner_bkpt = self.target.BreakpointCreateBySourceRegex(
100            "Stop here and step out of me", self.main_source_spec
101        )
102        self.assertTrue(inner_bkpt, VALID_BREAKPOINT)
103
104        # Now launch the process, and do not stop at entry point.
105        self.process = self.target.LaunchSimple(
106            None, None, self.get_process_working_directory()
107        )
108
109        self.assertTrue(self.process, PROCESS_IS_VALID)
110
111        # Now finish, and make sure the return value is correct.
112        threads = lldbutil.get_threads_stopped_at_breakpoint(self.process, inner_bkpt)
113        self.assertEqual(len(threads), 1, "Stopped at inner breakpoint.")
114        self.thread = threads[0]
115
116    def do_step_out_past_nodebug(self):
117        # The first step out takes us to the called_from_nodebug frame, just to make sure setting
118        # step-out-avoid-nodebug doesn't change the behavior in frames with
119        # debug info.
120        self.thread.StepOut()
121        self.hit_correct_line(
122            "intermediate_return_value = called_from_nodebug_actual(some_value)"
123        )
124        self.thread.StepOut()
125        self.hit_correct_line(
126            "int return_value = no_debug_caller(5, called_from_nodebug)"
127        )
128
129    def do_step_over_past_nodebug(self):
130        self.thread.StepOver()
131        self.hit_correct_line(
132            "intermediate_return_value = called_from_nodebug_actual(some_value)"
133        )
134        self.thread.StepOver()
135        self.hit_correct_line("return intermediate_return_value")
136        self.thread.StepOver()
137        # Note, lldb doesn't follow gdb's distinction between "step-out" and "step-over/step-in"
138        # when exiting a frame.  In all cases we leave the pc at the point where we exited the
139        # frame.  In gdb, step-over/step-in move to the end of the line they stepped out to.
140        # If we ever change this we will need to fix this test.
141        self.hit_correct_line(
142            "int return_value = no_debug_caller(5, called_from_nodebug)"
143        )
144
145    def do_step_in_past_nodebug(self):
146        self.thread.StepInto()
147        self.hit_correct_line(
148            "intermediate_return_value = called_from_nodebug_actual(some_value)"
149        )
150        self.thread.StepInto()
151        self.hit_correct_line("return intermediate_return_value")
152        self.thread.StepInto()
153        # Note, lldb doesn't follow gdb's distinction between "step-out" and "step-over/step-in"
154        # when exiting a frame.  In all cases we leave the pc at the point where we exited the
155        # frame.  In gdb, step-over/step-in move to the end of the line they stepped out to.
156        # If we ever change this we will need to fix this test.
157        self.hit_correct_line(
158            "int return_value = no_debug_caller(5, called_from_nodebug)"
159        )
160