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