1 """Test stepping over vrs. hitting breakpoints & subsequent stepping in various forms.""" 2 3 import os, time 4 import unittest2 5 import lldb 6 import lldbutil 7 from lldbtest import * 8 9 class TestObjCStepping(TestBase): 10 11 mydir = os.path.join("lang", "c", "stepping") 12 13 def getCategories(self): 14 return ['basic_process'] 15 16 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") 17 @python_api_test 18 @dsym_test 19 def test_with_dsym_and_python_api(self): 20 """Test stepping over vrs. hitting breakpoints & subsequent stepping in various forms.""" 21 self.buildDsym() 22 self.step_over_stepping() 23 24 @expectedFailureLinux # llvm.org/pr14437 25 @python_api_test 26 @dwarf_test 27 def test_with_dwarf_and_python_api(self): 28 """Test stepping over vrs. hitting breakpoints & subsequent stepping in various forms.""" 29 self.buildDwarf() 30 self.step_over_stepping() 31 32 def setUp(self): 33 # Call super's setUp(). 34 TestBase.setUp(self) 35 # Find the line numbers that we will step to in main: 36 self.main_source = "main.c" 37 38 def step_over_stepping(self): 39 """Use Python APIs to test stepping over and hitting breakpoints.""" 40 exe = os.path.join(os.getcwd(), "a.out") 41 42 target = self.dbg.CreateTarget(exe) 43 self.assertTrue(target, VALID_TARGET) 44 45 self.main_source_spec = lldb.SBFileSpec (self.main_source) 46 47 breakpoints_to_disable = [] 48 49 break_1_in_main = target.BreakpointCreateBySourceRegex ('// frame select 2, thread step-out while stopped at .c.1..', self.main_source_spec) 50 self.assertTrue(break_1_in_main, VALID_BREAKPOINT) 51 breakpoints_to_disable.append (break_1_in_main) 52 53 break_in_a = target.BreakpointCreateBySourceRegex ('// break here to stop in a before calling b', self.main_source_spec) 54 self.assertTrue(break_in_a, VALID_BREAKPOINT) 55 breakpoints_to_disable.append (break_in_a) 56 57 break_in_b = target.BreakpointCreateBySourceRegex ('// thread step-out while stopped at .c.2..', self.main_source_spec) 58 self.assertTrue(break_in_b, VALID_BREAKPOINT) 59 breakpoints_to_disable.append (break_in_b) 60 61 break_in_c = target.BreakpointCreateBySourceRegex ('// Find the line number of function .c. here.', self.main_source_spec) 62 self.assertTrue(break_in_c, VALID_BREAKPOINT) 63 breakpoints_to_disable.append (break_in_c) 64 65 # Now launch the process, and do not stop at entry point. 66 process = target.LaunchSimple (None, None, os.getcwd()) 67 68 self.assertTrue(process, PROCESS_IS_VALID) 69 70 # The stop reason of the thread should be breakpoint. 71 threads = lldbutil.get_threads_stopped_at_breakpoint (process, break_1_in_main) 72 73 if len(threads) != 1: 74 self.fail ("Failed to stop at first breakpoint in main.") 75 76 thread = threads[0] 77 78 # Get the stop id and for fun make sure it increases: 79 old_stop_id = process.GetStopID() 80 81 # Now step over, which should cause us to hit the breakpoint in "a" 82 thread.StepOver() 83 84 # The stop reason of the thread should be breakpoint. 85 threads = lldbutil.get_threads_stopped_at_breakpoint (process, break_in_a) 86 if len(threads) != 1: 87 self.fail ("Failed to stop at breakpoint in a.") 88 89 # Check that the stop ID increases: 90 new_stop_id = process.GetStopID() 91 self.assertTrue(new_stop_id > old_stop_id, "Stop ID increases monotonically.") 92 93 thread = threads[0] 94 95 # Step over, and we should hit the breakpoint in b: 96 thread.StepOver() 97 98 threads = lldbutil.get_threads_stopped_at_breakpoint (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.assertTrue (current_line == frame.GetLineEntry().GetLine(), "The line stayed the same after expression.") 119 self.assertTrue (current_file == frame.GetLineEntry().GetFileSpec(), "The file stayed the same after expression.") 120 self.assertTrue (thread.GetStopReason() == lldb.eStopReasonBreakpoint, "We still say we stopped for a breakpoint.") 121 self.assertTrue (thread.GetStopReasonDataAtIndex(0) == current_bp[0] and thread.GetStopReasonDataAtIndex(1) == current_bp[1], "And it is the same breakpoint.") 122 123 # Also make sure running the expression didn't change the public stop id 124 # but did change if we are asking for expression stops as well. 125 stop_id_after_expression = process.GetStopID() 126 stop_id_after_including_expressions = process.GetStopID(True) 127 128 self.assertTrue (stop_id_before_expression == stop_id_after_expression, "Expression calling doesn't change stop ID") 129 130 self.assertTrue (stop_id_after_including_expressions > stop_id_before_including_expressions, "Stop ID including expressions increments over expression call.") 131 132 # Do the same thing with an expression that's going to crash, and make sure we are still unchanged. 133 134 frame.EvaluateExpression ("((char *) 0)[0] = 'a'") 135 136 frame = thread.GetFrameAtIndex(0) 137 self.assertTrue (current_line == frame.GetLineEntry().GetLine(), "The line stayed the same after expression.") 138 self.assertTrue (current_file == frame.GetLineEntry().GetFileSpec(), "The file stayed the same after expression.") 139 self.assertTrue (thread.GetStopReason() == lldb.eStopReasonBreakpoint, "We still say we stopped for a breakpoint.") 140 self.assertTrue (thread.GetStopReasonDataAtIndex(0) == current_bp[0] and thread.GetStopReasonDataAtIndex(1) == current_bp[1], "And it is the same breakpoint.") 141 142 # Now continue and make sure we just complete the step: 143 # Disable all our breakpoints first - sometimes the compiler puts two line table entries in for the 144 # breakpoint a "b" and we don't want to hit that. 145 for bkpt in breakpoints_to_disable: 146 bkpt.SetEnabled(False) 147 148 process.Continue() 149 150 self.assertTrue (thread.GetFrameAtIndex(0).GetFunctionName() == "a") 151 self.assertTrue (thread.GetStopReason() == lldb.eStopReasonPlanComplete) 152 153 # And one more time should get us back to main: 154 process.Continue() 155 156 self.assertTrue (thread.GetFrameAtIndex(0).GetFunctionName() == "main") 157 self.assertTrue (thread.GetStopReason() == lldb.eStopReasonPlanComplete) 158 159 # Now make sure we can call a function, break in the called function, then have "continue" get us back out again: 160 frame = thread.GetFrameAtIndex(0) 161 frame = thread.GetFrameAtIndex(0) 162 current_line = frame.GetLineEntry().GetLine() 163 current_file = frame.GetLineEntry().GetFileSpec() 164 165 break_in_b.SetEnabled(True) 166 frame.EvaluateExpression ("b (4)", lldb.eNoDynamicValues, False) 167 168 threads = lldbutil.get_threads_stopped_at_breakpoint (process, break_in_b) 169 if len(threads) != 1: 170 self.fail ("Failed to stop at breakpoint in b when calling b.") 171 thread = threads[0] 172 173 # So do a step over here to make sure we can still do that: 174 175 thread.StepOver() 176 177 # See that we are still in b: 178 self.assertTrue (thread.GetFrameAtIndex(0).GetFunctionName() == "b") 179 180 # Okay, now if we continue, we will finish off our function call and we should end up back in "a" as if nothing had happened: 181 process.Continue () 182 183 self.assertTrue (thread.GetFrameAtIndex(0).GetLineEntry().GetLine() == current_line) 184 self.assertTrue (thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec() == current_file) 185 186 # Now we are going to test step in targetting a function: 187 188 break_in_b.SetEnabled (False) 189 190 break_before_complex_1 = target.BreakpointCreateBySourceRegex ('// Stop here to try step in targetting b.', self.main_source_spec) 191 self.assertTrue(break_before_complex_1, VALID_BREAKPOINT) 192 193 break_before_complex_2 = target.BreakpointCreateBySourceRegex ('// Stop here to try step in targetting complex.', self.main_source_spec) 194 self.assertTrue(break_before_complex_2, VALID_BREAKPOINT) 195 196 break_before_complex_3 = target.BreakpointCreateBySourceRegex ('// Stop here to step targetting b and hitting breakpoint.', self.main_source_spec) 197 self.assertTrue(break_before_complex_3, VALID_BREAKPOINT) 198 199 break_before_complex_4 = target.BreakpointCreateBySourceRegex ('// Stop here to make sure bogus target steps over.', self.main_source_spec) 200 self.assertTrue(break_before_complex_4, VALID_BREAKPOINT) 201 202 threads = lldbutil.continue_to_breakpoint(process, break_before_complex_1) 203 self.assertTrue (len(threads) == 1) 204 thread = threads[0] 205 break_before_complex_1.SetEnabled(False) 206 207 thread.StepInto ("b") 208 self.assertTrue (thread.GetFrameAtIndex(0).GetFunctionName() == "b") 209 210 # Now continue out and stop at the next call to complex. This time step all the way into complex: 211 threads = lldbutil.continue_to_breakpoint (process, break_before_complex_2) 212 self.assertTrue (len(threads) == 1) 213 thread = threads[0] 214 break_before_complex_2.SetEnabled(False) 215 216 thread.StepInto ("complex") 217 self.assertTrue (thread.GetFrameAtIndex(0).GetFunctionName() == "complex") 218 219 # Now continue out and stop at the next call to complex. This time enable breakpoints in a and c and then step targetting b: 220 threads = lldbutil.continue_to_breakpoint (process, break_before_complex_3) 221 self.assertTrue (len(threads) == 1) 222 thread = threads[0] 223 break_before_complex_3.SetEnabled(False) 224 225 break_at_start_of_a = target.BreakpointCreateByName ('a') 226 break_at_start_of_c = target.BreakpointCreateByName ('c') 227 228 thread.StepInto ("b") 229 threads = lldbutil.get_stopped_threads(process, lldb.eStopReasonBreakpoint); 230 231 self.assertTrue (len(threads) == 1) 232 thread = threads[0] 233 stop_break_id = thread.GetStopReasonDataAtIndex(0) 234 self.assertTrue(stop_break_id == break_at_start_of_a.GetID() or stop_break_id == break_at_start_of_c.GetID()) 235 236 break_at_start_of_a.SetEnabled(False) 237 break_at_start_of_c.SetEnabled(False) 238 239 process.Continue() 240 self.assertTrue (thread.GetFrameAtIndex(0).GetFunctionName() == "b") 241 242 # Now continue out and stop at the next call to complex. This time enable breakpoints in a and c and then step targetting b: 243 threads = lldbutil.continue_to_breakpoint (process, break_before_complex_4) 244 self.assertTrue (len(threads) == 1) 245 thread = threads[0] 246 break_before_complex_4.SetEnabled(False) 247 248 thread.StepInto("NoSuchFunction") 249 self.assertTrue (thread.GetFrameAtIndex(0).GetFunctionName() == "main") 250 251 if __name__ == '__main__': 252 import atexit 253 lldb.SBDebugger.Initialize() 254 atexit.register(lambda: lldb.SBDebugger.Terminate()) 255 unittest2.main() 256