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