Home | History | Annotate | Download | only in stepping
      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