1""" 2Use lldb Python SBFrame API to get the argument values of the call stacks. 3And other SBFrame API tests. 4""" 5 6import os, time 7import re 8import unittest2 9import lldb, lldbutil 10from lldbtest import * 11 12class 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 220if __name__ == '__main__': 221 import atexit 222 lldb.SBDebugger.Initialize() 223 atexit.register(lambda: lldb.SBDebugger.Terminate()) 224 unittest2.main() 225