220 lines · python
1"""2Use lldb Python SBFrame API to get the argument values of the call stacks.3And other SBFrame API tests.4"""5 6import io7 8import lldb9from lldbsuite.test.decorators import *10from lldbsuite.test.lldbtest import *11from lldbsuite.test import lldbutil12 13 14class FrameAPITestCase(TestBase):15 def test_get_arg_vals_for_call_stack(self):16 """Exercise SBFrame.GetVariables() API to get argument vals."""17 self.build()18 exe = self.getBuildArtifact("a.out")19 20 # Create a target by the debugger.21 target = self.dbg.CreateTarget(exe)22 self.assertTrue(target, VALID_TARGET)23 24 # Now create a breakpoint on main.c by name 'c'.25 breakpoint = target.BreakpointCreateByName("c", "a.out")26 self.trace("breakpoint:", breakpoint)27 self.assertTrue(28 breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT29 )30 31 # Now launch the process, and do not stop at the entry point.32 process = target.LaunchSimple(None, None, self.get_process_working_directory())33 34 process = target.GetProcess()35 self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)36 37 # Keeps track of the number of times 'a' is called where it is within a38 # depth of 3 of the 'c' leaf function.39 callsOfA = 040 41 session = io.StringIO()42 while process.GetState() == lldb.eStateStopped:43 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)44 self.assertIsNotNone(thread)45 # Inspect at most 3 frames.46 numFrames = min(3, thread.GetNumFrames())47 for i in range(numFrames):48 frame = thread.GetFrameAtIndex(i)49 if self.TraceOn():50 print("frame:", frame)51 52 name = frame.GetFunction().GetName()53 if name == "a":54 callsOfA = callsOfA + 155 56 # We'll inspect only the arguments for the current frame:57 #58 # arguments => True59 # locals => False60 # statics => False61 # in_scope_only => True62 valList = frame.GetVariables(True, False, False, True)63 argList = []64 for val in valList:65 argList.append(66 "(%s)%s=%s" % (val.GetTypeName(), val.GetName(), val.GetValue())67 )68 print("%s(%s)" % (name, ", ".join(argList)), file=session)69 70 # Also check the generic pc & stack pointer. We can't test their absolute values,71 # but they should be valid. Uses get_GPRs() from the lldbutil72 # module.73 gpr_reg_set = lldbutil.get_GPRs(frame)74 pc_value = gpr_reg_set.GetChildMemberWithName("pc")75 self.assertTrue(pc_value, "We should have a valid PC.")76 77 78 # Make sure on arm targets we dont mismatch PC value on the basis of thumb bit.79 # Frame PC will not have thumb bit set in case of a thumb80 # instruction as PC.81 pc_value_int = int(pc_value.GetValue(), 0)82 if self.getArchitecture() in ["arm", "armv7", "armv7k"]:83 pc_value_int &= ~184 self.assertEqual(85 pc_value_int,86 frame.GetPC(),87 "PC gotten as a value should equal frame's GetPC",88 )89 sp_value = gpr_reg_set.GetChildMemberWithName("sp")90 self.assertTrue(sp_value, "We should have a valid Stack Pointer.")91 self.assertEqual(92 int(sp_value.GetValue(), 0),93 frame.GetSP(),94 "SP gotten as a value should equal frame's GetSP",95 )96 # Test that the "register" property's flat list matches the list from97 # the "registers" property that returns register sets:98 register_regs = set()99 flattened_regs = set()100 for reg_set in frame.registers:101 for reg in reg_set:102 flattened_regs.add(reg.name)103 for reg in frame.register:104 register_regs.add(reg.name)105 self.assertEqual(register_regs, flattened_regs, "register matches registers")106 107 print("---", file=session)108 process.Continue()109 110 # At this point, the inferior process should have exited.111 self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED)112 113 # Expect to find 'a' on the call stacks two times.114 self.assertEqual(callsOfA, 2, "Expect to find 'a' on the call stacks two times")115 # By design, the 'a' call frame has the following arg vals:116 # o a((int)val=1, (char)ch='A')117 # o a((int)val=3, (char)ch='A')118 if self.TraceOn():119 print("Full stack traces when stopped on the breakpoint 'c':")120 print(session.getvalue())121 self.expect(122 session.getvalue(),123 "Argument values displayed correctly",124 exe=False,125 substrs=["a((int)val=1, (char)ch='A')", "a((int)val=3, (char)ch='A')"],126 )127 128 def test_frame_api_boundary_condition(self):129 """Exercise SBFrame APIs with boundary condition inputs."""130 self.build()131 exe = self.getBuildArtifact("a.out")132 133 # Create a target by the debugger.134 target = self.dbg.CreateTarget(exe)135 self.assertTrue(target, VALID_TARGET)136 137 # Now create a breakpoint on main.c by name 'c'.138 breakpoint = target.BreakpointCreateByName("c", "a.out")139 self.trace("breakpoint:", breakpoint)140 self.assertTrue(141 breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT142 )143 144 # Now launch the process, and do not stop at the entry point.145 process = target.LaunchSimple(None, None, self.get_process_working_directory())146 147 process = target.GetProcess()148 self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)149 150 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)151 self.assertIsNotNone(thread)152 frame = thread.GetFrameAtIndex(0)153 if self.TraceOn():154 print("frame:", frame)155 156 # Boundary condition testings.157 val1 = frame.FindVariable(None, True)158 val2 = frame.FindVariable(None, False)159 val3 = frame.FindValue(None, lldb.eValueTypeVariableGlobal)160 if self.TraceOn():161 print("val1:", val1)162 print("val2:", val2)163 164 frame.EvaluateExpression(None)165 166 def test_frame_api_IsEqual(self):167 """Exercise SBFrame API IsEqual."""168 self.build()169 exe = self.getBuildArtifact("a.out")170 171 # Create a target by the debugger.172 target = self.dbg.CreateTarget(exe)173 self.assertTrue(target, VALID_TARGET)174 175 # Now create a breakpoint on main.c by name 'c'.176 breakpoint = target.BreakpointCreateByName("c", "a.out")177 self.trace("breakpoint:", breakpoint)178 self.assertTrue(179 breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT180 )181 182 # Now launch the process, and do not stop at the entry point.183 process = target.LaunchSimple(None, None, self.get_process_working_directory())184 185 process = target.GetProcess()186 self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)187 188 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)189 self.assertIsNotNone(thread)190 191 frameEntered = thread.GetFrameAtIndex(0)192 if self.TraceOn():193 print(frameEntered)194 lldbutil.print_stacktrace(thread)195 self.assertTrue(frameEntered)196 197 # Doing two step overs while still inside c().198 thread.StepOver()199 thread.StepOver()200 self.assertTrue(thread)201 frameNow = thread.GetFrameAtIndex(0)202 if self.TraceOn():203 print(frameNow)204 lldbutil.print_stacktrace(thread)205 self.assertTrue(frameNow)206 207 # The latest two frames are considered equal.208 self.assertTrue(frameEntered.IsEqual(frameNow))209 210 # Now let's step out of frame c().211 thread.StepOutOfFrame(frameNow)212 frameOutOfC = thread.GetFrameAtIndex(0)213 if self.TraceOn():214 print(frameOutOfC)215 lldbutil.print_stacktrace(thread)216 self.assertTrue(frameOutOfC)217 218 # The latest two frames should not be equal.219 self.assertFalse(frameOutOfC.IsEqual(frameNow))220