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