1"""Test stepping over vrs. hitting breakpoints & subsequent stepping in various forms.""" 2 3 4 5import lldb 6from lldbsuite.test.decorators import * 7from lldbsuite.test.lldbtest import * 8from lldbsuite.test import lldbutil 9 10 11class TestCStepping(TestBase): 12 13 mydir = TestBase.compute_mydir(__file__) 14 15 def setUp(self): 16 # Call super's setUp(). 17 TestBase.setUp(self) 18 # Find the line numbers that we will step to in main: 19 self.main_source = "main.c" 20 21 @add_test_categories(['pyapi', 'basic_process']) 22 @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr17932') 23 @expectedFailureAll(oslist=["linux"], archs=no_match(["i386", "x86_64"])) 24 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24777") 25 @expectedFailureNetBSD 26 def test_and_python_api(self): 27 """Test stepping over vrs. hitting breakpoints & subsequent stepping in various forms.""" 28 self.build() 29 exe = self.getBuildArtifact("a.out") 30 31 target = self.dbg.CreateTarget(exe) 32 self.assertTrue(target, VALID_TARGET) 33 34 self.main_source_spec = lldb.SBFileSpec(self.main_source) 35 36 breakpoints_to_disable = [] 37 38 break_1_in_main = target.BreakpointCreateBySourceRegex( 39 '// frame select 2, thread step-out while stopped at .c.1..', 40 self.main_source_spec) 41 self.assertTrue(break_1_in_main, VALID_BREAKPOINT) 42 breakpoints_to_disable.append(break_1_in_main) 43 44 break_in_a = target.BreakpointCreateBySourceRegex( 45 '// break here to stop in a before calling b', self.main_source_spec) 46 self.assertTrue(break_in_a, VALID_BREAKPOINT) 47 breakpoints_to_disable.append(break_in_a) 48 49 break_in_b = target.BreakpointCreateBySourceRegex( 50 '// thread step-out while stopped at .c.2..', self.main_source_spec) 51 self.assertTrue(break_in_b, VALID_BREAKPOINT) 52 breakpoints_to_disable.append(break_in_b) 53 54 break_in_c = target.BreakpointCreateBySourceRegex( 55 '// Find the line number of function .c. here.', self.main_source_spec) 56 self.assertTrue(break_in_c, VALID_BREAKPOINT) 57 breakpoints_to_disable.append(break_in_c) 58 59 # Now launch the process, and do not stop at entry point. 60 process = target.LaunchSimple( 61 None, None, self.get_process_working_directory()) 62 63 self.assertTrue(process, PROCESS_IS_VALID) 64 65 # The stop reason of the thread should be breakpoint. 66 threads = lldbutil.get_threads_stopped_at_breakpoint( 67 process, break_1_in_main) 68 69 if len(threads) != 1: 70 self.fail("Failed to stop at first breakpoint in main.") 71 72 thread = threads[0] 73 74 # Get the stop id and for fun make sure it increases: 75 old_stop_id = process.GetStopID() 76 77 # Now step over, which should cause us to hit the breakpoint in "a" 78 thread.StepOver() 79 80 # The stop reason of the thread should be breakpoint. 81 threads = lldbutil.get_threads_stopped_at_breakpoint( 82 process, break_in_a) 83 if len(threads) != 1: 84 self.fail("Failed to stop at breakpoint in a.") 85 86 # Check that the stop ID increases: 87 new_stop_id = process.GetStopID() 88 self.assertTrue( 89 new_stop_id > old_stop_id, 90 "Stop ID increases monotonically.") 91 92 thread = threads[0] 93 94 # Step over, and we should hit the breakpoint in b: 95 thread.StepOver() 96 97 threads = lldbutil.get_threads_stopped_at_breakpoint( 98 process, break_in_b) 99 if len(threads) != 1: 100 self.fail("Failed to stop at breakpoint in b.") 101 thread = threads[0] 102 103 # Now try running some function, and make sure that we still end up in the same place 104 # and with the same stop reason. 105 frame = thread.GetFrameAtIndex(0) 106 current_line = frame.GetLineEntry().GetLine() 107 current_file = frame.GetLineEntry().GetFileSpec() 108 current_bp = [] 109 current_bp.append(thread.GetStopReasonDataAtIndex(0)) 110 current_bp.append(thread.GetStopReasonDataAtIndex(1)) 111 112 stop_id_before_expression = process.GetStopID() 113 stop_id_before_including_expressions = process.GetStopID(True) 114 115 frame.EvaluateExpression("(int) printf (print_string)") 116 117 frame = thread.GetFrameAtIndex(0) 118 self.assertEqual( 119 current_line, frame.GetLineEntry().GetLine(), 120 "The line stayed the same after expression.") 121 self.assertEqual( 122 current_file, frame.GetLineEntry().GetFileSpec(), 123 "The file stayed the same after expression.") 124 self.assertEqual( 125 thread.GetStopReason(), lldb.eStopReasonBreakpoint, 126 "We still say we stopped for a breakpoint.") 127 self.assertTrue(thread.GetStopReasonDataAtIndex(0) == current_bp[ 128 0] and thread.GetStopReasonDataAtIndex(1) == current_bp[1], "And it is the same breakpoint.") 129 130 # Also make sure running the expression didn't change the public stop id 131 # but did change if we are asking for expression stops as well. 132 stop_id_after_expression = process.GetStopID() 133 stop_id_after_including_expressions = process.GetStopID(True) 134 135 self.assertEqual( 136 stop_id_before_expression, stop_id_after_expression, 137 "Expression calling doesn't change stop ID") 138 139 self.assertTrue( 140 stop_id_after_including_expressions > stop_id_before_including_expressions, 141 "Stop ID including expressions increments over expression call.") 142 143 # Do the same thing with an expression that's going to crash, and make 144 # sure we are still unchanged. 145 146 frame.EvaluateExpression("((char *) 0)[0] = 'a'") 147 148 frame = thread.GetFrameAtIndex(0) 149 self.assertEqual( 150 current_line, frame.GetLineEntry().GetLine(), 151 "The line stayed the same after expression.") 152 self.assertEqual( 153 current_file, frame.GetLineEntry().GetFileSpec(), 154 "The file stayed the same after expression.") 155 self.assertEqual( 156 thread.GetStopReason(), lldb.eStopReasonBreakpoint, 157 "We still say we stopped for a breakpoint.") 158 self.assertTrue(thread.GetStopReasonDataAtIndex(0) == current_bp[ 159 0] and thread.GetStopReasonDataAtIndex(1) == current_bp[1], "And it is the same breakpoint.") 160 161 # Now continue and make sure we just complete the step: 162 # Disable all our breakpoints first - sometimes the compiler puts two line table entries in for the 163 # breakpoint a "b" and we don't want to hit that. 164 for bkpt in breakpoints_to_disable: 165 bkpt.SetEnabled(False) 166 167 process.Continue() 168 169 self.assertEqual(thread.GetFrameAtIndex(0).GetFunctionName(), "a") 170 self.assertEqual(thread.GetStopReason(), lldb.eStopReasonPlanComplete) 171 172 # And one more time should get us back to main: 173 process.Continue() 174 175 self.assertEqual(thread.GetFrameAtIndex(0).GetFunctionName(), "main") 176 self.assertEqual(thread.GetStopReason(), lldb.eStopReasonPlanComplete) 177 178 # Now make sure we can call a function, break in the called function, 179 # then have "continue" get us back out again: 180 frame = thread.GetFrameAtIndex(0) 181 frame = thread.GetFrameAtIndex(0) 182 current_line = frame.GetLineEntry().GetLine() 183 current_file = frame.GetLineEntry().GetFileSpec() 184 185 break_in_b.SetEnabled(True) 186 options = lldb.SBExpressionOptions() 187 options.SetIgnoreBreakpoints(False) 188 options.SetFetchDynamicValue(False) 189 options.SetUnwindOnError(False) 190 frame.EvaluateExpression("b (4)", options) 191 192 threads = lldbutil.get_threads_stopped_at_breakpoint( 193 process, break_in_b) 194 195 if len(threads) != 1: 196 self.fail("Failed to stop at breakpoint in b when calling b.") 197 thread = threads[0] 198 199 # So do a step over here to make sure we can still do that: 200 201 thread.StepOver() 202 203 # See that we are still in b: 204 func_name = thread.GetFrameAtIndex(0).GetFunctionName() 205 self.assertEqual( 206 func_name, "b", 207 "Should be in 'b', were in %s" % 208 (func_name)) 209 210 # Okay, now if we continue, we will finish off our function call and we 211 # should end up back in "a" as if nothing had happened: 212 process.Continue() 213 214 self.assertTrue(thread.GetFrameAtIndex( 215 0).GetLineEntry().GetLine() == current_line) 216 self.assertTrue(thread.GetFrameAtIndex( 217 0).GetLineEntry().GetFileSpec() == current_file) 218 219 # Now we are going to test step in targeting a function: 220 221 break_in_b.SetEnabled(False) 222 223 break_before_complex_1 = target.BreakpointCreateBySourceRegex( 224 '// Stop here to try step in targeting b.', self.main_source_spec) 225 self.assertTrue(break_before_complex_1, VALID_BREAKPOINT) 226 227 break_before_complex_2 = target.BreakpointCreateBySourceRegex( 228 '// Stop here to try step in targeting complex.', self.main_source_spec) 229 self.assertTrue(break_before_complex_2, VALID_BREAKPOINT) 230 231 break_before_complex_3 = target.BreakpointCreateBySourceRegex( 232 '// Stop here to step targeting b and hitting breakpoint.', self.main_source_spec) 233 self.assertTrue(break_before_complex_3, VALID_BREAKPOINT) 234 235 break_before_complex_4 = target.BreakpointCreateBySourceRegex( 236 '// Stop here to make sure bogus target steps over.', self.main_source_spec) 237 self.assertTrue(break_before_complex_4, VALID_BREAKPOINT) 238 239 threads = lldbutil.continue_to_breakpoint( 240 process, break_before_complex_1) 241 self.assertEqual(len(threads), 1) 242 thread = threads[0] 243 break_before_complex_1.SetEnabled(False) 244 245 thread.StepInto("b") 246 self.assertEqual(thread.GetFrameAtIndex(0).GetFunctionName(), "b") 247 248 # Now continue out and stop at the next call to complex. This time 249 # step all the way into complex: 250 threads = lldbutil.continue_to_breakpoint( 251 process, break_before_complex_2) 252 self.assertEqual(len(threads), 1) 253 thread = threads[0] 254 break_before_complex_2.SetEnabled(False) 255 256 thread.StepInto("complex") 257 self.assertTrue(thread.GetFrameAtIndex( 258 0).GetFunctionName() == "complex") 259 260 # Now continue out and stop at the next call to complex. This time 261 # enable breakpoints in a and c and then step targeting b: 262 threads = lldbutil.continue_to_breakpoint( 263 process, break_before_complex_3) 264 self.assertEqual(len(threads), 1) 265 thread = threads[0] 266 break_before_complex_3.SetEnabled(False) 267 268 break_at_start_of_a = target.BreakpointCreateByName('a') 269 break_at_start_of_c = target.BreakpointCreateByName('c') 270 271 thread.StepInto("b") 272 threads = lldbutil.get_stopped_threads( 273 process, lldb.eStopReasonBreakpoint) 274 275 self.assertEqual(len(threads), 1) 276 thread = threads[0] 277 stop_break_id = thread.GetStopReasonDataAtIndex(0) 278 self.assertTrue(stop_break_id == break_at_start_of_a.GetID() 279 or stop_break_id == break_at_start_of_c.GetID()) 280 281 break_at_start_of_a.SetEnabled(False) 282 break_at_start_of_c.SetEnabled(False) 283 284 process.Continue() 285 self.assertEqual(thread.GetFrameAtIndex(0).GetFunctionName(), "b") 286 287 # Now continue out and stop at the next call to complex. This time 288 # enable breakpoints in a and c and then step targeting b: 289 threads = lldbutil.continue_to_breakpoint( 290 process, break_before_complex_4) 291 self.assertEqual(len(threads), 1) 292 thread = threads[0] 293 break_before_complex_4.SetEnabled(False) 294 295 thread.StepInto("NoSuchFunction") 296 self.assertEqual(thread.GetFrameAtIndex(0).GetFunctionName(), "main") 297