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