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 | |
| 14 | mydir = os.path.join("python_api", "frame") |
| 15 | |
Johnny Chen | d5f66fc | 2010-12-23 01:12:19 +0000 | [diff] [blame] | 16 | @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") |
| 17 | @python_api_test |
Johnny Chen | 24086bc | 2012-04-06 19:54:10 +0000 | [diff] [blame] | 18 | @dsym_test |
Johnny Chen | d5f66fc | 2010-12-23 01:12:19 +0000 | [diff] [blame] | 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 | |
Johnny Chen | d5f66fc | 2010-12-23 01:12:19 +0000 | [diff] [blame] | 24 | @python_api_test |
Johnny Chen | 24086bc | 2012-04-06 19:54:10 +0000 | [diff] [blame] | 25 | @dwarf_test |
Johnny Chen | d5f66fc | 2010-12-23 01:12:19 +0000 | [diff] [blame] | 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 | |
Johnny Chen | 1317b16 | 2011-12-19 23:41:29 +0000 | [diff] [blame] | 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 | |
Johnny Chen | 35e2ab6 | 2012-03-05 19:53:24 +0000 | [diff] [blame] | 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 | |
Johnny Chen | d5f66fc | 2010-12-23 01:12:19 +0000 | [diff] [blame] | 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) |
Johnny Chen | 4ebd019 | 2011-05-24 18:22:45 +0000 | [diff] [blame] | 49 | self.assertTrue(target, VALID_TARGET) |
Johnny Chen | d5f66fc | 2010-12-23 01:12:19 +0000 | [diff] [blame] | 50 | |
| 51 | # Now create a breakpoint on main.c by name 'c'. |
| 52 | breakpoint = target.BreakpointCreateByName('c', 'a.out') |
| 53 | #print "breakpoint:", breakpoint |
Johnny Chen | 4ebd019 | 2011-05-24 18:22:45 +0000 | [diff] [blame] | 54 | self.assertTrue(breakpoint and |
Johnny Chen | d5f66fc | 2010-12-23 01:12:19 +0000 | [diff] [blame] | 55 | breakpoint.GetNumLocations() == 1, |
| 56 | VALID_BREAKPOINT) |
| 57 | |
| 58 | # Now launch the process, and do not stop at the entry point. |
Johnny Chen | fbf1cfe | 2011-04-19 19:34:41 +0000 | [diff] [blame] | 59 | process = target.LaunchSimple(None, None, os.getcwd()) |
Johnny Chen | d5f66fc | 2010-12-23 01:12:19 +0000 | [diff] [blame] | 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) |
Johnny Chen | fbf1cfe | 2011-04-19 19:34:41 +0000 | [diff] [blame] | 77 | if self.TraceOn(): |
| 78 | print "frame:", frame |
Johnny Chen | c8134ce | 2011-05-13 23:42:44 +0000 | [diff] [blame] | 79 | |
Johnny Chen | d5f66fc | 2010-12-23 01:12:19 +0000 | [diff] [blame] | 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 = [] |
Johnny Chen | e69c748 | 2011-04-28 22:57:01 +0000 | [diff] [blame] | 92 | for val in valList: |
Johnny Chen | d5f66fc | 2010-12-23 01:12:19 +0000 | [diff] [blame] | 93 | argList.append("(%s)%s=%s" % (val.GetTypeName(), |
| 94 | val.GetName(), |
Greg Clayton | fe42ac4 | 2011-08-03 22:57:10 +0000 | [diff] [blame] | 95 | val.GetValue())) |
Johnny Chen | d5f66fc | 2010-12-23 01:12:19 +0000 | [diff] [blame] | 96 | print >> session, "%s(%s)" % (name, ", ".join(argList)) |
Jim Ingham | 8d543de | 2011-03-31 23:01:21 +0000 | [diff] [blame] | 97 | |
| 98 | # 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] | 99 | # but they should be valid. Uses get_GPRs() from the lldbutil module. |
| 100 | gpr_reg_set = lldbutil.get_GPRs(frame) |
Jim Ingham | 8d543de | 2011-03-31 23:01:21 +0000 | [diff] [blame] | 101 | pc_value = gpr_reg_set.GetChildMemberWithName("pc") |
Johnny Chen | 4ebd019 | 2011-05-24 18:22:45 +0000 | [diff] [blame] | 102 | self.assertTrue (pc_value, "We should have a valid PC.") |
Matt Kopec | ee969f9 | 2013-09-26 23:30:59 +0000 | [diff] [blame] | 103 | pc_value_str = pc_value.GetValue() |
| 104 | self.assertTrue (pc_value_str, "We should have a valid PC string.") |
| 105 | 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] | 106 | sp_value = gpr_reg_set.GetChildMemberWithName("sp") |
Johnny Chen | 4ebd019 | 2011-05-24 18:22:45 +0000 | [diff] [blame] | 107 | self.assertTrue (sp_value, "We should have a valid Stack Pointer.") |
Greg Clayton | fe42ac4 | 2011-08-03 22:57:10 +0000 | [diff] [blame] | 108 | 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] | 109 | |
| 110 | print >> session, "---" |
| 111 | process.Continue() |
| 112 | |
| 113 | # At this point, the inferior process should have exited. |
| 114 | self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED) |
| 115 | |
| 116 | # Expect to find 'a' on the call stacks two times. |
| 117 | self.assertTrue(callsOfA == 2, |
| 118 | "Expect to find 'a' on the call stacks two times") |
| 119 | # By design, the 'a' call frame has the following arg vals: |
| 120 | # o a((int)val=1, (char)ch='A') |
| 121 | # o a((int)val=3, (char)ch='A') |
Johnny Chen | fbf1cfe | 2011-04-19 19:34:41 +0000 | [diff] [blame] | 122 | if self.TraceOn(): |
| 123 | print "Full stack traces when stopped on the breakpoint 'c':" |
| 124 | print session.getvalue() |
Johnny Chen | d5f66fc | 2010-12-23 01:12:19 +0000 | [diff] [blame] | 125 | self.expect(session.getvalue(), "Argugment values displayed correctly", |
| 126 | exe=False, |
| 127 | substrs = ["a((int)val=1, (char)ch='A')", |
| 128 | "a((int)val=3, (char)ch='A')"]) |
| 129 | |
Johnny Chen | 1317b16 | 2011-12-19 23:41:29 +0000 | [diff] [blame] | 130 | def frame_api_boundary_condition(self): |
| 131 | exe = os.path.join(os.getcwd(), "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 | #print "breakpoint:", breakpoint |
| 140 | self.assertTrue(breakpoint and |
| 141 | breakpoint.GetNumLocations() == 1, |
| 142 | VALID_BREAKPOINT) |
| 143 | |
| 144 | # Now launch the process, and do not stop at the entry point. |
| 145 | process = target.LaunchSimple(None, None, os.getcwd()) |
| 146 | |
| 147 | process = target.GetProcess() |
| 148 | self.assertTrue(process.GetState() == lldb.eStateStopped, |
| 149 | PROCESS_STOPPED) |
| 150 | |
| 151 | thread = process.GetThreadAtIndex(0) |
| 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 | |
Johnny Chen | 35e2ab6 | 2012-03-05 19:53:24 +0000 | [diff] [blame] | 166 | def frame_api_IsEqual(self): |
| 167 | """Exercise SBFrame API IsEqual.""" |
| 168 | exe = os.path.join(os.getcwd(), "a.out") |
| 169 | |
| 170 | # Create a target by the debugger. |
| 171 | target = self.dbg.CreateTarget(exe) |
| 172 | self.assertTrue(target, VALID_TARGET) |
| 173 | |
| 174 | # Now create a breakpoint on main.c by name 'c'. |
| 175 | breakpoint = target.BreakpointCreateByName('c', 'a.out') |
| 176 | #print "breakpoint:", breakpoint |
| 177 | self.assertTrue(breakpoint and |
| 178 | breakpoint.GetNumLocations() == 1, |
| 179 | VALID_BREAKPOINT) |
| 180 | |
| 181 | # Now launch the process, and do not stop at the entry point. |
| 182 | process = target.LaunchSimple(None, None, os.getcwd()) |
| 183 | |
| 184 | process = target.GetProcess() |
| 185 | self.assertTrue(process.GetState() == lldb.eStateStopped, |
| 186 | PROCESS_STOPPED) |
| 187 | |
| 188 | thread = process.GetThreadAtIndex(0) |
| 189 | self.assertTrue(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. |
Greg Clayton | 7fdf9ef | 2012-04-05 16:12:35 +0000 | [diff] [blame] | 219 | self.assertFalse(frameOutOfC.IsEqual(frameNow)) |
Johnny Chen | 35e2ab6 | 2012-03-05 19:53:24 +0000 | [diff] [blame] | 220 | |
Johnny Chen | d5f66fc | 2010-12-23 01:12:19 +0000 | [diff] [blame] | 221 | |
| 222 | if __name__ == '__main__': |
| 223 | import atexit |
| 224 | lldb.SBDebugger.Initialize() |
| 225 | atexit.register(lambda: lldb.SBDebugger.Terminate()) |
| 226 | unittest2.main() |