1""" 2Use lldb Python SBFrame API to get the argument values of the call stacks. 3And other SBFrame API tests. 4""" 5 6from __future__ import print_function 7 8import io 9 10import lldb 11from lldbsuite.test.decorators import * 12from lldbsuite.test.lldbtest import * 13from lldbsuite.test import lldbutil 14 15 16class FrameAPITestCase(TestBase): 17 18 def test_get_arg_vals_for_call_stack(self): 19 """Exercise SBFrame.GetVariables() API to get argument vals.""" 20 self.build() 21 exe = self.getBuildArtifact("a.out") 22 23 # Create a target by the debugger. 24 target = self.dbg.CreateTarget(exe) 25 self.assertTrue(target, VALID_TARGET) 26 27 # Now create a breakpoint on main.c by name 'c'. 28 breakpoint = target.BreakpointCreateByName('c', 'a.out') 29 self.trace("breakpoint:", breakpoint) 30 self.assertTrue(breakpoint and 31 breakpoint.GetNumLocations() == 1, 32 VALID_BREAKPOINT) 33 34 # Now launch the process, and do not stop at the entry point. 35 process = target.LaunchSimple( 36 None, None, self.get_process_working_directory()) 37 38 process = target.GetProcess() 39 self.assertState(process.GetState(), lldb.eStateStopped, 40 PROCESS_STOPPED) 41 42 # Keeps track of the number of times 'a' is called where it is within a 43 # depth of 3 of the 'c' leaf function. 44 callsOfA = 0 45 46 session = io.StringIO() 47 while process.GetState() == lldb.eStateStopped: 48 thread = lldbutil.get_stopped_thread( 49 process, lldb.eStopReasonBreakpoint) 50 self.assertIsNotNone(thread) 51 # Inspect at most 3 frames. 52 numFrames = min(3, thread.GetNumFrames()) 53 for i in range(numFrames): 54 frame = thread.GetFrameAtIndex(i) 55 if self.TraceOn(): 56 print("frame:", frame) 57 58 name = frame.GetFunction().GetName() 59 if name == 'a': 60 callsOfA = callsOfA + 1 61 62 # We'll inspect only the arguments for the current frame: 63 # 64 # arguments => True 65 # locals => False 66 # statics => False 67 # in_scope_only => True 68 valList = frame.GetVariables(True, False, False, True) 69 argList = [] 70 for val in valList: 71 argList.append("(%s)%s=%s" % (val.GetTypeName(), 72 val.GetName(), 73 val.GetValue())) 74 print("%s(%s)" % (name, ", ".join(argList)), file=session) 75 76 # Also check the generic pc & stack pointer. We can't test their absolute values, 77 # but they should be valid. Uses get_GPRs() from the lldbutil 78 # module. 79 gpr_reg_set = lldbutil.get_GPRs(frame) 80 pc_value = gpr_reg_set.GetChildMemberWithName("pc") 81 self.assertTrue(pc_value, "We should have a valid PC.") 82 pc_value_int = int(pc_value.GetValue(), 0) 83 # Make sure on arm targets we dont mismatch PC value on the basis of thumb bit. 84 # Frame PC will not have thumb bit set in case of a thumb 85 # instruction as PC. 86 if self.getArchitecture() in ['arm', 'armv7', 'armv7k']: 87 pc_value_int &= ~1 88 self.assertEqual( 89 pc_value_int, frame.GetPC(), 90 "PC gotten as a value should equal frame's GetPC") 91 sp_value = gpr_reg_set.GetChildMemberWithName("sp") 92 self.assertTrue( 93 sp_value, "We should have a valid Stack Pointer.") 94 self.assertEqual( 95 int(sp_value.GetValue(), 0), frame.GetSP(), 96 "SP gotten as a value should equal frame's GetSP") 97 98 print("---", file=session) 99 process.Continue() 100 101 # At this point, the inferior process should have exited. 102 self.assertEqual( 103 process.GetState(), lldb.eStateExited, 104 PROCESS_EXITED) 105 106 # Expect to find 'a' on the call stacks two times. 107 self.assertEqual(callsOfA, 2, 108 "Expect to find 'a' on the call stacks two times") 109 # By design, the 'a' call frame has the following arg vals: 110 # o a((int)val=1, (char)ch='A') 111 # o a((int)val=3, (char)ch='A') 112 if self.TraceOn(): 113 print("Full stack traces when stopped on the breakpoint 'c':") 114 print(session.getvalue()) 115 self.expect(session.getvalue(), "Argument values displayed correctly", 116 exe=False, 117 substrs=["a((int)val=1, (char)ch='A')", 118 "a((int)val=3, (char)ch='A')"]) 119 120 def test_frame_api_boundary_condition(self): 121 """Exercise SBFrame APIs with boundary condition inputs.""" 122 self.build() 123 exe = self.getBuildArtifact("a.out") 124 125 # Create a target by the debugger. 126 target = self.dbg.CreateTarget(exe) 127 self.assertTrue(target, VALID_TARGET) 128 129 # Now create a breakpoint on main.c by name 'c'. 130 breakpoint = target.BreakpointCreateByName('c', 'a.out') 131 self.trace("breakpoint:", breakpoint) 132 self.assertTrue(breakpoint and 133 breakpoint.GetNumLocations() == 1, 134 VALID_BREAKPOINT) 135 136 # Now launch the process, and do not stop at the entry point. 137 process = target.LaunchSimple( 138 None, None, self.get_process_working_directory()) 139 140 process = target.GetProcess() 141 self.assertState(process.GetState(), lldb.eStateStopped, 142 PROCESS_STOPPED) 143 144 thread = lldbutil.get_stopped_thread( 145 process, lldb.eStopReasonBreakpoint) 146 self.assertIsNotNone(thread) 147 frame = thread.GetFrameAtIndex(0) 148 if self.TraceOn(): 149 print("frame:", frame) 150 151 # Boundary condition testings. 152 val1 = frame.FindVariable(None, True) 153 val2 = frame.FindVariable(None, False) 154 val3 = frame.FindValue(None, lldb.eValueTypeVariableGlobal) 155 if self.TraceOn(): 156 print("val1:", val1) 157 print("val2:", val2) 158 159 frame.EvaluateExpression(None) 160 161 def test_frame_api_IsEqual(self): 162 """Exercise SBFrame API IsEqual.""" 163 self.build() 164 exe = self.getBuildArtifact("a.out") 165 166 # Create a target by the debugger. 167 target = self.dbg.CreateTarget(exe) 168 self.assertTrue(target, VALID_TARGET) 169 170 # Now create a breakpoint on main.c by name 'c'. 171 breakpoint = target.BreakpointCreateByName('c', 'a.out') 172 self.trace("breakpoint:", breakpoint) 173 self.assertTrue(breakpoint and 174 breakpoint.GetNumLocations() == 1, 175 VALID_BREAKPOINT) 176 177 # Now launch the process, and do not stop at the entry point. 178 process = target.LaunchSimple( 179 None, None, self.get_process_working_directory()) 180 181 process = target.GetProcess() 182 self.assertState(process.GetState(), lldb.eStateStopped, 183 PROCESS_STOPPED) 184 185 thread = lldbutil.get_stopped_thread( 186 process, lldb.eStopReasonBreakpoint) 187 self.assertIsNotNone(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