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