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 @expectedFailureAll(archs=["arm64"], bugnumber="<rdar://problem/34026777>") # lldb doesn't step past last source line in function on arm64 54 @expectedFailureAll(archs=["aarch64"], oslist=["freebsd", "linux"], 55 bugnumber="llvm.org/pr44057") 56 def test_step_in_with_python(self): 57 """Test stepping in using avoid-no-debug with dwarf.""" 58 self.build() 59 self.get_to_starting_point() 60 self.do_step_in_past_nodebug() 61 62 def setUp(self): 63 TestBase.setUp(self) 64 self.main_source = "with-debug.c" 65 self.main_source_spec = lldb.SBFileSpec("with-debug.c") 66 self.dbg.HandleCommand( 67 "settings set target.process.thread.step-out-avoid-nodebug true") 68 69 def tearDown(self): 70 self.dbg.HandleCommand( 71 "settings set target.process.thread.step-out-avoid-nodebug false") 72 TestBase.tearDown(self) 73 74 def hit_correct_line(self, pattern): 75 target_line = line_number(self.main_source, pattern) 76 self.assertTrue( 77 target_line != 0, 78 "Could not find source pattern " + 79 pattern) 80 cur_line = self.thread.frames[0].GetLineEntry().GetLine() 81 self.assertEqual( 82 cur_line, target_line, 83 "Stepped to line %d instead of expected %d with pattern '%s'." % 84 (cur_line, 85 target_line, 86 pattern)) 87 88 def hit_correct_function(self, pattern): 89 name = self.thread.frames[0].GetFunctionName() 90 self.assertTrue( 91 pattern in name, "Got to '%s' not the expected function '%s'." % 92 (name, pattern)) 93 94 def get_to_starting_point(self): 95 exe = self.getBuildArtifact("a.out") 96 error = lldb.SBError() 97 98 self.target = self.dbg.CreateTarget(exe) 99 self.assertTrue(self.target, VALID_TARGET) 100 101 inner_bkpt = self.target.BreakpointCreateBySourceRegex( 102 "Stop here and step out of me", self.main_source_spec) 103 self.assertTrue(inner_bkpt, VALID_BREAKPOINT) 104 105 # Now launch the process, and do not stop at entry point. 106 self.process = self.target.LaunchSimple( 107 None, None, self.get_process_working_directory()) 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( 113 self.process, inner_bkpt) 114 self.assertEquals(len(threads), 1, "Stopped at inner breakpoint.") 115 self.thread = threads[0] 116 117 def do_step_out_past_nodebug(self): 118 # The first step out takes us to the called_from_nodebug frame, just to make sure setting 119 # step-out-avoid-nodebug doesn't change the behavior in frames with 120 # debug info. 121 self.thread.StepOut() 122 self.hit_correct_line( 123 "intermediate_return_value = called_from_nodebug_actual(some_value)") 124 self.thread.StepOut() 125 self.hit_correct_line( 126 "int return_value = no_debug_caller(5, called_from_nodebug)") 127 128 def do_step_over_past_nodebug(self): 129 self.thread.StepOver() 130 self.hit_correct_line( 131 "intermediate_return_value = called_from_nodebug_actual(some_value)") 132 self.thread.StepOver() 133 self.hit_correct_line("return intermediate_return_value") 134 self.thread.StepOver() 135 # Note, lldb doesn't follow gdb's distinction between "step-out" and "step-over/step-in" 136 # when exiting a frame. In all cases we leave the pc at the point where we exited the 137 # frame. In gdb, step-over/step-in move to the end of the line they stepped out to. 138 # If we ever change this we will need to fix this test. 139 self.hit_correct_line( 140 "int return_value = no_debug_caller(5, called_from_nodebug)") 141 142 def do_step_in_past_nodebug(self): 143 self.thread.StepInto() 144 self.hit_correct_line( 145 "intermediate_return_value = called_from_nodebug_actual(some_value)") 146 self.thread.StepInto() 147 self.hit_correct_line("return intermediate_return_value") 148 self.thread.StepInto() 149 # Note, lldb doesn't follow gdb's distinction between "step-out" and "step-over/step-in" 150 # when exiting a frame. In all cases we leave the pc at the point where we exited the 151 # frame. In gdb, step-over/step-in move to the end of the line they stepped out to. 152 # If we ever change this we will need to fix this test. 153 self.hit_correct_line( 154 "int return_value = no_debug_caller(5, called_from_nodebug)") 155