199451b44SJordan Rupprecht"""
299451b44SJordan RupprechtUse lldb Python SBFrame API to get the argument values of the call stacks.
399451b44SJordan RupprechtAnd other SBFrame API tests.
499451b44SJordan Rupprecht"""
599451b44SJordan Rupprecht
699451b44SJordan Rupprechtfrom __future__ import print_function
799451b44SJordan Rupprecht
899451b44SJordan Rupprecht
999451b44SJordan Rupprechtimport lldb
1099451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
1199451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import *
1299451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil
1399451b44SJordan Rupprecht
1499451b44SJordan Rupprecht
1599451b44SJordan Rupprechtclass FrameAPITestCase(TestBase):
1699451b44SJordan Rupprecht
1799451b44SJordan Rupprecht    def test_get_arg_vals_for_call_stack(self):
1899451b44SJordan Rupprecht        """Exercise SBFrame.GetVariables() API to get argument vals."""
1999451b44SJordan Rupprecht        self.build()
2099451b44SJordan Rupprecht        exe = self.getBuildArtifact("a.out")
2199451b44SJordan Rupprecht
2299451b44SJordan Rupprecht        # Create a target by the debugger.
2399451b44SJordan Rupprecht        target = self.dbg.CreateTarget(exe)
2499451b44SJordan Rupprecht        self.assertTrue(target, VALID_TARGET)
2599451b44SJordan Rupprecht
2699451b44SJordan Rupprecht        # Now create a breakpoint on main.c by name 'c'.
2799451b44SJordan Rupprecht        breakpoint = target.BreakpointCreateByName('c', 'a.out')
28b321b429SJonas Devlieghere        self.trace("breakpoint:", breakpoint)
2999451b44SJordan Rupprecht        self.assertTrue(breakpoint and
3099451b44SJordan Rupprecht                        breakpoint.GetNumLocations() == 1,
3199451b44SJordan Rupprecht                        VALID_BREAKPOINT)
3299451b44SJordan Rupprecht
3399451b44SJordan Rupprecht        # Now launch the process, and do not stop at the entry point.
3499451b44SJordan Rupprecht        process = target.LaunchSimple(
3599451b44SJordan Rupprecht            None, None, self.get_process_working_directory())
3699451b44SJordan Rupprecht
3799451b44SJordan Rupprecht        process = target.GetProcess()
38*47c4c6a7SDave Lee        self.assertState(process.GetState(), lldb.eStateStopped,
3999451b44SJordan Rupprecht                         PROCESS_STOPPED)
4099451b44SJordan Rupprecht
4199451b44SJordan Rupprecht        # Keeps track of the number of times 'a' is called where it is within a
4299451b44SJordan Rupprecht        # depth of 3 of the 'c' leaf function.
4399451b44SJordan Rupprecht        callsOfA = 0
4499451b44SJordan Rupprecht
4599451b44SJordan Rupprecht        from six import StringIO as SixStringIO
4699451b44SJordan Rupprecht        session = SixStringIO()
4799451b44SJordan Rupprecht        while process.GetState() == lldb.eStateStopped:
4899451b44SJordan Rupprecht            thread = lldbutil.get_stopped_thread(
4999451b44SJordan Rupprecht                process, lldb.eStopReasonBreakpoint)
5099451b44SJordan Rupprecht            self.assertIsNotNone(thread)
5199451b44SJordan Rupprecht            # Inspect at most 3 frames.
5299451b44SJordan Rupprecht            numFrames = min(3, thread.GetNumFrames())
5399451b44SJordan Rupprecht            for i in range(numFrames):
5499451b44SJordan Rupprecht                frame = thread.GetFrameAtIndex(i)
5599451b44SJordan Rupprecht                if self.TraceOn():
5699451b44SJordan Rupprecht                    print("frame:", frame)
5799451b44SJordan Rupprecht
5899451b44SJordan Rupprecht                name = frame.GetFunction().GetName()
5999451b44SJordan Rupprecht                if name == 'a':
6099451b44SJordan Rupprecht                    callsOfA = callsOfA + 1
6199451b44SJordan Rupprecht
6299451b44SJordan Rupprecht                # We'll inspect only the arguments for the current frame:
6399451b44SJordan Rupprecht                #
6499451b44SJordan Rupprecht                # arguments     => True
6599451b44SJordan Rupprecht                # locals        => False
6699451b44SJordan Rupprecht                # statics       => False
6799451b44SJordan Rupprecht                # in_scope_only => True
6899451b44SJordan Rupprecht                valList = frame.GetVariables(True, False, False, True)
6999451b44SJordan Rupprecht                argList = []
7099451b44SJordan Rupprecht                for val in valList:
7199451b44SJordan Rupprecht                    argList.append("(%s)%s=%s" % (val.GetTypeName(),
7299451b44SJordan Rupprecht                                                  val.GetName(),
7399451b44SJordan Rupprecht                                                  val.GetValue()))
7499451b44SJordan Rupprecht                print("%s(%s)" % (name, ", ".join(argList)), file=session)
7599451b44SJordan Rupprecht
7699451b44SJordan Rupprecht                # Also check the generic pc & stack pointer.  We can't test their absolute values,
7799451b44SJordan Rupprecht                # but they should be valid.  Uses get_GPRs() from the lldbutil
7899451b44SJordan Rupprecht                # module.
7999451b44SJordan Rupprecht                gpr_reg_set = lldbutil.get_GPRs(frame)
8099451b44SJordan Rupprecht                pc_value = gpr_reg_set.GetChildMemberWithName("pc")
8199451b44SJordan Rupprecht                self.assertTrue(pc_value, "We should have a valid PC.")
8299451b44SJordan Rupprecht                pc_value_int = int(pc_value.GetValue(), 0)
8399451b44SJordan Rupprecht                # Make sure on arm targets we dont mismatch PC value on the basis of thumb bit.
8499451b44SJordan Rupprecht                # Frame PC will not have thumb bit set in case of a thumb
8599451b44SJordan Rupprecht                # instruction as PC.
8699451b44SJordan Rupprecht                if self.getArchitecture() in ['arm', 'armv7', 'armv7k']:
8799451b44SJordan Rupprecht                    pc_value_int &= ~1
880ed758b2SDave Lee                self.assertEqual(
890ed758b2SDave Lee                    pc_value_int, frame.GetPC(),
9099451b44SJordan Rupprecht                    "PC gotten as a value should equal frame's GetPC")
9199451b44SJordan Rupprecht                sp_value = gpr_reg_set.GetChildMemberWithName("sp")
9299451b44SJordan Rupprecht                self.assertTrue(
9399451b44SJordan Rupprecht                    sp_value, "We should have a valid Stack Pointer.")
94619e2e09SDave Lee                self.assertEqual(
95619e2e09SDave Lee                    int(sp_value.GetValue(), 0), frame.GetSP(),
96619e2e09SDave Lee                    "SP gotten as a value should equal frame's GetSP")
9799451b44SJordan Rupprecht
9899451b44SJordan Rupprecht            print("---", file=session)
9999451b44SJordan Rupprecht            process.Continue()
10099451b44SJordan Rupprecht
10199451b44SJordan Rupprecht        # At this point, the inferior process should have exited.
1020ed758b2SDave Lee        self.assertEqual(
1030ed758b2SDave Lee            process.GetState(), lldb.eStateExited,
10499451b44SJordan Rupprecht            PROCESS_EXITED)
10599451b44SJordan Rupprecht
10699451b44SJordan Rupprecht        # Expect to find 'a' on the call stacks two times.
107619e2e09SDave Lee        self.assertEqual(callsOfA, 2,
10899451b44SJordan Rupprecht                        "Expect to find 'a' on the call stacks two times")
10999451b44SJordan Rupprecht        # By design, the 'a' call frame has the following arg vals:
11099451b44SJordan Rupprecht        #     o a((int)val=1, (char)ch='A')
11199451b44SJordan Rupprecht        #     o a((int)val=3, (char)ch='A')
11299451b44SJordan Rupprecht        if self.TraceOn():
11399451b44SJordan Rupprecht            print("Full stack traces when stopped on the breakpoint 'c':")
11499451b44SJordan Rupprecht            print(session.getvalue())
115e9264b74SKazuaki Ishizaki        self.expect(session.getvalue(), "Argument values displayed correctly",
11699451b44SJordan Rupprecht                    exe=False,
11799451b44SJordan Rupprecht                    substrs=["a((int)val=1, (char)ch='A')",
11899451b44SJordan Rupprecht                             "a((int)val=3, (char)ch='A')"])
11999451b44SJordan Rupprecht
12099451b44SJordan Rupprecht    def test_frame_api_boundary_condition(self):
12199451b44SJordan Rupprecht        """Exercise SBFrame APIs with boundary condition inputs."""
12299451b44SJordan Rupprecht        self.build()
12399451b44SJordan Rupprecht        exe = self.getBuildArtifact("a.out")
12499451b44SJordan Rupprecht
12599451b44SJordan Rupprecht        # Create a target by the debugger.
12699451b44SJordan Rupprecht        target = self.dbg.CreateTarget(exe)
12799451b44SJordan Rupprecht        self.assertTrue(target, VALID_TARGET)
12899451b44SJordan Rupprecht
12999451b44SJordan Rupprecht        # Now create a breakpoint on main.c by name 'c'.
13099451b44SJordan Rupprecht        breakpoint = target.BreakpointCreateByName('c', 'a.out')
131b321b429SJonas Devlieghere        self.trace("breakpoint:", breakpoint)
13299451b44SJordan Rupprecht        self.assertTrue(breakpoint and
13399451b44SJordan Rupprecht                        breakpoint.GetNumLocations() == 1,
13499451b44SJordan Rupprecht                        VALID_BREAKPOINT)
13599451b44SJordan Rupprecht
13699451b44SJordan Rupprecht        # Now launch the process, and do not stop at the entry point.
13799451b44SJordan Rupprecht        process = target.LaunchSimple(
13899451b44SJordan Rupprecht            None, None, self.get_process_working_directory())
13999451b44SJordan Rupprecht
14099451b44SJordan Rupprecht        process = target.GetProcess()
141*47c4c6a7SDave Lee        self.assertState(process.GetState(), lldb.eStateStopped,
14299451b44SJordan Rupprecht                         PROCESS_STOPPED)
14399451b44SJordan Rupprecht
14499451b44SJordan Rupprecht        thread = lldbutil.get_stopped_thread(
14599451b44SJordan Rupprecht            process, lldb.eStopReasonBreakpoint)
14699451b44SJordan Rupprecht        self.assertIsNotNone(thread)
14799451b44SJordan Rupprecht        frame = thread.GetFrameAtIndex(0)
14899451b44SJordan Rupprecht        if self.TraceOn():
14999451b44SJordan Rupprecht            print("frame:", frame)
15099451b44SJordan Rupprecht
15199451b44SJordan Rupprecht        # Boundary condition testings.
15299451b44SJordan Rupprecht        val1 = frame.FindVariable(None, True)
15399451b44SJordan Rupprecht        val2 = frame.FindVariable(None, False)
15499451b44SJordan Rupprecht        val3 = frame.FindValue(None, lldb.eValueTypeVariableGlobal)
15599451b44SJordan Rupprecht        if self.TraceOn():
15699451b44SJordan Rupprecht            print("val1:", val1)
15799451b44SJordan Rupprecht            print("val2:", val2)
15899451b44SJordan Rupprecht
15999451b44SJordan Rupprecht        frame.EvaluateExpression(None)
16099451b44SJordan Rupprecht
16199451b44SJordan Rupprecht    def test_frame_api_IsEqual(self):
16299451b44SJordan Rupprecht        """Exercise SBFrame API IsEqual."""
16399451b44SJordan Rupprecht        self.build()
16499451b44SJordan Rupprecht        exe = self.getBuildArtifact("a.out")
16599451b44SJordan Rupprecht
16699451b44SJordan Rupprecht        # Create a target by the debugger.
16799451b44SJordan Rupprecht        target = self.dbg.CreateTarget(exe)
16899451b44SJordan Rupprecht        self.assertTrue(target, VALID_TARGET)
16999451b44SJordan Rupprecht
17099451b44SJordan Rupprecht        # Now create a breakpoint on main.c by name 'c'.
17199451b44SJordan Rupprecht        breakpoint = target.BreakpointCreateByName('c', 'a.out')
172b321b429SJonas Devlieghere        self.trace("breakpoint:", breakpoint)
17399451b44SJordan Rupprecht        self.assertTrue(breakpoint and
17499451b44SJordan Rupprecht                        breakpoint.GetNumLocations() == 1,
17599451b44SJordan Rupprecht                        VALID_BREAKPOINT)
17699451b44SJordan Rupprecht
17799451b44SJordan Rupprecht        # Now launch the process, and do not stop at the entry point.
17899451b44SJordan Rupprecht        process = target.LaunchSimple(
17999451b44SJordan Rupprecht            None, None, self.get_process_working_directory())
18099451b44SJordan Rupprecht
18199451b44SJordan Rupprecht        process = target.GetProcess()
182*47c4c6a7SDave Lee        self.assertState(process.GetState(), lldb.eStateStopped,
18399451b44SJordan Rupprecht                         PROCESS_STOPPED)
18499451b44SJordan Rupprecht
18599451b44SJordan Rupprecht        thread = lldbutil.get_stopped_thread(
18699451b44SJordan Rupprecht            process, lldb.eStopReasonBreakpoint)
18799451b44SJordan Rupprecht        self.assertIsNotNone(thread)
18899451b44SJordan Rupprecht
18999451b44SJordan Rupprecht        frameEntered = thread.GetFrameAtIndex(0)
19099451b44SJordan Rupprecht        if self.TraceOn():
19199451b44SJordan Rupprecht            print(frameEntered)
19299451b44SJordan Rupprecht            lldbutil.print_stacktrace(thread)
19399451b44SJordan Rupprecht        self.assertTrue(frameEntered)
19499451b44SJordan Rupprecht
19599451b44SJordan Rupprecht        # Doing two step overs while still inside c().
19699451b44SJordan Rupprecht        thread.StepOver()
19799451b44SJordan Rupprecht        thread.StepOver()
19899451b44SJordan Rupprecht        self.assertTrue(thread)
19999451b44SJordan Rupprecht        frameNow = thread.GetFrameAtIndex(0)
20099451b44SJordan Rupprecht        if self.TraceOn():
20199451b44SJordan Rupprecht            print(frameNow)
20299451b44SJordan Rupprecht            lldbutil.print_stacktrace(thread)
20399451b44SJordan Rupprecht        self.assertTrue(frameNow)
20499451b44SJordan Rupprecht
20599451b44SJordan Rupprecht        # The latest two frames are considered equal.
20699451b44SJordan Rupprecht        self.assertTrue(frameEntered.IsEqual(frameNow))
20799451b44SJordan Rupprecht
20899451b44SJordan Rupprecht        # Now let's step out of frame c().
20999451b44SJordan Rupprecht        thread.StepOutOfFrame(frameNow)
21099451b44SJordan Rupprecht        frameOutOfC = thread.GetFrameAtIndex(0)
21199451b44SJordan Rupprecht        if self.TraceOn():
21299451b44SJordan Rupprecht            print(frameOutOfC)
21399451b44SJordan Rupprecht            lldbutil.print_stacktrace(thread)
21499451b44SJordan Rupprecht        self.assertTrue(frameOutOfC)
21599451b44SJordan Rupprecht
21699451b44SJordan Rupprecht        # The latest two frames should not be equal.
21799451b44SJordan Rupprecht        self.assertFalse(frameOutOfC.IsEqual(frameNow))
218