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