199451b44SJordan Rupprecht"""
299451b44SJordan RupprechtTest thread step-in, step-over and step-out work with the "Avoid no debug" option.
399451b44SJordan Rupprecht"""
499451b44SJordan Rupprecht
599451b44SJordan Rupprecht
699451b44SJordan Rupprecht
799451b44SJordan Rupprecht
899451b44SJordan Rupprechtimport lldb
999451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
1099451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import *
1199451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil
1299451b44SJordan Rupprecht
1399451b44SJordan Rupprecht
1499451b44SJordan Rupprechtclass StepAvoidsNoDebugTestCase(TestBase):
1599451b44SJordan Rupprecht
1699451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
17*3d477bbeSMuhammad Omair Javaid    @expectedFailureAll(archs=["aarch64"], oslist=["windows"], bugnumber="llvm.org/pr56292")
1899451b44SJordan Rupprecht    def test_step_out_with_python(self):
1999451b44SJordan Rupprecht        """Test stepping out using avoid-no-debug with dsyms."""
2099451b44SJordan Rupprecht        self.build()
2199451b44SJordan Rupprecht        self.get_to_starting_point()
2299451b44SJordan Rupprecht        self.do_step_out_past_nodebug()
2399451b44SJordan Rupprecht
2499451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
2599451b44SJordan Rupprecht    @decorators.expectedFailureAll(
2699451b44SJordan Rupprecht        compiler="gcc", bugnumber="llvm.org/pr28549")
2799451b44SJordan Rupprecht    @decorators.expectedFailureAll(
2899451b44SJordan Rupprecht        compiler="clang",
2999451b44SJordan Rupprecht        compiler_version=[
3099451b44SJordan Rupprecht            ">=",
3199451b44SJordan Rupprecht            "3.9"],
3299451b44SJordan Rupprecht        archs=["i386"],
3397a2eac3SMichał Górny        oslist=no_match(["freebsd"]),
3499451b44SJordan Rupprecht        bugnumber="llvm.org/pr28549")
35*3d477bbeSMuhammad Omair Javaid    @expectedFailureAll(archs=["aarch64"], oslist=["windows"], bugnumber="llvm.org/pr56292")
3699451b44SJordan Rupprecht    def test_step_over_with_python(self):
3799451b44SJordan Rupprecht        """Test stepping over using avoid-no-debug with dwarf."""
3899451b44SJordan Rupprecht        self.build()
3999451b44SJordan Rupprecht        self.get_to_starting_point()
4099451b44SJordan Rupprecht        self.do_step_over_past_nodebug()
4199451b44SJordan Rupprecht
4299451b44SJordan Rupprecht    @add_test_categories(['pyapi'])
4399451b44SJordan Rupprecht    @decorators.expectedFailureAll(
4499451b44SJordan Rupprecht        compiler="gcc", bugnumber="llvm.org/pr28549")
4599451b44SJordan Rupprecht    @decorators.expectedFailureAll(
4699451b44SJordan Rupprecht        compiler="clang",
4799451b44SJordan Rupprecht        compiler_version=[
4899451b44SJordan Rupprecht            ">=",
4999451b44SJordan Rupprecht            "3.9"],
5099451b44SJordan Rupprecht        archs=["i386"],
5197a2eac3SMichał Górny        oslist=no_match(["freebsd"]),
5299451b44SJordan Rupprecht        bugnumber="llvm.org/pr28549")
53*3d477bbeSMuhammad Omair Javaid    @expectedFailureAll(archs=["aarch64"], oslist=["windows"], bugnumber="llvm.org/pr56292")
5499451b44SJordan Rupprecht    def test_step_in_with_python(self):
5599451b44SJordan Rupprecht        """Test stepping in using avoid-no-debug with dwarf."""
5699451b44SJordan Rupprecht        self.build()
5799451b44SJordan Rupprecht        self.get_to_starting_point()
5899451b44SJordan Rupprecht        self.do_step_in_past_nodebug()
5999451b44SJordan Rupprecht
6099451b44SJordan Rupprecht    def setUp(self):
6199451b44SJordan Rupprecht        TestBase.setUp(self)
6299451b44SJordan Rupprecht        self.main_source = "with-debug.c"
6399451b44SJordan Rupprecht        self.main_source_spec = lldb.SBFileSpec("with-debug.c")
6499451b44SJordan Rupprecht        self.dbg.HandleCommand(
6599451b44SJordan Rupprecht            "settings set target.process.thread.step-out-avoid-nodebug true")
6699451b44SJordan Rupprecht
6799451b44SJordan Rupprecht    def tearDown(self):
6899451b44SJordan Rupprecht        self.dbg.HandleCommand(
6999451b44SJordan Rupprecht            "settings set target.process.thread.step-out-avoid-nodebug false")
7099451b44SJordan Rupprecht        TestBase.tearDown(self)
7199451b44SJordan Rupprecht
7299451b44SJordan Rupprecht    def hit_correct_line(self, pattern):
7399451b44SJordan Rupprecht        target_line = line_number(self.main_source, pattern)
7499451b44SJordan Rupprecht        self.assertTrue(
7599451b44SJordan Rupprecht            target_line != 0,
7699451b44SJordan Rupprecht            "Could not find source pattern " +
7799451b44SJordan Rupprecht            pattern)
7899451b44SJordan Rupprecht        cur_line = self.thread.frames[0].GetLineEntry().GetLine()
790ed758b2SDave Lee        self.assertEqual(
800ed758b2SDave Lee            cur_line, target_line,
8199451b44SJordan Rupprecht            "Stepped to line %d instead of expected %d with pattern '%s'." %
8299451b44SJordan Rupprecht            (cur_line,
8399451b44SJordan Rupprecht             target_line,
8499451b44SJordan Rupprecht             pattern))
8599451b44SJordan Rupprecht
8699451b44SJordan Rupprecht    def hit_correct_function(self, pattern):
8799451b44SJordan Rupprecht        name = self.thread.frames[0].GetFunctionName()
8899451b44SJordan Rupprecht        self.assertTrue(
8999451b44SJordan Rupprecht            pattern in name, "Got to '%s' not the expected function '%s'." %
9099451b44SJordan Rupprecht            (name, pattern))
9199451b44SJordan Rupprecht
9299451b44SJordan Rupprecht    def get_to_starting_point(self):
9399451b44SJordan Rupprecht        exe = self.getBuildArtifact("a.out")
9499451b44SJordan Rupprecht        error = lldb.SBError()
9599451b44SJordan Rupprecht
9699451b44SJordan Rupprecht        self.target = self.dbg.CreateTarget(exe)
9799451b44SJordan Rupprecht        self.assertTrue(self.target, VALID_TARGET)
9899451b44SJordan Rupprecht
9999451b44SJordan Rupprecht        inner_bkpt = self.target.BreakpointCreateBySourceRegex(
10099451b44SJordan Rupprecht            "Stop here and step out of me", self.main_source_spec)
10199451b44SJordan Rupprecht        self.assertTrue(inner_bkpt, VALID_BREAKPOINT)
10299451b44SJordan Rupprecht
10399451b44SJordan Rupprecht        # Now launch the process, and do not stop at entry point.
10499451b44SJordan Rupprecht        self.process = self.target.LaunchSimple(
10599451b44SJordan Rupprecht            None, None, self.get_process_working_directory())
10699451b44SJordan Rupprecht
10799451b44SJordan Rupprecht        self.assertTrue(self.process, PROCESS_IS_VALID)
10899451b44SJordan Rupprecht
10999451b44SJordan Rupprecht        # Now finish, and make sure the return value is correct.
11099451b44SJordan Rupprecht        threads = lldbutil.get_threads_stopped_at_breakpoint(
11199451b44SJordan Rupprecht            self.process, inner_bkpt)
112b3a0c4d7SRaphael Isemann        self.assertEquals(len(threads), 1, "Stopped at inner breakpoint.")
11399451b44SJordan Rupprecht        self.thread = threads[0]
11499451b44SJordan Rupprecht
11599451b44SJordan Rupprecht    def do_step_out_past_nodebug(self):
11699451b44SJordan Rupprecht        # The first step out takes us to the called_from_nodebug frame, just to make sure setting
11799451b44SJordan Rupprecht        # step-out-avoid-nodebug doesn't change the behavior in frames with
11899451b44SJordan Rupprecht        # debug info.
11999451b44SJordan Rupprecht        self.thread.StepOut()
12099451b44SJordan Rupprecht        self.hit_correct_line(
12199451b44SJordan Rupprecht            "intermediate_return_value = called_from_nodebug_actual(some_value)")
12299451b44SJordan Rupprecht        self.thread.StepOut()
12399451b44SJordan Rupprecht        self.hit_correct_line(
12499451b44SJordan Rupprecht            "int return_value = no_debug_caller(5, called_from_nodebug)")
12599451b44SJordan Rupprecht
12699451b44SJordan Rupprecht    def do_step_over_past_nodebug(self):
12799451b44SJordan Rupprecht        self.thread.StepOver()
12899451b44SJordan Rupprecht        self.hit_correct_line(
12999451b44SJordan Rupprecht            "intermediate_return_value = called_from_nodebug_actual(some_value)")
13099451b44SJordan Rupprecht        self.thread.StepOver()
13199451b44SJordan Rupprecht        self.hit_correct_line("return intermediate_return_value")
13299451b44SJordan Rupprecht        self.thread.StepOver()
13399451b44SJordan Rupprecht        # Note, lldb doesn't follow gdb's distinction between "step-out" and "step-over/step-in"
13499451b44SJordan Rupprecht        # when exiting a frame.  In all cases we leave the pc at the point where we exited the
13599451b44SJordan Rupprecht        # frame.  In gdb, step-over/step-in move to the end of the line they stepped out to.
13699451b44SJordan Rupprecht        # If we ever change this we will need to fix this test.
13799451b44SJordan Rupprecht        self.hit_correct_line(
13899451b44SJordan Rupprecht            "int return_value = no_debug_caller(5, called_from_nodebug)")
13999451b44SJordan Rupprecht
14099451b44SJordan Rupprecht    def do_step_in_past_nodebug(self):
14199451b44SJordan Rupprecht        self.thread.StepInto()
14299451b44SJordan Rupprecht        self.hit_correct_line(
14399451b44SJordan Rupprecht            "intermediate_return_value = called_from_nodebug_actual(some_value)")
14499451b44SJordan Rupprecht        self.thread.StepInto()
14599451b44SJordan Rupprecht        self.hit_correct_line("return intermediate_return_value")
14699451b44SJordan Rupprecht        self.thread.StepInto()
14799451b44SJordan Rupprecht        # Note, lldb doesn't follow gdb's distinction between "step-out" and "step-over/step-in"
14899451b44SJordan Rupprecht        # when exiting a frame.  In all cases we leave the pc at the point where we exited the
14999451b44SJordan Rupprecht        # frame.  In gdb, step-over/step-in move to the end of the line they stepped out to.
15099451b44SJordan Rupprecht        # If we ever change this we will need to fix this test.
15199451b44SJordan Rupprecht        self.hit_correct_line(
15299451b44SJordan Rupprecht            "int return_value = no_debug_caller(5, called_from_nodebug)")
153