160 lines · python
1"""2Test thread step-in, step-over and step-out work with the "Avoid no debug" option.3"""4 5 6import lldb7from lldbsuite.test.decorators import *8from lldbsuite.test.lldbtest import *9from lldbsuite.test import lldbutil10 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_spec101 )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 setting118 # step-out-avoid-nodebug doesn't change the behavior in frames with119 # 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 the139 # 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 the155 # 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