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