Home | History | Annotate | Download | only in frame
      1 """
      2 Use lldb Python SBFrame API to get the argument values of the call stacks.
      3 And other SBFrame API tests.
      4 """
      5 
      6 import os, time
      7 import re
      8 import unittest2
      9 import lldb, lldbutil
     10 from lldbtest import *
     11 
     12 class FrameAPITestCase(TestBase):
     13 
     14     mydir = os.path.join("python_api", "frame")
     15 
     16     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     17     @python_api_test
     18     @dsym_test
     19     def test_get_arg_vals_for_call_stack_with_dsym(self):
     20         """Exercise SBFrame.GetVariables() API to get argument vals."""
     21         self.buildDsym()
     22         self.do_get_arg_vals()
     23 
     24     @python_api_test
     25     @dwarf_test
     26     def test_get_arg_vals_for_call_stack_with_dwarf(self):
     27         """Exercise SBFrame.GetVariables() API to get argument vals."""
     28         self.buildDwarf()
     29         self.do_get_arg_vals()
     30 
     31     @python_api_test
     32     def test_frame_api_boundary_condition(self):
     33         """Exercise SBFrame APIs with boundary condition inputs."""
     34         self.buildDefault()
     35         self.frame_api_boundary_condition()
     36 
     37     @python_api_test
     38     def test_frame_api_IsEqual(self):
     39         """Exercise SBFrame API IsEqual."""
     40         self.buildDefault()
     41         self.frame_api_IsEqual()
     42 
     43     def do_get_arg_vals(self):
     44         """Get argument vals for the call stack when stopped on a breakpoint."""
     45         exe = os.path.join(os.getcwd(), "a.out")
     46 
     47         # Create a target by the debugger.
     48         target = self.dbg.CreateTarget(exe)
     49         self.assertTrue(target, VALID_TARGET)
     50 
     51         # Now create a breakpoint on main.c by name 'c'.
     52         breakpoint = target.BreakpointCreateByName('c', 'a.out')
     53         #print "breakpoint:", breakpoint
     54         self.assertTrue(breakpoint and
     55                         breakpoint.GetNumLocations() == 1,
     56                         VALID_BREAKPOINT)
     57 
     58         # Now launch the process, and do not stop at the entry point.
     59         process = target.LaunchSimple(None, None, os.getcwd())
     60 
     61         process = target.GetProcess()
     62         self.assertTrue(process.GetState() == lldb.eStateStopped,
     63                         PROCESS_STOPPED)
     64 
     65         # Keeps track of the number of times 'a' is called where it is within a
     66         # depth of 3 of the 'c' leaf function.
     67         callsOfA = 0
     68 
     69         import StringIO
     70         session = StringIO.StringIO()
     71         while process.GetState() == lldb.eStateStopped:
     72             thread = process.GetThreadAtIndex(0)
     73             # Inspect at most 3 frames.
     74             numFrames = min(3, thread.GetNumFrames())
     75             for i in range(numFrames):
     76                 frame = thread.GetFrameAtIndex(i)
     77                 if self.TraceOn():
     78                     print "frame:", frame
     79 
     80                 name = frame.GetFunction().GetName()
     81                 if name == 'a':
     82                     callsOfA = callsOfA + 1
     83 
     84                 # We'll inspect only the arguments for the current frame:
     85                 #
     86                 # arguments     => True
     87                 # locals        => False
     88                 # statics       => False
     89                 # in_scope_only => True
     90                 valList = frame.GetVariables(True, False, False, True)
     91                 argList = []
     92                 for val in valList:
     93                     argList.append("(%s)%s=%s" % (val.GetTypeName(),
     94                                                   val.GetName(),
     95                                                   val.GetValue()))
     96                 print >> session, "%s(%s)" % (name, ", ".join(argList))
     97                 
     98                 # Also check the generic pc & stack pointer.  We can't test their absolute values,
     99                 # but they should be valid.  Uses get_GPRs() from the lldbutil module.
    100                 gpr_reg_set = lldbutil.get_GPRs(frame)
    101                 pc_value = gpr_reg_set.GetChildMemberWithName("pc")
    102                 self.assertTrue (pc_value, "We should have a valid PC.")
    103                 self.assertTrue (int(pc_value.GetValue(), 0) == frame.GetPC(), "PC gotten as a value should equal frame's GetPC")
    104                 sp_value = gpr_reg_set.GetChildMemberWithName("sp")
    105                 self.assertTrue (sp_value, "We should have a valid Stack Pointer.")
    106                 self.assertTrue (int(sp_value.GetValue(), 0) == frame.GetSP(), "SP gotten as a value should equal frame's GetSP")
    107 
    108             print >> session, "---"
    109             process.Continue()
    110 
    111         # At this point, the inferior process should have exited.
    112         self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)
    113 
    114         # Expect to find 'a' on the call stacks two times.
    115         self.assertTrue(callsOfA == 2,
    116                         "Expect to find 'a' on the call stacks two times")
    117         # By design, the 'a' call frame has the following arg vals:
    118         #     o a((int)val=1, (char)ch='A')
    119         #     o a((int)val=3, (char)ch='A')
    120         if self.TraceOn():
    121             print "Full stack traces when stopped on the breakpoint 'c':"
    122             print session.getvalue()
    123         self.expect(session.getvalue(), "Argugment values displayed correctly",
    124                     exe=False,
    125             substrs = ["a((int)val=1, (char)ch='A')",
    126                        "a((int)val=3, (char)ch='A')"])
    127 
    128     def frame_api_boundary_condition(self):
    129         exe = os.path.join(os.getcwd(), "a.out")
    130 
    131         # Create a target by the debugger.
    132         target = self.dbg.CreateTarget(exe)
    133         self.assertTrue(target, VALID_TARGET)
    134 
    135         # Now create a breakpoint on main.c by name 'c'.
    136         breakpoint = target.BreakpointCreateByName('c', 'a.out')
    137         #print "breakpoint:", breakpoint
    138         self.assertTrue(breakpoint and
    139                         breakpoint.GetNumLocations() == 1,
    140                         VALID_BREAKPOINT)
    141 
    142         # Now launch the process, and do not stop at the entry point.
    143         process = target.LaunchSimple(None, None, os.getcwd())
    144 
    145         process = target.GetProcess()
    146         self.assertTrue(process.GetState() == lldb.eStateStopped,
    147                         PROCESS_STOPPED)
    148 
    149         thread = process.GetThreadAtIndex(0)
    150         frame = thread.GetFrameAtIndex(0)
    151         if self.TraceOn():
    152             print "frame:", frame
    153 
    154         # Boundary condition testings.
    155         val1 = frame.FindVariable(None, True)
    156         val2 = frame.FindVariable(None, False)
    157         val3 = frame.FindValue(None, lldb.eValueTypeVariableGlobal)
    158         if self.TraceOn():
    159             print "val1:", val1
    160             print "val2:", val2
    161 
    162         frame.EvaluateExpression(None)
    163 
    164     def frame_api_IsEqual(self):
    165         """Exercise SBFrame API IsEqual."""
    166         exe = os.path.join(os.getcwd(), "a.out")
    167 
    168         # Create a target by the debugger.
    169         target = self.dbg.CreateTarget(exe)
    170         self.assertTrue(target, VALID_TARGET)
    171 
    172         # Now create a breakpoint on main.c by name 'c'.
    173         breakpoint = target.BreakpointCreateByName('c', 'a.out')
    174         #print "breakpoint:", breakpoint
    175         self.assertTrue(breakpoint and
    176                         breakpoint.GetNumLocations() == 1,
    177                         VALID_BREAKPOINT)
    178 
    179         # Now launch the process, and do not stop at the entry point.
    180         process = target.LaunchSimple(None, None, os.getcwd())
    181 
    182         process = target.GetProcess()
    183         self.assertTrue(process.GetState() == lldb.eStateStopped,
    184                         PROCESS_STOPPED)
    185 
    186         thread = process.GetThreadAtIndex(0)
    187         self.assertTrue(thread)
    188 
    189         frameEntered = thread.GetFrameAtIndex(0)
    190         if self.TraceOn():
    191             print frameEntered
    192             lldbutil.print_stacktrace(thread)
    193         self.assertTrue(frameEntered)
    194 
    195         # Doing two step overs while still inside c().
    196         thread.StepOver()
    197         thread.StepOver()
    198         self.assertTrue(thread)
    199         frameNow = thread.GetFrameAtIndex(0)
    200         if self.TraceOn():
    201             print frameNow
    202             lldbutil.print_stacktrace(thread)
    203         self.assertTrue(frameNow)
    204 
    205         # The latest two frames are considered equal.
    206         self.assertTrue(frameEntered.IsEqual(frameNow))
    207 
    208         # Now let's step out of frame c().
    209         thread.StepOutOfFrame(frameNow)
    210         frameOutOfC = thread.GetFrameAtIndex(0)
    211         if self.TraceOn():
    212             print frameOutOfC
    213             lldbutil.print_stacktrace(thread)
    214         self.assertTrue(frameOutOfC)
    215 
    216         # The latest two frames should not be equal.
    217         self.assertFalse(frameOutOfC.IsEqual(frameNow))
    218 
    219 
    220 if __name__ == '__main__':
    221     import atexit
    222     lldb.SBDebugger.Initialize()
    223     atexit.register(lambda: lldb.SBDebugger.Terminate())
    224     unittest2.main()
    225